1 /**
2  * Semantic analysis of expressions.
3  *
4  * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5  *
6  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d)
10  * Documentation:  https://dlang.org/phobos/dmd_expressionsem.html
11  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d
12  */
13 
14 module dmd.expressionsem;
15 
16 import core.stdc.stdio;
17 
18 import dmd.access;
19 import dmd.aggregate;
20 import dmd.aliasthis;
21 import dmd.arrayop;
22 import dmd.arraytypes;
23 import dmd.attrib;
24 import dmd.astcodegen;
25 import dmd.canthrow;
26 import dmd.chkformat;
27 import dmd.ctorflow;
28 import dmd.dscope;
29 import dmd.dsymbol;
30 import dmd.declaration;
31 import dmd.dclass;
32 import dmd.dcast;
33 import dmd.delegatize;
34 import dmd.denum;
35 import dmd.dimport;
36 import dmd.dinterpret;
37 import dmd.dmangle;
38 import dmd.dmodule;
39 import dmd.dstruct;
40 import dmd.dsymbolsem;
41 import dmd.dtemplate;
42 import dmd.errors;
43 import dmd.escape;
44 import dmd.expression;
45 import dmd.func;
46 import dmd.globals;
47 import dmd.hdrgen;
48 import dmd.id;
49 import dmd.identifier;
50 import dmd.imphint;
51 import dmd.init;
52 import dmd.initsem;
53 import dmd.inline;
54 import dmd.intrange;
55 import dmd.mtype;
56 import dmd.nspace;
57 import dmd.opover;
58 import dmd.optimize;
59 import dmd.parse;
60 import dmd.root.ctfloat;
61 import dmd.root.file;
62 import dmd.root.filename;
63 import dmd.root.outbuffer;
64 import dmd.root.rootobject;
65 import dmd.root.string;
66 import dmd.semantic2;
67 import dmd.semantic3;
68 import dmd.sideeffect;
69 import dmd.safe;
70 import dmd.target;
71 import dmd.tokens;
72 import dmd.traits;
73 import dmd.typesem;
74 import dmd.typinf;
75 import dmd.utf;
76 import dmd.utils;
77 import dmd.visitor;
78 
79 enum LOGSEMANTIC = false;
80 
81 /********************************************************
82  * Perform semantic analysis and CTFE on expressions to produce
83  * a string.
84  * Params:
85  *      buf = append generated string to buffer
86  *      sc = context
87  *      exps = array of Expressions
88  * Returns:
89  *      true on error
90  */
91 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
92 {
93     if (!exps)
94         return false;
95 
96     foreach (ex; *exps)
97     {
98         if (!ex)
99             continue;
100         auto sc2 = sc.startCTFE();
101         auto e2 = ex.expressionSemantic(sc2);
102         auto e3 = resolveProperties(sc2, e2);
103         sc2.endCTFE();
104 
105         // allowed to contain types as well as expressions
106         auto e4 = ctfeInterpretForPragmaMsg(e3);
107         if (!e4 || e4.op == TOK.error)
108             return true;
109 
110         // expand tuple
111         if (auto te = e4.isTupleExp())
112         {
113             if (expressionsToString(buf, sc, te.exps))
114                 return true;
115             continue;
116         }
117         // char literals exp `.toStringExp` return `null` but we cant override it
118         // because in most contexts we don't want the conversion to succeed.
119         IntegerExp ie = e4.isIntegerExp();
120         const ty = (ie && ie.type) ? ie.type.ty : Terror;
121         if (ty.isSomeChar)
122         {
123             auto tsa = new TypeSArray(ie.type, new IntegerExp(1));
124             e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
125         }
126 
127         if (StringExp se = e4.toStringExp())
128             buf.writestring(se.toUTF8(sc).peekString());
129         else
130             buf.writestring(e4.toString());
131     }
132     return false;
133 }
134 
135 
136 /***********************************************************
137  * Resolve `exp` as a compile-time known string.
138  * Params:
139  *  sc  = scope
140  *  exp = Expression which expected as a string
141  *  s   = What the string is expected for, will be used in error diagnostic.
142  * Returns:
143  *  String literal, or `null` if error happens.
144  */
145 StringExp semanticString(Scope *sc, Expression exp, const char* s)
146 {
147     sc = sc.startCTFE();
148     exp = exp.expressionSemantic(sc);
149     exp = resolveProperties(sc, exp);
150     sc = sc.endCTFE();
151 
152     if (exp.op == TOK.error)
153         return null;
154 
155     auto e = exp;
156     if (exp.type.isString())
157     {
158         e = e.ctfeInterpret();
159         if (e.op == TOK.error)
160             return null;
161     }
162 
163     auto se = e.toStringExp();
164     if (!se)
165     {
166         exp.error("`string` expected for %s, not `(%s)` of type `%s`",
167             s, exp.toChars(), exp.type.toChars());
168         return null;
169     }
170     return se;
171 }
172 
173 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
174 {
175     Expression e0;
176     Expression e1 = Expression.extractLast(ue.e1, e0);
177     // https://issues.dlang.org/show_bug.cgi?id=12585
178     // Extract the side effect part if ue.e1 is comma.
179 
180     if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
181     {
182         /* Even if opDollar is needed, 'e1' should be evaluate only once. So
183          * Rewrite:
184          *      e1.opIndex( ... use of $ ... )
185          *      e1.opSlice( ... use of $ ... )
186          * as:
187          *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
188          *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
189          */
190         e1 = extractSideEffect(sc, "__dop", e0, e1, false);
191         assert(e1.op == TOK.variable);
192         VarExp ve = cast(VarExp)e1;
193         ve.var.storage_class |= STC.exptemp;     // lifetime limited to expression
194     }
195     ue.e1 = e1;
196     return e0;
197 }
198 
199 /**************************************
200  * Runs semantic on ae.arguments. Declares temporary variables
201  * if '$' was used.
202  */
203 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
204 {
205     assert(!ae.lengthVar);
206     *pe0 = null;
207     AggregateDeclaration ad = isAggregate(ae.e1.type);
208     Dsymbol slice = search_function(ad, Id.slice);
209     //printf("slice = %s %s\n", slice.kind(), slice.toChars());
210     foreach (i, e; *ae.arguments)
211     {
212         if (i == 0)
213             *pe0 = extractOpDollarSideEffect(sc, ae);
214 
215         if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration()))
216         {
217         Lfallback:
218             if (ae.arguments.dim == 1)
219                 return null;
220             ae.error("multi-dimensional slicing requires template `opSlice`");
221             return new ErrorExp();
222         }
223         //printf("[%d] e = %s\n", i, e.toChars());
224 
225         // Create scope for '$' variable for this dimension
226         auto sym = new ArrayScopeSymbol(sc, ae);
227         sym.parent = sc.scopesym;
228         sc = sc.push(sym);
229         ae.lengthVar = null; // Create it only if required
230         ae.currentDimension = i; // Dimension for $, if required
231 
232         e = e.expressionSemantic(sc);
233         e = resolveProperties(sc, e);
234 
235         if (ae.lengthVar && sc.func)
236         {
237             // If $ was used, declare it now
238             Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
239             de = de.expressionSemantic(sc);
240             *pe0 = Expression.combine(*pe0, de);
241         }
242         sc = sc.pop();
243 
244         if (e.op == TOK.interval)
245         {
246             IntervalExp ie = cast(IntervalExp)e;
247 
248             auto tiargs = new Objects();
249             Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
250             edim = edim.expressionSemantic(sc);
251             tiargs.push(edim);
252 
253             auto fargs = new Expressions(2);
254             (*fargs)[0] = ie.lwr;
255             (*fargs)[1] = ie.upr;
256 
257             uint xerrors = global.startGagging();
258             sc = sc.push();
259             FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
260             sc = sc.pop();
261             global.endGagging(xerrors);
262             if (!fslice)
263                 goto Lfallback;
264 
265             e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
266             e = new CallExp(ae.loc, e, fargs);
267             e = e.expressionSemantic(sc);
268         }
269 
270         if (!e.type)
271         {
272             ae.error("`%s` has no value", e.toChars());
273             e = new ErrorExp();
274         }
275         if (e.op == TOK.error)
276             return e;
277 
278         (*ae.arguments)[i] = e;
279     }
280     return ae;
281 }
282 
283 /**************************************
284  * Runs semantic on se.lwr and se.upr. Declares a temporary variable
285  * if '$' was used.
286  * Returns:
287  *      ae, or ErrorExp if errors occurred
288  */
289 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
290 {
291     //assert(!ae.lengthVar);
292     if (!ie)
293         return ae;
294 
295     VarDeclaration lengthVar = ae.lengthVar;
296     bool errors = false;
297 
298     // create scope for '$'
299     auto sym = new ArrayScopeSymbol(sc, ae);
300     sym.parent = sc.scopesym;
301     sc = sc.push(sym);
302 
303     Expression sem(Expression e)
304     {
305         e = e.expressionSemantic(sc);
306         e = resolveProperties(sc, e);
307         if (!e.type)
308         {
309             ae.error("`%s` has no value", e.toChars());
310             errors = true;
311         }
312         return e;
313     }
314 
315     ie.lwr = sem(ie.lwr);
316     ie.upr = sem(ie.upr);
317 
318     if (lengthVar != ae.lengthVar && sc.func)
319     {
320         // If $ was used, declare it now
321         Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
322         de = de.expressionSemantic(sc);
323         *pe0 = Expression.combine(*pe0, de);
324     }
325 
326     sc = sc.pop();
327 
328     return errors ? new ErrorExp() : ae;
329 }
330 
331 /******************************
332  * Perform semantic() on an array of Expressions.
333  */
334 bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
335 {
336     bool err = false;
337     if (exps)
338     {
339         foreach (ref e; *exps)
340         {
341             if (e)
342             {
343                 auto e2 = e.expressionSemantic(sc);
344                 if (e2.op == TOK.error)
345                     err = true;
346                 if (preserveErrors || e2.op != TOK.error)
347                     e = e2;
348             }
349         }
350     }
351     return err;
352 }
353 
354 /******************************
355  * Check the tail CallExp is really property function call.
356  * Bugs:
357  * This doesn't appear to do anything.
358  */
359 private bool checkPropertyCall(Expression e)
360 {
361     e = lastComma(e);
362 
363     if (e.op == TOK.call)
364     {
365         CallExp ce = cast(CallExp)e;
366         TypeFunction tf;
367         if (ce.f)
368         {
369             tf = cast(TypeFunction)ce.f.type;
370             /* If a forward reference to ce.f, try to resolve it
371              */
372             if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
373             {
374                 ce.f.dsymbolSemantic(null);
375                 tf = cast(TypeFunction)ce.f.type;
376             }
377         }
378         else if (ce.e1.type.ty == Tfunction)
379             tf = cast(TypeFunction)ce.e1.type;
380         else if (ce.e1.type.ty == Tdelegate)
381             tf = cast(TypeFunction)ce.e1.type.nextOf();
382         else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction)
383             tf = cast(TypeFunction)ce.e1.type.nextOf();
384         else
385             assert(0);
386     }
387     return false;
388 }
389 
390 /******************************
391  * Find symbol in accordance with the UFCS name look up rule
392  */
393 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
394 {
395     //printf("searchUFCS(ident = %s)\n", ident.toChars());
396     Loc loc = ue.loc;
397 
398     // TODO: merge with Scope.search.searchScopes()
399     Dsymbol searchScopes(int flags)
400     {
401         Dsymbol s = null;
402         for (Scope* scx = sc; scx; scx = scx.enclosing)
403         {
404             if (!scx.scopesym)
405                 continue;
406             if (scx.scopesym.isModule())
407                 flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
408             s = scx.scopesym.search(loc, ident, flags);
409             if (s)
410             {
411                 // overload set contains only module scope symbols.
412                 if (s.isOverloadSet())
413                     break;
414                 // selective/renamed imports also be picked up
415                 if (AliasDeclaration ad = s.isAliasDeclaration())
416                 {
417                     if (ad._import)
418                         break;
419                 }
420                 // See only module scope symbols for UFCS target.
421                 Dsymbol p = s.toParent2();
422                 if (p && p.isModule())
423                     break;
424             }
425             s = null;
426 
427             // Stop when we hit a module, but keep going if that is not just under the global scope
428             if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
429                 break;
430         }
431         return s;
432     }
433 
434     int flags = 0;
435     Dsymbol s;
436 
437     if (sc.flags & SCOPE.ignoresymbolvisibility)
438         flags |= IgnoreSymbolVisibility;
439 
440     // First look in local scopes
441     s = searchScopes(flags | SearchLocalsOnly);
442     if (!s)
443     {
444         // Second look in imported modules
445         s = searchScopes(flags | SearchImportsOnly);
446     }
447 
448     if (!s)
449         return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
450 
451     FuncDeclaration f = s.isFuncDeclaration();
452     if (f)
453     {
454         TemplateDeclaration td = getFuncTemplateDecl(f);
455         if (td)
456         {
457             if (td.overroot)
458                 td = td.overroot;
459             s = td;
460         }
461     }
462 
463     if (ue.op == TOK.dotTemplateInstance)
464     {
465         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue;
466         auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
467         if (!ti.updateTempDecl(sc, s))
468             return new ErrorExp();
469         return new ScopeExp(loc, ti);
470     }
471     else
472     {
473         //printf("-searchUFCS() %s\n", s.toChars());
474         return new DsymbolExp(loc, s);
475     }
476 }
477 
478 /******************************
479  * Pull out callable entity with UFCS.
480  */
481 private Expression resolveUFCS(Scope* sc, CallExp ce)
482 {
483     Loc loc = ce.loc;
484     Expression eleft;
485     Expression e;
486 
487     if (ce.e1.op == TOK.dotIdentifier)
488     {
489         DotIdExp die = cast(DotIdExp)ce.e1;
490         Identifier ident = die.ident;
491 
492         Expression ex = die.semanticX(sc);
493         if (ex != die)
494         {
495             ce.e1 = ex;
496             return null;
497         }
498         eleft = die.e1;
499 
500         Type t = eleft.type.toBasetype();
501         if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
502         {
503             /* Built-in types and arrays have no callable properties, so do shortcut.
504              * It is necessary in: e.init()
505              */
506         }
507         else if (t.ty == Taarray)
508         {
509             if (ident == Id.remove)
510             {
511                 /* Transform:
512                  *  aa.remove(arg) into delete aa[arg]
513                  */
514                 if (!ce.arguments || ce.arguments.dim != 1)
515                 {
516                     ce.error("expected key as argument to `aa.remove()`");
517                     return new ErrorExp();
518                 }
519                 if (!eleft.type.isMutable())
520                 {
521                     ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
522                     return new ErrorExp();
523                 }
524                 Expression key = (*ce.arguments)[0];
525                 key = key.expressionSemantic(sc);
526                 key = resolveProperties(sc, key);
527 
528                 TypeAArray taa = cast(TypeAArray)t;
529                 key = key.implicitCastTo(sc, taa.index);
530 
531                 if (key.checkValue() || key.checkSharedAccess(sc))
532                     return new ErrorExp();
533 
534                 semanticTypeInfo(sc, taa.index);
535 
536                 return new RemoveExp(loc, eleft, key);
537             }
538         }
539         else
540         {
541             if (Expression ey = die.semanticY(sc, 1))
542             {
543                 if (ey.op == TOK.error)
544                     return ey;
545                 ce.e1 = ey;
546                 if (isDotOpDispatch(ey))
547                 {
548                     uint errors = global.startGagging();
549                     e = ce.syntaxCopy().expressionSemantic(sc);
550                     if (!global.endGagging(errors))
551                         return e;
552 
553                     // even opDispatch and UFCS must have valid arguments,
554                     // so now that we've seen indication of a problem,
555                     // check them for issues.
556                     Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
557 
558                     if (arrayExpressionSemantic(originalArguments, sc))
559                         return new ErrorExp();
560 
561                     /* fall down to UFCS */
562                 }
563                 else
564                     return null;
565             }
566         }
567 
568         /* https://issues.dlang.org/show_bug.cgi?id=13953
569          *
570          * If a struct has an alias this to an associative array
571          * and remove is used on a struct instance, we have to
572          * check first if there is a remove function that can be called
573          * on the struct. If not we must check the alias this.
574          *
575          * struct A
576          * {
577          *      string[string] a;
578          *      alias a this;
579          * }
580          *
581          * void fun()
582          * {
583          *      A s;
584          *      s.remove("foo");
585          * }
586          */
587         const errors = global.startGagging();
588         e = searchUFCS(sc, die, ident);
589         // if there were any errors and the identifier was remove
590         if (global.endGagging(errors))
591         {
592             if (ident == Id.remove)
593             {
594                 // check alias this
595                 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
596                 if (alias_e && alias_e != die.e1)
597                 {
598                     die.e1 = alias_e;
599                     CallExp ce2 = cast(CallExp)ce.syntaxCopy();
600                     ce2.e1 = die;
601                     e = cast(CallExp)ce2.trySemantic(sc);
602                     if (e)
603                         return e;
604                 }
605             }
606             // if alias this did not work out, print the initial errors
607             searchUFCS(sc, die, ident);
608         }
609     }
610     else if (ce.e1.op == TOK.dotTemplateInstance)
611     {
612         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1;
613         if (Expression ey = dti.semanticY(sc, 1))
614         {
615             ce.e1 = ey;
616             return null;
617         }
618         eleft = dti.e1;
619         e = searchUFCS(sc, dti, dti.ti.name);
620     }
621     else
622         return null;
623 
624     // Rewrite
625     ce.e1 = e;
626     if (!ce.arguments)
627         ce.arguments = new Expressions();
628     ce.arguments.shift(eleft);
629 
630     return null;
631 }
632 
633 /******************************
634  * Pull out property with UFCS.
635  */
636 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
637 {
638     Loc loc = e1.loc;
639     Expression eleft;
640     Expression e;
641 
642     if (e1.op == TOK.dotIdentifier)
643     {
644         DotIdExp die = cast(DotIdExp)e1;
645         eleft = die.e1;
646         e = searchUFCS(sc, die, die.ident);
647     }
648     else if (e1.op == TOK.dotTemplateInstance)
649     {
650         DotTemplateInstanceExp dti;
651         dti = cast(DotTemplateInstanceExp)e1;
652         eleft = dti.e1;
653         e = searchUFCS(sc, dti, dti.ti.name);
654     }
655     else
656         return null;
657 
658     if (e is null)
659         return null;
660 
661     // Rewrite
662     if (e2)
663     {
664         // run semantic without gagging
665         e2 = e2.expressionSemantic(sc);
666 
667         /* f(e1) = e2
668          */
669         Expression ex = e.copy();
670         auto a1 = new Expressions(1);
671         (*a1)[0] = eleft;
672         ex = new CallExp(loc, ex, a1);
673         auto e1PassSemantic = ex.trySemantic(sc);
674 
675         /* f(e1, e2)
676          */
677         auto a2 = new Expressions(2);
678         (*a2)[0] = eleft;
679         (*a2)[1] = e2;
680         e = new CallExp(loc, e, a2);
681         e = e.trySemantic(sc);
682         if (!e1PassSemantic && !e)
683         {
684             /* https://issues.dlang.org/show_bug.cgi?id=20448
685              *
686              * If both versions have failed to pass semantic,
687              * f(e1) = e2 gets priority in error printing
688              * because f might be a templated function that
689              * failed to instantiate and we have to print
690              * the instantiation errors.
691              */
692             return e1.expressionSemantic(sc);
693         }
694         else if (ex && !e)
695         {
696             checkPropertyCall(ex);
697             ex = new AssignExp(loc, ex, e2);
698             return ex.expressionSemantic(sc);
699         }
700         else
701         {
702             // strict setter prints errors if fails
703             e = e.expressionSemantic(sc);
704         }
705         checkPropertyCall(e);
706         return e;
707     }
708     else
709     {
710         /* f(e1)
711          */
712         auto arguments = new Expressions(1);
713         (*arguments)[0] = eleft;
714         e = new CallExp(loc, e, arguments);
715         e = e.expressionSemantic(sc);
716         checkPropertyCall(e);
717         return e.expressionSemantic(sc);
718     }
719 }
720 
721 /******************************
722  * If e1 is a property function (template), resolve it.
723  */
724 Expression resolvePropertiesOnly(Scope* sc, Expression e1)
725 {
726     //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars());
727 
728     Expression handleOverloadSet(OverloadSet os)
729     {
730         assert(os);
731         foreach (s; os.a)
732         {
733             auto fd = s.isFuncDeclaration();
734             auto td = s.isTemplateDeclaration();
735             if (fd)
736             {
737                 if ((cast(TypeFunction)fd.type).isproperty)
738                     return resolveProperties(sc, e1);
739             }
740             else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
741             {
742                 if ((cast(TypeFunction)fd.type).isproperty ||
743                     (fd.storage_class2 & STC.property) ||
744                     (td._scope.stc & STC.property))
745                     return resolveProperties(sc, e1);
746             }
747         }
748         return e1;
749     }
750 
751     Expression handleTemplateDecl(TemplateDeclaration td)
752     {
753         assert(td);
754         if (td.onemember)
755         {
756             if (auto fd = td.onemember.isFuncDeclaration())
757             {
758                 if ((cast(TypeFunction)fd.type).isproperty ||
759                     (fd.storage_class2 & STC.property) ||
760                     (td._scope.stc & STC.property))
761                     return resolveProperties(sc, e1);
762             }
763         }
764         return e1;
765     }
766 
767     Expression handleFuncDecl(FuncDeclaration fd)
768     {
769         assert(fd);
770         if ((cast(TypeFunction)fd.type).isproperty)
771             return resolveProperties(sc, e1);
772         return e1;
773     }
774 
775     if (auto de = e1.isDotExp())
776     {
777         if (auto os = de.e2.isOverExp())
778             return handleOverloadSet(os.vars);
779     }
780     else if (auto oe = e1.isOverExp())
781         return handleOverloadSet(oe.vars);
782     else if (auto dti = e1.isDotTemplateInstanceExp())
783     {
784         if (dti.ti.tempdecl)
785             if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
786                 return handleTemplateDecl(td);
787     }
788     else if (auto dte = e1.isDotTemplateExp())
789         return handleTemplateDecl(dte.td);
790     else if (e1.op == TOK.scope_)
791     {
792         Dsymbol s = (cast(ScopeExp)e1).sds;
793         TemplateInstance ti = s.isTemplateInstance();
794         if (ti && !ti.semanticRun && ti.tempdecl)
795             if (auto td = ti.tempdecl.isTemplateDeclaration())
796                 return handleTemplateDecl(td);
797     }
798     else if (e1.op == TOK.template_)
799         return handleTemplateDecl((cast(TemplateExp)e1).td);
800     else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction)
801     {
802         DotVarExp dve = cast(DotVarExp)e1;
803         return handleFuncDecl(dve.var.isFuncDeclaration());
804     }
805     else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis()))
806         return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration());
807     return e1;
808 }
809 
810 /****************************************
811  * Turn symbol `s` into the expression it represents.
812  *
813  * Params:
814  *      s = symbol to resolve
815  *      loc = location of use of `s`
816  *      sc = context
817  *      hasOverloads = applies if `s` represents a function.
818  *          true means it's overloaded and will be resolved later,
819  *          false means it's the exact function symbol.
820  * Returns:
821  *      `s` turned into an expression, `ErrorExp` if an error occurred
822  */
823 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
824 {
825     static if (LOGSEMANTIC)
826     {
827         printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
828     }
829 
830 Lagain:
831     Expression e;
832 
833     //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
834     //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
835     Dsymbol olds = s;
836     Declaration d = s.isDeclaration();
837     if (d && (d.storage_class & STC.templateparameter))
838     {
839         s = s.toAlias();
840     }
841     else
842     {
843         if (!s.isFuncDeclaration()) // functions are checked after overloading
844         {
845             s.checkDeprecated(loc, sc);
846             if (d)
847                 d.checkDisabled(loc, sc);
848         }
849 
850         // https://issues.dlang.org/show_bug.cgi?id=12023
851         // if 's' is a tuple variable, the tuple is returned.
852         s = s.toAlias();
853 
854         //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
855         if (s != olds && !s.isFuncDeclaration())
856         {
857             s.checkDeprecated(loc, sc);
858             if (d)
859                 d.checkDisabled(loc, sc);
860         }
861     }
862 
863     if (auto em = s.isEnumMember())
864     {
865         return em.getVarExp(loc, sc);
866     }
867     if (auto v = s.isVarDeclaration())
868     {
869         //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
870         if (sc.intypeof == 1 && !v.inuse)
871             v.dsymbolSemantic(sc);
872         if (!v.type ||                  // during variable type inference
873             !v.type.deco && v.inuse)    // during variable type semantic
874         {
875             if (v.inuse)    // variable type depends on the variable itself
876                 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
877             else            // variable type cannot be determined
878                 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
879             return new ErrorExp();
880         }
881         if (v.type.ty == Terror)
882             return new ErrorExp();
883 
884         if ((v.storage_class & STC.manifest) && v._init)
885         {
886             if (v.inuse)
887             {
888                 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
889                 return new ErrorExp();
890             }
891             e = v.expandInitializer(loc);
892             v.inuse++;
893             e = e.expressionSemantic(sc);
894             v.inuse--;
895             return e;
896         }
897 
898         // Change the ancestor lambdas to delegate before hasThis(sc) call.
899         if (v.checkNestedReference(sc, loc))
900             return new ErrorExp();
901 
902         if (v.needThis() && hasThis(sc))
903             e = new DotVarExp(loc, new ThisExp(loc), v);
904         else
905             e = new VarExp(loc, v);
906         e = e.expressionSemantic(sc);
907         return e;
908     }
909     if (auto fld = s.isFuncLiteralDeclaration())
910     {
911         //printf("'%s' is a function literal\n", fld.toChars());
912         e = new FuncExp(loc, fld);
913         return e.expressionSemantic(sc);
914     }
915     if (auto f = s.isFuncDeclaration())
916     {
917         f = f.toAliasFunc();
918         if (!f.functionSemantic())
919             return new ErrorExp();
920 
921         if (!hasOverloads && f.checkForwardRef(loc))
922             return new ErrorExp();
923 
924         auto fd = s.isFuncDeclaration();
925         fd.type = f.type;
926         return new VarExp(loc, fd, hasOverloads);
927     }
928     if (OverDeclaration od = s.isOverDeclaration())
929     {
930         e = new VarExp(loc, od, true);
931         e.type = Type.tvoid;
932         return e;
933     }
934     if (OverloadSet o = s.isOverloadSet())
935     {
936         //printf("'%s' is an overload set\n", o.toChars());
937         return new OverExp(loc, o);
938     }
939 
940     if (Import imp = s.isImport())
941     {
942         if (!imp.pkg)
943         {
944             .error(loc, "forward reference of import `%s`", imp.toChars());
945             return new ErrorExp();
946         }
947         auto ie = new ScopeExp(loc, imp.pkg);
948         return ie.expressionSemantic(sc);
949     }
950     if (Package pkg = s.isPackage())
951     {
952         auto ie = new ScopeExp(loc, pkg);
953         return ie.expressionSemantic(sc);
954     }
955     if (Module mod = s.isModule())
956     {
957         auto ie = new ScopeExp(loc, mod);
958         return ie.expressionSemantic(sc);
959     }
960     if (Nspace ns = s.isNspace())
961     {
962         auto ie = new ScopeExp(loc, ns);
963         return ie.expressionSemantic(sc);
964     }
965 
966     if (Type t = s.getType())
967     {
968         return (new TypeExp(loc, t)).expressionSemantic(sc);
969     }
970 
971     if (TupleDeclaration tup = s.isTupleDeclaration())
972     {
973         if (tup.needThis() && hasThis(sc))
974             e = new DotVarExp(loc, new ThisExp(loc), tup);
975         else
976             e = new TupleExp(loc, tup);
977         e = e.expressionSemantic(sc);
978         return e;
979     }
980 
981     if (TemplateInstance ti = s.isTemplateInstance())
982     {
983         ti.dsymbolSemantic(sc);
984         if (!ti.inst || ti.errors)
985             return new ErrorExp();
986         s = ti.toAlias();
987         if (!s.isTemplateInstance())
988             goto Lagain;
989         e = new ScopeExp(loc, ti);
990         e = e.expressionSemantic(sc);
991         return e;
992     }
993     if (TemplateDeclaration td = s.isTemplateDeclaration())
994     {
995         Dsymbol p = td.toParentLocal();
996         FuncDeclaration fdthis = hasThis(sc);
997         AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
998         if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
999         {
1000             e = new DotTemplateExp(loc, new ThisExp(loc), td);
1001         }
1002         else
1003             e = new TemplateExp(loc, td);
1004         e = e.expressionSemantic(sc);
1005         return e;
1006     }
1007 
1008     .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1009     return new ErrorExp();
1010 }
1011 
1012 /*************************************************************
1013  * Given var, get the
1014  * right `this` pointer if var is in an outer class, but our
1015  * existing `this` pointer is in an inner class.
1016  * Params:
1017  *      loc = location to use for error messages
1018  *      sc = context
1019  *      ad = struct or class we need the correct `this` for
1020  *      e1 = existing `this`
1021  *      var = the specific member of ad we're accessing
1022  *      flag = if true, return `null` instead of throwing an error
1023  * Returns:
1024  *      Expression representing the `this` for the var
1025  */
1026 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1027 {
1028     //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1029 L1:
1030     Type t = e1.type.toBasetype();
1031     //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1032 
1033     if (e1.op == TOK.objcClassReference)
1034     {
1035         // We already have an Objective-C class reference, just use that as 'this'.
1036         return e1;
1037     }
1038     else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1039              var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1040              var.isFuncDeclaration.selector)
1041     {
1042         return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad);
1043     }
1044 
1045     /* Access of a member which is a template parameter in dual-scope scenario
1046      * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1047      * class B {int m; inc() { new A().inc!m(); } }
1048      */
1049     if (e1.op == TOK.this_)
1050     {
1051         FuncDeclaration f = hasThis(sc);
1052         if (f && f.isThis2)
1053         {
1054             if (f.followInstantiationContext(ad))
1055             {
1056                 e1 = new VarExp(loc, f.vthis);
1057                 e1 = new PtrExp(loc, e1);
1058                 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1059                 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1060                 if (e1.op == TOK.error)
1061                     return e1;
1062                 goto L1;
1063             }
1064         }
1065     }
1066 
1067     /* If e1 is not the 'this' pointer for ad
1068      */
1069     if (ad &&
1070         !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) &&
1071         !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad))
1072     {
1073         ClassDeclaration cd = ad.isClassDeclaration();
1074         ClassDeclaration tcd = t.isClassHandle();
1075 
1076         /* e1 is the right this if ad is a base class of e1
1077          */
1078         if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1079         {
1080             /* Only classes can be inner classes with an 'outer'
1081              * member pointing to the enclosing class instance
1082              */
1083             if (tcd && tcd.isNested())
1084             {
1085                 /* e1 is the 'this' pointer for an inner class: tcd.
1086                  * Rewrite it as the 'this' pointer for the outer class.
1087                  */
1088                 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1089                 e1 = new DotVarExp(loc, e1, vthis);
1090                 e1.type = vthis.type;
1091                 e1.type = e1.type.addMod(t.mod);
1092                 // Do not call ensureStaticLinkTo()
1093                 //e1 = e1.semantic(sc);
1094 
1095                 // Skip up over nested functions, and get the enclosing
1096                 // class type.
1097                 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1098                 if (e1.op == TOK.error)
1099                     return e1;
1100                 goto L1;
1101             }
1102 
1103             /* Can't find a path from e1 to ad
1104              */
1105             if (flag)
1106                 return null;
1107             e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1108             return new ErrorExp();
1109         }
1110     }
1111     return e1;
1112 }
1113 
1114 /***************************************
1115  * Pull out any properties.
1116  */
1117 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1118 {
1119     //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null);
1120     Loc loc = e1.loc;
1121 
1122     OverloadSet os;
1123     Dsymbol s;
1124     Objects* tiargs;
1125     Type tthis;
1126     if (e1.op == TOK.dot)
1127     {
1128         DotExp de = cast(DotExp)e1;
1129         if (de.e2.op == TOK.overloadSet)
1130         {
1131             tiargs = null;
1132             tthis = de.e1.type;
1133             os = (cast(OverExp)de.e2).vars;
1134             goto Los;
1135         }
1136     }
1137     else if (e1.op == TOK.overloadSet)
1138     {
1139         tiargs = null;
1140         tthis = null;
1141         os = (cast(OverExp)e1).vars;
1142     Los:
1143         assert(os);
1144         FuncDeclaration fd = null;
1145         if (e2)
1146         {
1147             e2 = e2.expressionSemantic(sc);
1148             if (e2.op == TOK.error)
1149                 return new ErrorExp();
1150             e2 = resolveProperties(sc, e2);
1151 
1152             Expressions a;
1153             a.push(e2);
1154 
1155             for (size_t i = 0; i < os.a.dim; i++)
1156             {
1157                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1158                 {
1159                     if (f.errors)
1160                         return new ErrorExp();
1161                     fd = f;
1162                     assert(fd.type.ty == Tfunction);
1163                 }
1164             }
1165             if (fd)
1166             {
1167                 Expression e = new CallExp(loc, e1, e2);
1168                 return e.expressionSemantic(sc);
1169             }
1170         }
1171         {
1172             for (size_t i = 0; i < os.a.dim; i++)
1173             {
1174                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1175                 {
1176                     if (f.errors)
1177                         return new ErrorExp();
1178                     fd = f;
1179                     assert(fd.type.ty == Tfunction);
1180                     TypeFunction tf = cast(TypeFunction)fd.type;
1181                     if (!tf.isref && e2)
1182                     {
1183                         error(loc, "%s is not an lvalue", e1.toChars());
1184                         return new ErrorExp();
1185                     }
1186                 }
1187             }
1188             if (fd)
1189             {
1190                 Expression e = new CallExp(loc, e1);
1191                 if (e2)
1192                     e = new AssignExp(loc, e, e2);
1193                 return e.expressionSemantic(sc);
1194             }
1195         }
1196         if (e2)
1197             goto Leprop;
1198     }
1199     else if (e1.op == TOK.dotTemplateInstance)
1200     {
1201         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
1202         if (!dti.findTempDecl(sc))
1203             goto Leprop;
1204         if (!dti.ti.semanticTiargs(sc))
1205             goto Leprop;
1206         tiargs = dti.ti.tiargs;
1207         tthis = dti.e1.type;
1208         if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1209             goto Los;
1210         if ((s = dti.ti.tempdecl) !is null)
1211             goto Lfd;
1212     }
1213     else if (e1.op == TOK.dotTemplateDeclaration)
1214     {
1215         DotTemplateExp dte = cast(DotTemplateExp)e1;
1216         s = dte.td;
1217         tiargs = null;
1218         tthis = dte.e1.type;
1219         goto Lfd;
1220     }
1221     else if (e1.op == TOK.scope_)
1222     {
1223         s = (cast(ScopeExp)e1).sds;
1224         TemplateInstance ti = s.isTemplateInstance();
1225         if (ti && !ti.semanticRun && ti.tempdecl)
1226         {
1227             //assert(ti.needsTypeInference(sc));
1228             if (!ti.semanticTiargs(sc))
1229                 goto Leprop;
1230             tiargs = ti.tiargs;
1231             tthis = null;
1232             if ((os = ti.tempdecl.isOverloadSet()) !is null)
1233                 goto Los;
1234             if ((s = ti.tempdecl) !is null)
1235                 goto Lfd;
1236         }
1237     }
1238     else if (e1.op == TOK.template_)
1239     {
1240         s = (cast(TemplateExp)e1).td;
1241         tiargs = null;
1242         tthis = null;
1243         goto Lfd;
1244     }
1245     else if (e1.op == TOK.dotVariable && e1.type && e1.type.toBasetype().ty == Tfunction)
1246     {
1247         DotVarExp dve = cast(DotVarExp)e1;
1248         s = dve.var.isFuncDeclaration();
1249         tiargs = null;
1250         tthis = dve.e1.type;
1251         goto Lfd;
1252     }
1253     else if (e1.op == TOK.variable && e1.type && e1.type.toBasetype().ty == Tfunction)
1254     {
1255         s = (cast(VarExp)e1).var.isFuncDeclaration();
1256         tiargs = null;
1257         tthis = null;
1258     Lfd:
1259         assert(s);
1260         if (e2)
1261         {
1262             e2 = e2.expressionSemantic(sc);
1263             if (e2.op == TOK.error)
1264                 return new ErrorExp();
1265             e2 = resolveProperties(sc, e2);
1266 
1267             Expressions a;
1268             a.push(e2);
1269 
1270             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1271             if (fd && fd.type)
1272             {
1273                 if (fd.errors)
1274                     return new ErrorExp();
1275                 assert(fd.type.ty == Tfunction);
1276                 Expression e = new CallExp(loc, e1, e2);
1277                 return e.expressionSemantic(sc);
1278             }
1279         }
1280         {
1281             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1282             if (fd && fd.type)
1283             {
1284                 if (fd.errors)
1285                     return new ErrorExp();
1286                 assert(fd.type.ty == Tfunction);
1287                 TypeFunction tf = cast(TypeFunction)fd.type;
1288                 if (!e2 || tf.isref)
1289                 {
1290                     Expression e = new CallExp(loc, e1);
1291                     if (e2)
1292                         e = new AssignExp(loc, e, e2);
1293                     return e.expressionSemantic(sc);
1294                 }
1295             }
1296         }
1297         if (FuncDeclaration fd = s.isFuncDeclaration())
1298         {
1299             // Keep better diagnostic message for invalid property usage of functions
1300             assert(fd.type.ty == Tfunction);
1301             Expression e = new CallExp(loc, e1, e2);
1302             return e.expressionSemantic(sc);
1303         }
1304         if (e2)
1305             goto Leprop;
1306     }
1307     if (e1.op == TOK.variable)
1308     {
1309         VarExp ve = cast(VarExp)e1;
1310         VarDeclaration v = ve.var.isVarDeclaration();
1311         if (v && ve.checkPurity(sc, v))
1312             return new ErrorExp();
1313     }
1314     if (e2)
1315         return null;
1316 
1317     if (e1.type && e1.op != TOK.type) // function type is not a property
1318     {
1319         /* Look for e1 being a lazy parameter; rewrite as delegate call
1320          * only if the symbol wasn't already treated as a delegate
1321          */
1322         auto ve = e1.isVarExp();
1323         if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1324         {
1325                 Expression e = new CallExp(loc, e1);
1326                 return e.expressionSemantic(sc);
1327         }
1328         else if (e1.op == TOK.dotVariable)
1329         {
1330             // Check for reading overlapped pointer field in @safe code.
1331             if (checkUnsafeAccess(sc, e1, true, true))
1332                 return new ErrorExp();
1333         }
1334         else if (e1.op == TOK.dot)
1335         {
1336             e1.error("expression has no value");
1337             return new ErrorExp();
1338         }
1339         else if (e1.op == TOK.call)
1340         {
1341             CallExp ce = cast(CallExp)e1;
1342             // Check for reading overlapped pointer field in @safe code.
1343             if (checkUnsafeAccess(sc, ce.e1, true, true))
1344                 return new ErrorExp();
1345         }
1346     }
1347 
1348     if (!e1.type)
1349     {
1350         error(loc, "cannot resolve type for %s", e1.toChars());
1351         e1 = new ErrorExp();
1352     }
1353     return e1;
1354 
1355 Leprop:
1356     error(loc, "not a property %s", e1.toChars());
1357     return new ErrorExp();
1358 }
1359 
1360 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1361 {
1362     //printf("resolveProperties(%s)\n", e.toChars());
1363     e = resolvePropertiesX(sc, e);
1364     if (e.checkRightThis(sc))
1365         return new ErrorExp();
1366     return e;
1367 }
1368 
1369 /****************************************
1370  * The common type is determined by applying ?: to each pair.
1371  * Output:
1372  *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1373  *      *pt     if pt is not NULL, set to the common type
1374  * Returns:
1375  *      true    a semantic error was detected
1376  */
1377 private bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt)
1378 {
1379     /* Still have a problem with:
1380      *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1381      * which works if the array literal is initialized top down with the ubyte[][]
1382      * type, but fails with this function doing bottom up typing.
1383      */
1384 
1385     //printf("arrayExpressionToCommonType()\n");
1386     scope IntegerExp integerexp = IntegerExp.literal!0;
1387     scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1388 
1389     Type t0 = null;
1390     Expression e0 = null;
1391     size_t j0 = ~0;
1392     bool foundType;
1393 
1394     for (size_t i = 0; i < exps.dim; i++)
1395     {
1396         Expression e = (*exps)[i];
1397         if (!e)
1398             continue;
1399 
1400         e = resolveProperties(sc, e);
1401         if (!e.type)
1402         {
1403             e.error("`%s` has no value", e.toChars());
1404             t0 = Type.terror;
1405             continue;
1406         }
1407         if (e.op == TOK.type)
1408         {
1409             foundType = true; // do not break immediately, there might be more errors
1410             e.checkValue(); // report an error "type T has no value"
1411             t0 = Type.terror;
1412             continue;
1413         }
1414         if (e.type.ty == Tvoid)
1415         {
1416             // void expressions do not concur to the determination of the common
1417             // type.
1418             continue;
1419         }
1420         if (checkNonAssignmentArrayOp(e))
1421         {
1422             t0 = Type.terror;
1423             continue;
1424         }
1425 
1426         e = doCopyOrMove(sc, e);
1427 
1428         if (!foundType && t0 && !t0.equals(e.type))
1429         {
1430             /* This applies ?: to merge the types. It's backwards;
1431              * ?: should call this function to merge types.
1432              */
1433             condexp.type = null;
1434             condexp.e1 = e0;
1435             condexp.e2 = e;
1436             condexp.loc = e.loc;
1437             Expression ex = condexp.expressionSemantic(sc);
1438             if (ex.op == TOK.error)
1439                 e = ex;
1440             else
1441             {
1442                 (*exps)[j0] = condexp.e1;
1443                 e = condexp.e2;
1444             }
1445         }
1446         j0 = i;
1447         e0 = e;
1448         t0 = e.type;
1449         if (e.op != TOK.error)
1450             (*exps)[i] = e;
1451     }
1452 
1453     if (!t0)
1454         t0 = Type.tvoid; // [] is typed as void[]
1455     else if (t0.ty != Terror)
1456     {
1457         for (size_t i = 0; i < exps.dim; i++)
1458         {
1459             Expression e = (*exps)[i];
1460             if (!e)
1461                 continue;
1462 
1463             e = e.implicitCastTo(sc, t0);
1464             //assert(e.op != TOK.error);
1465             if (e.op == TOK.error)
1466             {
1467                 /* https://issues.dlang.org/show_bug.cgi?id=13024
1468                  * a workaround for the bug in typeMerge -
1469                  * it should paint e1 and e2 by deduced common type,
1470                  * but doesn't in this particular case.
1471                  */
1472                 t0 = Type.terror;
1473                 break;
1474             }
1475             (*exps)[i] = e;
1476         }
1477     }
1478     if (pt)
1479         *pt = t0;
1480 
1481     return (t0 == Type.terror);
1482 }
1483 
1484 private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2)
1485 {
1486     Expression e;
1487     switch (op)
1488     {
1489     case TOK.addAssign:
1490         e = new AddExp(loc, e1, e2);
1491         break;
1492 
1493     case TOK.minAssign:
1494         e = new MinExp(loc, e1, e2);
1495         break;
1496 
1497     case TOK.mulAssign:
1498         e = new MulExp(loc, e1, e2);
1499         break;
1500 
1501     case TOK.divAssign:
1502         e = new DivExp(loc, e1, e2);
1503         break;
1504 
1505     case TOK.modAssign:
1506         e = new ModExp(loc, e1, e2);
1507         break;
1508 
1509     case TOK.andAssign:
1510         e = new AndExp(loc, e1, e2);
1511         break;
1512 
1513     case TOK.orAssign:
1514         e = new OrExp(loc, e1, e2);
1515         break;
1516 
1517     case TOK.xorAssign:
1518         e = new XorExp(loc, e1, e2);
1519         break;
1520 
1521     case TOK.leftShiftAssign:
1522         e = new ShlExp(loc, e1, e2);
1523         break;
1524 
1525     case TOK.rightShiftAssign:
1526         e = new ShrExp(loc, e1, e2);
1527         break;
1528 
1529     case TOK.unsignedRightShiftAssign:
1530         e = new UshrExp(loc, e1, e2);
1531         break;
1532 
1533     default:
1534         assert(0);
1535     }
1536     return e;
1537 }
1538 
1539 /*********************
1540  * Rewrite:
1541  *    array.length op= e2
1542  * as:
1543  *    array.length = array.length op e2
1544  * or:
1545  *    auto tmp = &array;
1546  *    (*tmp).length = (*tmp).length op e2
1547  */
1548 private Expression rewriteOpAssign(BinExp exp)
1549 {
1550     Expression e;
1551 
1552     assert(exp.e1.op == TOK.arrayLength);
1553     ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
1554     if (ale.e1.op == TOK.variable)
1555     {
1556         e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1557         e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1558     }
1559     else
1560     {
1561         /*    auto tmp = &array;
1562          *    (*tmp).length = (*tmp).length op e2
1563          */
1564         auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1565 
1566         Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1567         Expression elvalue = e1.syntaxCopy();
1568         e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1569         e = new AssignExp(exp.loc, elvalue, e);
1570         e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1571     }
1572     return e;
1573 }
1574 
1575 /****************************************
1576  * Preprocess arguments to function.
1577  * Input:
1578  *      reportErrors    whether or not to report errors here.  Some callers are not
1579  *                      checking actual function params, so they'll do their own error reporting
1580  * Output:
1581  *      exps[]  tuples expanded, properties resolved, rewritten in place
1582  * Returns:
1583  *      true    a semantic error occurred
1584  */
1585 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1586 {
1587     bool err = false;
1588     if (exps)
1589     {
1590         expandTuples(exps);
1591 
1592         for (size_t i = 0; i < exps.dim; i++)
1593         {
1594             Expression arg = (*exps)[i];
1595             arg = resolveProperties(sc, arg);
1596             if (arg.op == TOK.type)
1597             {
1598                 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1599                 arg = resolveAliasThis(sc, arg);
1600 
1601                 if (arg.op == TOK.type)
1602                 {
1603                     if (reportErrors)
1604                     {
1605                         arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1606                         arg = new ErrorExp();
1607                     }
1608                     err = true;
1609                 }
1610             }
1611             else if (arg.type.toBasetype().ty == Tfunction)
1612             {
1613                 if (reportErrors)
1614                 {
1615                     arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1616                     arg = new ErrorExp();
1617                 }
1618                 err = true;
1619             }
1620             else if (checkNonAssignmentArrayOp(arg))
1621             {
1622                 arg = new ErrorExp();
1623                 err = true;
1624             }
1625             (*exps)[i] = arg;
1626         }
1627     }
1628     return err;
1629 }
1630 
1631 /********************************************
1632  * Issue an error if default construction is disabled for type t.
1633  * Default construction is required for arrays and 'out' parameters.
1634  * Returns:
1635  *      true    an error was issued
1636  */
1637 private bool checkDefCtor(Loc loc, Type t)
1638 {
1639     t = t.baseElemOf();
1640     if (t.ty == Tstruct)
1641     {
1642         StructDeclaration sd = (cast(TypeStruct)t).sym;
1643         if (sd.noDefaultCtor)
1644         {
1645             sd.error(loc, "default construction is disabled");
1646             return true;
1647         }
1648     }
1649     return false;
1650 }
1651 
1652 /****************************************
1653  * Now that we know the exact type of the function we're calling,
1654  * the arguments[] need to be adjusted:
1655  *      1. implicitly convert argument to the corresponding parameter type
1656  *      2. add default arguments for any missing arguments
1657  *      3. do default promotions on arguments corresponding to ...
1658  *      4. add hidden _arguments[] argument
1659  *      5. call copy constructor for struct value arguments
1660  * Params:
1661  *      loc       = location of function call
1662  *      sc        = context
1663  *      tf        = type of the function
1664  *      ethis     = `this` argument, `null` if none or not known
1665  *      tthis     = type of `this` argument, `null` if no `this` argument
1666  *      arguments = array of actual arguments to function call
1667  *      fd        = the function being called, `null` if called indirectly
1668  *      prettype  = set to return type of function
1669  *      peprefix  = set to expression to execute before `arguments[]` are evaluated, `null` if none
1670  * Returns:
1671  *      true    errors happened
1672  */
1673 private bool functionParameters(const ref Loc loc, Scope* sc,
1674     TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1675     Type* prettype, Expression* peprefix)
1676 {
1677     //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1678     assert(arguments);
1679     assert(fd || tf.next);
1680     size_t nargs = arguments ? arguments.dim : 0;
1681     const size_t nparams = tf.parameterList.length;
1682     const olderrors = global.errors;
1683     bool err = false;
1684     *prettype = Type.terror;
1685     Expression eprefix = null;
1686     *peprefix = null;
1687 
1688     if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1689     {
1690         error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1691         return true;
1692     }
1693 
1694     // If inferring return type, and semantic3() needs to be run if not already run
1695     if (!tf.next && fd.inferRetType)
1696     {
1697         fd.functionSemantic();
1698     }
1699     else if (fd && fd.parent)
1700     {
1701         TemplateInstance ti = fd.parent.isTemplateInstance();
1702         if (ti && ti.tempdecl)
1703         {
1704             fd.functionSemantic3();
1705         }
1706     }
1707     const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1708 
1709     const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1710 
1711     /* If the function return type has wildcards in it, we'll need to figure out the actual type
1712      * based on the actual argument types.
1713      * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1714      * of the arguments.
1715      */
1716     MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1717 
1718     bool done = false;
1719     foreach (const i; 0 .. n)
1720     {
1721         Expression arg = (i < nargs) ? (*arguments)[i] : null;
1722 
1723         if (i < nparams)
1724         {
1725             bool errorArgs()
1726             {
1727                 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1728                 return true;
1729             }
1730 
1731             Parameter p = tf.parameterList[i];
1732             const bool isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0;
1733 
1734             if (!arg)
1735             {
1736                 if (!p.defaultArg)
1737                 {
1738                     if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1739                         goto L2;
1740                     return errorArgs();
1741                 }
1742                 arg = p.defaultArg;
1743                 arg = inlineCopy(arg, sc);
1744                 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1745                 arg = arg.resolveLoc(loc, sc);
1746                 arguments.push(arg);
1747                 nargs++;
1748             }
1749             else
1750             {
1751                 if (arg.op == TOK.default_)
1752                 {
1753                     arg = arg.resolveLoc(loc, sc);
1754                     (*arguments)[i] = arg;
1755                 }
1756             }
1757 
1758 
1759             if (isRef && !p.type.isConst && !p.type.isImmutable
1760                 && (p.storageClass & STC.const_) != STC.const_
1761                 && (p.storageClass & STC.immutable_) != STC.immutable_
1762                 && checkIfIsStructLiteralDotExpr(arg))
1763                     break;
1764 
1765             if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1766             {
1767                 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1768                 {
1769                     MATCH m;
1770                     if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1771                     {
1772                         if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1773                             goto L2;
1774                         else if (nargs != nparams)
1775                             return errorArgs();
1776                         goto L1;
1777                     }
1778                 }
1779             L2:
1780                 Type tb = p.type.toBasetype();
1781                 switch (tb.ty)
1782                 {
1783                 case Tsarray:
1784                 case Tarray:
1785                     {
1786                         /* Create a static array variable v of type arg.type:
1787                          *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1788                          *
1789                          * The array literal in the initializer of the hidden variable
1790                          * is now optimized.
1791                          * https://issues.dlang.org/show_bug.cgi?id=2356
1792                          */
1793                         Type tbn = (cast(TypeArray)tb).next;    // array element type
1794                         Type tret = p.isLazyArray();
1795 
1796                         auto elements = new Expressions(nargs - i);
1797                         foreach (u; 0 .. elements.dim)
1798                         {
1799                             Expression a = (*arguments)[i + u];
1800                             if (tret && a.implicitConvTo(tret))
1801                             {
1802                                 // p is a lazy array of delegates, tret is return type of the delegates
1803                                 a = a.implicitCastTo(sc, tret)
1804                                      .optimize(WANTvalue)
1805                                      .toDelegate(tret, sc);
1806                             }
1807                             else
1808                                 a = a.implicitCastTo(sc, tbn);
1809                             a = a.addDtorHook(sc);
1810                             (*elements)[u] = a;
1811                         }
1812                         // https://issues.dlang.org/show_bug.cgi?id=14395
1813                         // Convert to a static array literal, or its slice.
1814                         arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1815                         if (tb.ty == Tarray)
1816                         {
1817                             arg = new SliceExp(loc, arg, null, null);
1818                             arg.type = p.type;
1819                         }
1820                         break;
1821                     }
1822                 case Tclass:
1823                     {
1824                         /* Set arg to be:
1825                          *      new Tclass(arg0, arg1, ..., argn)
1826                          */
1827                         auto args = new Expressions(nargs - i);
1828                         foreach (u; i .. nargs)
1829                             (*args)[u - i] = (*arguments)[u];
1830                         arg = new NewExp(loc, null, null, p.type, args);
1831                         break;
1832                     }
1833                 default:
1834                     if (!arg)
1835                     {
1836                         error(loc, "not enough arguments");
1837                         return true;
1838                     }
1839                     break;
1840                 }
1841                 arg = arg.expressionSemantic(sc);
1842                 //printf("\targ = '%s'\n", arg.toChars());
1843                 arguments.setDim(i + 1);
1844                 (*arguments)[i] = arg;
1845                 nargs = i + 1;
1846                 done = true;
1847             }
1848 
1849         L1:
1850             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1851             {
1852 
1853                 if (ubyte wm = arg.type.deduceWild(p.type, isRef))
1854                 {
1855                     wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1856                     //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1857                 }
1858             }
1859         }
1860         if (done)
1861             break;
1862     }
1863     if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1864         tf.next && tf.next.hasWild() &&
1865         (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1866     {
1867         bool errorInout(MOD wildmatch)
1868         {
1869             const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1870             error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1871             return true;
1872         }
1873 
1874         if (fd)
1875         {
1876             /* If the called function may return the reference to
1877              * outer inout data, it should be rejected.
1878              *
1879              * void foo(ref inout(int) x) {
1880              *   ref inout(int) bar(inout(int)) { return x; }
1881              *   struct S {
1882              *      ref inout(int) bar() inout { return x; }
1883              *      ref inout(int) baz(alias a)() inout { return x; }
1884              *   }
1885              *   bar(int.init) = 1;  // bad!
1886              *   S().bar() = 1;      // bad!
1887              * }
1888              * void test() {
1889              *   int a;
1890              *   auto s = foo(a);
1891              *   s.baz!a() = 1;      // bad!
1892              * }
1893              *
1894              */
1895             bool checkEnclosingWild(Dsymbol s)
1896             {
1897                 bool checkWild(Dsymbol s)
1898                 {
1899                     if (!s)
1900                         return false;
1901                     if (auto ad = s.isAggregateDeclaration())
1902                     {
1903                         if (ad.isNested())
1904                             return checkEnclosingWild(s);
1905                     }
1906                     else if (auto ff = s.isFuncDeclaration())
1907                     {
1908                         if ((cast(TypeFunction)ff.type).iswild)
1909                             return errorInout(wildmatch);
1910 
1911                         if (ff.isNested() || ff.isThis())
1912                             return checkEnclosingWild(s);
1913                     }
1914                     return false;
1915                 }
1916 
1917                 Dsymbol ctx0 = s.toParent2();
1918                 Dsymbol ctx1 = s.toParentLocal();
1919                 if (checkWild(ctx0))
1920                     return true;
1921                 if (ctx0 != ctx1)
1922                     return checkWild(ctx1);
1923                 return false;
1924             }
1925             if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1926                 return true;
1927         }
1928         else if (tf.isWild())
1929             return errorInout(wildmatch);
1930     }
1931 
1932     Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1933                            tthis &&
1934                            tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1935                            tthis.hasPointers())
1936                           ? ethis : null;
1937 
1938     assert(nargs >= nparams);
1939     foreach (const i, arg; (*arguments)[0 .. nargs])
1940     {
1941         assert(arg);
1942         if (i < nparams)
1943         {
1944             Parameter p = tf.parameterList[i];
1945             Type targ = arg.type;               // keep original type for isCopyable() because alias this
1946                                                 // resolution may hide an uncopyable type
1947 
1948             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1949             {
1950                 Type tprm = p.type.hasWild()
1951                     ? p.type.substWildTo(wildmatch)
1952                     : p.type;
1953 
1954                 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
1955                 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1956                 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1957                 {
1958                     //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1959                     arg = arg.implicitCastTo(sc, tprm);
1960                     arg = arg.optimize(WANTvalue, (p.storageClass & (STC.ref_ | STC.out_)) != 0);
1961                 }
1962             }
1963             if (p.storageClass & STC.ref_)
1964             {
1965                 if (global.params.rvalueRefParam &&
1966                     !arg.isLvalue() &&
1967                     targ.isCopyable())
1968                 {   /* allow rvalues to be passed to ref parameters by copying
1969                      * them to a temp, then pass the temp as the argument
1970                      */
1971                     auto v = copyToTemp(0, "__rvalue", arg);
1972                     Expression ev = new DeclarationExp(arg.loc, v);
1973                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1974                     arg = ev.expressionSemantic(sc);
1975                 }
1976                 arg = arg.toLvalue(sc, arg);
1977 
1978                 // Look for mutable misaligned pointer, etc., in @safe mode
1979                 err |= checkUnsafeAccess(sc, arg, false, true);
1980             }
1981             else if (p.storageClass & STC.out_)
1982             {
1983                 Type t = arg.type;
1984                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
1985                 {
1986                     arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
1987                     err = true;
1988                 }
1989                 else
1990                 {
1991                     // Look for misaligned pointer, etc., in @safe mode
1992                     err |= checkUnsafeAccess(sc, arg, false, true);
1993                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
1994                 }
1995                 arg = arg.toLvalue(sc, arg);
1996             }
1997             else if (p.storageClass & STC.lazy_)
1998             {
1999                 // Convert lazy argument to a delegate
2000                 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2001                 arg = toDelegate(arg, t, sc);
2002             }
2003             //printf("arg: %s\n", arg.toChars());
2004             //printf("type: %s\n", arg.type.toChars());
2005             //printf("param: %s\n", p.toChars());
2006 
2007             if (firstArg && p.storageClass & STC.return_)
2008             {
2009                 /* Argument value can be assigned to firstArg.
2010                  * Check arg to see if it matters.
2011                  */
2012                 if (global.params.vsafe)
2013                     err |= checkParamArgumentReturn(sc, firstArg, arg, false);
2014             }
2015             else if (tf.parameterEscapes(tthis, p))
2016             {
2017                 /* Argument value can escape from the called function.
2018                  * Check arg to see if it matters.
2019                  */
2020                 if (global.params.vsafe)
2021                     err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2022             }
2023             else
2024             {
2025                 /* Argument value cannot escape from the called function.
2026                  */
2027                 Expression a = arg;
2028                 if (a.op == TOK.cast_)
2029                     a = (cast(CastExp)a).e1;
2030 
2031                 ArrayLiteralExp ale;
2032                 if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) &&
2033                     (ale = a.isArrayLiteralExp()) !is null)
2034                 {
2035                     // allocate the array literal as temporary static array on the stack
2036                     ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
2037                     auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2038                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
2039                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
2040                     arg = CommaExp.combine(declareTmp, castToSlice);
2041                     arg = arg.expressionSemantic(sc);
2042                 }
2043                 else if (a.op == TOK.function_)
2044                 {
2045                     /* Function literals can only appear once, so if this
2046                      * appearance was scoped, there cannot be any others.
2047                      */
2048                     FuncExp fe = cast(FuncExp)a;
2049                     fe.fd.tookAddressOf = 0;
2050                 }
2051                 else if (a.op == TOK.delegate_)
2052                 {
2053                     /* For passing a delegate to a scoped parameter,
2054                      * this doesn't count as taking the address of it.
2055                      * We only worry about 'escaping' references to the function.
2056                      */
2057                     DelegateExp de = cast(DelegateExp)a;
2058                     if (de.e1.op == TOK.variable)
2059                     {
2060                         VarExp ve = cast(VarExp)de.e1;
2061                         FuncDeclaration f = ve.var.isFuncDeclaration();
2062                         if (f)
2063                         {
2064                             if (f.tookAddressOf)
2065                                 --f.tookAddressOf;
2066                             //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2067                         }
2068                     }
2069                 }
2070             }
2071             if (!(p.storageClass & (STC.ref_ | STC.out_)))
2072                 err |= arg.checkSharedAccess(sc);
2073 
2074             arg = arg.optimize(WANTvalue, (p.storageClass & (STC.ref_ | STC.out_)) != 0);
2075 
2076             /* Determine if this parameter is the "first reference" parameter through which
2077              * later "return" arguments can be stored.
2078              */
2079             if (i == 0 && !tthis && p.storageClass & (STC.ref_ | STC.out_) && p.type &&
2080                 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2081             {
2082                 Type tb = p.type.baseElemOf();
2083                 if (tb.isMutable() && tb.hasPointers())
2084                 {
2085                     firstArg = arg;
2086                 }
2087             }
2088         }
2089         else
2090         {
2091             // These will be the trailing ... arguments
2092             // If not D linkage, do promotions
2093             if (tf.linkage != LINK.d)
2094             {
2095                 // Promote bytes, words, etc., to ints
2096                 arg = integralPromotions(arg, sc);
2097 
2098                 // Promote floats to doubles
2099                 switch (arg.type.ty)
2100                 {
2101                 case Tfloat32:
2102                     arg = arg.castTo(sc, Type.tfloat64);
2103                     break;
2104 
2105                 case Timaginary32:
2106                     arg = arg.castTo(sc, Type.timaginary64);
2107                     break;
2108 
2109                 default:
2110                     break;
2111                 }
2112                 if (tf.parameterList.varargs == VarArg.variadic)
2113                 {
2114                     const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2115                     if (arg.type.ty == Tarray)
2116                     {
2117                         arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2118                         err = true;
2119                     }
2120                     if (arg.type.ty == Tsarray)
2121                     {
2122                         arg.error("cannot pass static arrays to `%s` vararg functions", p);
2123                         err = true;
2124                     }
2125                 }
2126             }
2127 
2128             // Do not allow types that need destructors or copy constructors.
2129             if (arg.type.needsDestruction())
2130             {
2131                 arg.error("cannot pass types that need destruction as variadic arguments");
2132                 err = true;
2133             }
2134             if (arg.type.needsCopyOrPostblit())
2135             {
2136                 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2137                 err = true;
2138             }
2139 
2140             // Convert static arrays to dynamic arrays
2141             // BUG: I don't think this is right for D2
2142             Type tb = arg.type.toBasetype();
2143             if (tb.ty == Tsarray)
2144             {
2145                 TypeSArray ts = cast(TypeSArray)tb;
2146                 Type ta = ts.next.arrayOf();
2147                 if (ts.size(arg.loc) == 0)
2148                     arg = new NullExp(arg.loc, ta);
2149                 else
2150                     arg = arg.castTo(sc, ta);
2151             }
2152             if (tb.ty == Tstruct)
2153             {
2154                 //arg = callCpCtor(sc, arg);
2155             }
2156             // Give error for overloaded function addresses
2157             if (arg.op == TOK.symbolOffset)
2158             {
2159                 SymOffExp se = cast(SymOffExp)arg;
2160                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2161                 {
2162                     arg.error("function `%s` is overloaded", arg.toChars());
2163                     err = true;
2164                 }
2165             }
2166             err |= arg.checkValue();
2167             err |= arg.checkSharedAccess(sc);
2168             arg = arg.optimize(WANTvalue);
2169         }
2170         (*arguments)[i] = arg;
2171     }
2172 
2173     /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2174      */
2175     const isVa_list = tf.parameterList.varargs == VarArg.none;
2176     if (fd && fd.flags & FUNCFLAG.printf)
2177     {
2178         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2179         {
2180             checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2181         }
2182     }
2183     else if (fd && fd.flags & FUNCFLAG.scanf)
2184     {
2185         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2186         {
2187             checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2188         }
2189     }
2190     else
2191     {
2192         // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2193     }
2194 
2195     /* Remaining problems:
2196      * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2197      *    implemented by calling a function) we'll defer this for now.
2198      * 2. value structs (or static arrays of them) that need to be copy constructed
2199      * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2200      *    function gets called (functions normally destroy their parameters)
2201      * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2202      * up properly. Pushing arguments on the stack then cannot fail.
2203      */
2204     {
2205         /* TODO: tackle problem 1)
2206          */
2207         const bool leftToRight = true; // TODO: something like !fd.isArrayOp
2208         if (!leftToRight)
2209             assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2210 
2211         const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2212         const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2213         const ptrdiff_t step = (leftToRight ? 1 : -1);
2214 
2215         /* Compute indices of last throwing argument and first arg needing destruction.
2216          * Used to not set up destructors unless an arg needs destruction on a throw
2217          * in a later argument.
2218          */
2219         ptrdiff_t lastthrow = -1;
2220         ptrdiff_t firstdtor = -1;
2221         for (ptrdiff_t i = start; i != end; i += step)
2222         {
2223             Expression arg = (*arguments)[i];
2224             if (canThrow(arg, sc.func, false))
2225                 lastthrow = i;
2226             if (firstdtor == -1 && arg.type.needsDestruction())
2227             {
2228                 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2229                 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
2230                     firstdtor = i;
2231             }
2232         }
2233 
2234         /* Does problem 3) apply to this call?
2235          */
2236         const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
2237             && (lastthrow - firstdtor) * step > 0);
2238 
2239         /* If so, initialize 'eprefix' by declaring the gate
2240          */
2241         VarDeclaration gate = null;
2242         if (needsPrefix)
2243         {
2244             // eprefix => bool __gate [= false]
2245             Identifier idtmp = Identifier.generateId("__gate");
2246             gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2247             gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2248             gate.dsymbolSemantic(sc);
2249 
2250             auto ae = new DeclarationExp(loc, gate);
2251             eprefix = ae.expressionSemantic(sc);
2252         }
2253 
2254         for (ptrdiff_t i = start; i != end; i += step)
2255         {
2256             Expression arg = (*arguments)[i];
2257 
2258             Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2259             const bool isRef = (parameter && (parameter.storageClass & (STC.ref_ | STC.out_)));
2260             const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2261 
2262             /* Skip lazy parameters
2263              */
2264             if (isLazy)
2265                 continue;
2266 
2267             /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
2268              * Declare a temporary variable for this arg and append that declaration to 'eprefix',
2269              * which will implicitly take care of potential problem 2) for this arg.
2270              * 'eprefix' will therefore finally contain all args up to and including the last
2271              * potentially throwing arg, excluding all lazy parameters.
2272              */
2273             if (gate)
2274             {
2275                 const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow);
2276 
2277                 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2278                  */
2279                 auto tmp = copyToTemp(0,
2280                     needsDtor ? "__pfx" : "__pfy",
2281                     !isRef ? arg : arg.addressOf());
2282                 tmp.dsymbolSemantic(sc);
2283 
2284                 /* Modify the destructor so it only runs if gate==false, i.e.,
2285                  * only if there was a throw while constructing the args
2286                  */
2287                 if (!needsDtor)
2288                 {
2289                     if (tmp.edtor)
2290                     {
2291                         assert(i == lastthrow);
2292                         tmp.edtor = null;
2293                     }
2294                 }
2295                 else
2296                 {
2297                     // edtor => (__gate || edtor)
2298                     assert(tmp.edtor);
2299                     Expression e = tmp.edtor;
2300                     e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e);
2301                     tmp.edtor = e.expressionSemantic(sc);
2302                     //printf("edtor: %s\n", tmp.edtor.toChars());
2303                 }
2304 
2305                 // eprefix => (eprefix, auto __pfx/y = arg)
2306                 auto ae = new DeclarationExp(loc, tmp);
2307                 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2308 
2309                 // arg => __pfx/y
2310                 arg = new VarExp(loc, tmp);
2311                 arg = arg.expressionSemantic(sc);
2312                 if (isRef)
2313                 {
2314                     arg = new PtrExp(loc, arg);
2315                     arg = arg.expressionSemantic(sc);
2316                 }
2317 
2318                 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
2319                  * i.e., disable the dtors right after constructing the last throwing arg.
2320                  * From now on, the callee will take care of destructing the args because
2321                  * the args are implicitly moved into function parameters.
2322                  *
2323                  * Set gate to null to let the next iterations know they don't need to
2324                  * append to eprefix anymore.
2325                  */
2326                 if (i == lastthrow)
2327                 {
2328                     auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2329                     eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2330                     gate = null;
2331                 }
2332             }
2333             else
2334             {
2335                 /* No gate, no prefix to append to.
2336                  * Handle problem 2) by calling the copy constructor for value structs
2337                  * (or static arrays of them) if appropriate.
2338                  */
2339                 Type tv = arg.type.baseElemOf();
2340                 if (!isRef && tv.ty == Tstruct)
2341                     arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2342             }
2343 
2344             (*arguments)[i] = arg;
2345         }
2346     }
2347     //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2348 
2349     /* Test compliance with DIP1021
2350      */
2351     if (global.params.useDIP1021 &&
2352         tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2353         err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2354 
2355     // If D linkage and variadic, add _arguments[] as first argument
2356     if (tf.isDstyleVariadic())
2357     {
2358         assert(arguments.dim >= nparams);
2359 
2360         auto args = new Parameters(arguments.dim - nparams);
2361         for (size_t i = 0; i < arguments.dim - nparams; i++)
2362         {
2363             auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2364             (*args)[i] = arg;
2365         }
2366         auto tup = new TypeTuple(args);
2367         Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2368         arguments.insert(0, e);
2369     }
2370 
2371     /* Determine function return type: tret
2372      */
2373     Type tret = tf.next;
2374     if (isCtorCall)
2375     {
2376         //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2377         //    wildmatch, tf.isWild(), fd.isReturnIsolated());
2378         if (!tthis)
2379         {
2380             assert(sc.intypeof || global.errors);
2381             tthis = fd.isThis().type.addMod(fd.type.mod);
2382         }
2383         if (tf.isWild() && !fd.isReturnIsolated())
2384         {
2385             if (wildmatch)
2386                 tret = tret.substWildTo(wildmatch);
2387             int offset;
2388             if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2389             {
2390                 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2391                 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2392                 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2393                 err = true;
2394             }
2395         }
2396         tret = tthis;
2397     }
2398     else if (wildmatch && tret)
2399     {
2400         /* Adjust function return type based on wildmatch
2401          */
2402         //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2403         tret = tret.substWildTo(wildmatch);
2404     }
2405 
2406     *prettype = tret;
2407     *peprefix = eprefix;
2408     return (err || olderrors != global.errors);
2409 }
2410 
2411 /**
2412  * Determines whether a symbol represents a module or package
2413  * (Used as a helper for is(type == module) and is(type == package))
2414  *
2415  * Params:
2416  *  sym = the symbol to be checked
2417  *
2418  * Returns:
2419  *  the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2420  */
2421 Package resolveIsPackage(Dsymbol sym)
2422 {
2423     Package pkg;
2424     if (Import imp = sym.isImport())
2425     {
2426         if (imp.pkg is null)
2427         {
2428             .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2429                     imp.toChars());
2430             assert(0);
2431         }
2432         pkg = imp.pkg;
2433     }
2434     else if (auto mod = sym.isModule())
2435         pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2436     else
2437         pkg = sym.isPackage();
2438     if (pkg)
2439         pkg.resolvePKGunknown();
2440     return pkg;
2441 }
2442 
2443 private Module loadStdMath()
2444 {
2445     __gshared Import impStdMath = null;
2446     if (!impStdMath)
2447     {
2448         auto a = new Identifiers();
2449         a.push(Id.std);
2450         auto s = new Import(Loc.initial, a, Id.math, null, false);
2451         // Module.load will call fatal() if there's no std.math available.
2452         // Gag the error here, pushing the error handling to the caller.
2453         uint errors = global.startGagging();
2454         s.load(null);
2455         if (s.mod)
2456         {
2457             s.mod.importAll(null);
2458             s.mod.dsymbolSemantic(null);
2459         }
2460         global.endGagging(errors);
2461         impStdMath = s;
2462     }
2463     return impStdMath.mod;
2464 }
2465 
2466 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2467 {
2468     alias visit = Visitor.visit;
2469 
2470     Scope* sc;
2471     Expression result;
2472 
2473     this(Scope* sc)
2474     {
2475         this.sc = sc;
2476     }
2477 
2478     private void setError()
2479     {
2480         result = new ErrorExp();
2481     }
2482 
2483     /**************************
2484      * Semantically analyze Expression.
2485      * Determine types, fold constants, etc.
2486      */
2487     override void visit(Expression e)
2488     {
2489         static if (LOGSEMANTIC)
2490         {
2491             printf("Expression::semantic() %s\n", e.toChars());
2492         }
2493         if (e.type)
2494             e.type = e.type.typeSemantic(e.loc, sc);
2495         else
2496             e.type = Type.tvoid;
2497         result = e;
2498     }
2499 
2500     override void visit(IntegerExp e)
2501     {
2502         assert(e.type);
2503         if (e.type.ty == Terror)
2504             return setError();
2505 
2506         assert(e.type.deco);
2507         e.setInteger(e.getInteger());
2508         result = e;
2509     }
2510 
2511     override void visit(RealExp e)
2512     {
2513         if (!e.type)
2514             e.type = Type.tfloat64;
2515         else
2516             e.type = e.type.typeSemantic(e.loc, sc);
2517         result = e;
2518     }
2519 
2520     override void visit(ComplexExp e)
2521     {
2522         if (!e.type)
2523             e.type = Type.tcomplex80;
2524         else
2525             e.type = e.type.typeSemantic(e.loc, sc);
2526         result = e;
2527     }
2528 
2529     override void visit(IdentifierExp exp)
2530     {
2531         static if (LOGSEMANTIC)
2532         {
2533             printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2534         }
2535         if (exp.type) // This is used as the dummy expression
2536         {
2537             result = exp;
2538             return;
2539         }
2540 
2541         Dsymbol scopesym;
2542         Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2543         if (s)
2544         {
2545             if (s.errors)
2546                 return setError();
2547 
2548             Expression e;
2549 
2550             /* See if the symbol was a member of an enclosing 'with'
2551              */
2552             WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2553             if (withsym && withsym.withstate.wthis)
2554             {
2555                 /* Disallow shadowing
2556                  */
2557                 // First find the scope of the with
2558                 Scope* scwith = sc;
2559                 while (scwith.scopesym != scopesym)
2560                 {
2561                     scwith = scwith.enclosing;
2562                     assert(scwith);
2563                 }
2564                 // Look at enclosing scopes for symbols with the same name,
2565                 // in the same function
2566                 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2567                 {
2568                     Dsymbol s2;
2569                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2570                     {
2571                         exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2572                         return setError();
2573                     }
2574                 }
2575                 s = s.toAlias();
2576 
2577                 // Same as wthis.ident
2578                 //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2579                 //  The redudancy should be removed.
2580                 e = new VarExp(exp.loc, withsym.withstate.wthis);
2581                 e = new DotIdExp(exp.loc, e, exp.ident);
2582                 e = e.expressionSemantic(sc);
2583             }
2584             else
2585             {
2586                 if (withsym)
2587                 {
2588                     if (auto t = withsym.withstate.exp.isTypeExp())
2589                     {
2590                         e = new TypeExp(exp.loc, t.type);
2591                         e = new DotIdExp(exp.loc, e, exp.ident);
2592                         result = e.expressionSemantic(sc);
2593                         return;
2594                     }
2595                 }
2596 
2597                 /* If f is really a function template,
2598                  * then replace f with the function template declaration.
2599                  */
2600                 FuncDeclaration f = s.isFuncDeclaration();
2601                 if (f)
2602                 {
2603                     TemplateDeclaration td = getFuncTemplateDecl(f);
2604                     if (td)
2605                     {
2606                         if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2607                             td = td.overroot; // then get the start
2608                         e = new TemplateExp(exp.loc, td, f);
2609                         e = e.expressionSemantic(sc);
2610                         result = e;
2611                         return;
2612                     }
2613                 }
2614 
2615                 if (global.params.fixAliasThis)
2616                 {
2617                     ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2618                     if (expDsym)
2619                     {
2620                         //printf("expDsym = %s\n", expDsym.exp.toChars());
2621                         result = expDsym.exp.expressionSemantic(sc);
2622                         return;
2623                     }
2624                 }
2625                 // Haven't done overload resolution yet, so pass 1
2626                 e = symbolToExp(s, exp.loc, sc, true);
2627             }
2628             result = e;
2629             return;
2630         }
2631 
2632         if (!global.params.fixAliasThis && hasThis(sc))
2633         {
2634             for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2635             {
2636                 if (ad.aliasthis)
2637                 {
2638                     Expression e;
2639                     e = new ThisExp(exp.loc);
2640                     e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2641                     e = new DotIdExp(exp.loc, e, exp.ident);
2642                     e = e.trySemantic(sc);
2643                     if (e)
2644                     {
2645                         result = e;
2646                         return;
2647                     }
2648                 }
2649 
2650                 auto cd = ad.isClassDeclaration();
2651                 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2652                 {
2653                     ad = cd.baseClass;
2654                     continue;
2655                 }
2656                 break;
2657             }
2658         }
2659 
2660         if (exp.ident == Id.ctfe)
2661         {
2662             if (sc.flags & SCOPE.ctfe)
2663             {
2664                 exp.error("variable `__ctfe` cannot be read at compile time");
2665                 return setError();
2666             }
2667 
2668             // Create the magic __ctfe bool variable
2669             auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2670             vd.storage_class |= STC.temp;
2671             vd.semanticRun = PASS.semanticdone;
2672             Expression e = new VarExp(exp.loc, vd);
2673             e = e.expressionSemantic(sc);
2674             result = e;
2675             return;
2676         }
2677 
2678         // If we've reached this point and are inside a with() scope then we may
2679         // try one last attempt by checking whether the 'wthis' object supports
2680         // dynamic dispatching via opDispatch.
2681         // This is done by rewriting this expression as wthis.ident.
2682         // The innermost with() scope of the hierarchy to satisfy the condition
2683         // above wins.
2684         // https://issues.dlang.org/show_bug.cgi?id=6400
2685         for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2686         {
2687             if (!sc2.scopesym)
2688                 continue;
2689 
2690             if (auto ss = sc2.scopesym.isWithScopeSymbol())
2691             {
2692                 if (ss.withstate.wthis)
2693                 {
2694                     Expression e;
2695                     e = new VarExp(exp.loc, ss.withstate.wthis);
2696                     e = new DotIdExp(exp.loc, e, exp.ident);
2697                     e = e.trySemantic(sc);
2698                     if (e)
2699                     {
2700                         result = e;
2701                         return;
2702                     }
2703                 }
2704                 // Try Type.opDispatch (so the static version)
2705                 else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type)
2706                 {
2707                     if (Type t = ss.withstate.exp.isTypeExp().type)
2708                     {
2709                         Expression e;
2710                         e = new TypeExp(exp.loc, t);
2711                         e = new DotIdExp(exp.loc, e, exp.ident);
2712                         e = e.trySemantic(sc);
2713                         if (e)
2714                         {
2715                             result = e;
2716                             return;
2717                         }
2718                     }
2719                 }
2720             }
2721         }
2722 
2723         /* Look for what user might have meant
2724          */
2725         if (const n = importHint(exp.ident.toString()))
2726             exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2727         else if (auto s2 = sc.search_correct(exp.ident))
2728             exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2729         else if (const p = Scope.search_correct_C(exp.ident))
2730             exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2731         else
2732             exp.error("undefined identifier `%s`", exp.ident.toChars());
2733 
2734         result = new ErrorExp();
2735     }
2736 
2737     override void visit(DsymbolExp e)
2738     {
2739         result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2740     }
2741 
2742     override void visit(ThisExp e)
2743     {
2744         static if (LOGSEMANTIC)
2745         {
2746             printf("ThisExp::semantic()\n");
2747         }
2748         if (e.type)
2749         {
2750             result = e;
2751             return;
2752         }
2753 
2754         FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2755         AggregateDeclaration ad;
2756 
2757         /* Special case for typeof(this) and typeof(super) since both
2758          * should work even if they are not inside a non-static member function
2759          */
2760         if (!fd && sc.intypeof == 1)
2761         {
2762             // Find enclosing struct or class
2763             for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2764             {
2765                 if (!s)
2766                 {
2767                     e.error("`%s` is not in a class or struct scope", e.toChars());
2768                     goto Lerr;
2769                 }
2770                 ClassDeclaration cd = s.isClassDeclaration();
2771                 if (cd)
2772                 {
2773                     e.type = cd.type;
2774                     result = e;
2775                     return;
2776                 }
2777                 StructDeclaration sd = s.isStructDeclaration();
2778                 if (sd)
2779                 {
2780                     e.type = sd.type;
2781                     result = e;
2782                     return;
2783                 }
2784             }
2785         }
2786         if (!fd)
2787             goto Lerr;
2788 
2789         assert(fd.vthis);
2790         e.var = fd.vthis;
2791         assert(e.var.parent);
2792         ad = fd.isMemberLocal();
2793         if (!ad)
2794             ad = fd.isMember2();
2795         assert(ad);
2796         e.type = ad.type.addMod(e.var.type.mod);
2797 
2798         if (e.var.checkNestedReference(sc, e.loc))
2799             return setError();
2800 
2801         result = e;
2802         return;
2803 
2804     Lerr:
2805         e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2806         result = new ErrorExp();
2807     }
2808 
2809     override void visit(SuperExp e)
2810     {
2811         static if (LOGSEMANTIC)
2812         {
2813             printf("SuperExp::semantic('%s')\n", e.toChars());
2814         }
2815         if (e.type)
2816         {
2817             result = e;
2818             return;
2819         }
2820 
2821         FuncDeclaration fd = hasThis(sc);
2822         ClassDeclaration cd;
2823         Dsymbol s;
2824 
2825         /* Special case for typeof(this) and typeof(super) since both
2826          * should work even if they are not inside a non-static member function
2827          */
2828         if (!fd && sc.intypeof == 1)
2829         {
2830             // Find enclosing class
2831             for (s = sc.getStructClassScope(); 1; s = s.parent)
2832             {
2833                 if (!s)
2834                 {
2835                     e.error("`%s` is not in a class scope", e.toChars());
2836                     goto Lerr;
2837                 }
2838                 cd = s.isClassDeclaration();
2839                 if (cd)
2840                 {
2841                     cd = cd.baseClass;
2842                     if (!cd)
2843                     {
2844                         e.error("class `%s` has no `super`", s.toChars());
2845                         goto Lerr;
2846                     }
2847                     e.type = cd.type;
2848                     result = e;
2849                     return;
2850                 }
2851             }
2852         }
2853         if (!fd)
2854             goto Lerr;
2855 
2856         e.var = fd.vthis;
2857         assert(e.var && e.var.parent);
2858 
2859         s = fd.toParentDecl();
2860         if (s.isTemplateDeclaration()) // allow inside template constraint
2861             s = s.toParent();
2862         assert(s);
2863         cd = s.isClassDeclaration();
2864         //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2865         if (!cd)
2866             goto Lerr;
2867         if (!cd.baseClass)
2868         {
2869             e.error("no base class for `%s`", cd.toChars());
2870             e.type = cd.type.addMod(e.var.type.mod);
2871         }
2872         else
2873         {
2874             e.type = cd.baseClass.type;
2875             e.type = e.type.castMod(e.var.type.mod);
2876         }
2877 
2878         if (e.var.checkNestedReference(sc, e.loc))
2879             return setError();
2880 
2881         result = e;
2882         return;
2883 
2884     Lerr:
2885         e.error("`super` is only allowed in non-static class member functions");
2886         result = new ErrorExp();
2887     }
2888 
2889     override void visit(NullExp e)
2890     {
2891         static if (LOGSEMANTIC)
2892         {
2893             printf("NullExp::semantic('%s')\n", e.toChars());
2894         }
2895         // NULL is the same as (void *)0
2896         if (e.type)
2897         {
2898             result = e;
2899             return;
2900         }
2901         e.type = Type.tnull;
2902         result = e;
2903     }
2904 
2905     override void visit(StringExp e)
2906     {
2907         static if (LOGSEMANTIC)
2908         {
2909             printf("StringExp::semantic() %s\n", e.toChars());
2910         }
2911         if (e.type)
2912         {
2913             result = e;
2914             return;
2915         }
2916 
2917         OutBuffer buffer;
2918         size_t newlen = 0;
2919         size_t u;
2920         dchar c;
2921 
2922         switch (e.postfix)
2923         {
2924         case 'd':
2925             for (u = 0; u < e.len;)
2926             {
2927                 if (const p = utf_decodeChar(e.peekString(), u, c))
2928                 {
2929                     e.error("%.*s", cast(int)p.length, p.ptr);
2930                     return setError();
2931                 }
2932                 else
2933                 {
2934                     buffer.write4(c);
2935                     newlen++;
2936                 }
2937             }
2938             buffer.write4(0);
2939             e.setData(buffer.extractData(), newlen, 4);
2940             e.type = new TypeDArray(Type.tdchar.immutableOf());
2941             e.committed = 1;
2942             break;
2943 
2944         case 'w':
2945             for (u = 0; u < e.len;)
2946             {
2947                 if (const p = utf_decodeChar(e.peekString(), u, c))
2948                 {
2949                     e.error("%.*s", cast(int)p.length, p.ptr);
2950                     return setError();
2951                 }
2952                 else
2953                 {
2954                     buffer.writeUTF16(c);
2955                     newlen++;
2956                     if (c >= 0x10000)
2957                         newlen++;
2958                 }
2959             }
2960             buffer.writeUTF16(0);
2961             e.setData(buffer.extractData(), newlen, 2);
2962             e.type = new TypeDArray(Type.twchar.immutableOf());
2963             e.committed = 1;
2964             break;
2965 
2966         case 'c':
2967             e.committed = 1;
2968             goto default;
2969 
2970         default:
2971             e.type = new TypeDArray(Type.tchar.immutableOf());
2972             break;
2973         }
2974         e.type = e.type.typeSemantic(e.loc, sc);
2975         //type = type.immutableOf();
2976         //printf("type = %s\n", type.toChars());
2977 
2978         result = e;
2979     }
2980 
2981     override void visit(TupleExp exp)
2982     {
2983         static if (LOGSEMANTIC)
2984         {
2985             printf("+TupleExp::semantic(%s)\n", exp.toChars());
2986         }
2987         if (exp.type)
2988         {
2989             result = exp;
2990             return;
2991         }
2992 
2993         if (exp.e0)
2994             exp.e0 = exp.e0.expressionSemantic(sc);
2995 
2996         // Run semantic() on each argument
2997         bool err = false;
2998         for (size_t i = 0; i < exp.exps.dim; i++)
2999         {
3000             Expression e = (*exp.exps)[i];
3001             e = e.expressionSemantic(sc);
3002             if (!e.type)
3003             {
3004                 exp.error("`%s` has no value", e.toChars());
3005                 err = true;
3006             }
3007             else if (e.op == TOK.error)
3008                 err = true;
3009             else
3010                 (*exp.exps)[i] = e;
3011         }
3012         if (err)
3013             return setError();
3014 
3015         expandTuples(exp.exps);
3016 
3017         exp.type = new TypeTuple(exp.exps);
3018         exp.type = exp.type.typeSemantic(exp.loc, sc);
3019         //printf("-TupleExp::semantic(%s)\n", toChars());
3020         result = exp;
3021     }
3022 
3023     override void visit(ArrayLiteralExp e)
3024     {
3025         static if (LOGSEMANTIC)
3026         {
3027             printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3028         }
3029         if (e.type)
3030         {
3031             result = e;
3032             return;
3033         }
3034 
3035         /* Perhaps an empty array literal [ ] should be rewritten as null?
3036          */
3037 
3038         if (e.basis)
3039             e.basis = e.basis.expressionSemantic(sc);
3040         if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error))
3041             return setError();
3042 
3043         expandTuples(e.elements);
3044 
3045         Type t0;
3046         if (e.basis)
3047             e.elements.push(e.basis);
3048         bool err = arrayExpressionToCommonType(sc, e.elements, &t0);
3049         if (e.basis)
3050             e.basis = e.elements.pop();
3051         if (err)
3052             return setError();
3053 
3054         e.type = t0.arrayOf();
3055         e.type = e.type.typeSemantic(e.loc, sc);
3056 
3057         /* Disallow array literals of type void being used.
3058          */
3059         if (e.elements.dim > 0 && t0.ty == Tvoid)
3060         {
3061             e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3062             return setError();
3063         }
3064 
3065         if (global.params.useTypeInfo && Type.dtypeinfo)
3066             semanticTypeInfo(sc, e.type);
3067 
3068         result = e;
3069     }
3070 
3071     override void visit(AssocArrayLiteralExp e)
3072     {
3073         static if (LOGSEMANTIC)
3074         {
3075             printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3076         }
3077         if (e.type)
3078         {
3079             result = e;
3080             return;
3081         }
3082 
3083         // Run semantic() on each element
3084         bool err_keys = arrayExpressionSemantic(e.keys, sc);
3085         bool err_vals = arrayExpressionSemantic(e.values, sc);
3086         if (err_keys || err_vals)
3087             return setError();
3088 
3089         expandTuples(e.keys);
3090         expandTuples(e.values);
3091         if (e.keys.dim != e.values.dim)
3092         {
3093             e.error("number of keys is %u, must match number of values %u", e.keys.dim, e.values.dim);
3094             return setError();
3095         }
3096 
3097         Type tkey = null;
3098         Type tvalue = null;
3099         err_keys = arrayExpressionToCommonType(sc, e.keys, &tkey);
3100         err_vals = arrayExpressionToCommonType(sc, e.values, &tvalue);
3101         if (err_keys || err_vals)
3102             return setError();
3103 
3104         if (tkey == Type.terror || tvalue == Type.terror)
3105             return setError();
3106 
3107         e.type = new TypeAArray(tvalue, tkey);
3108         e.type = e.type.typeSemantic(e.loc, sc);
3109 
3110         semanticTypeInfo(sc, e.type);
3111 
3112         if (global.params.vsafe)
3113         {
3114             if (checkAssocArrayLiteralEscape(sc, e, false))
3115                 return setError();
3116         }
3117 
3118         result = e;
3119     }
3120 
3121     override void visit(StructLiteralExp e)
3122     {
3123         static if (LOGSEMANTIC)
3124         {
3125             printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3126         }
3127         if (e.type)
3128         {
3129             result = e;
3130             return;
3131         }
3132 
3133         e.sd.size(e.loc);
3134         if (e.sd.sizeok != Sizeok.done)
3135             return setError();
3136 
3137         // run semantic() on each element
3138         if (arrayExpressionSemantic(e.elements, sc))
3139             return setError();
3140 
3141         expandTuples(e.elements);
3142 
3143         /* Fit elements[] to the corresponding type of field[].
3144          */
3145         if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3146             return setError();
3147 
3148         /* Fill out remainder of elements[] with default initializers for fields[]
3149          */
3150         if (!e.sd.fill(e.loc, e.elements, false))
3151         {
3152             /* An error in the initializer needs to be recorded as an error
3153              * in the enclosing function or template, since the initializer
3154              * will be part of the stuct declaration.
3155              */
3156             global.increaseErrorCount();
3157             return setError();
3158         }
3159 
3160         if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
3161             return setError();
3162 
3163         e.type = e.stype ? e.stype : e.sd.type;
3164         result = e;
3165     }
3166 
3167     override void visit(TypeExp exp)
3168     {
3169         if (exp.type.ty == Terror)
3170             return setError();
3171 
3172         //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3173         Expression e;
3174         Type t;
3175         Dsymbol s;
3176 
3177         dmd.typesem.resolve(exp.type, exp.loc, sc, &e, &t, &s, true);
3178         if (e)
3179         {
3180             // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3181             // then rewrite as `(this.var)` in case it would be followed by a DotVar
3182             // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3183             VarExp ve = e.isVarExp();
3184             if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3185                 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
3186             {
3187                 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3188                 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3189             }
3190             //printf("e = %s %s\n", Token::toChars(e.op), e.toChars());
3191             e = e.expressionSemantic(sc);
3192         }
3193         else if (t)
3194         {
3195             //printf("t = %d %s\n", t.ty, t.toChars());
3196             exp.type = t.typeSemantic(exp.loc, sc);
3197             e = exp;
3198         }
3199         else if (s)
3200         {
3201             //printf("s = %s %s\n", s.kind(), s.toChars());
3202             e = symbolToExp(s, exp.loc, sc, true);
3203         }
3204         else
3205             assert(0);
3206 
3207         if (global.params.vcomplex)
3208             exp.type.checkComplexTransition(exp.loc, sc);
3209 
3210         result = e;
3211     }
3212 
3213     override void visit(ScopeExp exp)
3214     {
3215         static if (LOGSEMANTIC)
3216         {
3217             printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3218         }
3219         if (exp.type)
3220         {
3221             result = exp;
3222             return;
3223         }
3224 
3225         ScopeDsymbol sds2 = exp.sds;
3226         TemplateInstance ti = sds2.isTemplateInstance();
3227         while (ti)
3228         {
3229             WithScopeSymbol withsym;
3230             if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3231                 return setError();
3232             if (withsym && withsym.withstate.wthis)
3233             {
3234                 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3235                 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3236                 result = e.expressionSemantic(sc);
3237                 return;
3238             }
3239             if (ti.needsTypeInference(sc))
3240             {
3241                 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3242                 {
3243                     Dsymbol p = td.toParentLocal();
3244                     FuncDeclaration fdthis = hasThis(sc);
3245                     AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3246                     if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3247                     {
3248                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti.name, ti.tiargs);
3249                         result = e.expressionSemantic(sc);
3250                         return;
3251                     }
3252                 }
3253                 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3254                 {
3255                     FuncDeclaration fdthis = hasThis(sc);
3256                     AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3257                     if (fdthis && ad && fdthis.isMemberLocal() == ad)
3258                     {
3259                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti.name, ti.tiargs);
3260                         result = e.expressionSemantic(sc);
3261                         return;
3262                     }
3263                 }
3264                 // ti is an instance which requires IFTI.
3265                 exp.sds = ti;
3266                 exp.type = Type.tvoid;
3267                 result = exp;
3268                 return;
3269             }
3270             ti.dsymbolSemantic(sc);
3271             if (!ti.inst || ti.errors)
3272                 return setError();
3273 
3274             Dsymbol s = ti.toAlias();
3275             if (s == ti)
3276             {
3277                 exp.sds = ti;
3278                 exp.type = Type.tvoid;
3279                 result = exp;
3280                 return;
3281             }
3282             sds2 = s.isScopeDsymbol();
3283             if (sds2)
3284             {
3285                 ti = sds2.isTemplateInstance();
3286                 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3287                 continue;
3288             }
3289 
3290             if (auto v = s.isVarDeclaration())
3291             {
3292                 if (!v.type)
3293                 {
3294                     exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3295                     return setError();
3296                 }
3297                 if ((v.storage_class & STC.manifest) && v._init)
3298                 {
3299                     /* When an instance that will be converted to a constant exists,
3300                      * the instance representation "foo!tiargs" is treated like a
3301                      * variable name, and its recursive appearance check (note that
3302                      * it's equivalent with a recursive instantiation of foo) is done
3303                      * separately from the circular initialization check for the
3304                      * eponymous enum variable declaration.
3305                      *
3306                      *  template foo(T) {
3307                      *    enum bool foo = foo;    // recursive definition check (v.inuse)
3308                      *  }
3309                      *  template bar(T) {
3310                      *    enum bool bar = bar!T;  // recursive instantiation check (ti.inuse)
3311                      *  }
3312                      */
3313                     if (ti.inuse)
3314                     {
3315                         exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3316                         return setError();
3317                     }
3318                     v.checkDeprecated(exp.loc, sc);
3319                     auto e = v.expandInitializer(exp.loc);
3320                     ti.inuse++;
3321                     e = e.expressionSemantic(sc);
3322                     ti.inuse--;
3323                     result = e;
3324                     return;
3325                 }
3326             }
3327 
3328             //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3329             auto e = symbolToExp(s, exp.loc, sc, true);
3330             //printf("-1ScopeExp::semantic()\n");
3331             result = e;
3332             return;
3333         }
3334 
3335         //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3336         //printf("\tparent = '%s'\n", sds2.parent.toChars());
3337         sds2.dsymbolSemantic(sc);
3338 
3339         // (Aggregate|Enum)Declaration
3340         if (auto t = sds2.getType())
3341         {
3342             result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3343             return;
3344         }
3345 
3346         if (auto td = sds2.isTemplateDeclaration())
3347         {
3348             result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3349             return;
3350         }
3351 
3352         exp.sds = sds2;
3353         exp.type = Type.tvoid;
3354         //printf("-2ScopeExp::semantic() %s\n", toChars());
3355         result = exp;
3356     }
3357 
3358     override void visit(NewExp exp)
3359     {
3360         static if (LOGSEMANTIC)
3361         {
3362             printf("NewExp::semantic() %s\n", exp.toChars());
3363             if (exp.thisexp)
3364                 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3365             printf("\tnewtype: %s\n", exp.newtype.toChars());
3366         }
3367         if (exp.type) // if semantic() already run
3368         {
3369             result = exp;
3370             return;
3371         }
3372 
3373         //for error messages if the argument in [] is not convertible to size_t
3374         const originalNewtype = exp.newtype;
3375 
3376         // https://issues.dlang.org/show_bug.cgi?id=11581
3377         // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3378         // T should be analyzed first and edim should go into arguments iff it's
3379         // not a tuple.
3380         Expression edim = null;
3381         if (!exp.arguments && exp.newtype.ty == Tsarray)
3382         {
3383             edim = (cast(TypeSArray)exp.newtype).dim;
3384             exp.newtype = (cast(TypeNext)exp.newtype).next;
3385         }
3386 
3387         ClassDeclaration cdthis = null;
3388         if (exp.thisexp)
3389         {
3390             exp.thisexp = exp.thisexp.expressionSemantic(sc);
3391             if (exp.thisexp.op == TOK.error)
3392                 return setError();
3393 
3394             cdthis = exp.thisexp.type.isClassHandle();
3395             if (!cdthis)
3396             {
3397                 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3398                 return setError();
3399             }
3400 
3401             sc = sc.push(cdthis);
3402             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3403             sc = sc.pop();
3404         }
3405         else
3406         {
3407             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3408         }
3409         if (exp.type.ty == Terror)
3410             return setError();
3411 
3412         if (edim)
3413         {
3414             if (exp.type.toBasetype().ty == Ttuple)
3415             {
3416                 // --> new T[edim]
3417                 exp.type = new TypeSArray(exp.type, edim);
3418                 exp.type = exp.type.typeSemantic(exp.loc, sc);
3419                 if (exp.type.ty == Terror)
3420                     return setError();
3421             }
3422             else
3423             {
3424                 // --> new T[](edim)
3425                 exp.arguments = new Expressions();
3426                 exp.arguments.push(edim);
3427                 exp.type = exp.type.arrayOf();
3428             }
3429         }
3430 
3431         exp.newtype = exp.type; // in case type gets cast to something else
3432         Type tb = exp.type.toBasetype();
3433         //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3434         if (arrayExpressionSemantic(exp.newargs, sc) ||
3435             preFunctionParameters(sc, exp.newargs))
3436         {
3437             return setError();
3438         }
3439         if (arrayExpressionSemantic(exp.arguments, sc))
3440         {
3441             return setError();
3442         }
3443         //https://issues.dlang.org/show_bug.cgi?id=20547
3444         //exp.arguments are the "parameters" to [], not to a real function
3445         //so the errors that come from preFunctionParameters are misleading
3446         if (originalNewtype.ty == Tsarray)
3447         {
3448             if (preFunctionParameters(sc, exp.arguments, false))
3449             {
3450                 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
3451                 return setError();
3452             }
3453         }
3454         else if (preFunctionParameters(sc, exp.arguments))
3455         {
3456             return setError();
3457         }
3458 
3459         if (exp.thisexp && tb.ty != Tclass)
3460         {
3461             exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3462             return setError();
3463         }
3464 
3465         const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
3466         Expression newprefix = null;
3467 
3468         if (tb.ty == Tclass)
3469         {
3470             auto cd = (cast(TypeClass)tb).sym;
3471             cd.size(exp.loc);
3472             if (cd.sizeok != Sizeok.done)
3473                 return setError();
3474             if (!cd.ctor)
3475                 cd.ctor = cd.searchCtor();
3476             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3477             {
3478                 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3479                 return setError();
3480             }
3481 
3482             if (cd.isInterfaceDeclaration())
3483             {
3484                 exp.error("cannot create instance of interface `%s`", cd.toChars());
3485                 return setError();
3486             }
3487 
3488             if (cd.isAbstract())
3489             {
3490                 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3491                 for (size_t i = 0; i < cd.vtbl.dim; i++)
3492                 {
3493                     FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3494                     if (fd && fd.isAbstract())
3495                     {
3496                         errorSupplemental(exp.loc, "function `%s` is not implemented",
3497                             fd.toFullSignature());
3498                     }
3499                 }
3500                 return setError();
3501             }
3502             // checkDeprecated() is already done in newtype.typeSemantic().
3503 
3504             if (cd.isNested())
3505             {
3506                 /* We need a 'this' pointer for the nested class.
3507                  * Ensure we have the right one.
3508                  */
3509                 Dsymbol s = cd.toParentLocal();
3510 
3511                 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3512                 if (auto cdn = s.isClassDeclaration())
3513                 {
3514                     if (!cdthis)
3515                     {
3516                         // Supply an implicit 'this' and try again
3517                         exp.thisexp = new ThisExp(exp.loc);
3518                         for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3519                         {
3520                             if (!sp)
3521                             {
3522                                 exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
3523                                     cdn.toChars(), cd.toChars());
3524                                 return setError();
3525                             }
3526                             ClassDeclaration cdp = sp.isClassDeclaration();
3527                             if (!cdp)
3528                                 continue;
3529                             if (cdp == cdn || cdn.isBaseOf(cdp, null))
3530                                 break;
3531                             // Add a '.outer' and try again
3532                             exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3533                         }
3534 
3535                         exp.thisexp = exp.thisexp.expressionSemantic(sc);
3536                         if (exp.thisexp.op == TOK.error)
3537                             return setError();
3538                         cdthis = exp.thisexp.type.isClassHandle();
3539                     }
3540                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3541                     {
3542                         //printf("cdthis = %s\n", cdthis.toChars());
3543                         exp.error("`this` for nested class must be of type `%s`, not `%s`",
3544                             cdn.toChars(), exp.thisexp.type.toChars());
3545                         return setError();
3546                     }
3547                     if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3548                     {
3549                         exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3550                             exp.newtype.toChars(), exp.thisexp.type.toChars());
3551                         return setError();
3552                     }
3553                 }
3554                 else if (exp.thisexp)
3555                 {
3556                     exp.error("`.new` is only for allocating nested classes");
3557                     return setError();
3558                 }
3559                 else if (auto fdn = s.isFuncDeclaration())
3560                 {
3561                     // make sure the parent context fdn of cd is reachable from sc
3562                     if (!ensureStaticLinkTo(sc.parent, fdn))
3563                     {
3564                         exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3565                             fdn.toPrettyChars(), cd.toPrettyChars());
3566                         return setError();
3567                     }
3568                 }
3569                 else
3570                     assert(0);
3571             }
3572             else if (exp.thisexp)
3573             {
3574                 exp.error("`.new` is only for allocating nested classes");
3575                 return setError();
3576             }
3577 
3578             if (cd.vthis2)
3579             {
3580                 if (AggregateDeclaration ad2 = cd.isMember2())
3581                 {
3582                     Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3583                     if (te.op != TOK.error)
3584                         te = getRightThis(exp.loc, sc, ad2, te, cd);
3585                     if (te.op == TOK.error)
3586                     {
3587                         exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3588                         return setError();
3589                     }
3590                 }
3591             }
3592 
3593             if (cd.aggNew)
3594             {
3595                 // Prepend the size argument to newargs[]
3596                 Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t);
3597                 if (!exp.newargs)
3598                     exp.newargs = new Expressions();
3599                 exp.newargs.shift(e);
3600 
3601                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3602                 if (!f || f.errors)
3603                     return setError();
3604 
3605                 checkFunctionAttributes(exp, sc, f);
3606                 checkAccess(cd, exp.loc, sc, f);
3607 
3608                 TypeFunction tf = cast(TypeFunction)f.type;
3609                 Type rettype;
3610                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3611                     return setError();
3612 
3613                 exp.allocator = f.isNewDeclaration();
3614                 assert(exp.allocator);
3615             }
3616             else
3617             {
3618                 if (exp.newargs && exp.newargs.dim)
3619                 {
3620                     exp.error("no allocator for `%s`", cd.toChars());
3621                     return setError();
3622                 }
3623             }
3624 
3625             if (cd.ctor)
3626             {
3627                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3628                 if (!f || f.errors)
3629                     return setError();
3630 
3631                 checkFunctionAttributes(exp, sc, f);
3632                 checkAccess(cd, exp.loc, sc, f);
3633 
3634                 TypeFunction tf = cast(TypeFunction)f.type;
3635                 if (!exp.arguments)
3636                     exp.arguments = new Expressions();
3637                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3638                     return setError();
3639 
3640                 exp.member = f.isCtorDeclaration();
3641                 assert(exp.member);
3642             }
3643             else
3644             {
3645                 if (nargs)
3646                 {
3647                     exp.error("no constructor for `%s`", cd.toChars());
3648                     return setError();
3649                 }
3650 
3651                 // https://issues.dlang.org/show_bug.cgi?id=19941
3652                 // Run semantic on all field initializers to resolve any forward
3653                 // references. This is the same as done for structs in sd.fill().
3654                 for (ClassDeclaration c = cd; c; c = c.baseClass)
3655                 {
3656                     foreach (v; c.fields)
3657                     {
3658                         if (v.inuse || v._scope is null || v._init is null ||
3659                             v._init.isVoidInitializer())
3660                             continue;
3661                         v.inuse++;
3662                         v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3663                         v.inuse--;
3664                     }
3665                 }
3666             }
3667         }
3668         else if (tb.ty == Tstruct)
3669         {
3670             auto sd = (cast(TypeStruct)tb).sym;
3671             sd.size(exp.loc);
3672             if (sd.sizeok != Sizeok.done)
3673                 return setError();
3674             if (!sd.ctor)
3675                 sd.ctor = sd.searchCtor();
3676             if (sd.noDefaultCtor && !nargs)
3677             {
3678                 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3679                 return setError();
3680             }
3681             // checkDeprecated() is already done in newtype.typeSemantic().
3682 
3683             if (sd.aggNew)
3684             {
3685                 // Prepend the uint size argument to newargs[]
3686                 Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t);
3687                 if (!exp.newargs)
3688                     exp.newargs = new Expressions();
3689                 exp.newargs.shift(e);
3690 
3691                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3692                 if (!f || f.errors)
3693                     return setError();
3694 
3695                 checkFunctionAttributes(exp, sc, f);
3696                 checkAccess(sd, exp.loc, sc, f);
3697 
3698                 TypeFunction tf = cast(TypeFunction)f.type;
3699                 Type rettype;
3700                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3701                     return setError();
3702 
3703                 exp.allocator = f.isNewDeclaration();
3704                 assert(exp.allocator);
3705             }
3706             else
3707             {
3708                 if (exp.newargs && exp.newargs.dim)
3709                 {
3710                     exp.error("no allocator for `%s`", sd.toChars());
3711                     return setError();
3712                 }
3713             }
3714 
3715             if (sd.ctor && nargs)
3716             {
3717                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3718                 if (!f || f.errors)
3719                     return setError();
3720 
3721                 checkFunctionAttributes(exp, sc, f);
3722                 checkAccess(sd, exp.loc, sc, f);
3723 
3724                 TypeFunction tf = cast(TypeFunction)f.type;
3725                 if (!exp.arguments)
3726                     exp.arguments = new Expressions();
3727                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3728                     return setError();
3729 
3730                 exp.member = f.isCtorDeclaration();
3731                 assert(exp.member);
3732 
3733                 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
3734                     return setError();
3735             }
3736             else
3737             {
3738                 if (!exp.arguments)
3739                     exp.arguments = new Expressions();
3740 
3741                 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3742                     return setError();
3743 
3744                 if (!sd.fill(exp.loc, exp.arguments, false))
3745                     return setError();
3746 
3747                 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
3748                     return setError();
3749 
3750                 /* Since a `new` allocation may escape, check each of the arguments for escaping
3751                  */
3752                 if (global.params.vsafe)
3753                 {
3754                     foreach (arg; *exp.arguments)
3755                     {
3756                         if (arg && checkNewEscape(sc, arg, false))
3757                             return setError();
3758                     }
3759                 }
3760             }
3761 
3762             exp.type = exp.type.pointerTo();
3763         }
3764         else if (tb.ty == Tarray && nargs)
3765         {
3766             Type tn = tb.nextOf().baseElemOf();
3767             Dsymbol s = tn.toDsymbol(sc);
3768             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3769             if (ad && ad.noDefaultCtor)
3770             {
3771                 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3772                 return setError();
3773             }
3774             for (size_t i = 0; i < nargs; i++)
3775             {
3776                 if (tb.ty != Tarray)
3777                 {
3778                     exp.error("too many arguments for array");
3779                     return setError();
3780                 }
3781 
3782                 Expression arg = (*exp.arguments)[i];
3783                 arg = resolveProperties(sc, arg);
3784                 arg = arg.implicitCastTo(sc, Type.tsize_t);
3785                 if (arg.op == TOK.error)
3786                     return setError();
3787                 arg = arg.optimize(WANTvalue);
3788                 if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0)
3789                 {
3790                     exp.error("negative array index `%s`", arg.toChars());
3791                     return setError();
3792                 }
3793                 (*exp.arguments)[i] = arg;
3794                 tb = (cast(TypeDArray)tb).next.toBasetype();
3795             }
3796         }
3797         else if (tb.isscalar())
3798         {
3799             if (!nargs)
3800             {
3801             }
3802             else if (nargs == 1)
3803             {
3804                 Expression e = (*exp.arguments)[0];
3805                 e = e.implicitCastTo(sc, tb);
3806                 (*exp.arguments)[0] = e;
3807             }
3808             else
3809             {
3810                 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3811                 return setError();
3812             }
3813 
3814             exp.type = exp.type.pointerTo();
3815         }
3816         else
3817         {
3818             exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3819             return setError();
3820         }
3821 
3822         //printf("NewExp: '%s'\n", toChars());
3823         //printf("NewExp:type '%s'\n", type.toChars());
3824         semanticTypeInfo(sc, exp.type);
3825 
3826         if (newprefix)
3827         {
3828             result = Expression.combine(newprefix, exp);
3829             return;
3830         }
3831         result = exp;
3832     }
3833 
3834     override void visit(NewAnonClassExp e)
3835     {
3836         static if (LOGSEMANTIC)
3837         {
3838             printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3839             //printf("thisexp = %p\n", thisexp);
3840             //printf("type: %s\n", type.toChars());
3841         }
3842 
3843         Expression d = new DeclarationExp(e.loc, e.cd);
3844         sc = sc.push(); // just create new scope
3845         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3846         d = d.expressionSemantic(sc);
3847         sc = sc.pop();
3848 
3849         if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3850         {
3851             ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3852             if (!sds.members)
3853                 sds.members = new Dsymbols();
3854             sds.members.push(e.cd);
3855         }
3856 
3857         Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments);
3858 
3859         Expression c = new CommaExp(e.loc, d, n);
3860         result = c.expressionSemantic(sc);
3861     }
3862 
3863     override void visit(SymOffExp e)
3864     {
3865         static if (LOGSEMANTIC)
3866         {
3867             printf("SymOffExp::semantic('%s')\n", e.toChars());
3868         }
3869         //var.dsymbolSemantic(sc);
3870         if (!e.type)
3871             e.type = e.var.type.pointerTo();
3872 
3873         if (auto v = e.var.isVarDeclaration())
3874         {
3875             if (v.checkNestedReference(sc, e.loc))
3876                 return setError();
3877         }
3878         else if (auto f = e.var.isFuncDeclaration())
3879         {
3880             if (f.checkNestedReference(sc, e.loc))
3881                 return setError();
3882         }
3883 
3884         result = e;
3885     }
3886 
3887     override void visit(VarExp e)
3888     {
3889         static if (LOGSEMANTIC)
3890         {
3891             printf("VarExp::semantic(%s)\n", e.toChars());
3892         }
3893 
3894         auto vd = e.var.isVarDeclaration();
3895         auto fd = e.var.isFuncDeclaration();
3896 
3897         if (fd)
3898         {
3899             //printf("L%d fd = %s\n", __LINE__, f.toChars());
3900             if (!fd.functionSemantic())
3901                 return setError();
3902         }
3903 
3904         if (!e.type)
3905             e.type = e.var.type;
3906         if (e.type && !e.type.deco)
3907         {
3908             auto decl = e.var.isDeclaration();
3909             if (decl)
3910                 decl.inuse++;
3911             e.type = e.type.typeSemantic(e.loc, sc);
3912             if (decl)
3913                 decl.inuse--;
3914         }
3915 
3916         /* Fix for 1161 doesn't work because it causes protection
3917          * problems when instantiating imported templates passing private
3918          * variables as alias template parameters.
3919          */
3920         //checkAccess(loc, sc, NULL, var);
3921 
3922         if (vd)
3923         {
3924             if (vd.checkNestedReference(sc, e.loc))
3925                 return setError();
3926 
3927             // https://issues.dlang.org/show_bug.cgi?id=12025
3928             // If the variable is not actually used in runtime code,
3929             // the purity violation error is redundant.
3930             //checkPurity(sc, vd);
3931         }
3932         else if (fd)
3933         {
3934             // TODO: If fd isn't yet resolved its overload, the checkNestedReference
3935             // call would cause incorrect validation.
3936             // Maybe here should be moved in CallExp, or AddrExp for functions.
3937             if (fd.checkNestedReference(sc, e.loc))
3938                 return setError();
3939         }
3940         else if (auto od = e.var.isOverDeclaration())
3941         {
3942             e.type = Type.tvoid; // ambiguous type?
3943         }
3944 
3945         result = e;
3946     }
3947 
3948     override void visit(FuncExp exp)
3949     {
3950         static if (LOGSEMANTIC)
3951         {
3952             printf("FuncExp::semantic(%s)\n", exp.toChars());
3953             if (exp.fd.treq)
3954                 printf("  treq = %s\n", exp.fd.treq.toChars());
3955         }
3956 
3957         if (exp.type)
3958         {
3959             result = exp;
3960             return;
3961         }
3962 
3963         Expression e = exp;
3964         uint olderrors;
3965 
3966         sc = sc.push(); // just create new scope
3967         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3968         sc.protection = Prot(Prot.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
3969 
3970         /* fd.treq might be incomplete type,
3971             * so should not semantic it.
3972             * void foo(T)(T delegate(int) dg){}
3973             * foo(a=>a); // in IFTI, treq == T delegate(int)
3974             */
3975         //if (fd.treq)
3976         //    fd.treq = fd.treq.dsymbolSemantic(loc, sc);
3977 
3978         exp.genIdent(sc);
3979 
3980         // Set target of return type inference
3981         if (exp.fd.treq && !exp.fd.type.nextOf())
3982         {
3983             TypeFunction tfv = null;
3984             if (exp.fd.treq.ty == Tdelegate || (exp.fd.treq.ty == Tpointer && exp.fd.treq.nextOf().ty == Tfunction))
3985                 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
3986             if (tfv)
3987             {
3988                 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
3989                 tfl.next = tfv.nextOf();
3990             }
3991         }
3992 
3993         //printf("td = %p, treq = %p\n", td, fd.treq);
3994         if (exp.td)
3995         {
3996             assert(exp.td.parameters && exp.td.parameters.dim);
3997             exp.td.dsymbolSemantic(sc);
3998             exp.type = Type.tvoid; // temporary type
3999 
4000             if (exp.fd.treq) // defer type determination
4001             {
4002                 FuncExp fe;
4003                 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4004                     e = fe;
4005                 else
4006                     e = new ErrorExp();
4007             }
4008             goto Ldone;
4009         }
4010 
4011         olderrors = global.errors;
4012         exp.fd.dsymbolSemantic(sc);
4013         if (olderrors == global.errors)
4014         {
4015             exp.fd.semantic2(sc);
4016             if (olderrors == global.errors)
4017                 exp.fd.semantic3(sc);
4018         }
4019         if (olderrors != global.errors)
4020         {
4021             if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4022                 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4023             e = new ErrorExp();
4024             goto Ldone;
4025         }
4026 
4027         // Type is a "delegate to" or "pointer to" the function literal
4028         if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4029         {
4030             exp.type = new TypeDelegate(exp.fd.type);
4031             exp.type = exp.type.typeSemantic(exp.loc, sc);
4032 
4033             exp.fd.tok = TOK.delegate_;
4034         }
4035         else
4036         {
4037             exp.type = new TypePointer(exp.fd.type);
4038             exp.type = exp.type.typeSemantic(exp.loc, sc);
4039             //type = fd.type.pointerTo();
4040 
4041             /* A lambda expression deduced to function pointer might become
4042                 * to a delegate literal implicitly.
4043                 *
4044                 *   auto foo(void function() fp) { return 1; }
4045                 *   assert(foo({}) == 1);
4046                 *
4047                 * So, should keep fd.tok == TOKreserve if fd.treq == NULL.
4048                 */
4049             if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4050             {
4051                 // change to non-nested
4052                 exp.fd.tok = TOK.function_;
4053                 exp.fd.vthis = null;
4054             }
4055         }
4056         exp.fd.tookAddressOf++;
4057 
4058     Ldone:
4059         sc = sc.pop();
4060         result = e;
4061     }
4062 
4063     /**
4064      * Perform semantic analysis on function literals
4065      *
4066      * Test the following construct:
4067      * ---
4068      * (x, y, z) { return x + y + z; }(42, 84, 1992);
4069      * ---
4070      */
4071     Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4072     {
4073         if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
4074         {
4075             for (size_t k = 0; k < arguments.dim; k++)
4076             {
4077                 Expression checkarg = (*arguments)[k];
4078                 if (checkarg.op == TOK.error)
4079                     return checkarg;
4080             }
4081 
4082             exp.genIdent(sc);
4083 
4084             assert(exp.td.parameters && exp.td.parameters.dim);
4085             exp.td.dsymbolSemantic(sc);
4086 
4087             TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4088             size_t dim = tfl.parameterList.length;
4089             if (arguments.dim < dim)
4090             {
4091                 // Default arguments are always typed, so they don't need inference.
4092                 Parameter p = tfl.parameterList[arguments.dim];
4093                 if (p.defaultArg)
4094                     dim = arguments.dim;
4095             }
4096 
4097             if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
4098                 arguments.dim < dim)
4099             {
4100                 OutBuffer buf;
4101                 foreach (idx, ref arg; *arguments)
4102                     buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4103                 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4104                           exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4105                           buf.peekChars());
4106                 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
4107                                       arguments.dim < dim ? "few".ptr : "many".ptr,
4108                                       cast(int)dim, cast(int)arguments.dim);
4109                 return new ErrorExp();
4110             }
4111 
4112             auto tiargs = new Objects();
4113             tiargs.reserve(exp.td.parameters.dim);
4114 
4115             for (size_t i = 0; i < exp.td.parameters.dim; i++)
4116             {
4117                 TemplateParameter tp = (*exp.td.parameters)[i];
4118                 for (size_t u = 0; u < dim; u++)
4119                 {
4120                     Parameter p = tfl.parameterList[u];
4121                     if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4122                     {
4123                         Expression e = (*arguments)[u];
4124                         tiargs.push(e.type);
4125                         u = dim; // break inner loop
4126                     }
4127                 }
4128             }
4129 
4130             auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4131             return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4132         }
4133         return exp.expressionSemantic(sc);
4134     }
4135 
4136     override void visit(CallExp exp)
4137     {
4138         static if (LOGSEMANTIC)
4139         {
4140             printf("CallExp::semantic() %s\n", exp.toChars());
4141         }
4142         if (exp.type)
4143         {
4144             result = exp;
4145             return; // semantic() already run
4146         }
4147 
4148         Objects* tiargs = null; // initial list of template arguments
4149         Expression ethis = null;
4150         Type tthis = null;
4151         Expression e1org = exp.e1;
4152 
4153         if (exp.e1.op == TOK.comma)
4154         {
4155             /* Rewrite (a,b)(args) as (a,(b(args)))
4156              */
4157             auto ce = cast(CommaExp)exp.e1;
4158             exp.e1 = ce.e2;
4159             ce.e2 = exp;
4160             result = ce.expressionSemantic(sc);
4161             return;
4162         }
4163         if (exp.e1.op == TOK.delegate_)
4164         {
4165             DelegateExp de = cast(DelegateExp)exp.e1;
4166             exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4167             visit(exp);
4168             return;
4169         }
4170         if (exp.e1.op == TOK.function_)
4171         {
4172             if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4173                 return setError();
4174 
4175             // Run e1 semantic even if arguments have any errors
4176             FuncExp fe = cast(FuncExp)exp.e1;
4177             exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4178             if (exp.e1.op == TOK.error)
4179             {
4180                 result = exp.e1;
4181                 return;
4182             }
4183         }
4184 
4185         if (Expression ex = resolveUFCS(sc, exp))
4186         {
4187             result = ex;
4188             return;
4189         }
4190 
4191         /* This recognizes:
4192          *  foo!(tiargs)(funcargs)
4193          */
4194         if (exp.e1.op == TOK.scope_)
4195         {
4196             ScopeExp se = cast(ScopeExp)exp.e1;
4197             TemplateInstance ti = se.sds.isTemplateInstance();
4198             if (ti)
4199             {
4200                 /* Attempt to instantiate ti. If that works, go with it.
4201                  * If not, go with partial explicit specialization.
4202                  */
4203                 WithScopeSymbol withsym;
4204                 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4205                     return setError();
4206                 if (withsym && withsym.withstate.wthis)
4207                 {
4208                     exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4209                     exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4210                     goto Ldotti;
4211                 }
4212                 if (ti.needsTypeInference(sc, 1))
4213                 {
4214                     /* Go with partial explicit specialization
4215                      */
4216                     tiargs = ti.tiargs;
4217                     assert(ti.tempdecl);
4218                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4219                         exp.e1 = new TemplateExp(exp.loc, td);
4220                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4221                         exp.e1 = new VarExp(exp.loc, od);
4222                     else
4223                         exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4224                 }
4225                 else
4226                 {
4227                     Expression e1x = exp.e1.expressionSemantic(sc);
4228                     if (e1x.op == TOK.error)
4229                     {
4230                         result = e1x;
4231                         return;
4232                     }
4233                     exp.e1 = e1x;
4234                 }
4235             }
4236         }
4237 
4238         /* This recognizes:
4239          *  expr.foo!(tiargs)(funcargs)
4240          */
4241     Ldotti:
4242         if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4243         {
4244             DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
4245             TemplateInstance ti = se.ti;
4246             {
4247                 /* Attempt to instantiate ti. If that works, go with it.
4248                  * If not, go with partial explicit specialization.
4249                  */
4250                 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4251                     return setError();
4252                 if (ti.needsTypeInference(sc, 1))
4253                 {
4254                     /* Go with partial explicit specialization
4255                      */
4256                     tiargs = ti.tiargs;
4257                     assert(ti.tempdecl);
4258                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4259                         exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4260                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4261                     {
4262                         exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4263                     }
4264                     else
4265                         exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4266                 }
4267                 else
4268                 {
4269                     Expression e1x = exp.e1.expressionSemantic(sc);
4270                     if (e1x.op == TOK.error)
4271                     {
4272                         result = e1x;
4273                         return;
4274                     }
4275                     exp.e1 = e1x;
4276                 }
4277             }
4278         }
4279 
4280     Lagain:
4281         //printf("Lagain: %s\n", toChars());
4282         exp.f = null;
4283         if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_)
4284         {
4285             // semantic() run later for these
4286         }
4287         else
4288         {
4289             if (exp.e1.op == TOK.dotIdentifier)
4290             {
4291                 DotIdExp die = cast(DotIdExp)exp.e1;
4292                 exp.e1 = die.expressionSemantic(sc);
4293                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4294                  * We handle such earlier, so go back.
4295                  * Note that in the rewrite, we carefully did not run semantic() on e1
4296                  */
4297                 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4298                 {
4299                     goto Ldotti;
4300                 }
4301             }
4302             else
4303             {
4304                 __gshared int nest;
4305                 if (++nest > global.recursionLimit)
4306                 {
4307                     exp.error("recursive evaluation of `%s`", exp.toChars());
4308                     --nest;
4309                     return setError();
4310                 }
4311                 Expression ex = unaSemantic(exp, sc);
4312                 --nest;
4313                 if (ex)
4314                 {
4315                     result = ex;
4316                     return;
4317                 }
4318             }
4319 
4320             /* Look for e1 being a lazy parameter
4321              */
4322             if (exp.e1.op == TOK.variable)
4323             {
4324                 VarExp ve = cast(VarExp)exp.e1;
4325                 if (ve.var.storage_class & STC.lazy_)
4326                 {
4327                     // lazy parameters can be called without violating purity and safety
4328                     Type tw = ve.var.type;
4329                     Type tc = ve.var.type.substWildTo(MODFlags.const_);
4330                     auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4331                     (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4332                     auto t = new TypeDelegate(tf);
4333                     ve.type = t.typeSemantic(exp.loc, sc);
4334                 }
4335                 VarDeclaration v = ve.var.isVarDeclaration();
4336                 if (v && ve.checkPurity(sc, v))
4337                     return setError();
4338             }
4339 
4340             if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4341             {
4342                 SymOffExp se = cast(SymOffExp)exp.e1;
4343                 exp.e1 = new VarExp(se.loc, se.var, true);
4344                 exp.e1 = exp.e1.expressionSemantic(sc);
4345             }
4346             else if (exp.e1.op == TOK.dot)
4347             {
4348                 DotExp de = cast(DotExp)exp.e1;
4349 
4350                 if (de.e2.op == TOK.overloadSet)
4351                 {
4352                     ethis = de.e1;
4353                     tthis = de.e1.type;
4354                     exp.e1 = de.e2;
4355                 }
4356             }
4357             else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction)
4358             {
4359                 // Rewrite (*fp)(arguments) to fp(arguments)
4360                 exp.e1 = (cast(PtrExp)exp.e1).e1;
4361             }
4362         }
4363 
4364         Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4365 
4366         if (exp.e1.op == TOK.error)
4367         {
4368             result = exp.e1;
4369             return;
4370         }
4371         if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4372             return setError();
4373 
4374         // Check for call operator overload
4375         if (t1)
4376         {
4377             if (t1.ty == Tstruct)
4378             {
4379                 auto sd = (cast(TypeStruct)t1).sym;
4380                 sd.size(exp.loc); // Resolve forward references to construct object
4381                 if (sd.sizeok != Sizeok.done)
4382                     return setError();
4383                 if (!sd.ctor)
4384                     sd.ctor = sd.searchCtor();
4385                 /* If `sd.ctor` is a generated copy constructor, this means that it
4386                    is the single constructor that this struct has. In order to not
4387                    disable default construction, the ctor is nullified. The side effect
4388                    of this is that the generated copy constructor cannot be called
4389                    explicitly, but that is ok, because when calling a constructor the
4390                    default constructor should have priority over the generated copy
4391                    constructor.
4392                 */
4393                 if (sd.ctor)
4394                 {
4395                     auto ctor = sd.ctor.isCtorDeclaration();
4396                     if (ctor && ctor.isCpCtor && ctor.generated)
4397                         sd.ctor = null;
4398                 }
4399 
4400                 // First look for constructor
4401                 if (exp.e1.op == TOK.type && sd.ctor)
4402                 {
4403                     if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
4404                         goto Lx;
4405 
4406                     auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4407                     if (!sd.fill(exp.loc, sle.elements, true))
4408                         return setError();
4409                     if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
4410                         return setError();
4411 
4412                     // https://issues.dlang.org/show_bug.cgi?id=14556
4413                     // Set concrete type to avoid further redundant semantic().
4414                     sle.type = exp.e1.type;
4415 
4416                     /* Constructor takes a mutable object, so don't use
4417                      * the immutable initializer symbol.
4418                      */
4419                     sle.useStaticInit = false;
4420 
4421                     Expression e = sle;
4422                     if (auto cf = sd.ctor.isCtorDeclaration())
4423                     {
4424                         e = new DotVarExp(exp.loc, e, cf, true);
4425                     }
4426                     else if (auto td = sd.ctor.isTemplateDeclaration())
4427                     {
4428                         e = new DotIdExp(exp.loc, e, td.ident);
4429                     }
4430                     else if (auto os = sd.ctor.isOverloadSet())
4431                     {
4432                         e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4433                     }
4434                     else
4435                         assert(0);
4436                     e = new CallExp(exp.loc, e, exp.arguments);
4437                     e = e.expressionSemantic(sc);
4438                     result = e;
4439                     return;
4440                 }
4441                 // No constructor, look for overload of opCall
4442                 if (search_function(sd, Id.call))
4443                     goto L1;
4444                 // overload of opCall, therefore it's a call
4445                 if (exp.e1.op != TOK.type)
4446                 {
4447                     if (sd.aliasthis && exp.e1.type != exp.att1)
4448                     {
4449                         if (!exp.att1 && exp.e1.type.checkAliasThisRec())
4450                             exp.att1 = exp.e1.type;
4451                         exp.e1 = resolveAliasThis(sc, exp.e1);
4452                         goto Lagain;
4453                     }
4454                     exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4455                     return setError();
4456                 }
4457 
4458                 /* It's a struct literal
4459                  */
4460             Lx:
4461                 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4462                 e = e.expressionSemantic(sc);
4463                 result = e;
4464                 return;
4465             }
4466             else if (t1.ty == Tclass)
4467             {
4468             L1:
4469                 // Rewrite as e1.call(arguments)
4470                 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4471                 e = new CallExp(exp.loc, e, exp.arguments);
4472                 e = e.expressionSemantic(sc);
4473                 result = e;
4474                 return;
4475             }
4476             else if (exp.e1.op == TOK.type && t1.isscalar())
4477             {
4478                 Expression e;
4479 
4480                 // Make sure to use the the enum type itself rather than its
4481                 // base type
4482                 // https://issues.dlang.org/show_bug.cgi?id=16346
4483                 if (exp.e1.type.ty == Tenum)
4484                 {
4485                     t1 = exp.e1.type;
4486                 }
4487 
4488                 if (!exp.arguments || exp.arguments.dim == 0)
4489                 {
4490                     e = t1.defaultInitLiteral(exp.loc);
4491                 }
4492                 else if (exp.arguments.dim == 1)
4493                 {
4494                     e = (*exp.arguments)[0];
4495                     e = e.implicitCastTo(sc, t1);
4496                     e = new CastExp(exp.loc, e, t1);
4497                 }
4498                 else
4499                 {
4500                     exp.error("more than one argument for construction of `%s`", t1.toChars());
4501                     return setError();
4502                 }
4503                 e = e.expressionSemantic(sc);
4504                 result = e;
4505                 return;
4506             }
4507         }
4508 
4509         static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4510             OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4511         {
4512             FuncDeclaration f = null;
4513             foreach (s; os.a)
4514             {
4515                 if (tiargs && s.isFuncDeclaration())
4516                     continue;
4517                 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4518                 {
4519                     if (f2.errors)
4520                         return null;
4521                     if (f)
4522                     {
4523                         /* Error if match in more than one overload set,
4524                          * even if one is a 'better' match than the other.
4525                          */
4526                         ScopeDsymbol.multiplyDefined(loc, f, f2);
4527                     }
4528                     else
4529                         f = f2;
4530                 }
4531             }
4532             if (!f)
4533                 .error(loc, "no overload matches for `%s`", os.toChars());
4534             else if (f.errors)
4535                 f = null;
4536             return f;
4537         }
4538 
4539         bool isSuper = false;
4540         if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration)
4541         {
4542             UnaExp ue = cast(UnaExp)exp.e1;
4543 
4544             Expression ue1 = ue.e1;
4545             Expression ue1old = ue1; // need for 'right this' check
4546             VarDeclaration v;
4547             if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
4548             {
4549                 ue.e1 = new TypeExp(ue1.loc, ue1.type);
4550                 ue1 = null;
4551             }
4552 
4553             DotVarExp dve;
4554             DotTemplateExp dte;
4555             Dsymbol s;
4556             if (exp.e1.op == TOK.dotVariable)
4557             {
4558                 dve = cast(DotVarExp)exp.e1;
4559                 dte = null;
4560                 s = dve.var;
4561                 tiargs = null;
4562             }
4563             else
4564             {
4565                 dve = null;
4566                 dte = cast(DotTemplateExp)exp.e1;
4567                 s = dte.td;
4568             }
4569 
4570             // Do overload resolution
4571             exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard);
4572             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4573                 return setError();
4574 
4575             if (exp.f.interfaceVirtual)
4576             {
4577                 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4578                  */
4579                 auto b = exp.f.interfaceVirtual;
4580                 auto ad2 = b.sym;
4581                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4582                 ue.e1 = ue.e1.expressionSemantic(sc);
4583                 ue1 = ue.e1;
4584                 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
4585                 assert(vi >= 0);
4586                 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4587                 assert(exp.f);
4588             }
4589             if (exp.f.needThis())
4590             {
4591                 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
4592                 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4593                 if (ue.e1.op == TOK.error)
4594                 {
4595                     result = ue.e1;
4596                     return;
4597                 }
4598                 ethis = ue.e1;
4599                 tthis = ue.e1.type;
4600                 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isscope))
4601                 {
4602                     if (global.params.vsafe && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
4603                         return setError();
4604                 }
4605             }
4606 
4607             /* Cannot call public functions from inside invariant
4608              * (because then the invariant would have infinite recursion)
4609              */
4610             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant())
4611             {
4612                 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4613                 return setError();
4614             }
4615 
4616             checkFunctionAttributes(exp, sc, exp.f);
4617             checkAccess(exp.loc, sc, ue.e1, exp.f);
4618             if (!exp.f.needThis())
4619             {
4620                 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4621             }
4622             else
4623             {
4624                 if (ue1old.checkRightThis(sc))
4625                     return setError();
4626                 if (exp.e1.op == TOK.dotVariable)
4627                 {
4628                     dve.var = exp.f;
4629                     exp.e1.type = exp.f.type;
4630                 }
4631                 else
4632                 {
4633                     exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4634                     exp.e1 = exp.e1.expressionSemantic(sc);
4635                     if (exp.e1.op == TOK.error)
4636                         return setError();
4637                     ue = cast(UnaExp)exp.e1;
4638                 }
4639                 version (none)
4640                 {
4641                     printf("ue.e1 = %s\n", ue.e1.toChars());
4642                     printf("f = %s\n", exp.f.toChars());
4643                     printf("t = %s\n", t.toChars());
4644                     printf("e1 = %s\n", exp.e1.toChars());
4645                     printf("e1.type = %s\n", exp.e1.type.toChars());
4646                 }
4647 
4648                 // See if we need to adjust the 'this' pointer
4649                 AggregateDeclaration ad = exp.f.isThis();
4650                 ClassDeclaration cd = ue.e1.type.isClassHandle();
4651                 if (ad && cd && ad.isClassDeclaration())
4652                 {
4653                     if (ue.e1.op == TOK.dotType)
4654                     {
4655                         ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4656                         exp.directcall = true;
4657                     }
4658                     else if (ue.e1.op == TOK.super_)
4659                         exp.directcall = true;
4660                     else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4661                         exp.directcall = true;
4662 
4663                     if (ad != cd)
4664                     {
4665                         ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4666                         ue.e1 = ue.e1.expressionSemantic(sc);
4667                     }
4668                 }
4669             }
4670             // If we've got a pointer to a function then deference it
4671             // https://issues.dlang.org/show_bug.cgi?id=16483
4672             if (exp.e1.type.ty == Tpointer && exp.e1.type.nextOf().ty == Tfunction)
4673             {
4674                 Expression e = new PtrExp(exp.loc, exp.e1);
4675                 e.type = exp.e1.type.nextOf();
4676                 exp.e1 = e;
4677             }
4678             t1 = exp.e1.type;
4679         }
4680         else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_)
4681         {
4682             auto ad = sc.func ? sc.func.isThis() : null;
4683             auto cd = ad ? ad.isClassDeclaration() : null;
4684 
4685             isSuper = exp.e1.op == TOK.super_;
4686             if (isSuper)
4687             {
4688                 // Base class constructor call
4689                 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4690                 {
4691                     exp.error("super class constructor call must be in a constructor");
4692                     return setError();
4693                 }
4694                 if (!cd.baseClass.ctor)
4695                 {
4696                     exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4697                     return setError();
4698                 }
4699             }
4700             else
4701             {
4702                 // `this` call expression must be inside a
4703                 // constructor
4704                 if (!ad || !sc.func.isCtorDeclaration())
4705                 {
4706                     exp.error("constructor call must be in a constructor");
4707                     return setError();
4708                 }
4709 
4710                 // https://issues.dlang.org/show_bug.cgi?id=18719
4711                 // If `exp` is a call expression to another constructor
4712                 // then it means that all struct/class fields will be
4713                 // initialized after this call.
4714                 foreach (ref field; sc.ctorflow.fieldinit)
4715                 {
4716                     field.csx |= CSX.this_ctor;
4717                 }
4718             }
4719 
4720             if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4721             {
4722                 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4723                     exp.error("constructor calls not allowed in loops or after labels");
4724                 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4725                     exp.error("multiple constructor calls");
4726                 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4727                     exp.error("an earlier `return` statement skips constructor");
4728                 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4729             }
4730 
4731             tthis = ad.type.addMod(sc.func.type.mod);
4732             auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4733             if (auto os = ctor.isOverloadSet())
4734                 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4735             else
4736                 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4737 
4738             if (!exp.f || exp.f.errors)
4739                 return setError();
4740 
4741             checkFunctionAttributes(exp, sc, exp.f);
4742             checkAccess(exp.loc, sc, null, exp.f);
4743 
4744             exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4745             exp.e1 = exp.e1.expressionSemantic(sc);
4746             t1 = exp.e1.type;
4747 
4748             // BUG: this should really be done by checking the static
4749             // call graph
4750             if (exp.f == sc.func)
4751             {
4752                 exp.error("cyclic constructor call");
4753                 return setError();
4754             }
4755         }
4756         else if (exp.e1.op == TOK.overloadSet)
4757         {
4758             auto os = (cast(OverExp)exp.e1).vars;
4759             exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
4760             if (!exp.f)
4761                 return setError();
4762             if (ethis)
4763                 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4764             else
4765                 exp.e1 = new VarExp(exp.loc, exp.f, false);
4766             goto Lagain;
4767         }
4768         else if (!t1)
4769         {
4770             exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4771             return setError();
4772         }
4773         else if (t1.ty == Terror)
4774         {
4775             return setError();
4776         }
4777         else if (t1.ty != Tfunction)
4778         {
4779             TypeFunction tf;
4780             const(char)* p;
4781             Dsymbol s;
4782             exp.f = null;
4783             if (exp.e1.op == TOK.function_)
4784             {
4785                 // function literal that direct called is always inferred.
4786                 assert((cast(FuncExp)exp.e1).fd);
4787                 exp.f = (cast(FuncExp)exp.e1).fd;
4788                 tf = cast(TypeFunction)exp.f.type;
4789                 p = "function literal";
4790             }
4791             else if (t1.ty == Tdelegate)
4792             {
4793                 TypeDelegate td = cast(TypeDelegate)t1;
4794                 assert(td.next.ty == Tfunction);
4795                 tf = cast(TypeFunction)td.next;
4796                 p = "delegate";
4797             }
4798             else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction)
4799             {
4800                 tf = cast(TypeFunction)(cast(TypePointer)t1).next;
4801                 p = "function pointer";
4802             }
4803             else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4804             {
4805                 DotVarExp dve = cast(DotVarExp)exp.e1;
4806                 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4807                 if (!exp.f)
4808                     return setError();
4809                 if (exp.f.needThis())
4810                 {
4811                     dve.var = exp.f;
4812                     dve.type = exp.f.type;
4813                     dve.hasOverloads = false;
4814                     goto Lagain;
4815                 }
4816                 exp.e1 = new VarExp(dve.loc, exp.f, false);
4817                 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4818                 result = e.expressionSemantic(sc);
4819                 return;
4820             }
4821             else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4822             {
4823                 s = (cast(VarExp)exp.e1).var;
4824                 goto L2;
4825             }
4826             else if (exp.e1.op == TOK.template_)
4827             {
4828                 s = (cast(TemplateExp)exp.e1).td;
4829             L2:
4830                 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
4831                 if (!exp.f || exp.f.errors)
4832                     return setError();
4833                 if (exp.f.needThis())
4834                 {
4835                     if (hasThis(sc))
4836                     {
4837                         // Supply an implicit 'this', as in
4838                         //    this.ident
4839                         exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
4840                         goto Lagain;
4841                     }
4842                     else if (isNeedThisScope(sc, exp.f))
4843                     {
4844                         exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4845                         return setError();
4846                     }
4847                 }
4848                 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
4849                 goto Lagain;
4850             }
4851             else
4852             {
4853                 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
4854                 return setError();
4855             }
4856 
4857             const(char)* failMessage;
4858             Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4859             if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4860             {
4861                 OutBuffer buf;
4862                 buf.writeByte('(');
4863                 argExpTypesToCBuffer(&buf, exp.arguments);
4864                 buf.writeByte(')');
4865                 if (tthis)
4866                     tthis.modToBuffer(&buf);
4867 
4868                 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4869                 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4870                     p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4871                 if (failMessage)
4872                     errorSupplemental(exp.loc, "%s", failMessage);
4873                 return setError();
4874             }
4875             // Purity and safety check should run after testing arguments matching
4876             if (exp.f)
4877             {
4878                 exp.checkPurity(sc, exp.f);
4879                 exp.checkSafety(sc, exp.f);
4880                 exp.checkNogc(sc, exp.f);
4881                 if (exp.f.checkNestedReference(sc, exp.loc))
4882                     return setError();
4883             }
4884             else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
4885             {
4886                 bool err = false;
4887                 if (!tf.purity && sc.func.setImpure())
4888                 {
4889                     exp.error("`pure` %s `%s` cannot call impure %s `%s`",
4890                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4891                     err = true;
4892                 }
4893                 if (!tf.isnogc && sc.func.setGC())
4894                 {
4895                     exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
4896                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4897                     err = true;
4898                 }
4899                 if (tf.trust <= TRUST.system && sc.func.setUnsafe())
4900                 {
4901                     exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
4902                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4903                     err = true;
4904                 }
4905                 if (err)
4906                     return setError();
4907             }
4908 
4909             if (t1.ty == Tpointer)
4910             {
4911                 Expression e = new PtrExp(exp.loc, exp.e1);
4912                 e.type = tf;
4913                 exp.e1 = e;
4914             }
4915             t1 = tf;
4916         }
4917         else if (exp.e1.op == TOK.variable)
4918         {
4919             // Do overload resolution
4920             VarExp ve = cast(VarExp)exp.e1;
4921 
4922             exp.f = ve.var.isFuncDeclaration();
4923             assert(exp.f);
4924             tiargs = null;
4925 
4926             if (exp.f.overnext)
4927                 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
4928             else
4929             {
4930                 exp.f = exp.f.toAliasFunc();
4931                 TypeFunction tf = cast(TypeFunction)exp.f.type;
4932                 const(char)* failMessage;
4933                 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4934                 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4935                 {
4936                     OutBuffer buf;
4937                     buf.writeByte('(');
4938                     argExpTypesToCBuffer(&buf, exp.arguments);
4939                     buf.writeByte(')');
4940 
4941                     //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4942                     .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4943                         exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4944                     if (failMessage)
4945                         errorSupplemental(exp.loc, "%s", failMessage);
4946                     exp.f = null;
4947                 }
4948             }
4949             if (!exp.f || exp.f.errors)
4950                 return setError();
4951 
4952             if (exp.f.needThis())
4953             {
4954                 // Change the ancestor lambdas to delegate before hasThis(sc) call.
4955                 if (exp.f.checkNestedReference(sc, exp.loc))
4956                     return setError();
4957 
4958                 if (hasThis(sc))
4959                 {
4960                     // Supply an implicit 'this', as in
4961                     //    this.ident
4962                     exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
4963                     // Note: we cannot use f directly, because further overload resolution
4964                     // through the supplied 'this' may cause different result.
4965                     goto Lagain;
4966                 }
4967                 else if (isNeedThisScope(sc, exp.f))
4968                 {
4969                     exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4970                     return setError();
4971                 }
4972             }
4973 
4974             checkFunctionAttributes(exp, sc, exp.f);
4975             checkAccess(exp.loc, sc, null, exp.f);
4976             if (exp.f.checkNestedReference(sc, exp.loc))
4977                 return setError();
4978 
4979             ethis = null;
4980             tthis = null;
4981 
4982             if (ve.hasOverloads)
4983             {
4984                 exp.e1 = new VarExp(ve.loc, exp.f, false);
4985                 exp.e1.type = exp.f.type;
4986             }
4987             t1 = exp.f.type;
4988         }
4989         assert(t1.ty == Tfunction);
4990 
4991         Expression argprefix;
4992         if (!exp.arguments)
4993             exp.arguments = new Expressions();
4994         if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
4995             return setError();
4996 
4997         if (!exp.type)
4998         {
4999             exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5000                         // avoid recursive expression printing
5001             exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5002             return setError();
5003         }
5004 
5005         if (exp.f && exp.f.tintro)
5006         {
5007             Type t = exp.type;
5008             int offset = 0;
5009             TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5010             if (tf.next.isBaseOf(t, &offset) && offset)
5011             {
5012                 exp.type = tf.next;
5013                 result = Expression.combine(argprefix, exp.castTo(sc, t));
5014                 return;
5015             }
5016         }
5017 
5018         // Handle the case of a direct lambda call
5019         if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5020         {
5021             exp.f.tookAddressOf = 0;
5022         }
5023 
5024         result = Expression.combine(argprefix, exp);
5025 
5026         if (isSuper)
5027         {
5028             auto ad = sc.func ? sc.func.isThis() : null;
5029             auto cd = ad ? ad.isClassDeclaration() : null;
5030             if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5031             {
5032                 // if super is defined in C++, it sets the vtable pointer to the base class
5033                 // so we have to restore it, but still return 'this' from super() call:
5034                 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5035                 Loc loc = exp.loc;
5036 
5037                 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5038                 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5039                 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5040 
5041                 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5042                 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5043 
5044                 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5045 
5046                 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5047 
5048                 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5049                 result = e.expressionSemantic(sc);
5050             }
5051         }
5052 
5053         // declare dual-context container
5054         if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func)
5055         {
5056             // check access to second `this`
5057             if (AggregateDeclaration ad2 = exp.f.isMember2())
5058             {
5059                 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5060                 if (te.op != TOK.error)
5061                     te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5062                 if (te.op == TOK.error)
5063                 {
5064                     exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5065                     return setError();
5066                 }
5067             }
5068             VarDeclaration vthis2 = makeThis2Argument(exp.loc, sc, exp.f);            exp.vthis2 = vthis2;
5069             Expression de = new DeclarationExp(exp.loc, vthis2);
5070             result = Expression.combine(de, result);
5071             result = result.expressionSemantic(sc);
5072         }
5073     }
5074 
5075     override void visit(DeclarationExp e)
5076     {
5077         if (e.type)
5078         {
5079             result = e;
5080             return;
5081         }
5082         static if (LOGSEMANTIC)
5083         {
5084             printf("DeclarationExp::semantic() %s\n", e.toChars());
5085         }
5086 
5087         uint olderrors = global.errors;
5088 
5089         /* This is here to support extern(linkage) declaration,
5090          * where the extern(linkage) winds up being an AttribDeclaration
5091          * wrapper.
5092          */
5093         Dsymbol s = e.declaration;
5094 
5095         while (1)
5096         {
5097             AttribDeclaration ad = s.isAttribDeclaration();
5098             if (ad)
5099             {
5100                 if (ad.decl && ad.decl.dim == 1)
5101                 {
5102                     s = (*ad.decl)[0];
5103                     continue;
5104                 }
5105             }
5106             break;
5107         }
5108 
5109         VarDeclaration v = s.isVarDeclaration();
5110         if (v)
5111         {
5112             // Do semantic() on initializer first, so:
5113             //      int a = a;
5114             // will be illegal.
5115             e.declaration.dsymbolSemantic(sc);
5116             s.parent = sc.parent;
5117         }
5118 
5119         //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5120         // Insert into both local scope and function scope.
5121         // Must be unique in both.
5122         if (s.ident)
5123         {
5124             if (!sc.insert(s))
5125             {
5126                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5127                 return setError();
5128             }
5129             else if (sc.func)
5130             {
5131                 // https://issues.dlang.org/show_bug.cgi?id=11720
5132                 // include Dataseg variables
5133                 if ((s.isFuncDeclaration() ||
5134                      s.isAggregateDeclaration() ||
5135                      s.isEnumDeclaration() ||
5136                      v && v.isDataseg()) && !sc.func.localsymtab.insert(s))
5137                 {
5138                     // https://issues.dlang.org/show_bug.cgi?id=18266
5139                     // set parent so that type semantic does not assert
5140                     s.parent = sc.parent;
5141                     Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5142                     assert(originalSymbol);
5143                     e.error("declaration `%s` is already defined in another scope in `%s` at line `%d`", s.toPrettyChars(), sc.func.toChars(), originalSymbol.loc.linnum);
5144                     return setError();
5145                 }
5146                 else
5147                 {
5148                     // Disallow shadowing
5149                     for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (scx.func && sc.func.fes)); scx = scx.enclosing)
5150                     {
5151                         Dsymbol s2;
5152                         if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5153                         {
5154                             // allow STC.local symbols to be shadowed
5155                             // TODO: not really an optimal design
5156                             auto decl = s2.isDeclaration();
5157                             if (!decl || !(decl.storage_class & STC.local))
5158                             {
5159                                 if (sc.func.fes)
5160                                 {
5161                                     e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5162                                 }
5163                                 else
5164                                 {
5165                                     e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5166                                     return setError();
5167                                 }
5168                             }
5169                         }
5170                     }
5171                 }
5172             }
5173         }
5174         if (!s.isVarDeclaration())
5175         {
5176             Scope* sc2 = sc;
5177             if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5178                 sc2 = sc.push();
5179             sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5180             e.declaration.dsymbolSemantic(sc2);
5181             if (sc2 != sc)
5182                 sc2.pop();
5183             s.parent = sc.parent;
5184         }
5185         if (global.errors == olderrors)
5186         {
5187             e.declaration.semantic2(sc);
5188             if (global.errors == olderrors)
5189             {
5190                 e.declaration.semantic3(sc);
5191             }
5192         }
5193         // todo: error in declaration should be propagated.
5194 
5195         e.type = Type.tvoid;
5196         result = e;
5197     }
5198 
5199     override void visit(TypeidExp exp)
5200     {
5201         static if (LOGSEMANTIC)
5202         {
5203             printf("TypeidExp::semantic() %s\n", exp.toChars());
5204         }
5205         Type ta = isType(exp.obj);
5206         Expression ea = isExpression(exp.obj);
5207         Dsymbol sa = isDsymbol(exp.obj);
5208         //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5209 
5210         if (ta)
5211         {
5212             dmd.typesem.resolve(ta, exp.loc, sc, &ea, &ta, &sa, true);
5213         }
5214 
5215         if (ea)
5216         {
5217             if (auto sym = getDsymbol(ea))
5218                 ea = symbolToExp(sym, exp.loc, sc, false);
5219             else
5220                 ea = ea.expressionSemantic(sc);
5221             ea = resolveProperties(sc, ea);
5222             ta = ea.type;
5223             if (ea.op == TOK.type)
5224                 ea = null;
5225         }
5226 
5227         if (!ta)
5228         {
5229             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5230             exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5231             return setError();
5232         }
5233 
5234         if (global.params.vcomplex)
5235             ta.checkComplexTransition(exp.loc, sc);
5236 
5237         Expression e;
5238         auto tb = ta.toBasetype();
5239         if (ea && tb.ty == Tclass)
5240         {
5241             if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5242             {
5243                 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
5244                 e = new ErrorExp();
5245             }
5246             else if (!Type.typeinfoclass)
5247             {
5248                 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5249                 e = new ErrorExp();
5250             }
5251             else
5252             {
5253                 /* Get the dynamic type, which is .classinfo
5254                 */
5255                 ea = ea.expressionSemantic(sc);
5256                 e = new TypeidExp(ea.loc, ea);
5257                 e.type = Type.typeinfoclass.type;
5258             }
5259         }
5260         else if (ta.ty == Terror)
5261         {
5262             e = new ErrorExp();
5263         }
5264         else
5265         {
5266             // Handle this in the glue layer
5267             e = new TypeidExp(exp.loc, ta);
5268             e.type = getTypeInfoType(exp.loc, ta, sc);
5269 
5270             semanticTypeInfo(sc, ta);
5271 
5272             if (ea)
5273             {
5274                 e = new CommaExp(exp.loc, ea, e); // execute ea
5275                 e = e.expressionSemantic(sc);
5276             }
5277         }
5278         result = e;
5279     }
5280 
5281     override void visit(TraitsExp e)
5282     {
5283         result = semanticTraits(e, sc);
5284     }
5285 
5286     override void visit(HaltExp e)
5287     {
5288         static if (LOGSEMANTIC)
5289         {
5290             printf("HaltExp::semantic()\n");
5291         }
5292         e.type = Type.tvoid;
5293         result = e;
5294     }
5295 
5296     override void visit(IsExp e)
5297     {
5298         /* is(targ id tok tspec)
5299          * is(targ id :  tok2)
5300          * is(targ id == tok2)
5301          */
5302         static if (LOGSEMANTIC)
5303         {
5304             printf("IsExp::semantic(%s)\n", e.toChars());
5305         }
5306         if (e.id && !(sc.flags & SCOPE.condition))
5307         {
5308             e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5309             return setError();
5310         }
5311 
5312         Type tded = null;
5313         if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5314         {
5315             const oldErrors = global.startGagging();
5316             Dsymbol sym = e.targ.toDsymbol(sc);
5317             global.endGagging(oldErrors);
5318 
5319             if (sym is null)
5320                 goto Lno;
5321             Package p = resolveIsPackage(sym);
5322             if (p is null)
5323                 goto Lno;
5324             if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5325                 goto Lno;
5326             else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5327                 goto Lno;
5328             tded = e.targ;
5329             goto Lyes;
5330         }
5331 
5332         {
5333             Scope* sc2 = sc.copy(); // keep sc.flags
5334             sc2.tinst = null;
5335             sc2.minst = null;
5336             sc2.flags |= SCOPE.fullinst;
5337             Type t = e.targ.trySemantic(e.loc, sc2);
5338             sc2.pop();
5339             if (!t) // errors, so condition is false
5340                 goto Lno;
5341             e.targ = t;
5342         }
5343 
5344         if (e.tok2 != TOK.reserved)
5345         {
5346             switch (e.tok2)
5347             {
5348             case TOK.struct_:
5349                 if (e.targ.ty != Tstruct)
5350                     goto Lno;
5351                 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5352                     goto Lno;
5353                 tded = e.targ;
5354                 break;
5355 
5356             case TOK.union_:
5357                 if (e.targ.ty != Tstruct)
5358                     goto Lno;
5359                 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5360                     goto Lno;
5361                 tded = e.targ;
5362                 break;
5363 
5364             case TOK.class_:
5365                 if (e.targ.ty != Tclass)
5366                     goto Lno;
5367                 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5368                     goto Lno;
5369                 tded = e.targ;
5370                 break;
5371 
5372             case TOK.interface_:
5373                 if (e.targ.ty != Tclass)
5374                     goto Lno;
5375                 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5376                     goto Lno;
5377                 tded = e.targ;
5378                 break;
5379 
5380             case TOK.const_:
5381                 if (!e.targ.isConst())
5382                     goto Lno;
5383                 tded = e.targ;
5384                 break;
5385 
5386             case TOK.immutable_:
5387                 if (!e.targ.isImmutable())
5388                     goto Lno;
5389                 tded = e.targ;
5390                 break;
5391 
5392             case TOK.shared_:
5393                 if (!e.targ.isShared())
5394                     goto Lno;
5395                 tded = e.targ;
5396                 break;
5397 
5398             case TOK.inout_:
5399                 if (!e.targ.isWild())
5400                     goto Lno;
5401                 tded = e.targ;
5402                 break;
5403 
5404             case TOK.super_:
5405                 // If class or interface, get the base class and interfaces
5406                 if (e.targ.ty != Tclass)
5407                     goto Lno;
5408                 else
5409                 {
5410                     ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5411                     auto args = new Parameters();
5412                     args.reserve(cd.baseclasses.dim);
5413                     if (cd.semanticRun < PASS.semanticdone)
5414                         cd.dsymbolSemantic(null);
5415                     for (size_t i = 0; i < cd.baseclasses.dim; i++)
5416                     {
5417                         BaseClass* b = (*cd.baseclasses)[i];
5418                         args.push(new Parameter(STC.in_, b.type, null, null, null));
5419                     }
5420                     tded = new TypeTuple(args);
5421                 }
5422                 break;
5423 
5424             case TOK.enum_:
5425                 if (e.targ.ty != Tenum)
5426                     goto Lno;
5427                 if (e.id)
5428                     tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5429                 else
5430                     tded = e.targ;
5431 
5432                 if (tded.ty == Terror)
5433                     return setError();
5434                 break;
5435 
5436             case TOK.delegate_:
5437                 if (e.targ.ty != Tdelegate)
5438                     goto Lno;
5439                 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5440                 break;
5441 
5442             case TOK.function_:
5443             case TOK.parameters:
5444                 {
5445                     if (e.targ.ty != Tfunction)
5446                         goto Lno;
5447                     tded = e.targ;
5448 
5449                     /* Generate tuple from function parameter types.
5450                      */
5451                     assert(tded.ty == Tfunction);
5452                     auto tdedf = tded.isTypeFunction();
5453                     size_t dim = tdedf.parameterList.length;
5454                     auto args = new Parameters();
5455                     args.reserve(dim);
5456                     for (size_t i = 0; i < dim; i++)
5457                     {
5458                         Parameter arg = tdedf.parameterList[i];
5459                         assert(arg && arg.type);
5460                         /* If one of the default arguments was an error,
5461                            don't return an invalid tuple
5462                          */
5463                         if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error)
5464                             return setError();
5465                         args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5466                     }
5467                     tded = new TypeTuple(args);
5468                     break;
5469                 }
5470             case TOK.return_:
5471                 /* Get the 'return type' for the function,
5472                  * delegate, or pointer to function.
5473                  */
5474                 if (e.targ.ty == Tfunction)
5475                     tded = (cast(TypeFunction)e.targ).next;
5476                 else if (e.targ.ty == Tdelegate)
5477                 {
5478                     tded = (cast(TypeDelegate)e.targ).next;
5479                     tded = (cast(TypeFunction)tded).next;
5480                 }
5481                 else if (e.targ.ty == Tpointer && (cast(TypePointer)e.targ).next.ty == Tfunction)
5482                 {
5483                     tded = (cast(TypePointer)e.targ).next;
5484                     tded = (cast(TypeFunction)tded).next;
5485                 }
5486                 else
5487                     goto Lno;
5488                 break;
5489 
5490             case TOK.argumentTypes:
5491                 /* Generate a type tuple of the equivalent types used to determine if a
5492                  * function argument of this type can be passed in registers.
5493                  * The results of this are highly platform dependent, and intended
5494                  * primarly for use in implementing va_arg().
5495                  */
5496                 tded = target.toArgTypes(e.targ);
5497                 if (!tded)
5498                     goto Lno;
5499                 // not valid for a parameter
5500                 break;
5501 
5502             case TOK.vector:
5503                 if (e.targ.ty != Tvector)
5504                     goto Lno;
5505                 tded = (cast(TypeVector)e.targ).basetype;
5506                 break;
5507 
5508             default:
5509                 assert(0);
5510             }
5511 
5512             // https://issues.dlang.org/show_bug.cgi?id=18753
5513             if (tded)
5514                 goto Lyes;
5515             goto Lno;
5516         }
5517         else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
5518         {
5519             /* Evaluate to true if targ matches tspec
5520              * is(targ == tspec)
5521              * is(targ : tspec)
5522              */
5523             e.tspec = e.tspec.typeSemantic(e.loc, sc);
5524             //printf("targ  = %s, %s\n", targ.toChars(), targ.deco);
5525             //printf("tspec = %s, %s\n", tspec.toChars(), tspec.deco);
5526 
5527             if (e.tok == TOK.colon)
5528             {
5529                 if (e.targ.implicitConvTo(e.tspec))
5530                     goto Lyes;
5531                 else
5532                     goto Lno;
5533             }
5534             else /* == */
5535             {
5536                 if (e.targ.equals(e.tspec))
5537                     goto Lyes;
5538                 else
5539                     goto Lno;
5540             }
5541         }
5542         else if (e.tspec)
5543         {
5544             /* Evaluate to true if targ matches tspec.
5545              * If true, declare id as an alias for the specialized type.
5546              * is(targ == tspec, tpl)
5547              * is(targ : tspec, tpl)
5548              * is(targ id == tspec)
5549              * is(targ id : tspec)
5550              * is(targ id == tspec, tpl)
5551              * is(targ id : tspec, tpl)
5552              */
5553             Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5554             e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5555 
5556             Objects dedtypes = Objects(e.parameters.dim);
5557             dedtypes.zero();
5558 
5559             MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5560             //printf("targ: %s\n", targ.toChars());
5561             //printf("tspec: %s\n", tspec.toChars());
5562             if (m <= MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5563             {
5564                 goto Lno;
5565             }
5566             else
5567             {
5568                 tded = cast(Type)dedtypes[0];
5569                 if (!tded)
5570                     tded = e.targ;
5571                 Objects tiargs = Objects(1);
5572                 tiargs[0] = e.targ;
5573 
5574                 /* Declare trailing parameters
5575                  */
5576                 for (size_t i = 1; i < e.parameters.dim; i++)
5577                 {
5578                     TemplateParameter tp = (*e.parameters)[i];
5579                     Declaration s = null;
5580 
5581                     m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5582                     if (m <= MATCH.nomatch)
5583                         goto Lno;
5584                     s.dsymbolSemantic(sc);
5585                     if (!sc.insert(s))
5586                         e.error("declaration `%s` is already defined", s.toChars());
5587 
5588                     unSpeculative(sc, s);
5589                 }
5590                 goto Lyes;
5591             }
5592         }
5593         else if (e.id)
5594         {
5595             /* Declare id as an alias for type targ. Evaluate to true
5596              * is(targ id)
5597              */
5598             tded = e.targ;
5599             goto Lyes;
5600         }
5601 
5602     Lyes:
5603         if (e.id)
5604         {
5605             Dsymbol s;
5606             Tuple tup = isTuple(tded);
5607             if (tup)
5608                 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5609             else
5610                 s = new AliasDeclaration(e.loc, e.id, tded);
5611             s.dsymbolSemantic(sc);
5612 
5613             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5614              * More investigation is needed.
5615              */
5616             if (!tup && !sc.insert(s))
5617                 e.error("declaration `%s` is already defined", s.toChars());
5618 
5619             unSpeculative(sc, s);
5620         }
5621         //printf("Lyes\n");
5622         result = IntegerExp.createBool(true);
5623         return;
5624 
5625     Lno:
5626         //printf("Lno\n");
5627         result = IntegerExp.createBool(false);
5628     }
5629 
5630     override void visit(BinAssignExp exp)
5631     {
5632         if (exp.type)
5633         {
5634             result = exp;
5635             return;
5636         }
5637 
5638         Expression e = exp.op_overload(sc);
5639         if (e)
5640         {
5641             result = e;
5642             return;
5643         }
5644 
5645         if (checkIfIsStructLiteralDotExpr(exp.e1))
5646             return setError();
5647         if (exp.e1.op == TOK.arrayLength)
5648         {
5649             // arr.length op= e2;
5650             e = rewriteOpAssign(exp);
5651             e = e.expressionSemantic(sc);
5652             result = e;
5653             return;
5654         }
5655         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5656         {
5657             if (checkNonAssignmentArrayOp(exp.e1))
5658                 return setError();
5659 
5660             if (exp.e1.op == TOK.slice)
5661                 (cast(SliceExp)exp.e1).arrayop = true;
5662 
5663             // T[] op= ...
5664             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5665             {
5666                 // T[] op= T
5667                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5668             }
5669             else if (Expression ex = typeCombine(exp, sc))
5670             {
5671                 result = ex;
5672                 return;
5673             }
5674             exp.type = exp.e1.type;
5675             result = arrayOp(exp, sc);
5676             return;
5677         }
5678 
5679         exp.e1 = exp.e1.expressionSemantic(sc);
5680         exp.e1 = exp.e1.optimize(WANTvalue);
5681         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5682         exp.type = exp.e1.type;
5683 
5684         if (auto ad = isAggregate(exp.e1.type))
5685         {
5686             if (const s = search_function(ad, Id.opOpAssign))
5687             {
5688                 error(exp.loc, "none of the `opOpAssign` overloads of `%s` are callable for `%s` of type `%s`", ad.toChars(), exp.e1.toChars(), exp.e1.type.toChars());
5689                 return setError();
5690             }
5691         }
5692         if (exp.e1.checkScalar() ||
5693             exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5694             exp.e1.checkSharedAccess(sc))
5695             return setError();
5696 
5697         int arith = (exp.op == TOK.addAssign || exp.op == TOK.minAssign || exp.op == TOK.mulAssign || exp.op == TOK.divAssign || exp.op == TOK.modAssign || exp.op == TOK.powAssign);
5698         int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign);
5699         int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign);
5700 
5701         if (bitwise && exp.type.toBasetype().ty == Tbool)
5702             exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5703         else if (exp.checkNoBool())
5704             return setError();
5705 
5706         if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5707         {
5708             result = scaleFactor(exp, sc);
5709             return;
5710         }
5711 
5712         if (Expression ex = typeCombine(exp, sc))
5713         {
5714             result = ex;
5715             return;
5716         }
5717 
5718         if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5719             return setError();
5720         if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5721             return setError();
5722 
5723         if (shift)
5724         {
5725             if (exp.e2.type.toBasetype().ty != Tvector)
5726                 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5727         }
5728 
5729         if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5730         {
5731             result = exp.incompatibleTypes();
5732             return;
5733         }
5734 
5735         if (exp.e1.op == TOK.error || exp.e2.op == TOK.error)
5736             return setError();
5737 
5738         e = exp.checkOpAssignTypes(sc);
5739         if (e.op == TOK.error)
5740         {
5741             result = e;
5742             return;
5743         }
5744 
5745         assert(e.op == TOK.assign || e == exp);
5746         result = (cast(BinExp)e).reorderSettingAAElem(sc);
5747     }
5748 
5749     private Expression compileIt(CompileExp exp)
5750     {
5751         OutBuffer buf;
5752         if (expressionsToString(buf, sc, exp.exps))
5753             return null;
5754 
5755         uint errors = global.errors;
5756         const len = buf.length;
5757         const str = buf.extractChars()[0 .. len];
5758         scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
5759         p.nextToken();
5760         //printf("p.loc.linnum = %d\n", p.loc.linnum);
5761 
5762         Expression e = p.parseExpression();
5763         p.reportDiagnostics();
5764         if (global.errors != errors)
5765             return null;
5766 
5767         if (p.token.value != TOK.endOfFile)
5768         {
5769             exp.error("incomplete mixin expression `%s`", str.ptr);
5770             return null;
5771         }
5772         return e;
5773     }
5774 
5775     override void visit(CompileExp exp)
5776     {
5777         /* https://dlang.org/spec/expression.html#mixin_expressions
5778          */
5779 
5780         static if (LOGSEMANTIC)
5781         {
5782             printf("CompileExp::semantic('%s')\n", exp.toChars());
5783         }
5784 
5785         auto e = compileIt(exp);
5786         if (!e)
5787             return setError();
5788         result = e.expressionSemantic(sc);
5789     }
5790 
5791     override void visit(ImportExp e)
5792     {
5793         static if (LOGSEMANTIC)
5794         {
5795             printf("ImportExp::semantic('%s')\n", e.toChars());
5796         }
5797 
5798         auto se = semanticString(sc, e.e1, "file name argument");
5799         if (!se)
5800             return setError();
5801         se = se.toUTF8(sc);
5802 
5803         auto namez = se.toStringz().ptr;
5804         if (!global.filePath)
5805         {
5806             e.error("need `-J` switch to import text file `%s`", namez);
5807             return setError();
5808         }
5809 
5810         /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5811          * ('Path Traversal') attacks.
5812          * http://cwe.mitre.org/data/definitions/22.html
5813          */
5814 
5815         auto name = FileName.safeSearchPath(global.filePath, namez);
5816         if (!name)
5817         {
5818             e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
5819             return setError();
5820         }
5821 
5822         sc._module.contentImportedFiles.push(name);
5823         if (global.params.verbose)
5824         {
5825             const slice = se.peekString();
5826             message("file      %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
5827         }
5828         if (global.params.moduleDeps !is null)
5829         {
5830             OutBuffer* ob = global.params.moduleDeps;
5831             Module imod = sc.instantiatingModule();
5832 
5833             if (!global.params.moduleDepsFile)
5834                 ob.writestring("depsFile ");
5835             ob.writestring(imod.toPrettyChars());
5836             ob.writestring(" (");
5837             escapePath(ob, imod.srcfile.toChars());
5838             ob.writestring(") : ");
5839             if (global.params.moduleDepsFile)
5840                 ob.writestring("string : ");
5841             ob.write(se.peekString());
5842             ob.writestring(" (");
5843             escapePath(ob, name);
5844             ob.writestring(")");
5845             ob.writenl();
5846         }
5847 
5848         {
5849             auto readResult = File.read(name);
5850             if (!readResult.success)
5851             {
5852                 e.error("cannot read file `%s`", name);
5853                 return setError();
5854             }
5855             else
5856             {
5857                 // take ownership of buffer (probably leaking)
5858                 auto data = readResult.extractSlice();
5859                 se = new StringExp(e.loc, data);
5860             }
5861         }
5862         result = se.expressionSemantic(sc);
5863     }
5864 
5865     override void visit(AssertExp exp)
5866     {
5867         // https://dlang.org/spec/expression.html#assert_expressions
5868         static if (LOGSEMANTIC)
5869         {
5870             printf("AssertExp::semantic('%s')\n", exp.toChars());
5871         }
5872 
5873         const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context;
5874         Expression temporariesPrefix;
5875 
5876         if (generateMsg)
5877         // no message - use assert expression as msg
5878         {
5879             /*
5880             {
5881               auto a = e1, b = e2;
5882               assert(a == b, _d_assert_fail!"=="(a, b));
5883             }()
5884             */
5885 
5886             /*
5887             Stores the result of an operand expression into a temporary
5888             if necessary, e.g. if it is an impure fuction call containing side
5889             effects as in https://issues.dlang.org/show_bug.cgi?id=20114
5890 
5891             Params:
5892                 op = an expression which may require a temporary (added to
5893                      `temporariesPrefix`: `auto tmp = op`) and will be replaced
5894                      by `tmp` if necessary
5895 
5896             Returns: (possibly replaced) `op`
5897             */
5898             Expression maybePromoteToTmp(ref Expression op)
5899             {
5900                 op = op.expressionSemantic(sc);
5901                 op = resolveProperties(sc, op);
5902                 if (op.hasSideEffect)
5903                 {
5904                     const stc = op.isLvalue() ? STC.ref_ : 0;
5905                     auto tmp = copyToTemp(stc, "__assertOp", op);
5906                     tmp.dsymbolSemantic(sc);
5907 
5908                     auto decl = new DeclarationExp(op.loc, tmp);
5909                     temporariesPrefix = Expression.combine(temporariesPrefix, decl);
5910 
5911                     op = new VarExp(op.loc, tmp);
5912                     op = op.expressionSemantic(sc);
5913                 }
5914                 return op;
5915             }
5916 
5917             // if the assert condition is a mixin expression, try to compile it
5918             if (auto ce = exp.e1.isCompileExp())
5919             {
5920                 if (auto e1 = compileIt(ce))
5921                     exp.e1 = e1;
5922             }
5923 
5924             const tok = exp.e1.op;
5925             bool isEqualsCallExpression;
5926             if (tok == TOK.call)
5927             {
5928                 const callExp = cast(CallExp) exp.e1;
5929 
5930                 // https://issues.dlang.org/show_bug.cgi?id=20331
5931                 // callExp.f may be null if the assert contains a call to
5932                 // a function pointer or literal
5933                 if (const callExpFunc = callExp.f)
5934                 {
5935                     const callExpIdent = callExpFunc.ident;
5936                     isEqualsCallExpression = callExpIdent == Id.__equals ||
5937                                              callExpIdent == Id.eq;
5938                 }
5939             }
5940             if (tok == TOK.equal || tok == TOK.notEqual ||
5941                 tok == TOK.lessThan || tok == TOK.greaterThan ||
5942                 tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual ||
5943                 tok == TOK.identity || tok == TOK.notIdentity ||
5944                 tok == TOK.in_ ||
5945                 isEqualsCallExpression)
5946             {
5947                 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
5948                     return setError();
5949 
5950                 auto es = new Expressions(2);
5951                 auto tiargs = new Objects(3);
5952                 Loc loc = exp.e1.loc;
5953 
5954                 if (isEqualsCallExpression)
5955                 {
5956                     auto callExp = cast(CallExp) exp.e1;
5957                     auto args = callExp.arguments;
5958 
5959                     // structs with opEquals get rewritten to a DotVarExp:
5960                     // a.opEquals(b)
5961                     // https://issues.dlang.org/show_bug.cgi?id=20100
5962                     if (args.length == 1)
5963                     {
5964                         auto dv = callExp.e1.isDotVarExp();
5965                         assert(dv);
5966 
5967                         // runtime args
5968                         (*es)[0] = maybePromoteToTmp(dv.e1);
5969                         (*es)[1] = maybePromoteToTmp((*args)[0]);
5970                     }
5971                     else
5972                     {
5973                         // runtime args
5974                         (*es)[0] = maybePromoteToTmp((*args)[0]);
5975                         (*es)[1] = maybePromoteToTmp((*args)[1]);
5976                     }
5977                 }
5978                 else
5979                 {
5980                     auto binExp = cast(EqualExp) exp.e1;
5981 
5982                     // runtime args
5983                     (*es)[0] = maybePromoteToTmp(binExp.e1);
5984                     (*es)[1] = maybePromoteToTmp(binExp.e2);
5985                 }
5986 
5987                 // template args
5988                 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op));
5989                 comp = comp.expressionSemantic(sc);
5990                 (*tiargs)[0] = comp;
5991                 (*tiargs)[1] = (*es)[0].type;
5992                 (*tiargs)[2] = (*es)[1].type;
5993 
5994                 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
5995                 auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
5996 
5997                 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
5998                 auto ec = CallExp.create(Loc.initial, dt, es);
5999                 exp.msg = ec;
6000             }
6001             else
6002             {
6003                 OutBuffer buf;
6004                 buf.printf("%s failed", exp.toChars());
6005                 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6006             }
6007         }
6008 
6009         if (Expression ex = unaSemantic(exp, sc))
6010         {
6011             result = ex;
6012             return;
6013         }
6014 
6015         exp.e1 = resolveProperties(sc, exp.e1);
6016         // BUG: see if we can do compile time elimination of the Assert
6017         exp.e1 = exp.e1.optimize(WANTvalue);
6018         exp.e1 = exp.e1.toBoolean(sc);
6019 
6020         if (exp.msg)
6021         {
6022             exp.msg = expressionSemantic(exp.msg, sc);
6023             exp.msg = resolveProperties(sc, exp.msg);
6024             exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6025             exp.msg = exp.msg.optimize(WANTvalue);
6026             checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
6027         }
6028 
6029         if (exp.e1.op == TOK.error)
6030         {
6031             result = exp.e1;
6032             return;
6033         }
6034         if (exp.msg && exp.msg.op == TOK.error)
6035         {
6036             result = exp.msg;
6037             return;
6038         }
6039 
6040         auto f1 = checkNonAssignmentArrayOp(exp.e1);
6041         auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6042         if (f1 || f2)
6043             return setError();
6044 
6045         if (exp.e1.isBool(false))
6046         {
6047             /* This is an `assert(0)` which means halt program execution
6048              */
6049             FuncDeclaration fd = sc.parent.isFuncDeclaration();
6050             if (fd)
6051                 fd.hasReturnExp |= 4;
6052             sc.ctorflow.orCSX(CSX.halt);
6053 
6054             if (global.params.useAssert == CHECKENABLE.off)
6055             {
6056                 Expression e = new HaltExp(exp.loc);
6057                 e = e.expressionSemantic(sc);
6058                 result = e;
6059                 return;
6060             }
6061         }
6062 
6063         exp.type = Type.tvoid;
6064 
6065         result = !temporariesPrefix
6066             ? exp
6067             : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6068     }
6069 
6070     override void visit(DotIdExp exp)
6071     {
6072         static if (LOGSEMANTIC)
6073         {
6074             printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6075             //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
6076         }
6077         Expression e = exp.semanticY(sc, 1);
6078         if (e && isDotOpDispatch(e))
6079         {
6080             uint errors = global.startGagging();
6081             e = resolvePropertiesX(sc, e);
6082             if (global.endGagging(errors))
6083                 e = null; /* fall down to UFCS */
6084             else
6085             {
6086                 result = e;
6087                 return;
6088             }
6089         }
6090         if (!e) // if failed to find the property
6091         {
6092             /* If ident is not a valid property, rewrite:
6093              *   e1.ident
6094              * as:
6095              *   .ident(e1)
6096              */
6097             e = resolveUFCSProperties(sc, exp);
6098         }
6099         result = e;
6100     }
6101 
6102     override void visit(DotTemplateExp e)
6103     {
6104         if (Expression ex = unaSemantic(e, sc))
6105         {
6106             result = ex;
6107             return;
6108         }
6109         result = e;
6110     }
6111 
6112     override void visit(DotVarExp exp)
6113     {
6114         static if (LOGSEMANTIC)
6115         {
6116             printf("DotVarExp::semantic('%s')\n", exp.toChars());
6117         }
6118         if (exp.type)
6119         {
6120             result = exp;
6121             return;
6122         }
6123 
6124         exp.var = exp.var.toAlias().isDeclaration();
6125 
6126         exp.e1 = exp.e1.expressionSemantic(sc);
6127 
6128         if (auto tup = exp.var.isTupleDeclaration())
6129         {
6130             /* Replace:
6131              *  e1.tuple(a, b, c)
6132              * with:
6133              *  tuple(e1.a, e1.b, e1.c)
6134              */
6135             Expression e0;
6136             Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6137 
6138             auto exps = new Expressions();
6139             exps.reserve(tup.objects.dim);
6140             for (size_t i = 0; i < tup.objects.dim; i++)
6141             {
6142                 RootObject o = (*tup.objects)[i];
6143                 Expression e;
6144                 Declaration var;
6145                 if (o.dyncast() == DYNCAST.expression)
6146                 {
6147                     e = cast(Expression)o;
6148                     if (auto se = e.isDsymbolExp())
6149                         var = se.s.isDeclaration();
6150                     else if (auto ve = e.isVarExp())
6151                         if (!ve.var.isFuncDeclaration())
6152                             // Exempt functions for backwards compatibility reasons.
6153                             // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6154                             var = ve.var;
6155                 }
6156                 else if (o.dyncast() == DYNCAST.dsymbol)
6157                 {
6158                     Dsymbol s = cast(Dsymbol) o;
6159                     Declaration d = s.isDeclaration();
6160                     if (!d || d.isFuncDeclaration())
6161                         // Exempt functions for backwards compatibility reasons.
6162                         // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6163                         e = new DsymbolExp(exp.loc, s);
6164                     else
6165                         var = d;
6166                 }
6167                 else if (o.dyncast() == DYNCAST.type)
6168                 {
6169                     e = new TypeExp(exp.loc, cast(Type)o);
6170                 }
6171                 else
6172                 {
6173                     exp.error("`%s` is not an expression", o.toChars());
6174                     return setError();
6175                 }
6176                 if (var)
6177                     e = new DotVarExp(exp.loc, ev, var);
6178                 exps.push(e);
6179             }
6180 
6181             Expression e = new TupleExp(exp.loc, e0, exps);
6182             e = e.expressionSemantic(sc);
6183             result = e;
6184             return;
6185         }
6186 
6187         exp.e1 = exp.e1.addDtorHook(sc);
6188 
6189         Type t1 = exp.e1.type;
6190 
6191         if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6192         {
6193             // for functions, do checks after overload resolution
6194             if (!fd.functionSemantic())
6195                 return setError();
6196 
6197             /* https://issues.dlang.org/show_bug.cgi?id=13843
6198              * If fd obviously has no overloads, we should
6199              * normalize AST, and it will give a chance to wrap fd with FuncExp.
6200              */
6201             if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6202             {
6203                 // (e1, fd)
6204                 auto e = symbolToExp(fd, exp.loc, sc, false);
6205                 result = Expression.combine(exp.e1, e);
6206                 return;
6207             }
6208 
6209             exp.type = fd.type;
6210             assert(exp.type);
6211         }
6212         else if (OverDeclaration od = exp.var.isOverDeclaration())
6213         {
6214             exp.type = Type.tvoid; // ambiguous type?
6215         }
6216         else
6217         {
6218             exp.type = exp.var.type;
6219             if (!exp.type && global.errors) // var is goofed up, just return error.
6220                 return setError();
6221             assert(exp.type);
6222 
6223             if (t1.ty == Tpointer)
6224                 t1 = t1.nextOf();
6225 
6226             exp.type = exp.type.addMod(t1.mod);
6227 
6228             Dsymbol vparent = exp.var.toParent();
6229             AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6230             if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6231                 exp.e1 = e1x;
6232             else
6233             {
6234                 /* Later checkRightThis will report correct error for invalid field variable access.
6235                  */
6236                 Expression e = new VarExp(exp.loc, exp.var);
6237                 e = e.expressionSemantic(sc);
6238                 result = e;
6239                 return;
6240             }
6241             checkAccess(exp.loc, sc, exp.e1, exp.var);
6242 
6243             VarDeclaration v = exp.var.isVarDeclaration();
6244             if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6245             {
6246                 Expression e = expandVar(WANTvalue, v);
6247                 if (e)
6248                 {
6249                     result = e;
6250                     return;
6251                 }
6252             }
6253 
6254             if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6255                       (!v.needThis() && v.semanticRun > PASS.init)))  // fix https://issues.dlang.org/show_bug.cgi?id=17258
6256             {
6257                 // (e1, v)
6258                 checkAccess(exp.loc, sc, exp.e1, v);
6259                 Expression e = new VarExp(exp.loc, v);
6260                 e = new CommaExp(exp.loc, exp.e1, e);
6261                 e = e.expressionSemantic(sc);
6262                 result = e;
6263                 return;
6264             }
6265         }
6266         //printf("-DotVarExp::semantic('%s')\n", toChars());
6267         result = exp;
6268     }
6269 
6270     override void visit(DotTemplateInstanceExp exp)
6271     {
6272         static if (LOGSEMANTIC)
6273         {
6274             printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6275         }
6276         // Indicate we need to resolve by UFCS.
6277         Expression e = exp.semanticY(sc, 1);
6278         if (!e)
6279             e = resolveUFCSProperties(sc, exp);
6280         result = e;
6281     }
6282 
6283     override void visit(DelegateExp e)
6284     {
6285         static if (LOGSEMANTIC)
6286         {
6287             printf("DelegateExp::semantic('%s')\n", e.toChars());
6288         }
6289         if (e.type)
6290         {
6291             result = e;
6292             return;
6293         }
6294 
6295         e.e1 = e.e1.expressionSemantic(sc);
6296 
6297         e.type = new TypeDelegate(e.func.type);
6298         e.type = e.type.typeSemantic(e.loc, sc);
6299 
6300         FuncDeclaration f = e.func.toAliasFunc();
6301         AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
6302         if (f.needThis())
6303             e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6304         if (e.e1.op == TOK.error)
6305             return setError();
6306 
6307         /* A delegate takes the address of e.e1 in order to set the .ptr field
6308          * https://issues.dlang.org/show_bug.cgi?id=18575
6309          */
6310         if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct)
6311         {
6312             if (auto v = expToVariable(e.e1))
6313             {
6314                 if (!checkAddressVar(sc, e, v))
6315                     return setError();
6316             }
6317         }
6318 
6319         if (f.type.ty == Tfunction)
6320         {
6321             TypeFunction tf = cast(TypeFunction)f.type;
6322             if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6323             {
6324                 OutBuffer thisBuf, funcBuf;
6325                 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6326                 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6327                 e.error("%smethod `%s` is not callable using a %s`%s`",
6328                     funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6329                 return setError();
6330             }
6331         }
6332         if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6333         {
6334             // A downcast is required for interfaces
6335             // https://issues.dlang.org/show_bug.cgi?id=3706
6336             e.e1 = new CastExp(e.loc, e.e1, ad.type);
6337             e.e1 = e.e1.expressionSemantic(sc);
6338         }
6339         result = e;
6340         // declare dual-context container
6341         if (f.isThis2 && !sc.intypeof && sc.func)
6342         {
6343             // check access to second `this`
6344             if (AggregateDeclaration ad2 = f.isMember2())
6345             {
6346                 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6347                 if (te.op != TOK.error)
6348                     te = getRightThis(e.loc, sc, ad2, te, f);
6349                 if (te.op == TOK.error)
6350                 {
6351                     e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6352                     return setError();
6353                 }
6354             }
6355             VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6356             e.vthis2 = vthis2;
6357             Expression de = new DeclarationExp(e.loc, vthis2);
6358             result = Expression.combine(de, result);
6359             result = result.expressionSemantic(sc);
6360         }
6361     }
6362 
6363     override void visit(DotTypeExp exp)
6364     {
6365         static if (LOGSEMANTIC)
6366         {
6367             printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6368         }
6369         if (exp.type)
6370         {
6371             result = exp;
6372             return;
6373         }
6374 
6375         if (auto e = unaSemantic(exp, sc))
6376         {
6377             result = e;
6378             return;
6379         }
6380 
6381         exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6382         result = exp;
6383     }
6384 
6385     override void visit(AddrExp exp)
6386     {
6387         static if (LOGSEMANTIC)
6388         {
6389             printf("AddrExp::semantic('%s')\n", exp.toChars());
6390         }
6391         if (exp.type)
6392         {
6393             result = exp;
6394             return;
6395         }
6396 
6397         if (Expression ex = unaSemantic(exp, sc))
6398         {
6399             result = ex;
6400             return;
6401         }
6402 
6403         int wasCond = exp.e1.op == TOK.question;
6404 
6405         if (exp.e1.op == TOK.dotTemplateInstance)
6406         {
6407             DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6408             TemplateInstance ti = dti.ti;
6409             {
6410                 //assert(ti.needsTypeInference(sc));
6411                 ti.dsymbolSemantic(sc);
6412                 if (!ti.inst || ti.errors) // if template failed to expand
6413                     return setError();
6414 
6415                 Dsymbol s = ti.toAlias();
6416                 FuncDeclaration f = s.isFuncDeclaration();
6417                 if (f)
6418                 {
6419                     exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6420                     exp.e1 = exp.e1.expressionSemantic(sc);
6421                 }
6422             }
6423         }
6424         else if (exp.e1.op == TOK.scope_)
6425         {
6426             TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6427             if (ti)
6428             {
6429                 //assert(ti.needsTypeInference(sc));
6430                 ti.dsymbolSemantic(sc);
6431                 if (!ti.inst || ti.errors) // if template failed to expand
6432                     return setError();
6433 
6434                 Dsymbol s = ti.toAlias();
6435                 FuncDeclaration f = s.isFuncDeclaration();
6436                 if (f)
6437                 {
6438                     exp.e1 = new VarExp(exp.e1.loc, f);
6439                     exp.e1 = exp.e1.expressionSemantic(sc);
6440                 }
6441             }
6442         }
6443         /* https://issues.dlang.org/show_bug.cgi?id=809
6444          *
6445          * If the address of a lazy variable is taken,
6446          * the expression is rewritten so that the type
6447          * of it is the delegate type. This means that
6448          * the symbol is not going to represent a call
6449          * to the delegate anymore, but rather, the
6450          * actual symbol.
6451          */
6452         if (auto ve = exp.e1.isVarExp())
6453         {
6454             if (ve.var.storage_class & STC.lazy_)
6455             {
6456                 exp.e1 = exp.e1.expressionSemantic(sc);
6457                 exp.e1 = resolveProperties(sc, exp.e1);
6458                 if (auto callExp = exp.e1.isCallExp())
6459                 {
6460                     if (callExp.e1.type.toBasetype().ty == Tdelegate)
6461                     {
6462                         /* https://issues.dlang.org/show_bug.cgi?id=20551
6463                          *
6464                          * Cannot take address of lazy parameter in @safe code
6465                          * because it might end up being a pointer to undefined
6466                          * memory.
6467                          */
6468                         if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6469                         {
6470                             exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
6471                                      ve.toChars(), sc.func.toChars());
6472                             setError();
6473                         }
6474                         else
6475                         {
6476                             VarExp ve2 = callExp.e1.isVarExp();
6477                             ve2.delegateWasExtracted = true;
6478                             ve2.var.storage_class |= STC.scope_;
6479                             result = ve2;
6480                         }
6481                         return;
6482                     }
6483                 }
6484             }
6485         }
6486 
6487         exp.e1 = exp.e1.toLvalue(sc, null);
6488         if (exp.e1.op == TOK.error)
6489         {
6490             result = exp.e1;
6491             return;
6492         }
6493         if (checkNonAssignmentArrayOp(exp.e1))
6494             return setError();
6495 
6496         if (!exp.e1.type)
6497         {
6498             exp.error("cannot take address of `%s`", exp.e1.toChars());
6499             return setError();
6500         }
6501 
6502         bool hasOverloads;
6503         if (auto f = isFuncAddress(exp, &hasOverloads))
6504         {
6505             if (!hasOverloads && f.checkForwardRef(exp.loc))
6506                 return setError();
6507         }
6508         else if (!exp.e1.type.deco)
6509         {
6510             if (exp.e1.op == TOK.variable)
6511             {
6512                 VarExp ve = cast(VarExp)exp.e1;
6513                 Declaration d = ve.var;
6514                 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
6515             }
6516             else
6517                 exp.error("forward reference to `%s`", exp.e1.toChars());
6518             return setError();
6519         }
6520 
6521         exp.type = exp.e1.type.pointerTo();
6522 
6523         // See if this should really be a delegate
6524         if (exp.e1.op == TOK.dotVariable)
6525         {
6526             DotVarExp dve = cast(DotVarExp)exp.e1;
6527             FuncDeclaration f = dve.var.isFuncDeclaration();
6528             if (f)
6529             {
6530                 f = f.toAliasFunc(); // FIXME, should see overloads
6531                                      // https://issues.dlang.org/show_bug.cgi?id=1983
6532                 if (!dve.hasOverloads)
6533                     f.tookAddressOf++;
6534 
6535                 Expression e;
6536                 if (f.needThis())
6537                     e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
6538                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
6539                     e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
6540                 e = e.expressionSemantic(sc);
6541                 result = e;
6542                 return;
6543             }
6544 
6545             // Look for misaligned pointer in @safe mode
6546             if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
6547                 return setError();
6548 
6549             if (global.params.vsafe)
6550             {
6551                 if (VarDeclaration v = expToVariable(dve.e1))
6552                 {
6553                     if (!checkAddressVar(sc, exp, v))
6554                         return setError();
6555                 }
6556             }
6557         }
6558         else if (exp.e1.op == TOK.variable)
6559         {
6560             VarExp ve = cast(VarExp)exp.e1;
6561             VarDeclaration v = ve.var.isVarDeclaration();
6562             if (v)
6563             {
6564                 if (!checkAddressVar(sc, exp, v))
6565                     return setError();
6566 
6567                 ve.checkPurity(sc, v);
6568             }
6569             FuncDeclaration f = ve.var.isFuncDeclaration();
6570             if (f)
6571             {
6572                 /* Because nested functions cannot be overloaded,
6573                  * mark here that we took its address because castTo()
6574                  * may not be called with an exact match.
6575                  */
6576                 if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
6577                     f.tookAddressOf++;
6578                 if (f.isNested() && !f.needThis())
6579                 {
6580                     if (f.isFuncLiteralDeclaration())
6581                     {
6582                         if (!f.FuncDeclaration.isNested())
6583                         {
6584                             /* Supply a 'null' for a this pointer if no this is available
6585                              */
6586                             Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
6587                             e = e.expressionSemantic(sc);
6588                             result = e;
6589                             return;
6590                         }
6591                     }
6592                     Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
6593                     e = e.expressionSemantic(sc);
6594                     result = e;
6595                     return;
6596                 }
6597                 if (f.needThis())
6598                 {
6599                     if (hasThis(sc))
6600                     {
6601                         /* Should probably supply 'this' after overload resolution,
6602                          * not before.
6603                          */
6604                         Expression ethis = new ThisExp(exp.loc);
6605                         Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
6606                         e = e.expressionSemantic(sc);
6607                         result = e;
6608                         return;
6609                     }
6610                     if (sc.func && !sc.intypeof)
6611                     {
6612                         if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6613                         {
6614                             exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
6615                         }
6616                     }
6617                 }
6618             }
6619         }
6620         else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe)
6621         {
6622             if (VarDeclaration v = expToVariable(exp.e1))
6623             {
6624                 if (!checkAddressVar(sc, exp, v))
6625                     return setError();
6626             }
6627         }
6628         else if (exp.e1.op == TOK.call)
6629         {
6630             CallExp ce = cast(CallExp)exp.e1;
6631             if (ce.e1.type.ty == Tfunction)
6632             {
6633                 TypeFunction tf = cast(TypeFunction)ce.e1.type;
6634                 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6635                 {
6636                     exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
6637                         ce.e1.toChars(), sc.func.toChars());
6638                 }
6639             }
6640         }
6641         else if (exp.e1.op == TOK.index)
6642         {
6643             /* For:
6644              *   int[3] a;
6645              *   &a[i]
6646              * check 'a' the same as for a regular variable
6647              */
6648             if (VarDeclaration v = expToVariable(exp.e1))
6649             {
6650                 if (global.params.vsafe && !checkAddressVar(sc, exp, v))
6651                     return setError();
6652 
6653                 exp.e1.checkPurity(sc, v);
6654             }
6655         }
6656         else if (wasCond)
6657         {
6658             /* a ? b : c was transformed to *(a ? &b : &c), but we still
6659              * need to do safety checks
6660              */
6661             assert(exp.e1.op == TOK.star);
6662             PtrExp pe = cast(PtrExp)exp.e1;
6663             assert(pe.e1.op == TOK.question);
6664             CondExp ce = cast(CondExp)pe.e1;
6665             assert(ce.e1.op == TOK.address);
6666             assert(ce.e2.op == TOK.address);
6667 
6668             // Re-run semantic on the address expressions only
6669             ce.e1.type = null;
6670             ce.e1 = ce.e1.expressionSemantic(sc);
6671             ce.e2.type = null;
6672             ce.e2 = ce.e2.expressionSemantic(sc);
6673         }
6674         result = exp.optimize(WANTvalue);
6675     }
6676 
6677     override void visit(PtrExp exp)
6678     {
6679         static if (LOGSEMANTIC)
6680         {
6681             printf("PtrExp::semantic('%s')\n", exp.toChars());
6682         }
6683         if (exp.type)
6684         {
6685             result = exp;
6686             return;
6687         }
6688 
6689         Expression e = exp.op_overload(sc);
6690         if (e)
6691         {
6692             result = e;
6693             return;
6694         }
6695 
6696         Type tb = exp.e1.type.toBasetype();
6697         switch (tb.ty)
6698         {
6699         case Tpointer:
6700             exp.type = (cast(TypePointer)tb).next;
6701             break;
6702 
6703         case Tsarray:
6704         case Tarray:
6705             if (isNonAssignmentArrayOp(exp.e1))
6706                 goto default;
6707             exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
6708             exp.type = (cast(TypeArray)tb).next;
6709             exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
6710             break;
6711 
6712         case Terror:
6713             return setError();
6714 
6715         default:
6716             exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
6717             goto case Terror;
6718         }
6719 
6720         if (exp.checkValue() || exp.checkSharedAccess(sc))
6721             return setError();
6722 
6723         result = exp;
6724     }
6725 
6726     override void visit(NegExp exp)
6727     {
6728         static if (LOGSEMANTIC)
6729         {
6730             printf("NegExp::semantic('%s')\n", exp.toChars());
6731         }
6732         if (exp.type)
6733         {
6734             result = exp;
6735             return;
6736         }
6737 
6738         Expression e = exp.op_overload(sc);
6739         if (e)
6740         {
6741             result = e;
6742             return;
6743         }
6744 
6745         fix16997(sc, exp);
6746         exp.type = exp.e1.type;
6747         Type tb = exp.type.toBasetype();
6748         if (tb.ty == Tarray || tb.ty == Tsarray)
6749         {
6750             if (!isArrayOpValid(exp.e1))
6751             {
6752                 result = arrayOpInvalidError(exp);
6753                 return;
6754             }
6755             result = exp;
6756             return;
6757         }
6758         if (!target.isVectorOpSupported(tb, exp.op))
6759         {
6760             result = exp.incompatibleTypes();
6761             return;
6762         }
6763         if (exp.e1.checkNoBool())
6764             return setError();
6765         if (exp.e1.checkArithmetic() ||
6766             exp.e1.checkSharedAccess(sc))
6767             return setError();
6768 
6769         result = exp;
6770     }
6771 
6772     override void visit(UAddExp exp)
6773     {
6774         static if (LOGSEMANTIC)
6775         {
6776             printf("UAddExp::semantic('%s')\n", exp.toChars());
6777         }
6778         assert(!exp.type);
6779 
6780         Expression e = exp.op_overload(sc);
6781         if (e)
6782         {
6783             result = e;
6784             return;
6785         }
6786 
6787         fix16997(sc, exp);
6788         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
6789         {
6790             result = exp.incompatibleTypes();
6791             return;
6792         }
6793         if (exp.e1.checkNoBool())
6794             return setError();
6795         if (exp.e1.checkArithmetic())
6796             return setError();
6797         if (exp.e1.checkSharedAccess(sc))
6798             return setError();
6799 
6800         result = exp.e1;
6801     }
6802 
6803     override void visit(ComExp exp)
6804     {
6805         if (exp.type)
6806         {
6807             result = exp;
6808             return;
6809         }
6810 
6811         Expression e = exp.op_overload(sc);
6812         if (e)
6813         {
6814             result = e;
6815             return;
6816         }
6817 
6818         fix16997(sc, exp);
6819         exp.type = exp.e1.type;
6820         Type tb = exp.type.toBasetype();
6821         if (tb.ty == Tarray || tb.ty == Tsarray)
6822         {
6823             if (!isArrayOpValid(exp.e1))
6824             {
6825                 result = arrayOpInvalidError(exp);
6826                 return;
6827             }
6828             result = exp;
6829             return;
6830         }
6831         if (!target.isVectorOpSupported(tb, exp.op))
6832         {
6833             result = exp.incompatibleTypes();
6834             return;
6835         }
6836         if (exp.e1.checkNoBool())
6837             return setError();
6838         if (exp.e1.checkIntegral() ||
6839             exp.e1.checkSharedAccess(sc))
6840             return setError();
6841 
6842         result = exp;
6843     }
6844 
6845     override void visit(NotExp e)
6846     {
6847         if (e.type)
6848         {
6849             result = e;
6850             return;
6851         }
6852 
6853         e.setNoderefOperand();
6854 
6855         // Note there is no operator overload
6856         if (Expression ex = unaSemantic(e, sc))
6857         {
6858             result = ex;
6859             return;
6860         }
6861 
6862         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
6863         if (e.e1.op == TOK.type)
6864             e.e1 = resolveAliasThis(sc, e.e1);
6865 
6866         e.e1 = resolveProperties(sc, e.e1);
6867         e.e1 = e.e1.toBoolean(sc);
6868         if (e.e1.type == Type.terror)
6869         {
6870             result = e.e1;
6871             return;
6872         }
6873 
6874         if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
6875         {
6876             result = e.incompatibleTypes();
6877         }
6878         // https://issues.dlang.org/show_bug.cgi?id=13910
6879         // Today NotExp can take an array as its operand.
6880         if (checkNonAssignmentArrayOp(e.e1))
6881             return setError();
6882 
6883         e.type = Type.tbool;
6884         result = e;
6885     }
6886 
6887     override void visit(DeleteExp exp)
6888     {
6889         if (!sc.isDeprecated)
6890         {
6891             // @@@DEPRECATED_2019-02@@@
6892             // 1. Deprecation for 1 year
6893             // 2. Error for 1 year
6894             // 3. Removal of keyword, "delete" can be used for other identities
6895             if (!exp.isRAII)
6896                 deprecation(exp.loc, "The `delete` keyword has been deprecated.  Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
6897         }
6898 
6899         if (Expression ex = unaSemantic(exp, sc))
6900         {
6901             result = ex;
6902             return;
6903         }
6904         exp.e1 = resolveProperties(sc, exp.e1);
6905         exp.e1 = exp.e1.modifiableLvalue(sc, null);
6906         if (exp.e1.op == TOK.error)
6907         {
6908             result = exp.e1;
6909             return;
6910         }
6911         exp.type = Type.tvoid;
6912 
6913         AggregateDeclaration ad = null;
6914         Type tb = exp.e1.type.toBasetype();
6915         switch (tb.ty)
6916         {
6917         case Tclass:
6918             {
6919                 auto cd = (cast(TypeClass)tb).sym;
6920                 if (cd.isCOMinterface())
6921                 {
6922                     /* Because COM classes are deleted by IUnknown.Release()
6923                      */
6924                     exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
6925                     return setError();
6926                 }
6927                 ad = cd;
6928                 break;
6929             }
6930         case Tpointer:
6931             tb = (cast(TypePointer)tb).next.toBasetype();
6932             if (tb.ty == Tstruct)
6933             {
6934                 ad = (cast(TypeStruct)tb).sym;
6935                 semanticTypeInfo(sc, tb);
6936             }
6937             break;
6938 
6939         case Tarray:
6940             {
6941                 Type tv = tb.nextOf().baseElemOf();
6942                 if (tv.ty == Tstruct)
6943                 {
6944                     ad = (cast(TypeStruct)tv).sym;
6945                     if (ad.dtor)
6946                         semanticTypeInfo(sc, ad.type);
6947                 }
6948                 break;
6949             }
6950         default:
6951             exp.error("cannot delete type `%s`", exp.e1.type.toChars());
6952             return setError();
6953         }
6954 
6955         bool err = false;
6956         if (ad)
6957         {
6958             if (ad.dtor)
6959             {
6960                 err |= exp.checkPurity(sc, ad.dtor);
6961                 err |= exp.checkSafety(sc, ad.dtor);
6962                 err |= exp.checkNogc(sc, ad.dtor);
6963             }
6964             if (err)
6965                 return setError();
6966         }
6967 
6968         if (!sc.intypeof && sc.func &&
6969             !exp.isRAII &&
6970             !(sc.flags & SCOPE.debug_) &&
6971             sc.func.setUnsafe())
6972         {
6973             exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars());
6974             err = true;
6975         }
6976         if (err)
6977             return setError();
6978 
6979         result = exp;
6980     }
6981 
6982     override void visit(CastExp exp)
6983     {
6984         static if (LOGSEMANTIC)
6985         {
6986             printf("CastExp::semantic('%s')\n", exp.toChars());
6987         }
6988         //static int x; assert(++x < 10);
6989         if (exp.type)
6990         {
6991             result = exp;
6992             return;
6993         }
6994 
6995         if (exp.to)
6996         {
6997             exp.to = exp.to.typeSemantic(exp.loc, sc);
6998             if (exp.to == Type.terror)
6999                 return setError();
7000 
7001             if (!exp.to.hasPointers())
7002                 exp.setNoderefOperand();
7003 
7004             // When e1 is a template lambda, this cast may instantiate it with
7005             // the type 'to'.
7006             exp.e1 = inferType(exp.e1, exp.to);
7007         }
7008 
7009         if (auto e = unaSemantic(exp, sc))
7010         {
7011             result = e;
7012             return;
7013         }
7014 
7015         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7016         if (exp.e1.op == TOK.type)
7017             exp.e1 = resolveAliasThis(sc, exp.e1);
7018 
7019         auto e1x = resolveProperties(sc, exp.e1);
7020         if (e1x.op == TOK.error)
7021         {
7022             result = e1x;
7023             return;
7024         }
7025         if (e1x.checkType())
7026             return setError();
7027         exp.e1 = e1x;
7028 
7029         if (!exp.e1.type)
7030         {
7031             exp.error("cannot cast `%s`", exp.e1.toChars());
7032             return setError();
7033         }
7034 
7035         // https://issues.dlang.org/show_bug.cgi?id=19954
7036         if (exp.e1.type.ty == Ttuple)
7037         {
7038             TupleExp te = exp.e1.isTupleExp();
7039             if (te.exps.dim == 1)
7040                 exp.e1 = (*te.exps)[0];
7041         }
7042 
7043         // only allow S(x) rewrite if cast specified S explicitly.
7044         // See https://issues.dlang.org/show_bug.cgi?id=18545
7045         const bool allowImplicitConstruction = exp.to !is null;
7046 
7047         if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7048         {
7049             exp.to = exp.e1.type.castMod(exp.mod);
7050             exp.to = exp.to.typeSemantic(exp.loc, sc);
7051 
7052             if (exp.to == Type.terror)
7053                 return setError();
7054         }
7055 
7056         if (exp.to.ty == Ttuple)
7057         {
7058             exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
7059             return setError();
7060         }
7061 
7062         // cast(void) is used to mark e1 as unused, so it is safe
7063         if (exp.to.ty == Tvoid)
7064         {
7065             exp.type = exp.to;
7066             result = exp;
7067             return;
7068         }
7069 
7070         if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7071         {
7072             if (Expression e = exp.op_overload(sc))
7073             {
7074                 result = e.implicitCastTo(sc, exp.to);
7075                 return;
7076             }
7077         }
7078 
7079         Type t1b = exp.e1.type.toBasetype();
7080         Type tob = exp.to.toBasetype();
7081 
7082         if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7083         {
7084             /* Look to replace:
7085              *  cast(S)t
7086              * with:
7087              *  S(t)
7088              */
7089 
7090             // Rewrite as to.call(e1)
7091             Expression e = new TypeExp(exp.loc, exp.to);
7092             e = new CallExp(exp.loc, e, exp.e1);
7093             e = e.trySemantic(sc);
7094             if (e)
7095             {
7096                 result = e;
7097                 return;
7098             }
7099         }
7100 
7101         if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7102         {
7103             if (checkNonAssignmentArrayOp(exp.e1))
7104                 return setError();
7105         }
7106 
7107         // Look for casting to a vector type
7108         if (tob.ty == Tvector && t1b.ty != Tvector)
7109         {
7110             result = new VectorExp(exp.loc, exp.e1, exp.to);
7111             result = result.expressionSemantic(sc);
7112             return;
7113         }
7114 
7115         Expression ex = exp.e1.castTo(sc, exp.to);
7116         if (ex.op == TOK.error)
7117         {
7118             result = ex;
7119             return;
7120         }
7121 
7122         // Check for unsafe casts
7123         if (!sc.intypeof &&
7124             !(sc.flags & SCOPE.debug_) &&
7125             !isSafeCast(ex, t1b, tob) &&
7126             (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe()))
7127         {
7128             exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
7129             return setError();
7130         }
7131 
7132         // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7133         // to handle certain casts.  Those casts which `object.__ArrayCast` does not support are filtered out.
7134         // See `e2ir.toElemCast` for other types of casts.  If `object.__ArrayCast` is improved to support more
7135         // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7136         if (tob.ty == Tarray)
7137         {
7138             // https://issues.dlang.org/show_bug.cgi?id=19840
7139             if (auto ad = isAggregate(t1b))
7140             {
7141                 if (ad.aliasthis)
7142                 {
7143                     Expression e = resolveAliasThis(sc, exp.e1);
7144                     e = new CastExp(exp.loc, e, exp.to);
7145                     result = e.expressionSemantic(sc);
7146                     return;
7147                 }
7148             }
7149 
7150             if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7151             {
7152                 auto tFrom = t1b.nextOf();
7153                 auto tTo = tob.nextOf();
7154 
7155                 // https://issues.dlang.org/show_bug.cgi?id=20130
7156                 if (exp.e1.op != TOK.string_ || !ex.isStringExp)
7157                 {
7158                     const uint fromSize = cast(uint)tFrom.size();
7159                     const uint toSize = cast(uint)tTo.size();
7160 
7161                     // If array element sizes do not match, we must adjust the dimensions
7162                     if (fromSize != toSize)
7163                     {
7164                         if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7165                             return setError();
7166 
7167                         // A runtime check is needed in case arrays don't line up.  That check should
7168                         // be done in the implementation of `object.__ArrayCast`
7169                         if (toSize == 0 || (fromSize % toSize) != 0)
7170                         {
7171                             // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7172 
7173                             // fully qualify as `object.__ArrayCast`
7174                             Expression id = new IdentifierExp(exp.loc, Id.empty);
7175                             auto dotid = new DotIdExp(exp.loc, id, Id.object);
7176 
7177                             auto tiargs = new Objects();
7178                             tiargs.push(tFrom);
7179                             tiargs.push(tTo);
7180                             auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7181 
7182                             auto arguments = new Expressions();
7183                             arguments.push(exp.e1);
7184                             Expression ce = new CallExp(exp.loc, dt, arguments);
7185 
7186                             result = expressionSemantic(ce, sc);
7187                             return;
7188                         }
7189                     }
7190                 }
7191             }
7192         }
7193 
7194         result = ex;
7195     }
7196 
7197     override void visit(VectorExp exp)
7198     {
7199         static if (LOGSEMANTIC)
7200         {
7201             printf("VectorExp::semantic('%s')\n", exp.toChars());
7202         }
7203         if (exp.type)
7204         {
7205             result = exp;
7206             return;
7207         }
7208 
7209         exp.e1 = exp.e1.expressionSemantic(sc);
7210         exp.type = exp.to.typeSemantic(exp.loc, sc);
7211         if (exp.e1.op == TOK.error || exp.type.ty == Terror)
7212         {
7213             result = exp.e1;
7214             return;
7215         }
7216 
7217         Type tb = exp.type.toBasetype();
7218         assert(tb.ty == Tvector);
7219         TypeVector tv = cast(TypeVector)tb;
7220         Type te = tv.elementType();
7221         exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7222 
7223         bool checkElem(Expression elem)
7224         {
7225             if (elem.isConst() == 1)
7226                 return false;
7227 
7228              exp.error("constant expression expected, not `%s`", elem.toChars());
7229              return true;
7230         }
7231 
7232         exp.e1 = exp.e1.optimize(WANTvalue);
7233         bool res;
7234         if (exp.e1.op == TOK.arrayLiteral)
7235         {
7236             foreach (i; 0 .. exp.dim)
7237             {
7238                 // Do not stop on first error - check all AST nodes even if error found
7239                 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7240             }
7241         }
7242         else if (exp.e1.type.ty == Tvoid)
7243             checkElem(exp.e1);
7244 
7245         result = res ? new ErrorExp() : exp;
7246     }
7247 
7248     override void visit(VectorArrayExp e)
7249     {
7250         static if (LOGSEMANTIC)
7251         {
7252             printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7253         }
7254         if (!e.type)
7255         {
7256             unaSemantic(e, sc);
7257             e.e1 = resolveProperties(sc, e.e1);
7258 
7259             if (e.e1.op == TOK.error)
7260             {
7261                 result = e.e1;
7262                 return;
7263             }
7264             assert(e.e1.type.ty == Tvector);
7265             e.type = e.e1.type.isTypeVector().basetype;
7266         }
7267         result = e;
7268     }
7269 
7270     override void visit(SliceExp exp)
7271     {
7272         static if (LOGSEMANTIC)
7273         {
7274             printf("SliceExp::semantic('%s')\n", exp.toChars());
7275         }
7276         if (exp.type)
7277         {
7278             result = exp;
7279             return;
7280         }
7281 
7282         // operator overloading should be handled in ArrayExp already.
7283         if (Expression ex = unaSemantic(exp, sc))
7284         {
7285             result = ex;
7286             return;
7287         }
7288         exp.e1 = resolveProperties(sc, exp.e1);
7289         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7290         {
7291             if (exp.lwr || exp.upr)
7292             {
7293                 exp.error("cannot slice type `%s`", exp.e1.toChars());
7294                 return setError();
7295             }
7296             Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7297             result = e.expressionSemantic(sc);
7298             return;
7299         }
7300         if (!exp.lwr && !exp.upr)
7301         {
7302             if (exp.e1.op == TOK.arrayLiteral)
7303             {
7304                 // Convert [a,b,c][] to [a,b,c]
7305                 Type t1b = exp.e1.type.toBasetype();
7306                 Expression e = exp.e1;
7307                 if (t1b.ty == Tsarray)
7308                 {
7309                     e = e.copy();
7310                     e.type = t1b.nextOf().arrayOf();
7311                 }
7312                 result = e;
7313                 return;
7314             }
7315             if (exp.e1.op == TOK.slice)
7316             {
7317                 // Convert e[][] to e[]
7318                 SliceExp se = cast(SliceExp)exp.e1;
7319                 if (!se.lwr && !se.upr)
7320                 {
7321                     result = se;
7322                     return;
7323                 }
7324             }
7325             if (isArrayOpOperand(exp.e1))
7326             {
7327                 // Convert (a[]+b[])[] to a[]+b[]
7328                 result = exp.e1;
7329                 return;
7330             }
7331         }
7332         if (exp.e1.op == TOK.error)
7333         {
7334             result = exp.e1;
7335             return;
7336         }
7337         if (exp.e1.type.ty == Terror)
7338             return setError();
7339 
7340         Type t1b = exp.e1.type.toBasetype();
7341         if (t1b.ty == Tpointer)
7342         {
7343             if ((cast(TypePointer)t1b).next.ty == Tfunction)
7344             {
7345                 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7346                 return setError();
7347             }
7348             if (!exp.lwr || !exp.upr)
7349             {
7350                 exp.error("need upper and lower bound to slice pointer");
7351                 return setError();
7352             }
7353             if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7354             {
7355                 exp.error("pointer slicing not allowed in safe functions");
7356                 return setError();
7357             }
7358         }
7359         else if (t1b.ty == Tarray)
7360         {
7361         }
7362         else if (t1b.ty == Tsarray)
7363         {
7364             if (!exp.arrayop && global.params.vsafe)
7365             {
7366                 /* Slicing a static array is like taking the address of it.
7367                  * Perform checks as if e[] was &e
7368                  */
7369                 if (VarDeclaration v = expToVariable(exp.e1))
7370                 {
7371                     if (exp.e1.op == TOK.dotVariable)
7372                     {
7373                         DotVarExp dve = cast(DotVarExp)exp.e1;
7374                         if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) &&
7375                             !(v.storage_class & STC.ref_))
7376                         {
7377                             // because it's a class
7378                             v = null;
7379                         }
7380                     }
7381 
7382                     if (v && !checkAddressVar(sc, exp, v))
7383                         return setError();
7384                 }
7385             }
7386         }
7387         else if (t1b.ty == Ttuple)
7388         {
7389             if (!exp.lwr && !exp.upr)
7390             {
7391                 result = exp.e1;
7392                 return;
7393             }
7394             if (!exp.lwr || !exp.upr)
7395             {
7396                 exp.error("need upper and lower bound to slice tuple");
7397                 return setError();
7398             }
7399         }
7400         else if (t1b.ty == Tvector)
7401         {
7402             // Convert e1 to corresponding static array
7403             TypeVector tv1 = cast(TypeVector)t1b;
7404             t1b = tv1.basetype;
7405             t1b = t1b.castMod(tv1.mod);
7406             exp.e1.type = t1b;
7407         }
7408         else
7409         {
7410             exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7411             return setError();
7412         }
7413 
7414         /* Run semantic on lwr and upr.
7415          */
7416         Scope* scx = sc;
7417         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7418         {
7419             // Create scope for 'length' variable
7420             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7421             sym.parent = sc.scopesym;
7422             sc = sc.push(sym);
7423         }
7424         if (exp.lwr)
7425         {
7426             if (t1b.ty == Ttuple)
7427                 sc = sc.startCTFE();
7428             exp.lwr = exp.lwr.expressionSemantic(sc);
7429             exp.lwr = resolveProperties(sc, exp.lwr);
7430             if (t1b.ty == Ttuple)
7431                 sc = sc.endCTFE();
7432             exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7433         }
7434         if (exp.upr)
7435         {
7436             if (t1b.ty == Ttuple)
7437                 sc = sc.startCTFE();
7438             exp.upr = exp.upr.expressionSemantic(sc);
7439             exp.upr = resolveProperties(sc, exp.upr);
7440             if (t1b.ty == Ttuple)
7441                 sc = sc.endCTFE();
7442             exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7443         }
7444         if (sc != scx)
7445             sc = sc.pop();
7446         if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7447             return setError();
7448 
7449         if (t1b.ty == Ttuple)
7450         {
7451             exp.lwr = exp.lwr.ctfeInterpret();
7452             exp.upr = exp.upr.ctfeInterpret();
7453             uinteger_t i1 = exp.lwr.toUInteger();
7454             uinteger_t i2 = exp.upr.toUInteger();
7455 
7456             TupleExp te;
7457             TypeTuple tup;
7458             size_t length;
7459             if (exp.e1.op == TOK.tuple) // slicing an expression tuple
7460             {
7461                 te = cast(TupleExp)exp.e1;
7462                 tup = null;
7463                 length = te.exps.dim;
7464             }
7465             else if (exp.e1.op == TOK.type) // slicing a type tuple
7466             {
7467                 te = null;
7468                 tup = cast(TypeTuple)t1b;
7469                 length = Parameter.dim(tup.arguments);
7470             }
7471             else
7472                 assert(0);
7473 
7474             if (i2 < i1 || length < i2)
7475             {
7476                 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7477                 return setError();
7478             }
7479 
7480             size_t j1 = cast(size_t)i1;
7481             size_t j2 = cast(size_t)i2;
7482             Expression e;
7483             if (exp.e1.op == TOK.tuple)
7484             {
7485                 auto exps = new Expressions(j2 - j1);
7486                 for (size_t i = 0; i < j2 - j1; i++)
7487                 {
7488                     (*exps)[i] = (*te.exps)[j1 + i];
7489                 }
7490                 e = new TupleExp(exp.loc, te.e0, exps);
7491             }
7492             else
7493             {
7494                 auto args = new Parameters();
7495                 args.reserve(j2 - j1);
7496                 for (size_t i = j1; i < j2; i++)
7497                 {
7498                     Parameter arg = Parameter.getNth(tup.arguments, i);
7499                     args.push(arg);
7500                 }
7501                 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
7502             }
7503             e = e.expressionSemantic(sc);
7504             result = e;
7505             return;
7506         }
7507 
7508         exp.type = t1b.nextOf().arrayOf();
7509         // Allow typedef[] -> typedef[]
7510         if (exp.type.equals(t1b))
7511             exp.type = exp.e1.type;
7512 
7513         // We might know $ now
7514         setLengthVarIfKnown(exp.lengthVar, t1b);
7515 
7516         if (exp.lwr && exp.upr)
7517         {
7518             exp.lwr = exp.lwr.optimize(WANTvalue);
7519             exp.upr = exp.upr.optimize(WANTvalue);
7520 
7521             IntRange lwrRange = getIntRange(exp.lwr);
7522             IntRange uprRange = getIntRange(exp.upr);
7523 
7524             if (t1b.ty == Tsarray || t1b.ty == Tarray)
7525             {
7526                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
7527                 el = el.expressionSemantic(sc);
7528                 el = el.optimize(WANTvalue);
7529                 if (el.op == TOK.int64)
7530                 {
7531                     // Array length is known at compile-time. Upper is in bounds if it fits length.
7532                     dinteger_t length = el.toInteger();
7533                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
7534                     exp.upperIsInBounds = bounds.contains(uprRange);
7535                 }
7536                 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
7537                 {
7538                     // Upper slice expression is '0'. Value is always in bounds.
7539                     exp.upperIsInBounds = true;
7540                 }
7541                 else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
7542                 {
7543                     // Upper slice expression is '$'. Value is always in bounds.
7544                     exp.upperIsInBounds = true;
7545                 }
7546             }
7547             else if (t1b.ty == Tpointer)
7548             {
7549                 exp.upperIsInBounds = true;
7550             }
7551             else
7552                 assert(0);
7553 
7554             exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
7555 
7556             //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
7557         }
7558 
7559         result = exp;
7560     }
7561 
7562     override void visit(ArrayLengthExp e)
7563     {
7564         static if (LOGSEMANTIC)
7565         {
7566             printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
7567         }
7568         if (e.type)
7569         {
7570             result = e;
7571             return;
7572         }
7573 
7574         if (Expression ex = unaSemantic(e, sc))
7575         {
7576             result = ex;
7577             return;
7578         }
7579         e.e1 = resolveProperties(sc, e.e1);
7580 
7581         e.type = Type.tsize_t;
7582         result = e;
7583     }
7584 
7585     override void visit(ArrayExp exp)
7586     {
7587         static if (LOGSEMANTIC)
7588         {
7589             printf("ArrayExp::semantic('%s')\n", exp.toChars());
7590         }
7591         assert(!exp.type);
7592         Expression e = exp.op_overload(sc);
7593         if (e)
7594         {
7595             result = e;
7596             return;
7597         }
7598 
7599         if (isAggregate(exp.e1.type))
7600             exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
7601         else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7602             exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
7603         else if (isIndexableNonAggregate(exp.e1.type))
7604             exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
7605         else
7606             exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
7607 
7608         result = new ErrorExp();
7609     }
7610 
7611     override void visit(DotExp exp)
7612     {
7613         static if (LOGSEMANTIC)
7614         {
7615             printf("DotExp::semantic('%s')\n", exp.toChars());
7616             if (exp.type)
7617                 printf("\ttype = %s\n", exp.type.toChars());
7618         }
7619         exp.e1 = exp.e1.expressionSemantic(sc);
7620         exp.e2 = exp.e2.expressionSemantic(sc);
7621 
7622         if (exp.e1.op == TOK.type)
7623         {
7624             result = exp.e2;
7625             return;
7626         }
7627         if (exp.e2.op == TOK.type)
7628         {
7629             result = exp.e2;
7630             return;
7631         }
7632         if (exp.e2.op == TOK.template_)
7633         {
7634             auto td = (cast(TemplateExp)exp.e2).td;
7635             Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
7636             result = e.expressionSemantic(sc);
7637             return;
7638         }
7639         if (!exp.type || exp.e1.op == TOK.this_)
7640             exp.type = exp.e2.type;
7641         result = exp;
7642     }
7643 
7644     override void visit(CommaExp e)
7645     {
7646         if (e.type)
7647         {
7648             result = e;
7649             return;
7650         }
7651 
7652         // Allow `((a,b),(x,y))`
7653         if (e.allowCommaExp)
7654         {
7655             CommaExp.allow(e.e1);
7656             CommaExp.allow(e.e2);
7657         }
7658 
7659         if (Expression ex = binSemanticProp(e, sc))
7660         {
7661             result = ex;
7662             return;
7663         }
7664         e.e1 = e.e1.addDtorHook(sc);
7665 
7666         if (checkNonAssignmentArrayOp(e.e1))
7667             return setError();
7668 
7669         e.type = e.e2.type;
7670         if (e.type !is Type.tvoid && !e.allowCommaExp && !e.isGenerated)
7671             e.error("Using the result of a comma expression is not allowed");
7672         result = e;
7673     }
7674 
7675     override void visit(IntervalExp e)
7676     {
7677         static if (LOGSEMANTIC)
7678         {
7679             printf("IntervalExp::semantic('%s')\n", e.toChars());
7680         }
7681         if (e.type)
7682         {
7683             result = e;
7684             return;
7685         }
7686 
7687         Expression le = e.lwr;
7688         le = le.expressionSemantic(sc);
7689         le = resolveProperties(sc, le);
7690 
7691         Expression ue = e.upr;
7692         ue = ue.expressionSemantic(sc);
7693         ue = resolveProperties(sc, ue);
7694 
7695         if (le.op == TOK.error)
7696         {
7697             result = le;
7698             return;
7699         }
7700         if (ue.op == TOK.error)
7701         {
7702             result = ue;
7703             return;
7704         }
7705 
7706         e.lwr = le;
7707         e.upr = ue;
7708 
7709         e.type = Type.tvoid;
7710         result = e;
7711     }
7712 
7713     override void visit(DelegatePtrExp e)
7714     {
7715         static if (LOGSEMANTIC)
7716         {
7717             printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
7718         }
7719         if (!e.type)
7720         {
7721             unaSemantic(e, sc);
7722             e.e1 = resolveProperties(sc, e.e1);
7723 
7724             if (e.e1.op == TOK.error)
7725             {
7726                 result = e.e1;
7727                 return;
7728             }
7729             e.type = Type.tvoidptr;
7730         }
7731         result = e;
7732     }
7733 
7734     override void visit(DelegateFuncptrExp e)
7735     {
7736         static if (LOGSEMANTIC)
7737         {
7738             printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
7739         }
7740         if (!e.type)
7741         {
7742             unaSemantic(e, sc);
7743             e.e1 = resolveProperties(sc, e.e1);
7744             if (e.e1.op == TOK.error)
7745             {
7746                 result = e.e1;
7747                 return;
7748             }
7749             e.type = e.e1.type.nextOf().pointerTo();
7750         }
7751         result = e;
7752     }
7753 
7754     override void visit(IndexExp exp)
7755     {
7756         static if (LOGSEMANTIC)
7757         {
7758             printf("IndexExp::semantic('%s')\n", exp.toChars());
7759         }
7760         if (exp.type)
7761         {
7762             result = exp;
7763             return;
7764         }
7765 
7766         // operator overloading should be handled in ArrayExp already.
7767         if (!exp.e1.type)
7768             exp.e1 = exp.e1.expressionSemantic(sc);
7769         assert(exp.e1.type); // semantic() should already be run on it
7770         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7771         {
7772             exp.e2 = exp.e2.expressionSemantic(sc);
7773             exp.e2 = resolveProperties(sc, exp.e2);
7774             Type nt;
7775             if (exp.e2.op == TOK.type)
7776                 nt = new TypeAArray(exp.e1.type, exp.e2.type);
7777             else
7778                 nt = new TypeSArray(exp.e1.type, exp.e2);
7779             Expression e = new TypeExp(exp.loc, nt);
7780             result = e.expressionSemantic(sc);
7781             return;
7782         }
7783         if (exp.e1.op == TOK.error)
7784         {
7785             result = exp.e1;
7786             return;
7787         }
7788         if (exp.e1.type.ty == Terror)
7789             return setError();
7790 
7791         // Note that unlike C we do not implement the int[ptr]
7792 
7793         Type t1b = exp.e1.type.toBasetype();
7794 
7795         if (t1b.ty == Tvector)
7796         {
7797             // Convert e1 to corresponding static array
7798             TypeVector tv1 = cast(TypeVector)t1b;
7799             t1b = tv1.basetype;
7800             t1b = t1b.castMod(tv1.mod);
7801             exp.e1.type = t1b;
7802         }
7803 
7804         /* Run semantic on e2
7805          */
7806         Scope* scx = sc;
7807         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7808         {
7809             // Create scope for 'length' variable
7810             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7811             sym.parent = sc.scopesym;
7812             sc = sc.push(sym);
7813         }
7814         if (t1b.ty == Ttuple)
7815             sc = sc.startCTFE();
7816         exp.e2 = exp.e2.expressionSemantic(sc);
7817         exp.e2 = resolveProperties(sc, exp.e2);
7818         if (t1b.ty == Ttuple)
7819             sc = sc.endCTFE();
7820         if (exp.e2.op == TOK.tuple)
7821         {
7822             TupleExp te = cast(TupleExp)exp.e2;
7823             if (te.exps && te.exps.dim == 1)
7824                 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
7825         }
7826         if (sc != scx)
7827             sc = sc.pop();
7828         if (exp.e2.type == Type.terror)
7829             return setError();
7830 
7831         if (checkNonAssignmentArrayOp(exp.e1))
7832             return setError();
7833 
7834         switch (t1b.ty)
7835         {
7836         case Tpointer:
7837             if ((cast(TypePointer)t1b).next.ty == Tfunction)
7838             {
7839                 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
7840                 return setError();
7841             }
7842             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
7843             if (exp.e2.type == Type.terror)
7844                 return setError();
7845             exp.e2 = exp.e2.optimize(WANTvalue);
7846             if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0)
7847             {
7848             }
7849             else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7850             {
7851                 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
7852                 return setError();
7853             }
7854             exp.type = (cast(TypeNext)t1b).next;
7855             break;
7856 
7857         case Tarray:
7858             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
7859             if (exp.e2.type == Type.terror)
7860                 return setError();
7861             exp.type = (cast(TypeNext)t1b).next;
7862             break;
7863 
7864         case Tsarray:
7865             {
7866                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
7867                 if (exp.e2.type == Type.terror)
7868                     return setError();
7869                 exp.type = t1b.nextOf();
7870                 break;
7871             }
7872         case Taarray:
7873             {
7874                 TypeAArray taa = cast(TypeAArray)t1b;
7875                 /* We can skip the implicit conversion if they differ only by
7876                  * constness
7877                  * https://issues.dlang.org/show_bug.cgi?id=2684
7878                  * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
7879                  */
7880                 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
7881                 {
7882                     exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
7883                     if (exp.e2.type == Type.terror)
7884                         return setError();
7885                 }
7886 
7887                 semanticTypeInfo(sc, taa);
7888 
7889                 exp.type = taa.next;
7890                 break;
7891             }
7892         case Ttuple:
7893             {
7894                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
7895                 if (exp.e2.type == Type.terror)
7896                     return setError();
7897 
7898                 exp.e2 = exp.e2.ctfeInterpret();
7899                 uinteger_t index = exp.e2.toUInteger();
7900 
7901                 TupleExp te;
7902                 TypeTuple tup;
7903                 size_t length;
7904                 if (exp.e1.op == TOK.tuple)
7905                 {
7906                     te = cast(TupleExp)exp.e1;
7907                     tup = null;
7908                     length = te.exps.dim;
7909                 }
7910                 else if (exp.e1.op == TOK.type)
7911                 {
7912                     te = null;
7913                     tup = cast(TypeTuple)t1b;
7914                     length = Parameter.dim(tup.arguments);
7915                 }
7916                 else
7917                     assert(0);
7918 
7919                 if (length <= index)
7920                 {
7921                     exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
7922                     return setError();
7923                 }
7924                 Expression e;
7925                 if (exp.e1.op == TOK.tuple)
7926                 {
7927                     e = (*te.exps)[cast(size_t)index];
7928                     e = Expression.combine(te.e0, e);
7929                 }
7930                 else
7931                     e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
7932                 result = e;
7933                 return;
7934             }
7935         default:
7936             exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
7937             return setError();
7938         }
7939 
7940         // We might know $ now
7941         setLengthVarIfKnown(exp.lengthVar, t1b);
7942 
7943         if (t1b.ty == Tsarray || t1b.ty == Tarray)
7944         {
7945             Expression el = new ArrayLengthExp(exp.loc, exp.e1);
7946             el = el.expressionSemantic(sc);
7947             el = el.optimize(WANTvalue);
7948             if (el.op == TOK.int64)
7949             {
7950                 exp.e2 = exp.e2.optimize(WANTvalue);
7951                 dinteger_t length = el.toInteger();
7952                 if (length)
7953                 {
7954                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
7955                     exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2));
7956                 }
7957             }
7958         }
7959 
7960         result = exp;
7961     }
7962 
7963     override void visit(PostExp exp)
7964     {
7965         static if (LOGSEMANTIC)
7966         {
7967             printf("PostExp::semantic('%s')\n", exp.toChars());
7968         }
7969         if (exp.type)
7970         {
7971             result = exp;
7972             return;
7973         }
7974 
7975         if (Expression ex = binSemantic(exp, sc))
7976         {
7977             result = ex;
7978             return;
7979         }
7980         Expression e1x = resolveProperties(sc, exp.e1);
7981         if (e1x.op == TOK.error)
7982         {
7983             result = e1x;
7984             return;
7985         }
7986         exp.e1 = e1x;
7987 
7988         Expression e = exp.op_overload(sc);
7989         if (e)
7990         {
7991             result = e;
7992             return;
7993         }
7994 
7995         if (exp.e1.checkReadModifyWrite(exp.op))
7996             return setError();
7997 
7998         if (exp.e1.op == TOK.slice)
7999         {
8000             const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement";
8001             exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8002             return setError();
8003         }
8004 
8005         exp.e1 = exp.e1.optimize(WANTvalue);
8006 
8007         Type t1 = exp.e1.type.toBasetype();
8008         if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength)
8009         {
8010             /* Check for operator overloading,
8011              * but rewrite in terms of ++e instead of e++
8012              */
8013 
8014             /* If e1 is not trivial, take a reference to it
8015              */
8016             Expression de = null;
8017             if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength)
8018             {
8019                 // ref v = e1;
8020                 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8021                 de = new DeclarationExp(exp.loc, v);
8022                 exp.e1 = new VarExp(exp.e1.loc, v);
8023             }
8024 
8025             /* Rewrite as:
8026              * auto tmp = e1; ++e1; tmp
8027              */
8028             auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8029             Expression ea = new DeclarationExp(exp.loc, tmp);
8030 
8031             Expression eb = exp.e1.syntaxCopy();
8032             eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb);
8033 
8034             Expression ec = new VarExp(exp.loc, tmp);
8035 
8036             // Combine de,ea,eb,ec
8037             if (de)
8038                 ea = new CommaExp(exp.loc, de, ea);
8039             e = new CommaExp(exp.loc, ea, eb);
8040             e = new CommaExp(exp.loc, e, ec);
8041             e = e.expressionSemantic(sc);
8042             result = e;
8043             return;
8044         }
8045 
8046         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8047 
8048         e = exp;
8049         if (exp.e1.checkScalar() ||
8050             exp.e1.checkSharedAccess(sc))
8051             return setError();
8052         if (exp.e1.checkNoBool())
8053             return setError();
8054 
8055         if (exp.e1.type.ty == Tpointer)
8056             e = scaleFactor(exp, sc);
8057         else
8058             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8059         e.type = exp.e1.type;
8060         result = e;
8061     }
8062 
8063     override void visit(PreExp exp)
8064     {
8065         Expression e = exp.op_overload(sc);
8066         // printf("PreExp::semantic('%s')\n", toChars());
8067         if (e)
8068         {
8069             result = e;
8070             return;
8071         }
8072 
8073         // Rewrite as e1+=1 or e1-=1
8074         if (exp.op == TOK.prePlusPlus)
8075             e = new AddAssignExp(exp.loc, exp.e1, new IntegerExp(exp.loc, 1, Type.tint32));
8076         else
8077             e = new MinAssignExp(exp.loc, exp.e1, new IntegerExp(exp.loc, 1, Type.tint32));
8078         result = e.expressionSemantic(sc);
8079     }
8080 
8081     /*
8082      * Get the expression initializer for a specific struct
8083      *
8084      * Params:
8085      *  sd = the struct for which the expression initializer is needed
8086      *  loc = the location of the initializer
8087      *  sc = the scope where the expression is located
8088      *  t = the type of the expression
8089      *
8090      * Returns:
8091      *  The expression initializer or error expression if any errors occured
8092      */
8093     private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8094     {
8095         if (sd.zeroInit && !sd.isNested())
8096         {
8097             // https://issues.dlang.org/show_bug.cgi?id=14606
8098             // Always use BlitExp for the special expression: (struct = 0)
8099             return new IntegerExp(loc, 0, Type.tint32);
8100         }
8101 
8102         if (sd.isNested())
8103         {
8104             auto sle = new StructLiteralExp(loc, sd, null, t);
8105             if (!sd.fill(loc, sle.elements, true))
8106                 return new ErrorExp();
8107             if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
8108                 return new ErrorExp();
8109 
8110             sle.type = t;
8111             return sle;
8112         }
8113 
8114         return t.defaultInit(loc);
8115     }
8116 
8117     override void visit(AssignExp exp)
8118     {
8119         static if (LOGSEMANTIC)
8120         {
8121             printf("AssignExp::semantic('%s')\n", exp.toChars());
8122         }
8123         //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op));
8124         //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op));
8125 
8126         void setResult(Expression e, int line = __LINE__)
8127         {
8128             //printf("line %d\n", line);
8129             result = e;
8130         }
8131 
8132         if (exp.type)
8133         {
8134             return setResult(exp);
8135         }
8136 
8137         Expression e1old = exp.e1;
8138 
8139         if (auto e2comma = exp.e2.isCommaExp())
8140         {
8141             if (!e2comma.isGenerated)
8142                 exp.error("Using the result of a comma expression is not allowed");
8143 
8144             /* Rewrite to get rid of the comma from rvalue
8145              *   e1=(e0,e2) => e0,(e1=e2)
8146              */
8147             Expression e0;
8148             exp.e2 = Expression.extractLast(e2comma, e0);
8149             Expression e = Expression.combine(e0, exp);
8150             return setResult(e.expressionSemantic(sc));
8151         }
8152 
8153         /* Look for operator overloading of a[arguments] = e2.
8154          * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8155          * converted to unary operator overloading already.
8156          */
8157         if (auto ae = exp.e1.isArrayExp())
8158         {
8159             Expression res;
8160 
8161             ae.e1 = ae.e1.expressionSemantic(sc);
8162             ae.e1 = resolveProperties(sc, ae.e1);
8163             Expression ae1old = ae.e1;
8164 
8165             const(bool) maybeSlice =
8166                 (ae.arguments.dim == 0 ||
8167                  ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval);
8168 
8169             IntervalExp ie = null;
8170             if (maybeSlice && ae.arguments.dim)
8171             {
8172                 assert((*ae.arguments)[0].op == TOK.interval);
8173                 ie = cast(IntervalExp)(*ae.arguments)[0];
8174             }
8175             while (true)
8176             {
8177                 if (ae.e1.op == TOK.error)
8178                     return setResult(ae.e1);
8179 
8180                 Expression e0 = null;
8181                 Expression ae1save = ae.e1;
8182                 ae.lengthVar = null;
8183 
8184                 Type t1b = ae.e1.type.toBasetype();
8185                 AggregateDeclaration ad = isAggregate(t1b);
8186                 if (!ad)
8187                     break;
8188                 if (search_function(ad, Id.indexass))
8189                 {
8190                     // Deal with $
8191                     res = resolveOpDollar(sc, ae, &e0);
8192                     if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8193                         goto Lfallback;
8194                     if (res.op == TOK.error)
8195                         return setResult(res);
8196 
8197                     res = exp.e2.expressionSemantic(sc);
8198                     if (res.op == TOK.error)
8199                         return setResult(res);
8200                     exp.e2 = res;
8201 
8202                     /* Rewrite (a[arguments] = e2) as:
8203                      *      a.opIndexAssign(e2, arguments)
8204                      */
8205                     Expressions* a = ae.arguments.copy();
8206                     a.insert(0, exp.e2);
8207                     res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8208                     res = new CallExp(exp.loc, res, a);
8209                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8210                         res = res.trySemantic(sc);
8211                     else
8212                         res = res.expressionSemantic(sc);
8213                     if (res)
8214                         return setResult(Expression.combine(e0, res));
8215                 }
8216 
8217             Lfallback:
8218                 if (maybeSlice && search_function(ad, Id.sliceass))
8219                 {
8220                     // Deal with $
8221                     res = resolveOpDollar(sc, ae, ie, &e0);
8222                     if (res.op == TOK.error)
8223                         return setResult(res);
8224 
8225                     res = exp.e2.expressionSemantic(sc);
8226                     if (res.op == TOK.error)
8227                         return setResult(res);
8228 
8229                     exp.e2 = res;
8230 
8231                     /* Rewrite (a[i..j] = e2) as:
8232                      *      a.opSliceAssign(e2, i, j)
8233                      */
8234                     auto a = new Expressions();
8235                     a.push(exp.e2);
8236                     if (ie)
8237                     {
8238                         a.push(ie.lwr);
8239                         a.push(ie.upr);
8240                     }
8241                     res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8242                     res = new CallExp(exp.loc, res, a);
8243                     res = res.expressionSemantic(sc);
8244                     return setResult(Expression.combine(e0, res));
8245                 }
8246 
8247                 // No operator overloading member function found yet, but
8248                 // there might be an alias this to try.
8249                 if (ad.aliasthis && t1b != ae.att1)
8250                 {
8251                     if (!ae.att1 && t1b.checkAliasThisRec())
8252                         ae.att1 = t1b;
8253 
8254                     /* Rewrite (a[arguments] op e2) as:
8255                      *      a.aliasthis[arguments] op e2
8256                      */
8257                     ae.e1 = resolveAliasThis(sc, ae1save, true);
8258                     if (ae.e1)
8259                         continue;
8260                 }
8261                 break;
8262             }
8263             ae.e1 = ae1old; // recovery
8264             ae.lengthVar = null;
8265         }
8266 
8267         /* Run this.e1 semantic.
8268          */
8269         {
8270             Expression e1x = exp.e1;
8271 
8272             /* With UFCS, e.f = value
8273              * Could mean:
8274              *      .f(e, value)
8275              * or:
8276              *      .f(e) = value
8277              */
8278             if (auto dti = e1x.isDotTemplateInstanceExp())
8279             {
8280                 Expression e = dti.semanticY(sc, 1);
8281                 if (!e)
8282                 {
8283                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8284                 }
8285 
8286                 e1x = e;
8287             }
8288             else if (auto die = e1x.isDotIdExp())
8289             {
8290                 Expression e = die.semanticY(sc, 1);
8291                 if (e && isDotOpDispatch(e))
8292                 {
8293                     /* https://issues.dlang.org/show_bug.cgi?id=19687
8294                      *
8295                      * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8296                      * but that call is done with gagged errors. That is the only time when
8297                      * semantic gets ran on e2, that is why the error never gets to be printed.
8298                      * In order to make sure that UFCS is tried with correct parameters, e2
8299                      * needs to have semantic ran on it.
8300                      */
8301                     exp.e2 = exp.e2.expressionSemantic(sc);
8302                     uint errors = global.startGagging();
8303                     e = resolvePropertiesX(sc, e, exp.e2);
8304                     if (global.endGagging(errors))
8305                         e = null; /* fall down to UFCS */
8306                     else
8307                         return setResult(e);
8308                 }
8309                 if (!e)
8310                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8311                 e1x = e;
8312             }
8313             else
8314             {
8315                 if (auto se = e1x.isSliceExp())
8316                     se.arrayop = true;
8317 
8318                 e1x = e1x.expressionSemantic(sc);
8319             }
8320 
8321             /* We have f = value.
8322              * Could mean:
8323              *      f(value)
8324              * or:
8325              *      f() = value
8326              */
8327             if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8328                 return setResult(e);
8329 
8330             if (e1x.checkRightThis(sc))
8331             {
8332                 return setError();
8333             }
8334             exp.e1 = e1x;
8335             assert(exp.e1.type);
8336         }
8337         Type t1 = exp.e1.type.toBasetype();
8338 
8339         /* Run this.e2 semantic.
8340          * Different from other binary expressions, the analysis of e2
8341          * depends on the result of e1 in assignments.
8342          */
8343         {
8344             Expression e2x = inferType(exp.e2, t1.baseElemOf());
8345             e2x = e2x.expressionSemantic(sc);
8346             e2x = resolveProperties(sc, e2x);
8347             if (e2x.op == TOK.type)
8348                 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8349             if (e2x.op == TOK.error)
8350                 return setResult(e2x);
8351             if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8352                 return setError();
8353             exp.e2 = e2x;
8354         }
8355 
8356         /* Rewrite tuple assignment as a tuple of assignments.
8357          */
8358         {
8359             Expression e2x = exp.e2;
8360 
8361         Ltupleassign:
8362             if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple)
8363             {
8364                 TupleExp tup1 = cast(TupleExp)exp.e1;
8365                 TupleExp tup2 = cast(TupleExp)e2x;
8366                 size_t dim = tup1.exps.dim;
8367                 Expression e = null;
8368                 if (dim != tup2.exps.dim)
8369                 {
8370                     exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
8371                     return setError();
8372                 }
8373                 if (dim == 0)
8374                 {
8375                     e = new IntegerExp(exp.loc, 0, Type.tint32);
8376                     e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8377                     e = Expression.combine(tup1.e0, tup2.e0, e);
8378                 }
8379                 else
8380                 {
8381                     auto exps = new Expressions(dim);
8382                     for (size_t i = 0; i < dim; i++)
8383                     {
8384                         Expression ex1 = (*tup1.exps)[i];
8385                         Expression ex2 = (*tup2.exps)[i];
8386                         (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8387                     }
8388                     e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8389                 }
8390                 return setResult(e.expressionSemantic(sc));
8391             }
8392 
8393             /* Look for form: e1 = e2.aliasthis.
8394              */
8395             if (exp.e1.op == TOK.tuple)
8396             {
8397                 TupleDeclaration td = isAliasThisTuple(e2x);
8398                 if (!td)
8399                     goto Lnomatch;
8400 
8401                 assert(exp.e1.type.ty == Ttuple);
8402                 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8403 
8404                 Expression e0;
8405                 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8406 
8407                 auto iexps = new Expressions();
8408                 iexps.push(ev);
8409                 for (size_t u = 0; u < iexps.dim; u++)
8410                 {
8411                 Lexpand:
8412                     Expression e = (*iexps)[u];
8413 
8414                     Parameter arg = Parameter.getNth(tt.arguments, u);
8415                     //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
8416                     //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars());
8417                     //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
8418 
8419                     if (!arg || !e.type.implicitConvTo(arg.type))
8420                     {
8421                         // expand initializer to tuple
8422                         if (expandAliasThisTuples(iexps, u) != -1)
8423                         {
8424                             if (iexps.dim <= u)
8425                                 break;
8426                             goto Lexpand;
8427                         }
8428                         goto Lnomatch;
8429                     }
8430                 }
8431                 e2x = new TupleExp(e2x.loc, e0, iexps);
8432                 e2x = e2x.expressionSemantic(sc);
8433                 if (e2x.op == TOK.error)
8434                 {
8435                     result = e2x;
8436                     return;
8437                 }
8438                 // Do not need to overwrite this.e2
8439                 goto Ltupleassign;
8440             }
8441         Lnomatch:
8442         }
8443 
8444         exp.e1.checkSharedAccess(sc);
8445 
8446         /* Inside constructor, if this is the first assignment of object field,
8447          * rewrite this to initializing the field.
8448          */
8449         if (exp.op == TOK.assign
8450             && exp.e1.checkModifiable(sc) == Modifiable.initialization)
8451         {
8452             //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
8453             auto t = exp.type;
8454             exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
8455             exp.type = t;
8456 
8457             // @@@DEPRECATED_2020-06@@@
8458             // When removing, alter `checkModifiable` to return the correct value.
8459             if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() &&
8460                 exp.e1.type.isImmutable())
8461             {
8462                 deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated.");
8463                 deprecationSupplemental(exp.loc, "Use `shared static this` instead.");
8464             }
8465 
8466             // https://issues.dlang.org/show_bug.cgi?id=13515
8467             // set Index::modifiable flag for complex AA element initialization
8468             if (auto ie1 = exp.e1.isIndexExp())
8469             {
8470                 Expression e1x = ie1.markSettingAAElem();
8471                 if (e1x.op == TOK.error)
8472                 {
8473                     result = e1x;
8474                     return;
8475                 }
8476             }
8477         }
8478         else if (exp.op == TOK.construct && exp.e1.op == TOK.variable &&
8479                  (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
8480         {
8481             exp.memset |= MemorySet.referenceInit;
8482         }
8483 
8484         /* If it is an assignment from a 'foreign' type,
8485          * check for operator overloading.
8486          */
8487         if (exp.memset & MemorySet.referenceInit)
8488         {
8489             // If this is an initialization of a reference,
8490             // do nothing
8491         }
8492         else if (t1.ty == Tstruct)
8493         {
8494             auto e1x = exp.e1;
8495             auto e2x = exp.e2;
8496             auto sd = (cast(TypeStruct)t1).sym;
8497 
8498             if (exp.op == TOK.construct)
8499             {
8500                 Type t2 = e2x.type.toBasetype();
8501                 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
8502                 {
8503                     sd.size(exp.loc);
8504                     if (sd.sizeok != Sizeok.done)
8505                         return setError();
8506                     if (!sd.ctor)
8507                         sd.ctor = sd.searchCtor();
8508 
8509                     // https://issues.dlang.org/show_bug.cgi?id=15661
8510                     // Look for the form from last of comma chain.
8511                     auto e2y = lastComma(e2x);
8512 
8513                     CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null;
8514                     DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable)
8515                         ? cast(DotVarExp)ce.e1 : null;
8516                     if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
8517                         // https://issues.dlang.org/show_bug.cgi?id=19389
8518                         dve.e1.op != TOK.dotVariable &&
8519                         e2y.type.implicitConvTo(t1))
8520                     {
8521                         /* Look for form of constructor call which is:
8522                          *    __ctmp.ctor(arguments...)
8523                          */
8524 
8525                         /* Before calling the constructor, initialize
8526                          * variable with a bit copy of the default
8527                          * initializer
8528                          */
8529                         Expression einit = getInitExp(sd, exp.loc, sc, t1);
8530                         if (einit.op == TOK.error)
8531                         {
8532                             result = einit;
8533                             return;
8534                         }
8535 
8536                         auto ae = new BlitExp(exp.loc, exp.e1, einit);
8537                         ae.type = e1x.type;
8538 
8539                         /* Replace __ctmp being constructed with e1.
8540                          * We need to copy constructor call expression,
8541                          * because it may be used in other place.
8542                          */
8543                         auto dvx = cast(DotVarExp)dve.copy();
8544                         dvx.e1 = e1x;
8545                         auto cx = cast(CallExp)ce.copy();
8546                         cx.e1 = dvx;
8547                         if (checkConstructorEscape(sc, cx, false))
8548                             return setError();
8549 
8550                         Expression e0;
8551                         Expression.extractLast(e2x, e0);
8552 
8553                         auto e = Expression.combine(e0, ae, cx);
8554                         e = e.expressionSemantic(sc);
8555                         result = e;
8556                         return;
8557                     }
8558                     if (sd.postblit || sd.hasCopyCtor)
8559                     {
8560                         /* We have a copy constructor for this
8561                          */
8562                         if (e2x.op == TOK.question)
8563                         {
8564                             /* Rewrite as:
8565                              *  a ? e1 = b : e1 = c;
8566                              */
8567                             CondExp econd = cast(CondExp)e2x;
8568                             Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
8569                             Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2);
8570                             Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
8571                             result = e.expressionSemantic(sc);
8572                             return;
8573                         }
8574 
8575                         if (e2x.isLvalue())
8576                         {
8577                             if (sd.hasCopyCtor)
8578                             {
8579                                 /* Rewrite as:
8580                                  * e1 = init, e1.copyCtor(e2);
8581                                  */
8582                                 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
8583                                 einit.type = e1x.type;
8584 
8585                                 Expression e;
8586                                 e = new DotIdExp(exp.loc, e1x, Id.ctor);
8587                                 e = new CallExp(exp.loc, e, e2x);
8588                                 e = new CommaExp(exp.loc, einit, e);
8589 
8590                                 //printf("e: %s\n", e.toChars());
8591 
8592                                 result = e.expressionSemantic(sc);
8593                                 return;
8594                             }
8595                             else
8596                             {
8597                                 if (!e2x.type.implicitConvTo(e1x.type))
8598                                 {
8599                                     exp.error("conversion error from `%s` to `%s`",
8600                                         e2x.type.toChars(), e1x.type.toChars());
8601                                     return setError();
8602                                 }
8603 
8604                                 /* Rewrite as:
8605                                  *  (e1 = e2).postblit();
8606                                  *
8607                                  * Blit assignment e1 = e2 returns a reference to the original e1,
8608                                  * then call the postblit on it.
8609                                  */
8610                                 Expression e = e1x.copy();
8611                                 e.type = e.type.mutableOf();
8612                                 if (e.type.isShared && !sd.type.isShared)
8613                                     e.type = e.type.unSharedOf();
8614                                 e = new BlitExp(exp.loc, e, e2x);
8615                                 e = new DotVarExp(exp.loc, e, sd.postblit, false);
8616                                 e = new CallExp(exp.loc, e);
8617                                 result = e.expressionSemantic(sc);
8618                                 return;
8619                             }
8620                         }
8621                         else
8622                         {
8623                             /* The struct value returned from the function is transferred
8624                              * so should not call the destructor on it.
8625                              */
8626                             e2x = valueNoDtor(e2x);
8627                         }
8628                     }
8629 
8630                     // https://issues.dlang.org/show_bug.cgi?id=19251
8631                     // if e2 cannot be converted to e1.type, maybe there is an alias this
8632                     if (!e2x.implicitConvTo(t1))
8633                     {
8634                         AggregateDeclaration ad2 = isAggregate(e2x.type);
8635                         if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2))
8636                         {
8637                             if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8638                             exp.att2 = exp.e2.type;
8639                             /* Rewrite (e1 op e2) as:
8640                              *      (e1 op e2.aliasthis)
8641                              */
8642                             exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8643                             result = exp.expressionSemantic(sc);
8644                             return;
8645                         }
8646                     }
8647                 }
8648                 else if (!e2x.implicitConvTo(t1))
8649                 {
8650                     sd.size(exp.loc);
8651                     if (sd.sizeok != Sizeok.done)
8652                         return setError();
8653                     if (!sd.ctor)
8654                         sd.ctor = sd.searchCtor();
8655 
8656                     if (sd.ctor)
8657                     {
8658                         /* Look for implicit constructor call
8659                          * Rewrite as:
8660                          *  e1 = init, e1.ctor(e2)
8661                          */
8662 
8663                         /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
8664                          * Using `new` to initialize a struct object is a common mistake, but
8665                          * the error message from the compiler is not very helpful in that
8666                          * case. If exp.e2 is a NewExp and the type of new is the same as
8667                          * the type as exp.e1 (struct in this case), then we know for sure
8668                          * that the user wants to instantiate a struct. This is done to avoid
8669                          * issuing an error when the user actually wants to call a constructor
8670                          * which receives a class object.
8671                          *
8672                          * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
8673                          * which receives an instance of a Foo2 class
8674                          */
8675                         if (exp.e2.op == TOK.new_)
8676                         {
8677                             auto newExp = cast(NewExp)(exp.e2);
8678                             if (newExp.newtype && newExp.newtype == t1)
8679                             {
8680                                 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
8681                                       newExp.toChars(), newExp.type.toChars(), t1.toChars());
8682                                 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
8683                                 return setError();
8684                             }
8685                         }
8686 
8687                         Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
8688                         einit.type = e1x.type;
8689 
8690                         Expression e;
8691                         e = new DotIdExp(exp.loc, e1x, Id.ctor);
8692                         e = new CallExp(exp.loc, e, e2x);
8693                         e = new CommaExp(exp.loc, einit, e);
8694                         e = e.expressionSemantic(sc);
8695                         result = e;
8696                         return;
8697                     }
8698                     if (search_function(sd, Id.call))
8699                     {
8700                         /* Look for static opCall
8701                          * https://issues.dlang.org/show_bug.cgi?id=2702
8702                          * Rewrite as:
8703                          *  e1 = typeof(e1).opCall(arguments)
8704                          */
8705                         e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
8706                         e2x = new CallExp(exp.loc, e2x, exp.e2);
8707 
8708                         e2x = e2x.expressionSemantic(sc);
8709                         e2x = resolveProperties(sc, e2x);
8710                         if (e2x.op == TOK.error)
8711                         {
8712                             result = e2x;
8713                             return;
8714                         }
8715                         if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8716                             return setError();
8717                     }
8718                 }
8719                 else // https://issues.dlang.org/show_bug.cgi?id=11355
8720                 {
8721                     AggregateDeclaration ad2 = isAggregate(e2x.type);
8722                     if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2))
8723                     {
8724                         if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8725                             exp.att2 = exp.e2.type;
8726                         /* Rewrite (e1 op e2) as:
8727                          *      (e1 op e2.aliasthis)
8728                          */
8729                         exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8730                         result = exp.expressionSemantic(sc);
8731                         return;
8732                     }
8733                 }
8734             }
8735             else if (exp.op == TOK.assign)
8736             {
8737                 if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
8738                 {
8739                     /*
8740                      * Rewrite:
8741                      *      aa[key] = e2;
8742                      * as:
8743                      *      ref __aatmp = aa;
8744                      *      ref __aakey = key;
8745                      *      ref __aaval = e2;
8746                      *      (__aakey in __aatmp
8747                      *          ? __aatmp[__aakey].opAssign(__aaval)
8748                      *          : ConstructExp(__aatmp[__aakey], __aaval));
8749                      */
8750                     // ensure we keep the expr modifiable
8751                     Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
8752                     if (esetting.op == TOK.error)
8753                     {
8754                         result = esetting;
8755                         return;
8756                     }
8757                     assert(esetting.op == TOK.index);
8758                     IndexExp ie = cast(IndexExp) esetting;
8759                     Type t2 = e2x.type.toBasetype();
8760 
8761                     Expression e0 = null;
8762                     Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
8763                     Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
8764                     Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
8765 
8766                     AssignExp ae = cast(AssignExp)exp.copy();
8767                     ae.e1 = new IndexExp(exp.loc, ea, ek);
8768                     ae.e1 = ae.e1.expressionSemantic(sc);
8769                     ae.e1 = ae.e1.optimize(WANTvalue);
8770                     ae.e2 = ev;
8771                     Expression e = ae.op_overload(sc);
8772                     if (e)
8773                     {
8774                         Expression ey = null;
8775                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
8776                         {
8777                             ey = ev;
8778                         }
8779                         else if (!ev.implicitConvTo(ie.type) && sd.ctor)
8780                         {
8781                             // Look for implicit constructor call
8782                             // Rewrite as S().ctor(e2)
8783                             ey = new StructLiteralExp(exp.loc, sd, null);
8784                             ey = new DotIdExp(exp.loc, ey, Id.ctor);
8785                             ey = new CallExp(exp.loc, ey, ev);
8786                             ey = ey.trySemantic(sc);
8787                         }
8788                         if (ey)
8789                         {
8790                             Expression ex;
8791                             ex = new IndexExp(exp.loc, ea, ek);
8792                             ex = ex.expressionSemantic(sc);
8793                             ex = ex.optimize(WANTvalue);
8794                             ex = ex.modifiableLvalue(sc, ex); // allocate new slot
8795 
8796                             ey = new ConstructExp(exp.loc, ex, ey);
8797                             ey = ey.expressionSemantic(sc);
8798                             if (ey.op == TOK.error)
8799                             {
8800                                 result = ey;
8801                                 return;
8802                             }
8803                             ex = e;
8804 
8805                             // https://issues.dlang.org/show_bug.cgi?id=14144
8806                             // The whole expression should have the common type
8807                             // of opAssign() return and assigned AA entry.
8808                             // Even if there's no common type, expression should be typed as void.
8809                             Type t = null;
8810                             if (!typeMerge(sc, TOK.question, &t, &ex, &ey))
8811                             {
8812                                 ex = new CastExp(ex.loc, ex, Type.tvoid);
8813                                 ey = new CastExp(ey.loc, ey, Type.tvoid);
8814                             }
8815                             e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
8816                         }
8817                         e = Expression.combine(e0, e);
8818                         e = e.expressionSemantic(sc);
8819                         result = e;
8820                         return;
8821                     }
8822                 }
8823                 else
8824                 {
8825                     Expression e = exp.op_overload(sc);
8826                     if (e)
8827                     {
8828                         result = e;
8829                         return;
8830                     }
8831                 }
8832             }
8833             else
8834                 assert(exp.op == TOK.blit);
8835 
8836             exp.e1 = e1x;
8837             exp.e2 = e2x;
8838         }
8839         else if (t1.ty == Tclass)
8840         {
8841             // Disallow assignment operator overloads for same type
8842             if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type))
8843             {
8844                 Expression e = exp.op_overload(sc);
8845                 if (e)
8846                 {
8847                     result = e;
8848                     return;
8849                 }
8850             }
8851         }
8852         else if (t1.ty == Tsarray)
8853         {
8854             // SliceExp cannot have static array type without context inference.
8855             assert(exp.e1.op != TOK.slice);
8856             Expression e1x = exp.e1;
8857             Expression e2x = exp.e2;
8858 
8859             if (e2x.implicitConvTo(e1x.type))
8860             {
8861                 if (exp.op != TOK.blit && (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != TOK.slice && e2x.isLvalue()))
8862                 {
8863                     if (e1x.checkPostblit(sc, t1))
8864                         return setError();
8865                 }
8866 
8867                 // e2 matches to t1 because of the implicit length match, so
8868                 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
8869                 {
8870                     // convert e1 to e1[]
8871                     // e.g. e1[] = a[] + b[];
8872                     auto sle = new SliceExp(e1x.loc, e1x, null, null);
8873                     sle.arrayop = true;
8874                     e1x = sle.expressionSemantic(sc);
8875                 }
8876                 else
8877                 {
8878                     // convert e2 to t1 later
8879                     // e.g. e1 = [1, 2, 3];
8880                 }
8881             }
8882             else
8883             {
8884                 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
8885                 {
8886                     uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
8887                     uinteger_t dim2 = dim1;
8888                     if (auto ale = e2x.isArrayLiteralExp())
8889                     {
8890                         dim2 = ale.elements ? ale.elements.dim : 0;
8891                     }
8892                     else if (auto se = e2x.isSliceExp())
8893                     {
8894                         Type tx = toStaticArrayType(se);
8895                         if (tx)
8896                             dim2 = (cast(TypeSArray)tx).dim.toInteger();
8897                     }
8898                     if (dim1 != dim2)
8899                     {
8900                         exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
8901                         return setError();
8902                     }
8903                 }
8904 
8905                 // May be block or element-wise assignment, so
8906                 // convert e1 to e1[]
8907                 if (exp.op != TOK.assign)
8908                 {
8909                     // If multidimensional static array, treat as one large array
8910                     //
8911                     // Find the appropriate array type depending on the assignment, e.g.
8912                     // int[3] = int => int[3]
8913                     // int[3][2] = int => int[6]
8914                     // int[3][2] = int[] => int[3][2]
8915                     // int[3][2][4] + int => int[24]
8916                     // int[3][2][4] + int[] => int[3][8]
8917                     ulong dim = t1.isTypeSArray().dim.toUInteger();
8918                     auto type = t1.nextOf();
8919 
8920                     for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
8921                     {
8922                         import core.checkedint : mulu;
8923 
8924                         // Accumulate skipped dimensions
8925                         bool overflow = false;
8926                         dim = mulu(dim, tsa.dim.toUInteger(), overflow);
8927                         if (overflow || dim >= uint.max)
8928                         {
8929                             // dym exceeds maximum array size
8930                             exp.error("static array `%s` size overflowed to %llu",
8931                                         e1x.type.toChars(), cast(ulong) dim);
8932                             return setError();
8933                         }
8934 
8935                         // Move to the element type
8936                         type = tsa.nextOf().toBasetype();
8937 
8938                         // Rewrite ex1 as a static array if a matching type was found
8939                         if (e2x.implicitConvTo(type) > MATCH.nomatch)
8940                         {
8941                             e1x.type = type.sarrayOf(dim);
8942                             break;
8943                         }
8944                     }
8945                 }
8946                 auto sle = new SliceExp(e1x.loc, e1x, null, null);
8947                 sle.arrayop = true;
8948                 e1x = sle.expressionSemantic(sc);
8949             }
8950             if (e1x.op == TOK.error)
8951                 return setResult(e1x);
8952             if (e2x.op == TOK.error)
8953                 return setResult(e2x);
8954 
8955             exp.e1 = e1x;
8956             exp.e2 = e2x;
8957             t1 = e1x.type.toBasetype();
8958         }
8959         /* Check the mutability of e1.
8960          */
8961         if (auto ale = exp.e1.isArrayLengthExp())
8962         {
8963             // e1 is not an lvalue, but we let code generator handle it
8964 
8965             auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
8966             if (ale1x.op == TOK.error)
8967                 return setResult(ale1x);
8968             ale.e1 = ale1x;
8969 
8970             Type tn = ale.e1.type.toBasetype().nextOf();
8971             checkDefCtor(ale.loc, tn);
8972 
8973             Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
8974             if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
8975                 return setError();
8976 
8977             // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
8978             Expression id = new IdentifierExp(ale.loc, Id.empty);
8979             id = new DotIdExp(ale.loc, id, Id.object);
8980             auto tiargs = new Objects();
8981             tiargs.push(ale.e1.type);
8982             id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
8983             id = new DotIdExp(ale.loc, id, hook);
8984             id = id.expressionSemantic(sc);
8985 
8986             auto arguments = new Expressions();
8987             arguments.reserve(5);
8988             if (global.params.tracegc)
8989             {
8990                 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
8991                 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
8992                 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
8993                 arguments.push(new StringExp(exp.loc, funcname.toDString()));
8994             }
8995             arguments.push(ale.e1);
8996             arguments.push(exp.e2);
8997 
8998             Expression ce = new CallExp(ale.loc, id, arguments);
8999             auto res = ce.expressionSemantic(sc);
9000             // if (global.params.verbose)
9001             //     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
9002             return setResult(res);
9003         }
9004         else if (auto se = exp.e1.isSliceExp())
9005         {
9006             Type tn = se.type.nextOf();
9007             const fun = sc.func;
9008             if (exp.op == TOK.assign && !tn.isMutable() &&
9009                 // allow modifiation in module ctor, see
9010                 // https://issues.dlang.org/show_bug.cgi?id=9884
9011                 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9012             {
9013                 exp.error("slice `%s` is not mutable", se.toChars());
9014                 return setError();
9015             }
9016 
9017             if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable())
9018             {
9019                 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9020                     exp.e1.toChars(), tn.baseElemOf().toChars());
9021                 result = new ErrorExp();
9022                 return;
9023             }
9024 
9025             // For conditional operator, both branches need conversion.
9026             while (se.e1.op == TOK.slice)
9027                 se = cast(SliceExp)se.e1;
9028             if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray)
9029             {
9030                 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9031                 if (se.e1.op == TOK.error)
9032                     return setResult(se.e1);
9033             }
9034         }
9035         else
9036         {
9037             if (t1.ty == Tsarray && exp.op == TOK.assign)
9038             {
9039                 Type tn = exp.e1.type.nextOf();
9040                 if (tn && !tn.baseElemOf().isAssignable())
9041                 {
9042                     exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9043                         exp.e1.toChars(), tn.baseElemOf().toChars());
9044                     result = new ErrorExp();
9045                     return;
9046                 }
9047             }
9048 
9049             Expression e1x = exp.e1;
9050 
9051             // Try to do a decent error message with the expression
9052             // before it got constant folded
9053 
9054             if (e1x.op != TOK.variable)
9055                 e1x = e1x.optimize(WANTvalue);
9056 
9057             if (exp.op == TOK.assign)
9058                 e1x = e1x.modifiableLvalue(sc, e1old);
9059 
9060             if (checkIfIsStructLiteralDotExpr(e1x))
9061                 return setError();
9062 
9063             if (e1x.op == TOK.error)
9064             {
9065                 result = e1x;
9066                 return;
9067             }
9068             exp.e1 = e1x;
9069         }
9070 
9071         /* Tweak e2 based on the type of e1.
9072          */
9073         Expression e2x = exp.e2;
9074         Type t2 = e2x.type.toBasetype();
9075 
9076         // If it is a array, get the element type. Note that it may be
9077         // multi-dimensional.
9078         Type telem = t1;
9079         while (telem.ty == Tarray)
9080             telem = telem.nextOf();
9081 
9082         if (exp.e1.op == TOK.slice && t1.nextOf() &&
9083             (telem.ty != Tvoid || e2x.op == TOK.null_) &&
9084             e2x.implicitConvTo(t1.nextOf()))
9085         {
9086             // Check for block assignment. If it is of type void[], void[][], etc,
9087             // '= null' is the only allowable block assignment (Bug 7493)
9088             exp.memset |= MemorySet.blockAssign;    // make it easy for back end to tell what this is
9089             e2x = e2x.implicitCastTo(sc, t1.nextOf());
9090             if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9091                 return setError();
9092         }
9093         else if (exp.e1.op == TOK.slice &&
9094                  (t2.ty == Tarray || t2.ty == Tsarray) &&
9095                  t2.nextOf().implicitConvTo(t1.nextOf()))
9096         {
9097             // Check element-wise assignment.
9098 
9099             /* If assigned elements number is known at compile time,
9100              * check the mismatch.
9101              */
9102             SliceExp se1 = cast(SliceExp)exp.e1;
9103             TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9104             TypeSArray tsa2 = null;
9105             if (auto ale = e2x.isArrayLiteralExp())
9106                 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
9107             else if (auto se = e2x.isSliceExp())
9108                 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9109             else
9110                 tsa2 = t2.isTypeSArray();
9111             if (tsa1 && tsa2)
9112             {
9113                 uinteger_t dim1 = tsa1.dim.toInteger();
9114                 uinteger_t dim2 = tsa2.dim.toInteger();
9115                 if (dim1 != dim2)
9116                 {
9117                     exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9118                     return setError();
9119                 }
9120             }
9121 
9122             if (exp.op != TOK.blit &&
9123                 (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9124                  e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9125                  e2x.op != TOK.slice && e2x.isLvalue()))
9126             {
9127                 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9128                     return setError();
9129             }
9130 
9131             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9132                 e2x.op != TOK.slice && e2x.op != TOK.assign &&
9133                 e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ &&
9134                 !(e2x.op == TOK.add || e2x.op == TOK.min ||
9135                   e2x.op == TOK.mul || e2x.op == TOK.div ||
9136                   e2x.op == TOK.mod || e2x.op == TOK.xor ||
9137                   e2x.op == TOK.and || e2x.op == TOK.or ||
9138                   e2x.op == TOK.pow ||
9139                   e2x.op == TOK.tilde || e2x.op == TOK.negate))
9140             {
9141                 const(char)* e1str = exp.e1.toChars();
9142                 const(char)* e2str = e2x.toChars();
9143                 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9144             }
9145 
9146             Type t2n = t2.nextOf();
9147             Type t1n = t1.nextOf();
9148             int offset;
9149             if (t2n.equivalent(t1n) ||
9150                 t1n.isBaseOf(t2n, &offset) && offset == 0)
9151             {
9152                 /* Allow copy of distinct qualifier elements.
9153                  * eg.
9154                  *  char[] dst;  const(char)[] src;
9155                  *  dst[] = src;
9156                  *
9157                  *  class C {}   class D : C {}
9158                  *  C[2] ca;  D[] da;
9159                  *  ca[] = da;
9160                  */
9161                 if (isArrayOpValid(e2x))
9162                 {
9163                     // Don't add CastExp to keep AST for array operations
9164                     e2x = e2x.copy();
9165                     e2x.type = exp.e1.type.constOf();
9166                 }
9167                 else
9168                     e2x = e2x.castTo(sc, exp.e1.type.constOf());
9169             }
9170             else
9171             {
9172                 /* https://issues.dlang.org/show_bug.cgi?id=15778
9173                  * A string literal has an array type of immutable
9174                  * elements by default, and normally it cannot be convertible to
9175                  * array type of mutable elements. But for element-wise assignment,
9176                  * elements need to be const at best. So we should give a chance
9177                  * to change code unit size for polysemous string literal.
9178                  */
9179                 if (e2x.op == TOK.string_)
9180                     e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9181                 else
9182                     e2x = e2x.implicitCastTo(sc, exp.e1.type);
9183             }
9184             if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9185             {
9186                 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
9187                 {
9188                     exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
9189                     return setError();
9190                 }
9191             }
9192         }
9193         else
9194         {
9195             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9196                 t1.ty == Tarray && t2.ty == Tsarray &&
9197                 e2x.op != TOK.slice &&
9198                 t2.implicitConvTo(t1))
9199             {
9200                 // Disallow ar[] = sa (Converted to ar[] = sa[])
9201                 // Disallow da   = sa (Converted to da   = sa[])
9202                 const(char)* e1str = exp.e1.toChars();
9203                 const(char)* e2str = e2x.toChars();
9204                 const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice";
9205                 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9206             }
9207             if (exp.op == TOK.blit)
9208                 e2x = e2x.castTo(sc, exp.e1.type);
9209             else
9210             {
9211                 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9212 
9213                 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9214 
9215                 // If the implicit cast has failed and the assign expression is
9216                 // the initialization of a struct member field
9217                 if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct)
9218                 {
9219                     scope sd = (cast(TypeStruct)t1).sym;
9220                     Dsymbol opAssign = search_function(sd, Id.assign);
9221 
9222                     // and the struct defines an opAssign
9223                     if (opAssign)
9224                     {
9225                         // offer more information about the cause of the problem
9226                         errorSupplemental(exp.loc,
9227                                           "`%s` is the first assignment of `%s` therefore it represents its initialization",
9228                                           exp.toChars(), exp.e1.toChars());
9229                         errorSupplemental(exp.loc,
9230                                           "`opAssign` methods are not used for initialization, but for subsequent assignments");
9231                     }
9232                 }
9233             }
9234         }
9235         if (e2x.op == TOK.error)
9236         {
9237             result = e2x;
9238             return;
9239         }
9240         exp.e2 = e2x;
9241         t2 = exp.e2.type.toBasetype();
9242 
9243         /* Look for array operations
9244          */
9245         if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9246         {
9247             // Look for valid array operations
9248             if (!(exp.memset & MemorySet.blockAssign) &&
9249                 exp.e1.op == TOK.slice &&
9250                 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9251             {
9252                 exp.type = exp.e1.type;
9253                 if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9254                                         // tweak mutability of e1 element
9255                     exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9256                 result = arrayOp(exp, sc);
9257                 return;
9258             }
9259 
9260             // Drop invalid array operations in e2
9261             //  d = a[] + b[], d = (a[] + b[])[0..2], etc
9262             if (checkNonAssignmentArrayOp(exp.e2, !(exp.memset & MemorySet.blockAssign) && exp.op == TOK.assign))
9263                 return setError();
9264 
9265             // Remains valid array assignments
9266             //  d = d[], d = [1,2,3], etc
9267         }
9268 
9269         /* Don't allow assignment to classes that were allocated on the stack with:
9270          *      scope Class c = new Class();
9271          */
9272         if (exp.e1.op == TOK.variable && exp.op == TOK.assign)
9273         {
9274             VarExp ve = cast(VarExp)exp.e1;
9275             VarDeclaration vd = ve.var.isVarDeclaration();
9276             if (vd && (vd.onstack || vd.mynew))
9277             {
9278                 assert(t1.ty == Tclass);
9279                 exp.error("cannot rebind scope variables");
9280             }
9281         }
9282 
9283         if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9284         {
9285             exp.error("cannot modify compiler-generated variable `__ctfe`");
9286         }
9287 
9288         exp.type = exp.e1.type;
9289         assert(exp.type);
9290         auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
9291         checkAssignEscape(sc, res, false);
9292         return setResult(res);
9293     }
9294 
9295     override void visit(PowAssignExp exp)
9296     {
9297         if (exp.type)
9298         {
9299             result = exp;
9300             return;
9301         }
9302 
9303         Expression e = exp.op_overload(sc);
9304         if (e)
9305         {
9306             result = e;
9307             return;
9308         }
9309 
9310         if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
9311             return setError();
9312 
9313         assert(exp.e1.type && exp.e2.type);
9314         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
9315         {
9316             if (checkNonAssignmentArrayOp(exp.e1))
9317                 return setError();
9318 
9319             // T[] ^^= ...
9320             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
9321             {
9322                 // T[] ^^= T
9323                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
9324             }
9325             else if (Expression ex = typeCombine(exp, sc))
9326             {
9327                 result = ex;
9328                 return;
9329             }
9330 
9331             // Check element types are arithmetic
9332             Type tb1 = exp.e1.type.nextOf().toBasetype();
9333             Type tb2 = exp.e2.type.toBasetype();
9334             if (tb2.ty == Tarray || tb2.ty == Tsarray)
9335                 tb2 = tb2.nextOf().toBasetype();
9336             if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
9337             {
9338                 exp.type = exp.e1.type;
9339                 result = arrayOp(exp, sc);
9340                 return;
9341             }
9342         }
9343         else
9344         {
9345             exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9346         }
9347 
9348         if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
9349         {
9350             Expression e0 = null;
9351             e = exp.reorderSettingAAElem(sc);
9352             e = Expression.extractLast(e, e0);
9353             assert(e == exp);
9354 
9355             if (exp.e1.op == TOK.variable)
9356             {
9357                 // Rewrite: e1 = e1 ^^ e2
9358                 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
9359                 e = new AssignExp(exp.loc, exp.e1, e);
9360             }
9361             else
9362             {
9363                 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
9364                 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
9365                 auto de = new DeclarationExp(exp.e1.loc, v);
9366                 auto ve = new VarExp(exp.e1.loc, v);
9367                 e = new PowExp(exp.loc, ve, exp.e2);
9368                 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
9369                 e = new CommaExp(exp.loc, de, e);
9370             }
9371             e = Expression.combine(e0, e);
9372             e = e.expressionSemantic(sc);
9373             result = e;
9374             return;
9375         }
9376         result = exp.incompatibleTypes();
9377     }
9378 
9379     override void visit(CatAssignExp exp)
9380     {
9381         if (exp.type)
9382         {
9383             result = exp;
9384             return;
9385         }
9386 
9387         //printf("CatAssignExp::semantic() %s\n", exp.toChars());
9388         Expression e = exp.op_overload(sc);
9389         if (e)
9390         {
9391             result = e;
9392             return;
9393         }
9394 
9395         if (exp.e1.op == TOK.slice)
9396         {
9397             SliceExp se = cast(SliceExp)exp.e1;
9398             if (se.e1.type.toBasetype().ty == Tsarray)
9399             {
9400                 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
9401                 return setError();
9402             }
9403         }
9404 
9405         if (checkIfIsStructLiteralDotExpr(exp.e1))
9406             return setError();
9407 
9408         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9409         if (exp.e1.op == TOK.error)
9410         {
9411             result = exp.e1;
9412             return;
9413         }
9414         if (exp.e2.op == TOK.error)
9415         {
9416             result = exp.e2;
9417             return;
9418         }
9419 
9420         if (checkNonAssignmentArrayOp(exp.e2))
9421             return setError();
9422 
9423         Type tb1 = exp.e1.type.toBasetype();
9424         Type tb1next = tb1.nextOf();
9425         Type tb2 = exp.e2.type.toBasetype();
9426 
9427         /* Possibilities:
9428          * TOK.concatenateAssign: appending T[] to T[]
9429          * TOK.concatenateElemAssign: appending T to T[]
9430          * TOK.concatenateDcharAssign: appending dchar to T[]
9431          */
9432         if ((tb1.ty == Tarray) &&
9433             (tb2.ty == Tarray || tb2.ty == Tsarray) &&
9434             (exp.e2.implicitConvTo(exp.e1.type) ||
9435              (tb2.nextOf().implicitConvTo(tb1next) &&
9436               (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
9437         {
9438             // TOK.concatenateAssign
9439             assert(exp.op == TOK.concatenateAssign);
9440             if (exp.e1.checkPostblit(sc, tb1next))
9441                 return setError();
9442 
9443             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
9444         }
9445         else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
9446         {
9447             /* https://issues.dlang.org/show_bug.cgi?id=19782
9448              *
9449              * If e2 is implicitly convertible to tb1next, the conversion
9450              * might be done through alias this, in which case, e2 needs to
9451              * be modified accordingly (e2 => e2.aliasthis).
9452              */
9453             if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
9454                 goto Laliasthis;
9455             if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
9456                 goto Laliasthis;
9457             // Append element
9458             if (exp.e2.checkPostblit(sc, tb2))
9459                 return setError();
9460 
9461             if (checkNewEscape(sc, exp.e2, false))
9462                 return setError();
9463 
9464             exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
9465             exp.e2 = doCopyOrMove(sc, exp.e2);
9466         }
9467         else if (tb1.ty == Tarray &&
9468                  (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
9469                  exp.e2.type.ty != tb1next.ty &&
9470                  exp.e2.implicitConvTo(Type.tdchar))
9471         {
9472             // Append dchar to char[] or wchar[]
9473             exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
9474 
9475             /* Do not allow appending wchar to char[] because if wchar happens
9476              * to be a surrogate pair, nothing good can result.
9477              */
9478         }
9479         else
9480         {
9481             // Try alias this on first operand
9482             static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
9483             {
9484                 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
9485                 if (!ad1 || !ad1.aliasthis)
9486                     return null;
9487 
9488                 /* Rewrite (e1 op e2) as:
9489                  *      (e1.aliasthis op e2)
9490                  */
9491                 if (exp.att1 && exp.e1.type == exp.att1)
9492                     return null;
9493                 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
9494                 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
9495                 BinExp be = cast(BinExp)exp.copy();
9496                 if (!be.att1 && exp.e1.type.checkAliasThisRec())
9497                     be.att1 = exp.e1.type;
9498                 be.e1 = e1;
9499                 return be.trySemantic(sc);
9500             }
9501 
9502             // Try alias this on second operand
9503             static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
9504             {
9505                 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
9506                 if (!ad2 || !ad2.aliasthis)
9507                     return null;
9508                 /* Rewrite (e1 op e2) as:
9509                  *      (e1 op e2.aliasthis)
9510                  */
9511                 if (exp.att2 && exp.e2.type == exp.att2)
9512                     return null;
9513                 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
9514                 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
9515                 BinExp be = cast(BinExp)exp.copy();
9516                 if (!be.att2 && exp.e2.type.checkAliasThisRec())
9517                     be.att2 = exp.e2.type;
9518                 be.e2 = e2;
9519                 return be.trySemantic(sc);
9520             }
9521 
9522     Laliasthis:
9523             result = tryAliasThisForLhs(exp, sc);
9524             if (result)
9525                 return;
9526 
9527             result = tryAliasThisForRhs(exp, sc);
9528             if (result)
9529                 return;
9530 
9531             exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
9532             return setError();
9533         }
9534 
9535         if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
9536             return setError();
9537 
9538         exp.type = exp.e1.type;
9539         auto res = exp.reorderSettingAAElem(sc);
9540         if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) && global.params.vsafe)
9541             checkAssignEscape(sc, res, false);
9542         result = res;
9543     }
9544 
9545     override void visit(AddExp exp)
9546     {
9547         static if (LOGSEMANTIC)
9548         {
9549             printf("AddExp::semantic('%s')\n", exp.toChars());
9550         }
9551         if (exp.type)
9552         {
9553             result = exp;
9554             return;
9555         }
9556 
9557         if (Expression ex = binSemanticProp(exp, sc))
9558         {
9559             result = ex;
9560             return;
9561         }
9562         Expression e = exp.op_overload(sc);
9563         if (e)
9564         {
9565             result = e;
9566             return;
9567         }
9568 
9569         Type tb1 = exp.e1.type.toBasetype();
9570         Type tb2 = exp.e2.type.toBasetype();
9571 
9572         bool err = false;
9573         if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction)
9574         {
9575             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9576         }
9577         if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction)
9578         {
9579             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9580         }
9581         if (err)
9582             return setError();
9583 
9584         if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
9585         {
9586             result = scaleFactor(exp, sc);
9587             return;
9588         }
9589 
9590         if (tb1.ty == Tpointer && tb2.ty == Tpointer)
9591         {
9592             result = exp.incompatibleTypes();
9593             return;
9594         }
9595 
9596         if (Expression ex = typeCombine(exp, sc))
9597         {
9598             result = ex;
9599             return;
9600         }
9601 
9602         Type tb = exp.type.toBasetype();
9603         if (tb.ty == Tarray || tb.ty == Tsarray)
9604         {
9605             if (!isArrayOpValid(exp))
9606             {
9607                 result = arrayOpInvalidError(exp);
9608                 return;
9609             }
9610             result = exp;
9611             return;
9612         }
9613 
9614         tb1 = exp.e1.type.toBasetype();
9615         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
9616         {
9617             result = exp.incompatibleTypes();
9618             return;
9619         }
9620         if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
9621         {
9622             switch (exp.type.toBasetype().ty)
9623             {
9624             case Tfloat32:
9625             case Timaginary32:
9626                 exp.type = Type.tcomplex32;
9627                 break;
9628 
9629             case Tfloat64:
9630             case Timaginary64:
9631                 exp.type = Type.tcomplex64;
9632                 break;
9633 
9634             case Tfloat80:
9635             case Timaginary80:
9636                 exp.type = Type.tcomplex80;
9637                 break;
9638 
9639             default:
9640                 assert(0);
9641             }
9642         }
9643         result = exp;
9644     }
9645 
9646     override void visit(MinExp exp)
9647     {
9648         static if (LOGSEMANTIC)
9649         {
9650             printf("MinExp::semantic('%s')\n", exp.toChars());
9651         }
9652         if (exp.type)
9653         {
9654             result = exp;
9655             return;
9656         }
9657 
9658         if (Expression ex = binSemanticProp(exp, sc))
9659         {
9660             result = ex;
9661             return;
9662         }
9663         Expression e = exp.op_overload(sc);
9664         if (e)
9665         {
9666             result = e;
9667             return;
9668         }
9669 
9670         Type t1 = exp.e1.type.toBasetype();
9671         Type t2 = exp.e2.type.toBasetype();
9672 
9673         bool err = false;
9674         if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction)
9675         {
9676             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9677         }
9678         if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction)
9679         {
9680             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9681         }
9682         if (err)
9683             return setError();
9684 
9685         if (t1.ty == Tpointer)
9686         {
9687             if (t2.ty == Tpointer)
9688             {
9689                 // https://dlang.org/spec/expression.html#add_expressions
9690                 // "If both operands are pointers, and the operator is -, the pointers are
9691                 // subtracted and the result is divided by the size of the type pointed to
9692                 // by the operands. It is an error if the pointers point to different types."
9693                 Type p1 = t1.nextOf();
9694                 Type p2 = t2.nextOf();
9695 
9696                 if (!p1.equivalent(p2))
9697                 {
9698                     // Deprecation to remain for at least a year, after which this should be
9699                     // changed to an error
9700                     // See https://github.com/dlang/dmd/pull/7332
9701                     deprecation(exp.loc,
9702                         "cannot subtract pointers to different types: `%s` and `%s`.",
9703                         t1.toChars(), t2.toChars());
9704                 }
9705 
9706                 // Need to divide the result by the stride
9707                 // Replace (ptr - ptr) with (ptr - ptr) / stride
9708                 d_int64 stride;
9709 
9710                 // make sure pointer types are compatible
9711                 if (Expression ex = typeCombine(exp, sc))
9712                 {
9713                     result = ex;
9714                     return;
9715                 }
9716 
9717                 exp.type = Type.tptrdiff_t;
9718                 stride = t2.nextOf().size();
9719                 if (stride == 0)
9720                 {
9721                     e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
9722                 }
9723                 else
9724                 {
9725                     e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
9726                     e.type = Type.tptrdiff_t;
9727                 }
9728             }
9729             else if (t2.isintegral())
9730                 e = scaleFactor(exp, sc);
9731             else
9732             {
9733                 exp.error("can't subtract `%s` from pointer", t2.toChars());
9734                 e = new ErrorExp();
9735             }
9736             result = e;
9737             return;
9738         }
9739         if (t2.ty == Tpointer)
9740         {
9741             exp.type = exp.e2.type;
9742             exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
9743             return setError();
9744         }
9745 
9746         if (Expression ex = typeCombine(exp, sc))
9747         {
9748             result = ex;
9749             return;
9750         }
9751 
9752         Type tb = exp.type.toBasetype();
9753         if (tb.ty == Tarray || tb.ty == Tsarray)
9754         {
9755             if (!isArrayOpValid(exp))
9756             {
9757                 result = arrayOpInvalidError(exp);
9758                 return;
9759             }
9760             result = exp;
9761             return;
9762         }
9763 
9764         t1 = exp.e1.type.toBasetype();
9765         t2 = exp.e2.type.toBasetype();
9766         if (!target.isVectorOpSupported(t1, exp.op, t2))
9767         {
9768             result = exp.incompatibleTypes();
9769             return;
9770         }
9771         if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
9772         {
9773             switch (exp.type.ty)
9774             {
9775             case Tfloat32:
9776             case Timaginary32:
9777                 exp.type = Type.tcomplex32;
9778                 break;
9779 
9780             case Tfloat64:
9781             case Timaginary64:
9782                 exp.type = Type.tcomplex64;
9783                 break;
9784 
9785             case Tfloat80:
9786             case Timaginary80:
9787                 exp.type = Type.tcomplex80;
9788                 break;
9789 
9790             default:
9791                 assert(0);
9792             }
9793         }
9794         result = exp;
9795         return;
9796     }
9797 
9798     override void visit(CatExp exp)
9799     {
9800         // https://dlang.org/spec/expression.html#cat_expressions
9801         //printf("CatExp.semantic() %s\n", toChars());
9802         if (exp.type)
9803         {
9804             result = exp;
9805             return;
9806         }
9807 
9808         if (Expression ex = binSemanticProp(exp, sc))
9809         {
9810             result = ex;
9811             return;
9812         }
9813         Expression e = exp.op_overload(sc);
9814         if (e)
9815         {
9816             result = e;
9817             return;
9818         }
9819 
9820         Type tb1 = exp.e1.type.toBasetype();
9821         Type tb2 = exp.e2.type.toBasetype();
9822 
9823         auto f1 = checkNonAssignmentArrayOp(exp.e1);
9824         auto f2 = checkNonAssignmentArrayOp(exp.e2);
9825         if (f1 || f2)
9826             return setError();
9827 
9828         /* BUG: Should handle things like:
9829          *      char c;
9830          *      c ~ ' '
9831          *      ' ' ~ c;
9832          */
9833 
9834         Type tb1next = tb1.nextOf();
9835         Type tb2next = tb2.nextOf();
9836 
9837         // Check for: array ~ array
9838         if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1)))
9839         {
9840             /* https://issues.dlang.org/show_bug.cgi?id=9248
9841              * Here to avoid the case of:
9842              *    void*[] a = [cast(void*)1];
9843              *    void*[] b = [cast(void*)2];
9844              *    a ~ b;
9845              * becoming:
9846              *    a ~ [cast(void*)b];
9847              */
9848 
9849             /* https://issues.dlang.org/show_bug.cgi?id=14682
9850              * Also to avoid the case of:
9851              *    int[][] a;
9852              *    a ~ [];
9853              * becoming:
9854              *    a ~ cast(int[])[];
9855              */
9856             goto Lpeer;
9857         }
9858 
9859         // Check for: array ~ element
9860         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
9861         {
9862             if (exp.e1.op == TOK.arrayLiteral)
9863             {
9864                 exp.e2 = doCopyOrMove(sc, exp.e2);
9865                 // https://issues.dlang.org/show_bug.cgi?id=14686
9866                 // Postblit call appears in AST, and this is
9867                 // finally translated  to an ArrayLiteralExp in below optimize().
9868             }
9869             else if (exp.e1.op == TOK.string_)
9870             {
9871                 // No postblit call exists on character (integer) value.
9872             }
9873             else
9874             {
9875                 if (exp.e2.checkPostblit(sc, tb2))
9876                     return setError();
9877                 // Postblit call will be done in runtime helper function
9878             }
9879 
9880             if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
9881             {
9882                 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
9883                 exp.type = tb2.arrayOf();
9884                 goto L2elem;
9885             }
9886             if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
9887             {
9888                 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
9889                 exp.type = tb1next.arrayOf();
9890             L2elem:
9891                 if (tb2.ty == Tarray || tb2.ty == Tsarray)
9892                 {
9893                     // Make e2 into [e2]
9894                     exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
9895                 }
9896                 else if (checkNewEscape(sc, exp.e2, false))
9897                     return setError();
9898                 result = exp.optimize(WANTvalue);
9899                 return;
9900             }
9901         }
9902         // Check for: element ~ array
9903         if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
9904         {
9905             if (exp.e2.op == TOK.arrayLiteral)
9906             {
9907                 exp.e1 = doCopyOrMove(sc, exp.e1);
9908             }
9909             else if (exp.e2.op == TOK.string_)
9910             {
9911             }
9912             else
9913             {
9914                 if (exp.e1.checkPostblit(sc, tb1))
9915                     return setError();
9916             }
9917 
9918             if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
9919             {
9920                 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
9921                 exp.type = tb1.arrayOf();
9922                 goto L1elem;
9923             }
9924             if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
9925             {
9926                 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
9927                 exp.type = tb2next.arrayOf();
9928             L1elem:
9929                 if (tb1.ty == Tarray || tb1.ty == Tsarray)
9930                 {
9931                     // Make e1 into [e1]
9932                     exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
9933                 }
9934                 else if (checkNewEscape(sc, exp.e1, false))
9935                     return setError();
9936                 result = exp.optimize(WANTvalue);
9937                 return;
9938             }
9939         }
9940 
9941     Lpeer:
9942         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
9943         {
9944             Type t1 = tb1next.mutableOf().constOf().arrayOf();
9945             Type t2 = tb2next.mutableOf().constOf().arrayOf();
9946             if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed)
9947                 exp.e1.type = t1;
9948             else
9949                 exp.e1 = exp.e1.castTo(sc, t1);
9950             if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed)
9951                 exp.e2.type = t2;
9952             else
9953                 exp.e2 = exp.e2.castTo(sc, t2);
9954         }
9955 
9956         if (Expression ex = typeCombine(exp, sc))
9957         {
9958             result = ex;
9959             return;
9960         }
9961         exp.type = exp.type.toHeadMutable();
9962 
9963         Type tb = exp.type.toBasetype();
9964         if (tb.ty == Tsarray)
9965             exp.type = tb.nextOf().arrayOf();
9966         if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
9967         {
9968             exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
9969         }
9970         if (Type tbn = tb.nextOf())
9971         {
9972             if (exp.checkPostblit(sc, tbn))
9973                 return setError();
9974         }
9975         Type t1 = exp.e1.type.toBasetype();
9976         Type t2 = exp.e2.type.toBasetype();
9977         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
9978             (t2.ty == Tarray || t2.ty == Tsarray))
9979         {
9980             // Normalize to ArrayLiteralExp or StringExp as far as possible
9981             e = exp.optimize(WANTvalue);
9982         }
9983         else
9984         {
9985             //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
9986             result = exp.incompatibleTypes();
9987             return;
9988         }
9989 
9990         result = e;
9991     }
9992 
9993     override void visit(MulExp exp)
9994     {
9995         version (none)
9996         {
9997             printf("MulExp::semantic() %s\n", exp.toChars());
9998         }
9999         if (exp.type)
10000         {
10001             result = exp;
10002             return;
10003         }
10004 
10005         if (Expression ex = binSemanticProp(exp, sc))
10006         {
10007             result = ex;
10008             return;
10009         }
10010         Expression e = exp.op_overload(sc);
10011         if (e)
10012         {
10013             result = e;
10014             return;
10015         }
10016 
10017         if (Expression ex = typeCombine(exp, sc))
10018         {
10019             result = ex;
10020             return;
10021         }
10022 
10023         Type tb = exp.type.toBasetype();
10024         if (tb.ty == Tarray || tb.ty == Tsarray)
10025         {
10026             if (!isArrayOpValid(exp))
10027             {
10028                 result = arrayOpInvalidError(exp);
10029                 return;
10030             }
10031             result = exp;
10032             return;
10033         }
10034 
10035         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10036             return setError();
10037 
10038         if (exp.type.isfloating())
10039         {
10040             Type t1 = exp.e1.type;
10041             Type t2 = exp.e2.type;
10042 
10043             if (t1.isreal())
10044             {
10045                 exp.type = t2;
10046             }
10047             else if (t2.isreal())
10048             {
10049                 exp.type = t1;
10050             }
10051             else if (t1.isimaginary())
10052             {
10053                 if (t2.isimaginary())
10054                 {
10055                     switch (t1.toBasetype().ty)
10056                     {
10057                     case Timaginary32:
10058                         exp.type = Type.tfloat32;
10059                         break;
10060 
10061                     case Timaginary64:
10062                         exp.type = Type.tfloat64;
10063                         break;
10064 
10065                     case Timaginary80:
10066                         exp.type = Type.tfloat80;
10067                         break;
10068 
10069                     default:
10070                         assert(0);
10071                     }
10072 
10073                     // iy * iv = -yv
10074                     exp.e1.type = exp.type;
10075                     exp.e2.type = exp.type;
10076                     e = new NegExp(exp.loc, exp);
10077                     e = e.expressionSemantic(sc);
10078                     result = e;
10079                     return;
10080                 }
10081                 else
10082                     exp.type = t2; // t2 is complex
10083             }
10084             else if (t2.isimaginary())
10085             {
10086                 exp.type = t1; // t1 is complex
10087             }
10088         }
10089         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10090         {
10091             result = exp.incompatibleTypes();
10092             return;
10093         }
10094         result = exp;
10095     }
10096 
10097     override void visit(DivExp exp)
10098     {
10099         if (exp.type)
10100         {
10101             result = exp;
10102             return;
10103         }
10104 
10105         if (Expression ex = binSemanticProp(exp, sc))
10106         {
10107             result = ex;
10108             return;
10109         }
10110         Expression e = exp.op_overload(sc);
10111         if (e)
10112         {
10113             result = e;
10114             return;
10115         }
10116 
10117         if (Expression ex = typeCombine(exp, sc))
10118         {
10119             result = ex;
10120             return;
10121         }
10122 
10123         Type tb = exp.type.toBasetype();
10124         if (tb.ty == Tarray || tb.ty == Tsarray)
10125         {
10126             if (!isArrayOpValid(exp))
10127             {
10128                 result = arrayOpInvalidError(exp);
10129                 return;
10130             }
10131             result = exp;
10132             return;
10133         }
10134 
10135         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10136             return setError();
10137 
10138         if (exp.type.isfloating())
10139         {
10140             Type t1 = exp.e1.type;
10141             Type t2 = exp.e2.type;
10142 
10143             if (t1.isreal())
10144             {
10145                 exp.type = t2;
10146                 if (t2.isimaginary())
10147                 {
10148                     // x/iv = i(-x/v)
10149                     exp.e2.type = t1;
10150                     e = new NegExp(exp.loc, exp);
10151                     e = e.expressionSemantic(sc);
10152                     result = e;
10153                     return;
10154                 }
10155             }
10156             else if (t2.isreal())
10157             {
10158                 exp.type = t1;
10159             }
10160             else if (t1.isimaginary())
10161             {
10162                 if (t2.isimaginary())
10163                 {
10164                     switch (t1.toBasetype().ty)
10165                     {
10166                     case Timaginary32:
10167                         exp.type = Type.tfloat32;
10168                         break;
10169 
10170                     case Timaginary64:
10171                         exp.type = Type.tfloat64;
10172                         break;
10173 
10174                     case Timaginary80:
10175                         exp.type = Type.tfloat80;
10176                         break;
10177 
10178                     default:
10179                         assert(0);
10180                     }
10181                 }
10182                 else
10183                     exp.type = t2; // t2 is complex
10184             }
10185             else if (t2.isimaginary())
10186             {
10187                 exp.type = t1; // t1 is complex
10188             }
10189         }
10190         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10191         {
10192             result = exp.incompatibleTypes();
10193             return;
10194         }
10195         result = exp;
10196     }
10197 
10198     override void visit(ModExp exp)
10199     {
10200         if (exp.type)
10201         {
10202             result = exp;
10203             return;
10204         }
10205 
10206         if (Expression ex = binSemanticProp(exp, sc))
10207         {
10208             result = ex;
10209             return;
10210         }
10211         Expression e = exp.op_overload(sc);
10212         if (e)
10213         {
10214             result = e;
10215             return;
10216         }
10217 
10218         if (Expression ex = typeCombine(exp, sc))
10219         {
10220             result = ex;
10221             return;
10222         }
10223 
10224         Type tb = exp.type.toBasetype();
10225         if (tb.ty == Tarray || tb.ty == Tsarray)
10226         {
10227             if (!isArrayOpValid(exp))
10228             {
10229                 result = arrayOpInvalidError(exp);
10230                 return;
10231             }
10232             result = exp;
10233             return;
10234         }
10235         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10236         {
10237             result = exp.incompatibleTypes();
10238             return;
10239         }
10240 
10241         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10242             return setError();
10243 
10244         if (exp.type.isfloating())
10245         {
10246             exp.type = exp.e1.type;
10247             if (exp.e2.type.iscomplex())
10248             {
10249                 exp.error("cannot perform modulo complex arithmetic");
10250                 return setError();
10251             }
10252         }
10253         result = exp;
10254     }
10255 
10256     override void visit(PowExp exp)
10257     {
10258         if (exp.type)
10259         {
10260             result = exp;
10261             return;
10262         }
10263 
10264         //printf("PowExp::semantic() %s\n", toChars());
10265         if (Expression ex = binSemanticProp(exp, sc))
10266         {
10267             result = ex;
10268             return;
10269         }
10270         Expression e = exp.op_overload(sc);
10271         if (e)
10272         {
10273             result = e;
10274             return;
10275         }
10276 
10277         if (Expression ex = typeCombine(exp, sc))
10278         {
10279             result = ex;
10280             return;
10281         }
10282 
10283         Type tb = exp.type.toBasetype();
10284         if (tb.ty == Tarray || tb.ty == Tsarray)
10285         {
10286             if (!isArrayOpValid(exp))
10287             {
10288                 result = arrayOpInvalidError(exp);
10289                 return;
10290             }
10291             result = exp;
10292             return;
10293         }
10294 
10295         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10296             return setError();
10297 
10298         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10299         {
10300             result = exp.incompatibleTypes();
10301             return;
10302         }
10303 
10304         // First, attempt to fold the expression.
10305         e = exp.optimize(WANTvalue);
10306         if (e.op != TOK.pow)
10307         {
10308             e = e.expressionSemantic(sc);
10309             result = e;
10310             return;
10311         }
10312 
10313         Module mmath = loadStdMath();
10314         if (!mmath)
10315         {
10316             e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
10317             return setError();
10318         }
10319         e = new ScopeExp(exp.loc, mmath);
10320 
10321         if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half)
10322         {
10323             // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
10324             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
10325         }
10326         else
10327         {
10328             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
10329             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
10330         }
10331         e = e.expressionSemantic(sc);
10332         result = e;
10333         return;
10334     }
10335 
10336     override void visit(ShlExp exp)
10337     {
10338         //printf("ShlExp::semantic(), type = %p\n", type);
10339         if (exp.type)
10340         {
10341             result = exp;
10342             return;
10343         }
10344 
10345         if (Expression ex = binSemanticProp(exp, sc))
10346         {
10347             result = ex;
10348             return;
10349         }
10350         Expression e = exp.op_overload(sc);
10351         if (e)
10352         {
10353             result = e;
10354             return;
10355         }
10356 
10357         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10358             return setError();
10359 
10360         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10361         {
10362             result = exp.incompatibleTypes();
10363             return;
10364         }
10365         exp.e1 = integralPromotions(exp.e1, sc);
10366         if (exp.e2.type.toBasetype().ty != Tvector)
10367             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10368 
10369         exp.type = exp.e1.type;
10370         result = exp;
10371     }
10372 
10373     override void visit(ShrExp exp)
10374     {
10375         if (exp.type)
10376         {
10377             result = exp;
10378             return;
10379         }
10380 
10381         if (Expression ex = binSemanticProp(exp, sc))
10382         {
10383             result = ex;
10384             return;
10385         }
10386         Expression e = exp.op_overload(sc);
10387         if (e)
10388         {
10389             result = e;
10390             return;
10391         }
10392 
10393         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10394             return setError();
10395 
10396         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10397         {
10398             result = exp.incompatibleTypes();
10399             return;
10400         }
10401         exp.e1 = integralPromotions(exp.e1, sc);
10402         if (exp.e2.type.toBasetype().ty != Tvector)
10403             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10404 
10405         exp.type = exp.e1.type;
10406         result = exp;
10407     }
10408 
10409     override void visit(UshrExp exp)
10410     {
10411         if (exp.type)
10412         {
10413             result = exp;
10414             return;
10415         }
10416 
10417         if (Expression ex = binSemanticProp(exp, sc))
10418         {
10419             result = ex;
10420             return;
10421         }
10422         Expression e = exp.op_overload(sc);
10423         if (e)
10424         {
10425             result = e;
10426             return;
10427         }
10428 
10429         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10430             return setError();
10431 
10432         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10433         {
10434             result = exp.incompatibleTypes();
10435             return;
10436         }
10437         exp.e1 = integralPromotions(exp.e1, sc);
10438         if (exp.e2.type.toBasetype().ty != Tvector)
10439             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10440 
10441         exp.type = exp.e1.type;
10442         result = exp;
10443     }
10444 
10445     override void visit(AndExp exp)
10446     {
10447         if (exp.type)
10448         {
10449             result = exp;
10450             return;
10451         }
10452 
10453         if (Expression ex = binSemanticProp(exp, sc))
10454         {
10455             result = ex;
10456             return;
10457         }
10458         Expression e = exp.op_overload(sc);
10459         if (e)
10460         {
10461             result = e;
10462             return;
10463         }
10464 
10465         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10466         {
10467             exp.type = exp.e1.type;
10468             result = exp;
10469             return;
10470         }
10471 
10472         if (Expression ex = typeCombine(exp, sc))
10473         {
10474             result = ex;
10475             return;
10476         }
10477 
10478         Type tb = exp.type.toBasetype();
10479         if (tb.ty == Tarray || tb.ty == Tsarray)
10480         {
10481             if (!isArrayOpValid(exp))
10482             {
10483                 result = arrayOpInvalidError(exp);
10484                 return;
10485             }
10486             result = exp;
10487             return;
10488         }
10489         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10490         {
10491             result = exp.incompatibleTypes();
10492             return;
10493         }
10494         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10495             return setError();
10496 
10497         result = exp;
10498     }
10499 
10500     override void visit(OrExp exp)
10501     {
10502         if (exp.type)
10503         {
10504             result = exp;
10505             return;
10506         }
10507 
10508         if (Expression ex = binSemanticProp(exp, sc))
10509         {
10510             result = ex;
10511             return;
10512         }
10513         Expression e = exp.op_overload(sc);
10514         if (e)
10515         {
10516             result = e;
10517             return;
10518         }
10519 
10520         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10521         {
10522             exp.type = exp.e1.type;
10523             result = exp;
10524             return;
10525         }
10526 
10527         if (Expression ex = typeCombine(exp, sc))
10528         {
10529             result = ex;
10530             return;
10531         }
10532 
10533         Type tb = exp.type.toBasetype();
10534         if (tb.ty == Tarray || tb.ty == Tsarray)
10535         {
10536             if (!isArrayOpValid(exp))
10537             {
10538                 result = arrayOpInvalidError(exp);
10539                 return;
10540             }
10541             result = exp;
10542             return;
10543         }
10544         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10545         {
10546             result = exp.incompatibleTypes();
10547             return;
10548         }
10549         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10550             return setError();
10551 
10552         result = exp;
10553     }
10554 
10555     override void visit(XorExp exp)
10556     {
10557         if (exp.type)
10558         {
10559             result = exp;
10560             return;
10561         }
10562 
10563         if (Expression ex = binSemanticProp(exp, sc))
10564         {
10565             result = ex;
10566             return;
10567         }
10568         Expression e = exp.op_overload(sc);
10569         if (e)
10570         {
10571             result = e;
10572             return;
10573         }
10574 
10575         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10576         {
10577             exp.type = exp.e1.type;
10578             result = exp;
10579             return;
10580         }
10581 
10582         if (Expression ex = typeCombine(exp, sc))
10583         {
10584             result = ex;
10585             return;
10586         }
10587 
10588         Type tb = exp.type.toBasetype();
10589         if (tb.ty == Tarray || tb.ty == Tsarray)
10590         {
10591             if (!isArrayOpValid(exp))
10592             {
10593                 result = arrayOpInvalidError(exp);
10594                 return;
10595             }
10596             result = exp;
10597             return;
10598         }
10599         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10600         {
10601             result = exp.incompatibleTypes();
10602             return;
10603         }
10604         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10605             return setError();
10606 
10607         result = exp;
10608     }
10609 
10610     override void visit(LogicalExp exp)
10611     {
10612         static if (LOGSEMANTIC)
10613         {
10614             printf("LogicalExp::semantic() %s\n", exp.toChars());
10615         }
10616 
10617         if (exp.type)
10618         {
10619             result = exp;
10620             return;
10621         }
10622 
10623         exp.setNoderefOperands();
10624 
10625         Expression e1x = exp.e1.expressionSemantic(sc);
10626 
10627         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10628         if (e1x.op == TOK.type)
10629             e1x = resolveAliasThis(sc, e1x);
10630 
10631         e1x = resolveProperties(sc, e1x);
10632         e1x = e1x.toBoolean(sc);
10633 
10634         if (sc.flags & SCOPE.condition)
10635         {
10636             /* If in static if, don't evaluate e2 if we don't have to.
10637              */
10638             e1x = e1x.optimize(WANTvalue);
10639             if (e1x.isBool(exp.op == TOK.orOr))
10640             {
10641                 result = IntegerExp.createBool(exp.op == TOK.orOr);
10642                 return;
10643             }
10644         }
10645 
10646         CtorFlow ctorflow = sc.ctorflow.clone();
10647         Expression e2x = exp.e2.expressionSemantic(sc);
10648         sc.merge(exp.loc, ctorflow);
10649         ctorflow.freeFieldinit();
10650 
10651         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10652         if (e2x.op == TOK.type)
10653             e2x = resolveAliasThis(sc, e2x);
10654 
10655         e2x = resolveProperties(sc, e2x);
10656 
10657         auto f1 = checkNonAssignmentArrayOp(e1x);
10658         auto f2 = checkNonAssignmentArrayOp(e2x);
10659         if (f1 || f2)
10660             return setError();
10661 
10662         // Unless the right operand is 'void', the expression is converted to 'bool'.
10663         if (e2x.type.ty != Tvoid)
10664             e2x = e2x.toBoolean(sc);
10665 
10666         if (e2x.op == TOK.type || e2x.op == TOK.scope_)
10667         {
10668             exp.error("`%s` is not an expression", exp.e2.toChars());
10669             return setError();
10670         }
10671         if (e1x.op == TOK.error)
10672         {
10673             result = e1x;
10674             return;
10675         }
10676         if (e2x.op == TOK.error)
10677         {
10678             result = e2x;
10679             return;
10680         }
10681 
10682         // The result type is 'bool', unless the right operand has type 'void'.
10683         if (e2x.type.ty == Tvoid)
10684             exp.type = Type.tvoid;
10685         else
10686             exp.type = Type.tbool;
10687 
10688         exp.e1 = e1x;
10689         exp.e2 = e2x;
10690         result = exp;
10691     }
10692 
10693 
10694     override void visit(CmpExp exp)
10695     {
10696         static if (LOGSEMANTIC)
10697         {
10698             printf("CmpExp::semantic('%s')\n", exp.toChars());
10699         }
10700         if (exp.type)
10701         {
10702             result = exp;
10703             return;
10704         }
10705 
10706         exp.setNoderefOperands();
10707 
10708         if (Expression ex = binSemanticProp(exp, sc))
10709         {
10710             result = ex;
10711             return;
10712         }
10713         Type t1 = exp.e1.type.toBasetype();
10714         Type t2 = exp.e2.type.toBasetype();
10715         if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_)
10716         {
10717             exp.error("do not use `null` when comparing class types");
10718             return setError();
10719         }
10720 
10721         TOK cmpop;
10722         if (auto e = exp.op_overload(sc, &cmpop))
10723         {
10724             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
10725             {
10726                 exp.error("recursive `opCmp` expansion");
10727                 return setError();
10728             }
10729             if (e.op == TOK.call)
10730             {
10731                 e = new CmpExp(cmpop, exp.loc, e, new IntegerExp(exp.loc, 0, Type.tint32));
10732                 e = e.expressionSemantic(sc);
10733             }
10734             result = e;
10735             return;
10736         }
10737 
10738         if (Expression ex = typeCombine(exp, sc))
10739         {
10740             result = ex;
10741             return;
10742         }
10743 
10744         auto f1 = checkNonAssignmentArrayOp(exp.e1);
10745         auto f2 = checkNonAssignmentArrayOp(exp.e2);
10746         if (f1 || f2)
10747             return setError();
10748 
10749         exp.type = Type.tbool;
10750 
10751         // Special handling for array comparisons
10752         Expression arrayLowering = null;
10753         t1 = exp.e1.type.toBasetype();
10754         t2 = exp.e2.type.toBasetype();
10755         if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
10756         {
10757             Type t1next = t1.nextOf();
10758             Type t2next = t2.nextOf();
10759             if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
10760             {
10761                 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
10762                 return setError();
10763             }
10764             if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
10765             {
10766                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
10767                     return setError();
10768 
10769                 // Lower to object.__cmp(e1, e2)
10770                 Expression al = new IdentifierExp(exp.loc, Id.empty);
10771                 al = new DotIdExp(exp.loc, al, Id.object);
10772                 al = new DotIdExp(exp.loc, al, Id.__cmp);
10773                 al = al.expressionSemantic(sc);
10774 
10775                 auto arguments = new Expressions(2);
10776                 (*arguments)[0] = exp.e1;
10777                 (*arguments)[1] = exp.e2;
10778 
10779                 al = new CallExp(exp.loc, al, arguments);
10780                 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
10781 
10782                 arrayLowering = al;
10783             }
10784         }
10785         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
10786         {
10787             if (t2.ty == Tstruct)
10788                 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
10789             else
10790                 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
10791             return setError();
10792         }
10793         else if (t1.iscomplex() || t2.iscomplex())
10794         {
10795             exp.error("compare not defined for complex operands");
10796             return setError();
10797         }
10798         else if (t1.ty == Taarray || t2.ty == Taarray)
10799         {
10800             exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op));
10801             return setError();
10802         }
10803         else if (!target.isVectorOpSupported(t1, exp.op, t2))
10804         {
10805             result = exp.incompatibleTypes();
10806             return;
10807         }
10808         else
10809         {
10810             bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
10811             bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
10812             if (r1 || r2)
10813                 return setError();
10814         }
10815 
10816         //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
10817         if (arrayLowering)
10818         {
10819             arrayLowering = arrayLowering.expressionSemantic(sc);
10820             result = arrayLowering;
10821             return;
10822         }
10823         result = exp;
10824         return;
10825     }
10826 
10827     override void visit(InExp exp)
10828     {
10829         if (exp.type)
10830         {
10831             result = exp;
10832             return;
10833         }
10834 
10835         if (Expression ex = binSemanticProp(exp, sc))
10836         {
10837             result = ex;
10838             return;
10839         }
10840         Expression e = exp.op_overload(sc);
10841         if (e)
10842         {
10843             result = e;
10844             return;
10845         }
10846 
10847         Type t2b = exp.e2.type.toBasetype();
10848         switch (t2b.ty)
10849         {
10850         case Taarray:
10851             {
10852                 TypeAArray ta = cast(TypeAArray)t2b;
10853 
10854                 // Special handling for array keys
10855                 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
10856                 {
10857                     // Convert key to type of key
10858                     exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
10859                 }
10860 
10861                 semanticTypeInfo(sc, ta.index);
10862 
10863                 // Return type is pointer to value
10864                 exp.type = ta.nextOf().pointerTo();
10865                 break;
10866             }
10867 
10868         case Terror:
10869             return setError();
10870 
10871         default:
10872             result = exp.incompatibleTypes();
10873             return;
10874         }
10875         result = exp;
10876     }
10877 
10878     override void visit(RemoveExp e)
10879     {
10880         if (Expression ex = binSemantic(e, sc))
10881         {
10882             result = ex;
10883             return;
10884         }
10885         result = e;
10886     }
10887 
10888     override void visit(EqualExp exp)
10889     {
10890         //printf("EqualExp::semantic('%s')\n", exp.toChars());
10891         if (exp.type)
10892         {
10893             result = exp;
10894             return;
10895         }
10896 
10897         exp.setNoderefOperands();
10898 
10899         if (auto e = binSemanticProp(exp, sc))
10900         {
10901             result = e;
10902             return;
10903         }
10904         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
10905         {
10906             result = exp.incompatibleTypes();
10907             return;
10908         }
10909 
10910         {
10911             auto t1 = exp.e1.type;
10912             auto t2 = exp.e2.type;
10913             if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
10914                 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
10915                     t1.toChars(), t2.toChars());
10916         }
10917 
10918         /* Before checking for operator overloading, check to see if we're
10919          * comparing the addresses of two statics. If so, we can just see
10920          * if they are the same symbol.
10921          */
10922         if (exp.e1.op == TOK.address && exp.e2.op == TOK.address)
10923         {
10924             AddrExp ae1 = cast(AddrExp)exp.e1;
10925             AddrExp ae2 = cast(AddrExp)exp.e2;
10926             if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable)
10927             {
10928                 VarExp ve1 = cast(VarExp)ae1.e1;
10929                 VarExp ve2 = cast(VarExp)ae2.e1;
10930                 if (ve1.var == ve2.var)
10931                 {
10932                     // They are the same, result is 'true' for ==, 'false' for !=
10933                     result = IntegerExp.createBool(exp.op == TOK.equal);
10934                     return;
10935                 }
10936             }
10937         }
10938 
10939         Type t1 = exp.e1.type.toBasetype();
10940         Type t2 = exp.e2.type.toBasetype();
10941 
10942         bool needsDirectEq(Type t1, Type t2)
10943         {
10944             Type t1n = t1.nextOf().toBasetype();
10945             Type t2n = t2.nextOf().toBasetype();
10946             if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
10947                 (t1n.ty == Tvoid || t2n.ty == Tvoid))
10948             {
10949                 return false;
10950             }
10951             if (t1n.constOf() != t2n.constOf())
10952                 return true;
10953 
10954             Type t = t1n;
10955             while (t.toBasetype().nextOf())
10956                 t = t.nextOf().toBasetype();
10957             if (t.ty != Tstruct)
10958                 return false;
10959 
10960             if (global.params.useTypeInfo && Type.dtypeinfo)
10961                 semanticTypeInfo(sc, t);
10962 
10963             return (cast(TypeStruct)t).sym.hasIdentityEquals;
10964         }
10965 
10966         if (auto e = exp.op_overload(sc))
10967         {
10968             result = e;
10969             return;
10970         }
10971 
10972 
10973         if (!(t1.ty == Tarray && t2.ty == Tarray && needsDirectEq(t1, t2)))
10974         {
10975             if (auto e = typeCombine(exp, sc))
10976             {
10977                 result = e;
10978                 return;
10979             }
10980         }
10981 
10982         auto f1 = checkNonAssignmentArrayOp(exp.e1);
10983         auto f2 = checkNonAssignmentArrayOp(exp.e2);
10984         if (f1 || f2)
10985             return setError();
10986 
10987         exp.type = Type.tbool;
10988 
10989         // Special handling for array comparisons
10990         if (!(t1.ty == Tarray && t2.ty == Tarray && needsDirectEq(t1, t2)))
10991         {
10992             if (!arrayTypeCompatible(exp.loc, exp.e1.type, exp.e2.type))
10993             {
10994                 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
10995                 {
10996                     // Cast both to complex
10997                     exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
10998                     exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
10999                 }
11000             }
11001         }
11002 
11003         if (t1.ty == Tarray && t2.ty == Tarray)
11004         {
11005             //printf("Lowering to __equals %s %s\n", e1.toChars(), e2.toChars());
11006 
11007             // For e1 and e2 of struct type, lowers e1 == e2 to object.__equals(e1, e2)
11008             // and e1 != e2 to !(object.__equals(e1, e2)).
11009 
11010             if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
11011                 return setError();
11012 
11013             Expression __equals = new IdentifierExp(exp.loc, Id.empty);
11014             Identifier id = Identifier.idPool("__equals");
11015             __equals = new DotIdExp(exp.loc, __equals, Id.object);
11016             __equals = new DotIdExp(exp.loc, __equals, id);
11017 
11018             auto arguments = new Expressions(2);
11019             (*arguments)[0] = exp.e1;
11020             (*arguments)[1] = exp.e2;
11021 
11022             __equals = new CallExp(exp.loc, __equals, arguments);
11023             if (exp.op == TOK.notEqual)
11024             {
11025                 __equals = new NotExp(exp.loc, __equals);
11026             }
11027             __equals = __equals.expressionSemantic(sc);
11028 
11029             result = __equals;
11030             return;
11031         }
11032 
11033         if (exp.e1.type.toBasetype().ty == Taarray)
11034             semanticTypeInfo(sc, exp.e1.type.toBasetype());
11035 
11036 
11037         if (!target.isVectorOpSupported(t1, exp.op, t2))
11038         {
11039             result = exp.incompatibleTypes();
11040             return;
11041         }
11042 
11043         result = exp;
11044     }
11045 
11046     override void visit(IdentityExp exp)
11047     {
11048         if (exp.type)
11049         {
11050             result = exp;
11051             return;
11052         }
11053 
11054         exp.setNoderefOperands();
11055 
11056         if (auto e = binSemanticProp(exp, sc))
11057         {
11058             result = e;
11059             return;
11060         }
11061 
11062         if (auto e = typeCombine(exp, sc))
11063         {
11064             result = e;
11065             return;
11066         }
11067 
11068         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11069         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11070         if (f1 || f2)
11071             return setError();
11072 
11073         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
11074         {
11075             result = exp.incompatibleTypes();
11076             return;
11077         }
11078 
11079         exp.type = Type.tbool;
11080 
11081         if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11082         {
11083             // Cast both to complex
11084             exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11085             exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11086         }
11087 
11088         auto tb1 = exp.e1.type.toBasetype();
11089         auto tb2 = exp.e2.type.toBasetype();
11090         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
11091         {
11092             result = exp.incompatibleTypes();
11093             return;
11094         }
11095 
11096         if (exp.e1.op == TOK.call)
11097             exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
11098         if (exp.e2.op == TOK.call)
11099             exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
11100 
11101         if (exp.e1.type.toBasetype().ty == Tsarray ||
11102             exp.e2.type.toBasetype().ty == Tsarray)
11103             exp.deprecation("identity comparison of static arrays "
11104                 ~ "implicitly coerces them to slices, "
11105                 ~ "which are compared by reference");
11106 
11107         result = exp;
11108     }
11109 
11110     override void visit(CondExp exp)
11111     {
11112         static if (LOGSEMANTIC)
11113         {
11114             printf("CondExp::semantic('%s')\n", exp.toChars());
11115         }
11116         if (exp.type)
11117         {
11118             result = exp;
11119             return;
11120         }
11121 
11122         if (exp.econd.op == TOK.dotIdentifier)
11123             (cast(DotIdExp)exp.econd).noderef = true;
11124 
11125         Expression ec = exp.econd.expressionSemantic(sc);
11126         ec = resolveProperties(sc, ec);
11127         ec = ec.toBoolean(sc);
11128 
11129         CtorFlow ctorflow_root = sc.ctorflow.clone();
11130         Expression e1x = exp.e1.expressionSemantic(sc);
11131         e1x = resolveProperties(sc, e1x);
11132 
11133         CtorFlow ctorflow1 = sc.ctorflow;
11134         sc.ctorflow = ctorflow_root;
11135         Expression e2x = exp.e2.expressionSemantic(sc);
11136         e2x = resolveProperties(sc, e2x);
11137 
11138         sc.merge(exp.loc, ctorflow1);
11139         ctorflow1.freeFieldinit();
11140 
11141         if (ec.op == TOK.error)
11142         {
11143             result = ec;
11144             return;
11145         }
11146         if (ec.type == Type.terror)
11147             return setError();
11148         exp.econd = ec;
11149 
11150         if (e1x.op == TOK.error)
11151         {
11152             result = e1x;
11153             return;
11154         }
11155         if (e1x.type == Type.terror)
11156             return setError();
11157         exp.e1 = e1x;
11158 
11159         if (e2x.op == TOK.error)
11160         {
11161             result = e2x;
11162             return;
11163         }
11164         if (e2x.type == Type.terror)
11165             return setError();
11166         exp.e2 = e2x;
11167 
11168         auto f0 = checkNonAssignmentArrayOp(exp.econd);
11169         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11170         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11171         if (f0 || f1 || f2)
11172             return setError();
11173 
11174         Type t1 = exp.e1.type;
11175         Type t2 = exp.e2.type;
11176         // If either operand is void the result is void, we have to cast both
11177         // the expression to void so that we explicitly discard the expression
11178         // value if any
11179         // https://issues.dlang.org/show_bug.cgi?id=16598
11180         if (t1.ty == Tvoid || t2.ty == Tvoid)
11181         {
11182             exp.type = Type.tvoid;
11183             exp.e1 = exp.e1.castTo(sc, exp.type);
11184             exp.e2 = exp.e2.castTo(sc, exp.type);
11185         }
11186         else if (t1 == t2)
11187             exp.type = t1;
11188         else
11189         {
11190             if (Expression ex = typeCombine(exp, sc))
11191             {
11192                 result = ex;
11193                 return;
11194             }
11195 
11196             switch (exp.e1.type.toBasetype().ty)
11197             {
11198             case Tcomplex32:
11199             case Tcomplex64:
11200             case Tcomplex80:
11201                 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
11202                 break;
11203             default:
11204                 break;
11205             }
11206             switch (exp.e2.type.toBasetype().ty)
11207             {
11208             case Tcomplex32:
11209             case Tcomplex64:
11210             case Tcomplex80:
11211                 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
11212                 break;
11213             default:
11214                 break;
11215             }
11216             if (exp.type.toBasetype().ty == Tarray)
11217             {
11218                 exp.e1 = exp.e1.castTo(sc, exp.type);
11219                 exp.e2 = exp.e2.castTo(sc, exp.type);
11220             }
11221         }
11222         exp.type = exp.type.merge2();
11223         version (none)
11224         {
11225             printf("res: %s\n", exp.type.toChars());
11226             printf("e1 : %s\n", exp.e1.type.toChars());
11227             printf("e2 : %s\n", exp.e2.type.toChars());
11228         }
11229 
11230         /* https://issues.dlang.org/show_bug.cgi?id=14696
11231          * If either e1 or e2 contain temporaries which need dtor,
11232          * make them conditional.
11233          * Rewrite:
11234          *      cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
11235          * to:
11236          *      (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
11237          * and replace edtors of __tmp1 and __tmp2 with:
11238          *      __tmp1.edtor --> __cond && __tmp1.dtor()
11239          *      __tmp2.edtor --> __cond || __tmp2.dtor()
11240          */
11241         exp.hookDtors(sc);
11242 
11243         result = exp;
11244     }
11245 
11246     override void visit(FileInitExp e)
11247     {
11248         //printf("FileInitExp::semantic()\n");
11249         e.type = Type.tstring;
11250         result = e;
11251     }
11252 
11253     override void visit(LineInitExp e)
11254     {
11255         e.type = Type.tint32;
11256         result = e;
11257     }
11258 
11259     override void visit(ModuleInitExp e)
11260     {
11261         //printf("ModuleInitExp::semantic()\n");
11262         e.type = Type.tstring;
11263         result = e;
11264     }
11265 
11266     override void visit(FuncInitExp e)
11267     {
11268         //printf("FuncInitExp::semantic()\n");
11269         e.type = Type.tstring;
11270         if (sc.func)
11271         {
11272             result = e.resolveLoc(Loc.initial, sc);
11273             return;
11274         }
11275         result = e;
11276     }
11277 
11278     override void visit(PrettyFuncInitExp e)
11279     {
11280         //printf("PrettyFuncInitExp::semantic()\n");
11281         e.type = Type.tstring;
11282         if (sc.func)
11283         {
11284             result = e.resolveLoc(Loc.initial, sc);
11285             return;
11286         }
11287 
11288         result = e;
11289     }
11290 }
11291 
11292 /**********************************
11293  * Try to run semantic routines.
11294  * If they fail, return NULL.
11295  */
11296 Expression trySemantic(Expression exp, Scope* sc)
11297 {
11298     //printf("+trySemantic(%s)\n", exp.toChars());
11299     uint errors = global.startGagging();
11300     Expression e = expressionSemantic(exp, sc);
11301     if (global.endGagging(errors))
11302     {
11303         e = null;
11304     }
11305     //printf("-trySemantic(%s)\n", exp.toChars());
11306     return e;
11307 }
11308 
11309 /**************************
11310  * Helper function for easy error propagation.
11311  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11312  */
11313 Expression unaSemantic(UnaExp e, Scope* sc)
11314 {
11315     static if (LOGSEMANTIC)
11316     {
11317         printf("UnaExp::semantic('%s')\n", e.toChars());
11318     }
11319     Expression e1x = e.e1.expressionSemantic(sc);
11320     if (e1x.op == TOK.error)
11321         return e1x;
11322     e.e1 = e1x;
11323     return null;
11324 }
11325 
11326 /**************************
11327  * Helper function for easy error propagation.
11328  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11329  */
11330 Expression binSemantic(BinExp e, Scope* sc)
11331 {
11332     static if (LOGSEMANTIC)
11333     {
11334         printf("BinExp::semantic('%s')\n", e.toChars());
11335     }
11336     Expression e1x = e.e1.expressionSemantic(sc);
11337     Expression e2x = e.e2.expressionSemantic(sc);
11338 
11339     // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11340     if (e1x.op == TOK.type)
11341         e1x = resolveAliasThis(sc, e1x);
11342     if (e2x.op == TOK.type)
11343         e2x = resolveAliasThis(sc, e2x);
11344 
11345     if (e1x.op == TOK.error)
11346         return e1x;
11347     if (e2x.op == TOK.error)
11348         return e2x;
11349     e.e1 = e1x;
11350     e.e2 = e2x;
11351     return null;
11352 }
11353 
11354 Expression binSemanticProp(BinExp e, Scope* sc)
11355 {
11356     if (Expression ex = binSemantic(e, sc))
11357         return ex;
11358     Expression e1x = resolveProperties(sc, e.e1);
11359     Expression e2x = resolveProperties(sc, e.e2);
11360     if (e1x.op == TOK.error)
11361         return e1x;
11362     if (e2x.op == TOK.error)
11363         return e2x;
11364     e.e1 = e1x;
11365     e.e2 = e2x;
11366     return null;
11367 }
11368 
11369 // entrypoint for semantic ExpressionSemanticVisitor
11370 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
11371 {
11372     scope v = new ExpressionSemanticVisitor(sc);
11373     e.accept(v);
11374     return v.result;
11375 }
11376 
11377 Expression semanticX(DotIdExp exp, Scope* sc)
11378 {
11379     //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
11380     if (Expression ex = unaSemantic(exp, sc))
11381         return ex;
11382 
11383     if (exp.ident == Id._mangleof)
11384     {
11385         // symbol.mangleof
11386         Dsymbol ds;
11387         switch (exp.e1.op)
11388         {
11389         case TOK.scope_:
11390             ds = (cast(ScopeExp)exp.e1).sds;
11391             goto L1;
11392         case TOK.variable:
11393             ds = (cast(VarExp)exp.e1).var;
11394             goto L1;
11395         case TOK.dotVariable:
11396             ds = (cast(DotVarExp)exp.e1).var;
11397             goto L1;
11398         case TOK.overloadSet:
11399             ds = (cast(OverExp)exp.e1).vars;
11400             goto L1;
11401         case TOK.template_:
11402             {
11403                 TemplateExp te = cast(TemplateExp)exp.e1;
11404                 ds = te.fd ? cast(Dsymbol)te.fd : te.td;
11405             }
11406         L1:
11407             {
11408                 assert(ds);
11409                 if (auto f = ds.isFuncDeclaration())
11410                 {
11411                     if (f.checkForwardRef(exp.loc))
11412                     {
11413                         return new ErrorExp();
11414                     }
11415                     if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
11416                                    FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
11417                     {
11418                         f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes");
11419                         return new ErrorExp();
11420                     }
11421                 }
11422                 OutBuffer buf;
11423                 mangleToBuffer(ds, &buf);
11424                 Expression e = new StringExp(exp.loc, buf.extractSlice());
11425                 e = e.expressionSemantic(sc);
11426                 return e;
11427             }
11428         default:
11429             break;
11430         }
11431     }
11432 
11433     if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length)
11434     {
11435         // bypass checkPurity
11436         return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
11437     }
11438 
11439     if (exp.e1.op == TOK.dot)
11440     {
11441     }
11442     else
11443     {
11444         exp.e1 = resolvePropertiesX(sc, exp.e1);
11445     }
11446     if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof)
11447     {
11448         /* 'distribute' the .offsetof to each of the tuple elements.
11449          */
11450         TupleExp te = cast(TupleExp)exp.e1;
11451         auto exps = new Expressions(te.exps.dim);
11452         for (size_t i = 0; i < exps.dim; i++)
11453         {
11454             Expression e = (*te.exps)[i];
11455             e = e.expressionSemantic(sc);
11456             e = new DotIdExp(e.loc, e, Id.offsetof);
11457             (*exps)[i] = e;
11458         }
11459         // Don't evaluate te.e0 in runtime
11460         Expression e = new TupleExp(exp.loc, null, exps);
11461         e = e.expressionSemantic(sc);
11462         return e;
11463     }
11464     if (exp.e1.op == TOK.tuple && exp.ident == Id.length)
11465     {
11466         TupleExp te = cast(TupleExp)exp.e1;
11467         // Don't evaluate te.e0 in runtime
11468         Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
11469         return e;
11470     }
11471 
11472     // https://issues.dlang.org/show_bug.cgi?id=14416
11473     // Template has no built-in properties except for 'stringof'.
11474     if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof)
11475     {
11476         exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11477         return new ErrorExp();
11478     }
11479     if (!exp.e1.type)
11480     {
11481         exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11482         return new ErrorExp();
11483     }
11484 
11485     return exp;
11486 }
11487 
11488 // Resolve e1.ident without seeing UFCS.
11489 // If flag == 1, stop "not a property" error and return NULL.
11490 Expression semanticY(DotIdExp exp, Scope* sc, int flag)
11491 {
11492     //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
11493 
11494     //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
11495 
11496     /* Special case: rewrite this.id and super.id
11497      * to be classtype.id and baseclasstype.id
11498      * if we have no this pointer.
11499      */
11500     if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc))
11501     {
11502         if (AggregateDeclaration ad = sc.getStructClassScope())
11503         {
11504             if (exp.e1.op == TOK.this_)
11505             {
11506                 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
11507             }
11508             else
11509             {
11510                 ClassDeclaration cd = ad.isClassDeclaration();
11511                 if (cd && cd.baseClass)
11512                     exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
11513             }
11514         }
11515     }
11516 
11517     Expression e = semanticX(exp, sc);
11518     if (e != exp)
11519         return e;
11520 
11521     Expression eleft;
11522     Expression eright;
11523     if (exp.e1.op == TOK.dot)
11524     {
11525         DotExp de = cast(DotExp)exp.e1;
11526         eleft = de.e1;
11527         eright = de.e2;
11528     }
11529     else
11530     {
11531         eleft = null;
11532         eright = exp.e1;
11533     }
11534 
11535     Type t1b = exp.e1.type.toBasetype();
11536 
11537     if (eright.op == TOK.scope_) // also used for template alias's
11538     {
11539         ScopeExp ie = cast(ScopeExp)eright;
11540 
11541         int flags = SearchLocalsOnly;
11542         /* Disable access to another module's private imports.
11543          * The check for 'is sds our current module' is because
11544          * the current module should have access to its own imports.
11545          */
11546         if (ie.sds.isModule() && ie.sds != sc._module)
11547             flags |= IgnorePrivateImports;
11548         if (sc.flags & SCOPE.ignoresymbolvisibility)
11549             flags |= IgnoreSymbolVisibility;
11550         Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
11551         /* Check for visibility before resolving aliases because public
11552          * aliases to private symbols are public.
11553          */
11554         if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
11555         {
11556             s = null;
11557         }
11558         if (s)
11559         {
11560             auto p = s.isPackage();
11561             if (p && checkAccess(sc, p))
11562             {
11563                 s = null;
11564             }
11565         }
11566         if (s)
11567         {
11568             // if 's' is a tuple variable, the tuple is returned.
11569             s = s.toAlias();
11570 
11571             exp.checkDeprecated(sc, s);
11572             exp.checkDisabled(sc, s);
11573 
11574             EnumMember em = s.isEnumMember();
11575             if (em)
11576             {
11577                 return em.getVarExp(exp.loc, sc);
11578             }
11579             VarDeclaration v = s.isVarDeclaration();
11580             if (v)
11581             {
11582                 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
11583                 if (!v.type ||
11584                     !v.type.deco && v.inuse)
11585                 {
11586                     if (v.inuse)
11587                         exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
11588                     else
11589                         exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
11590                     return new ErrorExp();
11591                 }
11592                 if (v.type.ty == Terror)
11593                     return new ErrorExp();
11594 
11595                 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
11596                 {
11597                     /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
11598                      * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
11599                      * be reverted. `wantsym` is the hack to work around the problem.
11600                      */
11601                     if (v.inuse)
11602                     {
11603                         error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
11604                         return new ErrorExp();
11605                     }
11606                     e = v.expandInitializer(exp.loc);
11607                     v.inuse++;
11608                     e = e.expressionSemantic(sc);
11609                     v.inuse--;
11610                     return e;
11611                 }
11612 
11613                 if (v.needThis())
11614                 {
11615                     if (!eleft)
11616                         eleft = new ThisExp(exp.loc);
11617                     e = new DotVarExp(exp.loc, eleft, v);
11618                     e = e.expressionSemantic(sc);
11619                 }
11620                 else
11621                 {
11622                     e = new VarExp(exp.loc, v);
11623                     if (eleft)
11624                     {
11625                         e = new CommaExp(exp.loc, eleft, e);
11626                         e.type = v.type;
11627                     }
11628                 }
11629                 e = e.deref();
11630                 return e.expressionSemantic(sc);
11631             }
11632 
11633             FuncDeclaration f = s.isFuncDeclaration();
11634             if (f)
11635             {
11636                 //printf("it's a function\n");
11637                 if (!f.functionSemantic())
11638                     return new ErrorExp();
11639                 if (f.needThis())
11640                 {
11641                     if (!eleft)
11642                         eleft = new ThisExp(exp.loc);
11643                     e = new DotVarExp(exp.loc, eleft, f, true);
11644                     e = e.expressionSemantic(sc);
11645                 }
11646                 else
11647                 {
11648                     e = new VarExp(exp.loc, f, true);
11649                     if (eleft)
11650                     {
11651                         e = new CommaExp(exp.loc, eleft, e);
11652                         e.type = f.type;
11653                     }
11654                 }
11655                 return e;
11656             }
11657             if (auto td = s.isTemplateDeclaration())
11658             {
11659                 if (eleft)
11660                     e = new DotTemplateExp(exp.loc, eleft, td);
11661                 else
11662                     e = new TemplateExp(exp.loc, td);
11663                 e = e.expressionSemantic(sc);
11664                 return e;
11665             }
11666             if (OverDeclaration od = s.isOverDeclaration())
11667             {
11668                 e = new VarExp(exp.loc, od, true);
11669                 if (eleft)
11670                 {
11671                     e = new CommaExp(exp.loc, eleft, e);
11672                     e.type = Type.tvoid; // ambiguous type?
11673                 }
11674                 return e;
11675             }
11676             OverloadSet o = s.isOverloadSet();
11677             if (o)
11678             {
11679                 //printf("'%s' is an overload set\n", o.toChars());
11680                 return new OverExp(exp.loc, o);
11681             }
11682 
11683             if (auto t = s.getType())
11684             {
11685                 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
11686             }
11687 
11688             TupleDeclaration tup = s.isTupleDeclaration();
11689             if (tup)
11690             {
11691                 if (eleft)
11692                 {
11693                     e = new DotVarExp(exp.loc, eleft, tup);
11694                     e = e.expressionSemantic(sc);
11695                     return e;
11696                 }
11697                 e = new TupleExp(exp.loc, tup);
11698                 e = e.expressionSemantic(sc);
11699                 return e;
11700             }
11701 
11702             ScopeDsymbol sds = s.isScopeDsymbol();
11703             if (sds)
11704             {
11705                 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
11706                 e = new ScopeExp(exp.loc, sds);
11707                 e = e.expressionSemantic(sc);
11708                 if (eleft)
11709                     e = new DotExp(exp.loc, eleft, e);
11710                 return e;
11711             }
11712 
11713             Import imp = s.isImport();
11714             if (imp)
11715             {
11716                 ie = new ScopeExp(exp.loc, imp.pkg);
11717                 return ie.expressionSemantic(sc);
11718             }
11719             // BUG: handle other cases like in IdentifierExp::semantic()
11720             debug
11721             {
11722                 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
11723             }
11724             assert(0);
11725         }
11726         else if (exp.ident == Id.stringof)
11727         {
11728             e = new StringExp(exp.loc, ie.toString());
11729             e = e.expressionSemantic(sc);
11730             return e;
11731         }
11732         if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
11733         {
11734             flag = 0;
11735         }
11736         if (flag)
11737             return null;
11738         s = ie.sds.search_correct(exp.ident);
11739         if (s && symbolIsVisible(sc, s))
11740         {
11741             if (s.isPackage())
11742                 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
11743             else
11744                 exp.error("undefined identifier `%s` in %s `%s`, did you mean %s `%s`?", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars());
11745         }
11746         else
11747             exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
11748         return new ErrorExp();
11749     }
11750     else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum && exp.ident != Id._init && exp.ident != Id.__sizeof && exp.ident != Id.__xalignof && exp.ident != Id.offsetof && exp.ident != Id._mangleof && exp.ident != Id.stringof)
11751     {
11752         Type t1bn = t1b.nextOf();
11753         if (flag)
11754         {
11755             AggregateDeclaration ad = isAggregate(t1bn);
11756             if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
11757                 return null;
11758         }
11759 
11760         /* Rewrite:
11761          *   p.ident
11762          * as:
11763          *   (*p).ident
11764          */
11765         if (flag && t1bn.ty == Tvoid)
11766             return null;
11767         e = new PtrExp(exp.loc, exp.e1);
11768         e = e.expressionSemantic(sc);
11769         return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
11770     }
11771     else
11772     {
11773         if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_)
11774             flag = 0;
11775         e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
11776         if (e)
11777             e = e.expressionSemantic(sc);
11778         return e;
11779     }
11780 }
11781 
11782 // Resolve e1.ident!tiargs without seeing UFCS.
11783 // If flag == 1, stop "not a property" error and return NULL.
11784 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
11785 {
11786     static if (LOGSEMANTIC)
11787     {
11788         printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
11789     }
11790 
11791     static Expression errorExp()
11792     {
11793         return new ErrorExp();
11794     }
11795 
11796     auto die = new DotIdExp(exp.loc, exp.e1, exp.ti.name);
11797 
11798     Expression e = die.semanticX(sc);
11799     if (e == die)
11800     {
11801         exp.e1 = die.e1; // take back
11802         Type t1b = exp.e1.type.toBasetype();
11803         if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
11804         {
11805             /* No built-in type has templatized properties, so do shortcut.
11806              * It is necessary in: 1024.max!"a < b"
11807              */
11808             if (flag)
11809                 return null;
11810         }
11811         e = die.semanticY(sc, flag);
11812         if (flag)
11813         {
11814             if (!e ||
11815                 isDotOpDispatch(e))
11816             {
11817                 /* opDispatch!tiargs would be a function template that needs IFTI,
11818                  * so it's not a template
11819                  */
11820                 return null;
11821             }
11822         }
11823     }
11824     assert(e);
11825 
11826     if (e.op == TOK.error)
11827         return e;
11828     if (e.op == TOK.dotVariable)
11829     {
11830         DotVarExp dve = cast(DotVarExp)e;
11831         if (FuncDeclaration fd = dve.var.isFuncDeclaration())
11832         {
11833             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
11834             {
11835                 e = new DotTemplateExp(dve.loc, dve.e1, td);
11836                 e = e.expressionSemantic(sc);
11837             }
11838         }
11839         else if (OverDeclaration od = dve.var.isOverDeclaration())
11840         {
11841             exp.e1 = dve.e1; // pull semantic() result
11842 
11843             if (!exp.findTempDecl(sc))
11844                 goto Lerr;
11845             if (exp.ti.needsTypeInference(sc))
11846                 return exp;
11847             exp.ti.dsymbolSemantic(sc);
11848             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
11849                 return errorExp();
11850 
11851             if (Declaration v = exp.ti.toAlias().isDeclaration())
11852             {
11853                 if (v.type && !v.type.deco)
11854                     v.type = v.type.typeSemantic(v.loc, sc);
11855                 return new DotVarExp(exp.loc, exp.e1, v)
11856                        .expressionSemantic(sc);
11857             }
11858             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
11859                    .expressionSemantic(sc);
11860         }
11861     }
11862     else if (e.op == TOK.variable)
11863     {
11864         VarExp ve = cast(VarExp)e;
11865         if (FuncDeclaration fd = ve.var.isFuncDeclaration())
11866         {
11867             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
11868             {
11869                 e = new TemplateExp(ve.loc, td)
11870                     .expressionSemantic(sc);
11871             }
11872         }
11873         else if (OverDeclaration od = ve.var.isOverDeclaration())
11874         {
11875             exp.ti.tempdecl = od;
11876             return new ScopeExp(exp.loc, exp.ti)
11877                    .expressionSemantic(sc);
11878         }
11879     }
11880 
11881     if (e.op == TOK.dotTemplateDeclaration)
11882     {
11883         DotTemplateExp dte = cast(DotTemplateExp)e;
11884         exp.e1 = dte.e1; // pull semantic() result
11885 
11886         exp.ti.tempdecl = dte.td;
11887         if (!exp.ti.semanticTiargs(sc))
11888             return errorExp();
11889         if (exp.ti.needsTypeInference(sc))
11890             return exp;
11891         exp.ti.dsymbolSemantic(sc);
11892         if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
11893             return errorExp();
11894 
11895         if (Declaration v = exp.ti.toAlias().isDeclaration())
11896         {
11897             if (v.isFuncDeclaration() || v.isVarDeclaration())
11898             {
11899                 return new DotVarExp(exp.loc, exp.e1, v)
11900                        .expressionSemantic(sc);
11901             }
11902         }
11903         return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
11904                .expressionSemantic(sc);
11905     }
11906     else if (e.op == TOK.template_)
11907     {
11908         exp.ti.tempdecl = (cast(TemplateExp)e).td;
11909         return new ScopeExp(exp.loc, exp.ti)
11910                .expressionSemantic(sc);
11911     }
11912     else if (e.op == TOK.dot)
11913     {
11914         DotExp de = cast(DotExp)e;
11915 
11916         if (de.e2.op == TOK.overloadSet)
11917         {
11918             if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
11919             {
11920                 return errorExp();
11921             }
11922             if (exp.ti.needsTypeInference(sc))
11923                 return exp;
11924             exp.ti.dsymbolSemantic(sc);
11925             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
11926                 return errorExp();
11927 
11928             if (Declaration v = exp.ti.toAlias().isDeclaration())
11929             {
11930                 if (v.type && !v.type.deco)
11931                     v.type = v.type.typeSemantic(v.loc, sc);
11932                 return new DotVarExp(exp.loc, exp.e1, v)
11933                        .expressionSemantic(sc);
11934             }
11935             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
11936                    .expressionSemantic(sc);
11937         }
11938     }
11939     else if (e.op == TOK.overloadSet)
11940     {
11941         OverExp oe = cast(OverExp)e;
11942         exp.ti.tempdecl = oe.vars;
11943         return new ScopeExp(exp.loc, exp.ti)
11944                .expressionSemantic(sc);
11945     }
11946 
11947 Lerr:
11948     exp.error("`%s` isn't a template", e.toChars());
11949     return errorExp();
11950 }
11951 
11952 /***************************************
11953  * If expression is shared, check that we can access it.
11954  * Give error message if not.
11955  * Params:
11956  *      e = expression to check
11957  *      sc = context
11958  * Returns:
11959  *      true on error
11960  */
11961 bool checkSharedAccess(Expression e, Scope* sc)
11962 {
11963     if (!global.params.noSharedAccess ||
11964         sc.intypeof ||
11965         sc.flags & SCOPE.ctfe)
11966     {
11967         return false;
11968     }
11969 
11970     //printf("checkSharedAccess() %s\n", e.toChars());
11971 
11972     static bool check(Expression e)
11973     {
11974         static bool sharedError(Expression e)
11975         {
11976             // https://dlang.org/phobos/core_atomic.html
11977             e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
11978             return true;
11979         }
11980 
11981         bool visitVar(VarExp ve)
11982         {
11983             return ve.var.type.isShared() ? sharedError(ve) : false;
11984         }
11985 
11986         bool visitPtr(PtrExp pe)
11987         {
11988             return pe.e1.type.nextOf().isShared() ? sharedError(pe) : false;
11989         }
11990 
11991         bool visitDotVar(DotVarExp dve)
11992         {
11993             return dve.var.type.isShared() || check(dve.e1) ? sharedError(dve) : false;
11994         }
11995 
11996         bool visitIndex(IndexExp ie)
11997         {
11998             return ie.e1.type.nextOf().isShared() ? sharedError(ie) : false;
11999         }
12000 
12001         bool visitComma(CommaExp ce)
12002         {
12003             return check(ce.e2);
12004         }
12005 
12006         switch (e.op)
12007         {
12008             case TOK.variable:    return visitVar(e.isVarExp());
12009             case TOK.star:        return visitPtr(e.isPtrExp());
12010             case TOK.dotVariable: return visitDotVar(e.isDotVarExp());
12011             case TOK.index:       return visitIndex(e.isIndexExp());
12012             case TOK.comma:       return visitComma(e.isCommaExp());
12013             default:
12014                 return false;
12015         }
12016     }
12017 
12018     return check(e);
12019 }
12020 
12021 
12022 
12023 /****************************************************
12024  * Determine if `exp`, which takes the address of `v`, can do so safely.
12025  * Params:
12026  *      sc = context
12027  *      exp = expression that takes the address of `v`
12028  *      v = the variable getting its address taken
12029  * Returns:
12030  *      `true` if ok, `false` for error
12031  */
12032 private bool checkAddressVar(Scope* sc, UnaExp exp, VarDeclaration v)
12033 {
12034     //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
12035     if (v)
12036     {
12037         if (!v.canTakeAddressOf())
12038         {
12039             exp.error("cannot take address of `%s`", exp.e1.toChars());
12040             return false;
12041         }
12042         if (sc.func && !sc.intypeof && !v.isDataseg())
12043         {
12044             const(char)* p = v.isParameter() ? "parameter" : "local";
12045             if (global.params.vsafe)
12046             {
12047                 // Taking the address of v means it cannot be set to 'scope' later
12048                 v.storage_class &= ~STC.maybescope;
12049                 v.doNotInferScope = true;
12050                 if (exp.e1.type.hasPointers() && v.storage_class & STC.scope_ &&
12051                     !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
12052                 {
12053                     exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12054                     return false;
12055                 }
12056             }
12057             else if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
12058             {
12059                 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12060                 return false;
12061             }
12062         }
12063     }
12064     return true;
12065 }
12066 
12067 /*******************************
12068  * Checks the attributes of a function.
12069  * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
12070  * and usage of `deprecated` and `@disabled`-ed symbols are checked.
12071  *
12072  * Params:
12073  *  exp = expression to check attributes for
12074  *  sc  = scope of the function
12075  *  f   = function to be checked
12076  * Returns: `true` if error occur.
12077  */
12078 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
12079 {
12080     with(exp)
12081     {
12082         bool error = checkDisabled(sc, f);
12083         error |= checkDeprecated(sc, f);
12084         error |= checkPurity(sc, f);
12085         error |= checkSafety(sc, f);
12086         error |= checkNogc(sc, f);
12087         return error;
12088     }
12089 }
12090 
12091 /*******************************
12092  * Helper function for `getRightThis()`.
12093  * Gets `this` of the next outer aggregate.
12094  * Params:
12095  *      loc = location to use for error messages
12096  *      sc = context
12097  *      s = the parent symbol of the existing `this`
12098  *      ad = struct or class we need the correct `this` for
12099  *      e1 = existing `this`
12100  *      t = type of the existing `this`
12101  *      var = the specific member of ad we're accessing
12102  *      flag = if true, return `null` instead of throwing an error
12103  * Returns:
12104  *      Expression representing the `this` for the var
12105  */
12106 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
12107 {
12108     int n = 0;
12109     while (s && s.isFuncDeclaration())
12110     {
12111         FuncDeclaration f = s.isFuncDeclaration();
12112         if (f.vthis)
12113         {
12114             n++;
12115             e1 = new VarExp(loc, f.vthis);
12116             if (f.isThis2)
12117             {
12118                 // (*__this)[i]
12119                 if (n > 1)
12120                     e1 = e1.expressionSemantic(sc);
12121                 e1 = new PtrExp(loc, e1);
12122                 uint i = f.followInstantiationContext(ad);
12123                 e1 = new IndexExp(loc, e1, new IntegerExp(i));
12124                 s = f.toParentP(ad);
12125                 continue;
12126             }
12127         }
12128         else
12129         {
12130             if (flag)
12131                 return null;
12132             e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
12133             e1 = new ErrorExp();
12134             return e1;
12135         }
12136         s = s.toParent2();
12137     }
12138     if (n > 1 || e1.op == TOK.index)
12139         e1 = e1.expressionSemantic(sc);
12140     if (s && e1.type.equivalent(Type.tvoidptr))
12141     {
12142         if (auto sad = s.isAggregateDeclaration())
12143         {
12144             Type ta = sad.handleType();
12145             if (ta.ty == Tstruct)
12146                 ta = ta.pointerTo();
12147             e1.type = ta;
12148         }
12149     }
12150     e1.type = e1.type.addMod(t.mod);
12151     return e1;
12152 }
12153 
12154 /*******************************
12155  * Make a dual-context container for use as a `this` argument.
12156  * Params:
12157  *      loc = location to use for error messages
12158  *      sc = current scope
12159  *      fd = target function that will take the `this` argument
12160  * Returns:
12161  *      Temporary closure variable.
12162  * Note:
12163  *      The function `fd` is added to the nested references of the
12164  *      newly created variable such that a closure is made for the variable when
12165  *      the address of `fd` is taken.
12166  */
12167 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
12168 {
12169     Type tthis2 = Type.tvoidptr.sarrayOf(2);
12170     VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
12171     vthis2.storage_class |= STC.temp;
12172     vthis2.dsymbolSemantic(sc);
12173     vthis2.parent = sc.parent;
12174     // make it a closure var
12175     assert(sc.func);
12176     sc.func.closureVars.push(vthis2);
12177     // add `fd` to the nested refs
12178     vthis2.nestedrefs.push(fd);
12179     return vthis2;
12180 }
12181 
12182 /*******************************
12183  * Make sure that the runtime hook `id` exists.
12184  * Params:
12185  *      loc = location to use for error messages
12186  *      sc = current scope
12187  *      id = the hook identifier
12188  *      description = what the hook does
12189  *      module_ = what module the hook is located in
12190  * Returns:
12191  *      a `bool` indicating if the hook is present.
12192  */
12193 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
12194 {
12195     auto rootSymbol = sc.search(loc, Id.empty, null);
12196     if (auto moduleSymbol = rootSymbol.search(loc, module_))
12197         if (moduleSymbol.search(loc, id))
12198           return true;
12199     error(loc, "`%s.%s` not found. The current runtime does not support %.*s, or the runtime is corrupt.", module_.toChars(), id.toChars(), cast(int)description.length, description.ptr);
12200     return false;
12201 }
12202 
12203 /**
12204  * Check if an expression is an access to a struct member with the struct
12205  * defined from a literal.
12206  *
12207  * This happens with manifest constants since the initializer is reused as is,
12208  * each time the declaration is part of an expression, which means that the
12209  * literal used as initializer can become a Lvalue. This Lvalue must not be modifiable.
12210  *
12211  * Params:
12212  *      exp = An expression that's attempted to be written.
12213  *            Must be the LHS of an `AssignExp`, `BinAssignExp`, `CatAssignExp`,
12214  *            or the expression passed to a modifiable function parameter.
12215  * Returns:
12216  *      `true` if `expr` is a dot var or a dot identifier touching to a struct literal,
12217  *      in which case an error message is issued, and `false` otherwise.
12218  */
12219 private bool checkIfIsStructLiteralDotExpr(Expression exp)
12220 {
12221     // e1.var = ...
12222     // e1.ident = ...
12223     Expression e1;
12224     if (exp.op == TOK.dotVariable)
12225         e1 = exp.isDotVarExp().e1;
12226     else if (exp.op == TOK.dotIdentifier)
12227         e1 = exp.isDotIdExp().e1;
12228     else
12229         return false;
12230 
12231     // enum SomeStruct ss = { ... }
12232     // also true for access from a .init: SomeStruct.init.member = ...
12233     if (e1.op != TOK.structLiteral)
12234         return false;
12235 
12236     error(exp.loc, "cannot modify constant expression `%s`", exp.toChars());
12237     return true;
12238 }