1 /**
2  * Semantic analysis of expressions.
3  *
4  * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5  *
6  * Copyright:   Copyright (C) 1999-2021 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.printast;
61 import dmd.root.ctfloat;
62 import dmd.root.file;
63 import dmd.root.filename;
64 import dmd.root.outbuffer;
65 import dmd.root.rootobject;
66 import dmd.root.string;
67 import dmd.semantic2;
68 import dmd.semantic3;
69 import dmd.sideeffect;
70 import dmd.safe;
71 import dmd.target;
72 import dmd.tokens;
73 import dmd.traits;
74 import dmd.typesem;
75 import dmd.typinf;
76 import dmd.utf;
77 import dmd.utils;
78 import dmd.visitor;
79 
80 enum LOGSEMANTIC = false;
81 
82 /********************************************************
83  * Perform semantic analysis and CTFE on expressions to produce
84  * a string.
85  * Params:
86  *      buf = append generated string to buffer
87  *      sc = context
88  *      exps = array of Expressions
89  * Returns:
90  *      true on error
91  */
92 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
93 {
94     if (!exps)
95         return false;
96 
97     foreach (ex; *exps)
98     {
99         if (!ex)
100             continue;
101         auto sc2 = sc.startCTFE();
102         auto e2 = ex.expressionSemantic(sc2);
103         auto e3 = resolveProperties(sc2, e2);
104         sc2.endCTFE();
105 
106         // allowed to contain types as well as expressions
107         auto e4 = ctfeInterpretForPragmaMsg(e3);
108         if (!e4 || e4.op == TOK.error)
109             return true;
110 
111         // expand tuple
112         if (auto te = e4.isTupleExp())
113         {
114             if (expressionsToString(buf, sc, te.exps))
115                 return true;
116             continue;
117         }
118         // char literals exp `.toStringExp` return `null` but we cant override it
119         // because in most contexts we don't want the conversion to succeed.
120         IntegerExp ie = e4.isIntegerExp();
121         const ty = (ie && ie.type) ? ie.type.ty : Terror;
122         if (ty.isSomeChar)
123         {
124             auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
125             e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
126         }
127 
128         if (StringExp se = e4.toStringExp())
129             buf.writestring(se.toUTF8(sc).peekString());
130         else
131             buf.writestring(e4.toString());
132     }
133     return false;
134 }
135 
136 
137 /***********************************************************
138  * Resolve `exp` as a compile-time known string.
139  * Params:
140  *  sc  = scope
141  *  exp = Expression which expected as a string
142  *  s   = What the string is expected for, will be used in error diagnostic.
143  * Returns:
144  *  String literal, or `null` if error happens.
145  */
146 StringExp semanticString(Scope *sc, Expression exp, const char* s)
147 {
148     sc = sc.startCTFE();
149     exp = exp.expressionSemantic(sc);
150     exp = resolveProperties(sc, exp);
151     sc = sc.endCTFE();
152 
153     if (exp.op == TOK.error)
154         return null;
155 
156     auto e = exp;
157     if (exp.type.isString())
158     {
159         e = e.ctfeInterpret();
160         if (e.op == TOK.error)
161             return null;
162     }
163 
164     auto se = e.toStringExp();
165     if (!se)
166     {
167         exp.error("`string` expected for %s, not `(%s)` of type `%s`",
168             s, exp.toChars(), exp.type.toChars());
169         return null;
170     }
171     return se;
172 }
173 
174 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
175 {
176     Expression e0;
177     Expression e1 = Expression.extractLast(ue.e1, e0);
178     // https://issues.dlang.org/show_bug.cgi?id=12585
179     // Extract the side effect part if ue.e1 is comma.
180 
181     if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
182     {
183         /* Even if opDollar is needed, 'e1' should be evaluate only once. So
184          * Rewrite:
185          *      e1.opIndex( ... use of $ ... )
186          *      e1.opSlice( ... use of $ ... )
187          * as:
188          *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
189          *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
190          */
191         e1 = extractSideEffect(sc, "__dop", e0, e1, false);
192         assert(e1.op == TOK.variable);
193         VarExp ve = cast(VarExp)e1;
194         ve.var.storage_class |= STC.exptemp;     // lifetime limited to expression
195     }
196     ue.e1 = e1;
197     return e0;
198 }
199 
200 /**************************************
201  * Runs semantic on ae.arguments. Declares temporary variables
202  * if '$' was used.
203  */
204 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
205 {
206     assert(!ae.lengthVar);
207     *pe0 = null;
208     AggregateDeclaration ad = isAggregate(ae.e1.type);
209     Dsymbol slice = search_function(ad, Id.slice);
210     //printf("slice = %s %s\n", slice.kind(), slice.toChars());
211     foreach (i, e; *ae.arguments)
212     {
213         if (i == 0)
214             *pe0 = extractOpDollarSideEffect(sc, ae);
215 
216         if (e.op == TOK.interval && !(slice && slice.isTemplateDeclaration()))
217         {
218         Lfallback:
219             if (ae.arguments.dim == 1)
220                 return null;
221             ae.error("multi-dimensional slicing requires template `opSlice`");
222             return ErrorExp.get();
223         }
224         //printf("[%d] e = %s\n", i, e.toChars());
225 
226         // Create scope for '$' variable for this dimension
227         auto sym = new ArrayScopeSymbol(sc, ae);
228         sym.parent = sc.scopesym;
229         sc = sc.push(sym);
230         ae.lengthVar = null; // Create it only if required
231         ae.currentDimension = i; // Dimension for $, if required
232 
233         e = e.expressionSemantic(sc);
234         e = resolveProperties(sc, e);
235 
236         if (ae.lengthVar && sc.func)
237         {
238             // If $ was used, declare it now
239             Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
240             de = de.expressionSemantic(sc);
241             *pe0 = Expression.combine(*pe0, de);
242         }
243         sc = sc.pop();
244 
245         if (e.op == TOK.interval)
246         {
247             IntervalExp ie = cast(IntervalExp)e;
248 
249             auto tiargs = new Objects();
250             Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
251             edim = edim.expressionSemantic(sc);
252             tiargs.push(edim);
253 
254             auto fargs = new Expressions(2);
255             (*fargs)[0] = ie.lwr;
256             (*fargs)[1] = ie.upr;
257 
258             uint xerrors = global.startGagging();
259             sc = sc.push();
260             FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
261             sc = sc.pop();
262             global.endGagging(xerrors);
263             if (!fslice)
264                 goto Lfallback;
265 
266             e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
267             e = new CallExp(ae.loc, e, fargs);
268             e = e.expressionSemantic(sc);
269         }
270 
271         if (!e.type)
272         {
273             ae.error("`%s` has no value", e.toChars());
274             e = ErrorExp.get();
275         }
276         if (e.op == TOK.error)
277             return e;
278 
279         (*ae.arguments)[i] = e;
280     }
281     return ae;
282 }
283 
284 /**************************************
285  * Runs semantic on se.lwr and se.upr. Declares a temporary variable
286  * if '$' was used.
287  * Returns:
288  *      ae, or ErrorExp if errors occurred
289  */
290 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
291 {
292     //assert(!ae.lengthVar);
293     if (!ie)
294         return ae;
295 
296     VarDeclaration lengthVar = ae.lengthVar;
297     bool errors = false;
298 
299     // create scope for '$'
300     auto sym = new ArrayScopeSymbol(sc, ae);
301     sym.parent = sc.scopesym;
302     sc = sc.push(sym);
303 
304     Expression sem(Expression e)
305     {
306         e = e.expressionSemantic(sc);
307         e = resolveProperties(sc, e);
308         if (!e.type)
309         {
310             ae.error("`%s` has no value", e.toChars());
311             errors = true;
312         }
313         return e;
314     }
315 
316     ie.lwr = sem(ie.lwr);
317     ie.upr = sem(ie.upr);
318 
319     if (lengthVar != ae.lengthVar && sc.func)
320     {
321         // If $ was used, declare it now
322         Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
323         de = de.expressionSemantic(sc);
324         *pe0 = Expression.combine(*pe0, de);
325     }
326 
327     sc = sc.pop();
328 
329     return errors ? ErrorExp.get() : ae;
330 }
331 
332 /******************************
333  * Perform semantic() on an array of Expressions.
334  */
335 bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
336 {
337     bool err = false;
338     if (exps)
339     {
340         foreach (ref e; *exps)
341         {
342             if (e)
343             {
344                 auto e2 = e.expressionSemantic(sc);
345                 if (e2.op == TOK.error)
346                     err = true;
347                 if (preserveErrors || e2.op != TOK.error)
348                     e = e2;
349             }
350         }
351     }
352     return err;
353 }
354 
355 /******************************
356  * Check the tail CallExp is really property function call.
357  * Bugs:
358  * This doesn't appear to do anything.
359  */
360 private bool checkPropertyCall(Expression e)
361 {
362     e = lastComma(e);
363 
364     if (e.op == TOK.call)
365     {
366         CallExp ce = cast(CallExp)e;
367         TypeFunction tf;
368         if (ce.f)
369         {
370             tf = cast(TypeFunction)ce.f.type;
371             /* If a forward reference to ce.f, try to resolve it
372              */
373             if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
374             {
375                 ce.f.dsymbolSemantic(null);
376                 tf = cast(TypeFunction)ce.f.type;
377             }
378         }
379         else if (ce.e1.type.ty == Tfunction)
380             tf = cast(TypeFunction)ce.e1.type;
381         else if (ce.e1.type.ty == Tdelegate)
382             tf = cast(TypeFunction)ce.e1.type.nextOf();
383         else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction)
384             tf = cast(TypeFunction)ce.e1.type.nextOf();
385         else
386             assert(0);
387     }
388     return false;
389 }
390 
391 /******************************
392  * Find symbol in accordance with the UFCS name look up rule
393  */
394 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
395 {
396     //printf("searchUFCS(ident = %s)\n", ident.toChars());
397     Loc loc = ue.loc;
398 
399     // TODO: merge with Scope.search.searchScopes()
400     Dsymbol searchScopes(int flags)
401     {
402         Dsymbol s = null;
403         for (Scope* scx = sc; scx; scx = scx.enclosing)
404         {
405             if (!scx.scopesym)
406                 continue;
407             if (scx.scopesym.isModule())
408                 flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
409             s = scx.scopesym.search(loc, ident, flags);
410             if (s)
411             {
412                 // overload set contains only module scope symbols.
413                 if (s.isOverloadSet())
414                     break;
415                 // selective/renamed imports also be picked up
416                 if (AliasDeclaration ad = s.isAliasDeclaration())
417                 {
418                     if (ad._import)
419                         break;
420                 }
421                 // See only module scope symbols for UFCS target.
422                 Dsymbol p = s.toParent2();
423                 if (p && p.isModule())
424                     break;
425             }
426             s = null;
427 
428             // Stop when we hit a module, but keep going if that is not just under the global scope
429             if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
430                 break;
431         }
432         return s;
433     }
434 
435     int flags = 0;
436     Dsymbol s;
437 
438     if (sc.flags & SCOPE.ignoresymbolvisibility)
439         flags |= IgnoreSymbolVisibility;
440 
441     // First look in local scopes
442     s = searchScopes(flags | SearchLocalsOnly);
443     if (!s)
444     {
445         // Second look in imported modules
446         s = searchScopes(flags | SearchImportsOnly);
447     }
448 
449     if (!s)
450         return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
451 
452     FuncDeclaration f = s.isFuncDeclaration();
453     if (f)
454     {
455         TemplateDeclaration td = getFuncTemplateDecl(f);
456         if (td)
457         {
458             if (td.overroot)
459                 td = td.overroot;
460             s = td;
461         }
462     }
463 
464     if (ue.op == TOK.dotTemplateInstance)
465     {
466         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue;
467         auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
468         if (!ti.updateTempDecl(sc, s))
469             return ErrorExp.get();
470         return new ScopeExp(loc, ti);
471     }
472     else
473     {
474         //printf("-searchUFCS() %s\n", s.toChars());
475         return new DsymbolExp(loc, s);
476     }
477 }
478 
479 /******************************
480  * Pull out callable entity with UFCS.
481  */
482 private Expression resolveUFCS(Scope* sc, CallExp ce)
483 {
484     Loc loc = ce.loc;
485     Expression eleft;
486     Expression e;
487 
488     if (ce.e1.op == TOK.dotIdentifier)
489     {
490         DotIdExp die = cast(DotIdExp)ce.e1;
491         Identifier ident = die.ident;
492 
493         Expression ex = die.semanticX(sc);
494         if (ex != die)
495         {
496             ce.e1 = ex;
497             return null;
498         }
499         eleft = die.e1;
500 
501         Type t = eleft.type.toBasetype();
502         if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
503         {
504             /* Built-in types and arrays have no callable properties, so do shortcut.
505              * It is necessary in: e.init()
506              */
507         }
508         else if (t.ty == Taarray)
509         {
510             if (ident == Id.remove)
511             {
512                 /* Transform:
513                  *  aa.remove(arg) into delete aa[arg]
514                  */
515                 if (!ce.arguments || ce.arguments.dim != 1)
516                 {
517                     ce.error("expected key as argument to `aa.remove()`");
518                     return ErrorExp.get();
519                 }
520                 if (!eleft.type.isMutable())
521                 {
522                     ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
523                     return ErrorExp.get();
524                 }
525                 Expression key = (*ce.arguments)[0];
526                 key = key.expressionSemantic(sc);
527                 key = resolveProperties(sc, key);
528 
529                 TypeAArray taa = cast(TypeAArray)t;
530                 key = key.implicitCastTo(sc, taa.index);
531 
532                 if (key.checkValue() || key.checkSharedAccess(sc))
533                     return ErrorExp.get();
534 
535                 semanticTypeInfo(sc, taa.index);
536 
537                 return new RemoveExp(loc, eleft, key);
538             }
539         }
540         else
541         {
542             if (Expression ey = die.semanticY(sc, 1))
543             {
544                 if (ey.op == TOK.error)
545                     return ey;
546                 ce.e1 = ey;
547                 if (isDotOpDispatch(ey))
548                 {
549                     uint errors = global.startGagging();
550                     e = ce.syntaxCopy().expressionSemantic(sc);
551                     if (!global.endGagging(errors))
552                         return e;
553 
554                     // even opDispatch and UFCS must have valid arguments,
555                     // so now that we've seen indication of a problem,
556                     // check them for issues.
557                     Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
558 
559                     if (arrayExpressionSemantic(originalArguments, sc))
560                         return ErrorExp.get();
561 
562                     /* fall down to UFCS */
563                 }
564                 else
565                     return null;
566             }
567         }
568 
569         /* https://issues.dlang.org/show_bug.cgi?id=13953
570          *
571          * If a struct has an alias this to an associative array
572          * and remove is used on a struct instance, we have to
573          * check first if there is a remove function that can be called
574          * on the struct. If not we must check the alias this.
575          *
576          * struct A
577          * {
578          *      string[string] a;
579          *      alias a this;
580          * }
581          *
582          * void fun()
583          * {
584          *      A s;
585          *      s.remove("foo");
586          * }
587          */
588         const errors = global.startGagging();
589         e = searchUFCS(sc, die, ident);
590         // if there were any errors and the identifier was remove
591         if (global.endGagging(errors))
592         {
593             if (ident == Id.remove)
594             {
595                 // check alias this
596                 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
597                 if (alias_e && alias_e != die.e1)
598                 {
599                     die.e1 = alias_e;
600                     CallExp ce2 = ce.syntaxCopy();
601                     ce2.e1 = die;
602                     e = cast(CallExp)ce2.trySemantic(sc);
603                     if (e)
604                         return e;
605                 }
606             }
607             // if alias this did not work out, print the initial errors
608             searchUFCS(sc, die, ident);
609         }
610     }
611     else if (ce.e1.op == TOK.dotTemplateInstance)
612     {
613         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ce.e1;
614         if (Expression ey = dti.semanticY(sc, 1))
615         {
616             ce.e1 = ey;
617             return null;
618         }
619         eleft = dti.e1;
620         e = searchUFCS(sc, dti, dti.ti.name);
621     }
622     else
623         return null;
624 
625     // Rewrite
626     ce.e1 = e;
627     if (!ce.arguments)
628         ce.arguments = new Expressions();
629     ce.arguments.shift(eleft);
630 
631     return null;
632 }
633 
634 /******************************
635  * Pull out property with UFCS.
636  */
637 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
638 {
639     Loc loc = e1.loc;
640     Expression eleft;
641     Expression e;
642 
643     if (e1.op == TOK.dotIdentifier)
644     {
645         DotIdExp die = cast(DotIdExp)e1;
646         eleft = die.e1;
647         e = searchUFCS(sc, die, die.ident);
648     }
649     else if (e1.op == TOK.dotTemplateInstance)
650     {
651         DotTemplateInstanceExp dti;
652         dti = cast(DotTemplateInstanceExp)e1;
653         eleft = dti.e1;
654         e = searchUFCS(sc, dti, dti.ti.name);
655     }
656     else
657         return null;
658 
659     if (e is null)
660         return null;
661 
662     // Rewrite
663     if (e2)
664     {
665         // run semantic without gagging
666         e2 = e2.expressionSemantic(sc);
667 
668         /* f(e1) = e2
669          */
670         Expression ex = e.copy();
671         auto a1 = new Expressions(1);
672         (*a1)[0] = eleft;
673         ex = new CallExp(loc, ex, a1);
674         auto e1PassSemantic = ex.trySemantic(sc);
675 
676         /* f(e1, e2)
677          */
678         auto a2 = new Expressions(2);
679         (*a2)[0] = eleft;
680         (*a2)[1] = e2;
681         e = new CallExp(loc, e, a2);
682         e = e.trySemantic(sc);
683         if (!e1PassSemantic && !e)
684         {
685             /* https://issues.dlang.org/show_bug.cgi?id=20448
686              *
687              * If both versions have failed to pass semantic,
688              * f(e1) = e2 gets priority in error printing
689              * because f might be a templated function that
690              * failed to instantiate and we have to print
691              * the instantiation errors.
692              */
693             return e1.expressionSemantic(sc);
694         }
695         else if (ex && !e)
696         {
697             checkPropertyCall(ex);
698             ex = new AssignExp(loc, ex, e2);
699             return ex.expressionSemantic(sc);
700         }
701         else
702         {
703             // strict setter prints errors if fails
704             e = e.expressionSemantic(sc);
705         }
706         checkPropertyCall(e);
707         return e;
708     }
709     else
710     {
711         /* f(e1)
712          */
713         auto arguments = new Expressions(1);
714         (*arguments)[0] = eleft;
715         e = new CallExp(loc, e, arguments);
716         e = e.expressionSemantic(sc);
717         checkPropertyCall(e);
718         return e.expressionSemantic(sc);
719     }
720 }
721 
722 /******************************
723  * If e1 is a property function (template), resolve it.
724  */
725 Expression resolvePropertiesOnly(Scope* sc, Expression e1)
726 {
727     //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars());
728 
729     Expression handleOverloadSet(OverloadSet os)
730     {
731         assert(os);
732         foreach (s; os.a)
733         {
734             auto fd = s.isFuncDeclaration();
735             auto td = s.isTemplateDeclaration();
736             if (fd)
737             {
738                 if ((cast(TypeFunction)fd.type).isproperty)
739                     return resolveProperties(sc, e1);
740             }
741             else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
742             {
743                 if ((cast(TypeFunction)fd.type).isproperty ||
744                     (fd.storage_class2 & STC.property) ||
745                     (td._scope.stc & STC.property))
746                     return resolveProperties(sc, e1);
747             }
748         }
749         return e1;
750     }
751 
752     Expression handleTemplateDecl(TemplateDeclaration td)
753     {
754         assert(td);
755         if (td.onemember)
756         {
757             if (auto fd = td.onemember.isFuncDeclaration())
758             {
759                 if ((cast(TypeFunction)fd.type).isproperty ||
760                     (fd.storage_class2 & STC.property) ||
761                     (td._scope.stc & STC.property))
762                     return resolveProperties(sc, e1);
763             }
764         }
765         return e1;
766     }
767 
768     Expression handleFuncDecl(FuncDeclaration fd)
769     {
770         assert(fd);
771         if ((cast(TypeFunction)fd.type).isproperty)
772             return resolveProperties(sc, e1);
773         return e1;
774     }
775 
776     if (auto de = e1.isDotExp())
777     {
778         if (auto os = de.e2.isOverExp())
779             return handleOverloadSet(os.vars);
780     }
781     else if (auto oe = e1.isOverExp())
782         return handleOverloadSet(oe.vars);
783     else if (auto dti = e1.isDotTemplateInstanceExp())
784     {
785         if (dti.ti.tempdecl)
786             if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
787                 return handleTemplateDecl(td);
788     }
789     else if (auto dte = e1.isDotTemplateExp())
790         return handleTemplateDecl(dte.td);
791     else if (e1.op == TOK.scope_)
792     {
793         Dsymbol s = (cast(ScopeExp)e1).sds;
794         TemplateInstance ti = s.isTemplateInstance();
795         if (ti && !ti.semanticRun && ti.tempdecl)
796             if (auto td = ti.tempdecl.isTemplateDeclaration())
797                 return handleTemplateDecl(td);
798     }
799     else if (e1.op == TOK.template_)
800         return handleTemplateDecl((cast(TemplateExp)e1).td);
801     else if (e1.op == TOK.dotVariable && e1.type.ty == Tfunction)
802     {
803         DotVarExp dve = cast(DotVarExp)e1;
804         return handleFuncDecl(dve.var.isFuncDeclaration());
805     }
806     else if (e1.op == TOK.variable && e1.type && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis()))
807         return handleFuncDecl((cast(VarExp)e1).var.isFuncDeclaration());
808     return e1;
809 }
810 
811 /****************************************
812  * Turn symbol `s` into the expression it represents.
813  *
814  * Params:
815  *      s = symbol to resolve
816  *      loc = location of use of `s`
817  *      sc = context
818  *      hasOverloads = applies if `s` represents a function.
819  *          true means it's overloaded and will be resolved later,
820  *          false means it's the exact function symbol.
821  * Returns:
822  *      `s` turned into an expression, `ErrorExp` if an error occurred
823  */
824 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
825 {
826     static if (LOGSEMANTIC)
827     {
828         printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
829     }
830 
831 Lagain:
832     Expression e;
833 
834     //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
835     //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
836     Dsymbol olds = s;
837     Declaration d = s.isDeclaration();
838     if (d && (d.storage_class & STC.templateparameter))
839     {
840         s = s.toAlias();
841     }
842     else
843     {
844         if (!s.isFuncDeclaration()) // functions are checked after overloading
845         {
846             s.checkDeprecated(loc, sc);
847             if (d)
848                 d.checkDisabled(loc, sc);
849         }
850 
851         // https://issues.dlang.org/show_bug.cgi?id=12023
852         // if 's' is a tuple variable, the tuple is returned.
853         s = s.toAlias();
854 
855         //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
856         if (s != olds && !s.isFuncDeclaration())
857         {
858             s.checkDeprecated(loc, sc);
859             if (d)
860                 d.checkDisabled(loc, sc);
861         }
862     }
863 
864     if (auto em = s.isEnumMember())
865     {
866         return em.getVarExp(loc, sc);
867     }
868     if (auto v = s.isVarDeclaration())
869     {
870         //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
871         if (sc.intypeof == 1 && !v.inuse)
872             v.dsymbolSemantic(sc);
873         if (!v.type ||                  // during variable type inference
874             !v.type.deco && v.inuse)    // during variable type semantic
875         {
876             if (v.inuse)    // variable type depends on the variable itself
877                 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
878             else            // variable type cannot be determined
879                 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
880             return ErrorExp.get();
881         }
882         if (v.type.ty == Terror)
883             return ErrorExp.get();
884 
885         if ((v.storage_class & STC.manifest) && v._init)
886         {
887             if (v.inuse)
888             {
889                 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
890                 return ErrorExp.get();
891             }
892             e = v.expandInitializer(loc);
893             v.inuse++;
894             e = e.expressionSemantic(sc);
895             v.inuse--;
896             return e;
897         }
898 
899         // Change the ancestor lambdas to delegate before hasThis(sc) call.
900         if (v.checkNestedReference(sc, loc))
901             return ErrorExp.get();
902 
903         if (v.needThis() && hasThis(sc))
904             e = new DotVarExp(loc, new ThisExp(loc), v);
905         else
906             e = new VarExp(loc, v);
907         e = e.expressionSemantic(sc);
908         return e;
909     }
910     if (auto fld = s.isFuncLiteralDeclaration())
911     {
912         //printf("'%s' is a function literal\n", fld.toChars());
913         e = new FuncExp(loc, fld);
914         return e.expressionSemantic(sc);
915     }
916     if (auto f = s.isFuncDeclaration())
917     {
918         f = f.toAliasFunc();
919         if (!f.functionSemantic())
920             return ErrorExp.get();
921 
922         if (!hasOverloads && f.checkForwardRef(loc))
923             return ErrorExp.get();
924 
925         auto fd = s.isFuncDeclaration();
926         fd.type = f.type;
927         return new VarExp(loc, fd, hasOverloads);
928     }
929     if (OverDeclaration od = s.isOverDeclaration())
930     {
931         e = new VarExp(loc, od, true);
932         e.type = Type.tvoid;
933         return e;
934     }
935     if (OverloadSet o = s.isOverloadSet())
936     {
937         //printf("'%s' is an overload set\n", o.toChars());
938         return new OverExp(loc, o);
939     }
940 
941     if (Import imp = s.isImport())
942     {
943         if (!imp.pkg)
944         {
945             .error(loc, "forward reference of import `%s`", imp.toChars());
946             return ErrorExp.get();
947         }
948         auto ie = new ScopeExp(loc, imp.pkg);
949         return ie.expressionSemantic(sc);
950     }
951     if (Package pkg = s.isPackage())
952     {
953         auto ie = new ScopeExp(loc, pkg);
954         return ie.expressionSemantic(sc);
955     }
956     if (Module mod = s.isModule())
957     {
958         auto ie = new ScopeExp(loc, mod);
959         return ie.expressionSemantic(sc);
960     }
961     if (Nspace ns = s.isNspace())
962     {
963         auto ie = new ScopeExp(loc, ns);
964         return ie.expressionSemantic(sc);
965     }
966 
967     if (Type t = s.getType())
968     {
969         return (new TypeExp(loc, t)).expressionSemantic(sc);
970     }
971 
972     if (TupleDeclaration tup = s.isTupleDeclaration())
973     {
974         if (tup.needThis() && hasThis(sc))
975             e = new DotVarExp(loc, new ThisExp(loc), tup);
976         else
977             e = new TupleExp(loc, tup);
978         e = e.expressionSemantic(sc);
979         return e;
980     }
981 
982     if (TemplateInstance ti = s.isTemplateInstance())
983     {
984         ti.dsymbolSemantic(sc);
985         if (!ti.inst || ti.errors)
986             return ErrorExp.get();
987         s = ti.toAlias();
988         if (!s.isTemplateInstance())
989             goto Lagain;
990         e = new ScopeExp(loc, ti);
991         e = e.expressionSemantic(sc);
992         return e;
993     }
994     if (TemplateDeclaration td = s.isTemplateDeclaration())
995     {
996         Dsymbol p = td.toParentLocal();
997         FuncDeclaration fdthis = hasThis(sc);
998         AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
999         if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
1000         {
1001             e = new DotTemplateExp(loc, new ThisExp(loc), td);
1002         }
1003         else
1004             e = new TemplateExp(loc, td);
1005         e = e.expressionSemantic(sc);
1006         return e;
1007     }
1008 
1009     .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1010     return ErrorExp.get();
1011 }
1012 
1013 /*************************************************************
1014  * Given var, get the
1015  * right `this` pointer if var is in an outer class, but our
1016  * existing `this` pointer is in an inner class.
1017  * Params:
1018  *      loc = location to use for error messages
1019  *      sc = context
1020  *      ad = struct or class we need the correct `this` for
1021  *      e1 = existing `this`
1022  *      var = the specific member of ad we're accessing
1023  *      flag = if true, return `null` instead of throwing an error
1024  * Returns:
1025  *      Expression representing the `this` for the var
1026  */
1027 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1028 {
1029     //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1030 L1:
1031     Type t = e1.type.toBasetype();
1032     //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1033 
1034     if (e1.op == TOK.objcClassReference)
1035     {
1036         // We already have an Objective-C class reference, just use that as 'this'.
1037         return e1;
1038     }
1039     else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1040              var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1041              var.isFuncDeclaration.objc.selector)
1042     {
1043         return new ObjcClassReferenceExp(e1.loc, cast(ClassDeclaration) ad);
1044     }
1045 
1046     /* Access of a member which is a template parameter in dual-scope scenario
1047      * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1048      * class B {int m; inc() { new A().inc!m(); } }
1049      */
1050     if (e1.op == TOK.this_)
1051     {
1052         FuncDeclaration f = hasThis(sc);
1053         if (f && f.isThis2)
1054         {
1055             if (f.followInstantiationContext(ad))
1056             {
1057                 e1 = new VarExp(loc, f.vthis);
1058                 e1 = new PtrExp(loc, e1);
1059                 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1060                 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1061                 if (e1.op == TOK.error)
1062                     return e1;
1063                 goto L1;
1064             }
1065         }
1066     }
1067 
1068     /* If e1 is not the 'this' pointer for ad
1069      */
1070     if (ad &&
1071         !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) &&
1072         !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad))
1073     {
1074         ClassDeclaration cd = ad.isClassDeclaration();
1075         ClassDeclaration tcd = t.isClassHandle();
1076 
1077         /* e1 is the right this if ad is a base class of e1
1078          */
1079         if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1080         {
1081             /* Only classes can be inner classes with an 'outer'
1082              * member pointing to the enclosing class instance
1083              */
1084             if (tcd && tcd.isNested())
1085             {
1086                 /* e1 is the 'this' pointer for an inner class: tcd.
1087                  * Rewrite it as the 'this' pointer for the outer class.
1088                  */
1089                 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1090                 e1 = new DotVarExp(loc, e1, vthis);
1091                 e1.type = vthis.type;
1092                 e1.type = e1.type.addMod(t.mod);
1093                 // Do not call ensureStaticLinkTo()
1094                 //e1 = e1.semantic(sc);
1095 
1096                 // Skip up over nested functions, and get the enclosing
1097                 // class type.
1098                 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1099                 if (e1.op == TOK.error)
1100                     return e1;
1101                 goto L1;
1102             }
1103 
1104             /* Can't find a path from e1 to ad
1105              */
1106             if (flag)
1107                 return null;
1108             e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1109             return ErrorExp.get();
1110         }
1111     }
1112     return e1;
1113 }
1114 
1115 /***************************************
1116  * Pull out any properties.
1117  */
1118 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1119 {
1120     //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null);
1121     Loc loc = e1.loc;
1122 
1123     OverloadSet os;
1124     Dsymbol s;
1125     Objects* tiargs;
1126     Type tthis;
1127     if (e1.op == TOK.dot)
1128     {
1129         DotExp de = cast(DotExp)e1;
1130         if (de.e2.op == TOK.overloadSet)
1131         {
1132             tiargs = null;
1133             tthis = de.e1.type;
1134             os = (cast(OverExp)de.e2).vars;
1135             goto Los;
1136         }
1137     }
1138     else if (e1.op == TOK.overloadSet)
1139     {
1140         tiargs = null;
1141         tthis = null;
1142         os = (cast(OverExp)e1).vars;
1143     Los:
1144         assert(os);
1145         FuncDeclaration fd = null;
1146         if (e2)
1147         {
1148             e2 = e2.expressionSemantic(sc);
1149             if (e2.op == TOK.error)
1150                 return ErrorExp.get();
1151             e2 = resolveProperties(sc, e2);
1152 
1153             Expressions a;
1154             a.push(e2);
1155 
1156             for (size_t i = 0; i < os.a.dim; i++)
1157             {
1158                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1159                 {
1160                     if (f.errors)
1161                         return ErrorExp.get();
1162                     fd = f;
1163                     assert(fd.type.ty == Tfunction);
1164                 }
1165             }
1166             if (fd)
1167             {
1168                 Expression e = new CallExp(loc, e1, e2);
1169                 return e.expressionSemantic(sc);
1170             }
1171         }
1172         {
1173             for (size_t i = 0; i < os.a.dim; i++)
1174             {
1175                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1176                 {
1177                     if (f.errors)
1178                         return ErrorExp.get();
1179                     fd = f;
1180                     assert(fd.type.ty == Tfunction);
1181                     TypeFunction tf = cast(TypeFunction)fd.type;
1182                     if (!tf.isref && e2)
1183                     {
1184                         error(loc, "%s is not an lvalue", e1.toChars());
1185                         return ErrorExp.get();
1186                     }
1187                 }
1188             }
1189             if (fd)
1190             {
1191                 Expression e = new CallExp(loc, e1);
1192                 if (e2)
1193                     e = new AssignExp(loc, e, e2);
1194                 return e.expressionSemantic(sc);
1195             }
1196         }
1197         if (e2)
1198             goto Leprop;
1199     }
1200     else if (e1.op == TOK.dotTemplateInstance)
1201     {
1202         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
1203         if (!dti.findTempDecl(sc))
1204             goto Leprop;
1205         if (!dti.ti.semanticTiargs(sc))
1206             goto Leprop;
1207         tiargs = dti.ti.tiargs;
1208         tthis = dti.e1.type;
1209         if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1210             goto Los;
1211         if ((s = dti.ti.tempdecl) !is null)
1212             goto Lfd;
1213     }
1214     else if (e1.op == TOK.dotTemplateDeclaration)
1215     {
1216         DotTemplateExp dte = cast(DotTemplateExp)e1;
1217         s = dte.td;
1218         tiargs = null;
1219         tthis = dte.e1.type;
1220         goto Lfd;
1221     }
1222     else if (e1.op == TOK.scope_)
1223     {
1224         s = (cast(ScopeExp)e1).sds;
1225         TemplateInstance ti = s.isTemplateInstance();
1226         if (ti && !ti.semanticRun && ti.tempdecl)
1227         {
1228             //assert(ti.needsTypeInference(sc));
1229             if (!ti.semanticTiargs(sc))
1230                 goto Leprop;
1231             tiargs = ti.tiargs;
1232             tthis = null;
1233             if ((os = ti.tempdecl.isOverloadSet()) !is null)
1234                 goto Los;
1235             if ((s = ti.tempdecl) !is null)
1236                 goto Lfd;
1237         }
1238     }
1239     else if (e1.op == TOK.template_)
1240     {
1241         s = (cast(TemplateExp)e1).td;
1242         tiargs = null;
1243         tthis = null;
1244         goto Lfd;
1245     }
1246     else if (e1.op == TOK.dotVariable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(DotVarExp)e1).var.isOverDeclaration()))
1247     {
1248         DotVarExp dve = cast(DotVarExp)e1;
1249         s = dve.var;
1250         tiargs = null;
1251         tthis = dve.e1.type;
1252         goto Lfd;
1253     }
1254     else if (e1.op == TOK.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
1255     {
1256         s = (cast(VarExp)e1).var;
1257         tiargs = null;
1258         tthis = null;
1259     Lfd:
1260         assert(s);
1261         if (e2)
1262         {
1263             e2 = e2.expressionSemantic(sc);
1264             if (e2.op == TOK.error)
1265                 return ErrorExp.get();
1266             e2 = resolveProperties(sc, e2);
1267 
1268             Expressions a;
1269             a.push(e2);
1270 
1271             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1272             if (fd && fd.type)
1273             {
1274                 if (fd.errors)
1275                     return ErrorExp.get();
1276                 if (!checkSymbolAccess(sc, fd))
1277                 {
1278                     // @@@DEPRECATED_2020-10@@@
1279                     // When turning into error, uncomment the return statement
1280                     TypeFunction tf = cast(TypeFunction)fd.type;
1281                     deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1282                                 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1283                     //return ErrorExp.get();
1284                 }
1285                 assert(fd.type.ty == Tfunction);
1286                 Expression e = new CallExp(loc, e1, e2);
1287                 return e.expressionSemantic(sc);
1288             }
1289         }
1290         {
1291             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1292             if (fd && fd.type)
1293             {
1294                 if (fd.errors)
1295                     return ErrorExp.get();
1296                 assert(fd.type.ty == Tfunction);
1297                 TypeFunction tf = cast(TypeFunction)fd.type;
1298                 if (!e2 || tf.isref)
1299                 {
1300                     if (!checkSymbolAccess(sc, fd))
1301                     {
1302                         // @@@DEPRECATED_2020-10@@@
1303                         // When turning into error, uncomment the return statement
1304                         deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1305                                     fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1306                         //return ErrorExp.get();
1307                     }
1308                     Expression e = new CallExp(loc, e1);
1309                     if (e2)
1310                         e = new AssignExp(loc, e, e2);
1311                     return e.expressionSemantic(sc);
1312                 }
1313             }
1314         }
1315         if (FuncDeclaration fd = s.isFuncDeclaration())
1316         {
1317             // Keep better diagnostic message for invalid property usage of functions
1318             assert(fd.type.ty == Tfunction);
1319             Expression e = new CallExp(loc, e1, e2);
1320             return e.expressionSemantic(sc);
1321         }
1322         if (e2)
1323             goto Leprop;
1324     }
1325     if (e1.op == TOK.variable)
1326     {
1327         VarExp ve = cast(VarExp)e1;
1328         VarDeclaration v = ve.var.isVarDeclaration();
1329         if (v && ve.checkPurity(sc, v))
1330             return ErrorExp.get();
1331     }
1332     if (e2)
1333         return null;
1334 
1335     if (e1.type && e1.op != TOK.type) // function type is not a property
1336     {
1337         /* Look for e1 being a lazy parameter; rewrite as delegate call
1338          * only if the symbol wasn't already treated as a delegate
1339          */
1340         auto ve = e1.isVarExp();
1341         if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1342         {
1343                 Expression e = new CallExp(loc, e1);
1344                 return e.expressionSemantic(sc);
1345         }
1346         else if (e1.op == TOK.dotVariable)
1347         {
1348             // Check for reading overlapped pointer field in @safe code.
1349             if (checkUnsafeAccess(sc, e1, true, true))
1350                 return ErrorExp.get();
1351         }
1352         else if (e1.op == TOK.dot)
1353         {
1354             e1.error("expression has no value");
1355             return ErrorExp.get();
1356         }
1357         else if (e1.op == TOK.call)
1358         {
1359             CallExp ce = cast(CallExp)e1;
1360             // Check for reading overlapped pointer field in @safe code.
1361             if (checkUnsafeAccess(sc, ce.e1, true, true))
1362                 return ErrorExp.get();
1363         }
1364     }
1365 
1366     if (!e1.type)
1367     {
1368         error(loc, "cannot resolve type for %s", e1.toChars());
1369         e1 = ErrorExp.get();
1370     }
1371     return e1;
1372 
1373 Leprop:
1374     error(loc, "not a property %s", e1.toChars());
1375     return ErrorExp.get();
1376 }
1377 
1378 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1379 {
1380     //printf("resolveProperties(%s)\n", e.toChars());
1381     e = resolvePropertiesX(sc, e);
1382     if (e.checkRightThis(sc))
1383         return ErrorExp.get();
1384     return e;
1385 }
1386 
1387 /****************************************
1388  * The common type is determined by applying ?: to each pair.
1389  * Output:
1390  *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1391  * Returns:
1392  *      The common type, or `null` if an error has occured
1393  */
1394 private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
1395 {
1396     /* Still have a problem with:
1397      *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1398      * which works if the array literal is initialized top down with the ubyte[][]
1399      * type, but fails with this function doing bottom up typing.
1400      */
1401 
1402     //printf("arrayExpressionToCommonType()\n");
1403     scope IntegerExp integerexp = IntegerExp.literal!0;
1404     scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1405 
1406     Type t0 = null;
1407     Expression e0 = null;
1408     size_t j0 = ~0;
1409     bool foundType;
1410 
1411     for (size_t i = 0; i < exps.dim; i++)
1412     {
1413         Expression e = exps[i];
1414         if (!e)
1415             continue;
1416 
1417         e = resolveProperties(sc, e);
1418         if (!e.type)
1419         {
1420             e.error("`%s` has no value", e.toChars());
1421             t0 = Type.terror;
1422             continue;
1423         }
1424         if (e.op == TOK.type)
1425         {
1426             foundType = true; // do not break immediately, there might be more errors
1427             e.checkValue(); // report an error "type T has no value"
1428             t0 = Type.terror;
1429             continue;
1430         }
1431         if (e.type.ty == Tvoid)
1432         {
1433             // void expressions do not concur to the determination of the common
1434             // type.
1435             continue;
1436         }
1437         if (checkNonAssignmentArrayOp(e))
1438         {
1439             t0 = Type.terror;
1440             continue;
1441         }
1442 
1443         e = doCopyOrMove(sc, e);
1444 
1445         if (!foundType && t0 && !t0.equals(e.type))
1446         {
1447             /* This applies ?: to merge the types. It's backwards;
1448              * ?: should call this function to merge types.
1449              */
1450             condexp.type = null;
1451             condexp.e1 = e0;
1452             condexp.e2 = e;
1453             condexp.loc = e.loc;
1454             Expression ex = condexp.expressionSemantic(sc);
1455             if (ex.op == TOK.error)
1456                 e = ex;
1457             else if (e.op == TOK.function_ || e.op == TOK.delegate_)
1458             {
1459                 // https://issues.dlang.org/show_bug.cgi?id=21285
1460                 // Functions and delegates don't convert correctly with castTo below
1461                 exps[j0] = condexp.e1;
1462                 e = condexp.e2;
1463             }
1464             else
1465             {
1466                 // Convert to common type
1467                 exps[j0] = condexp.e1.castTo(sc, condexp.type);
1468                 e = condexp.e2.castTo(sc, condexp.type);
1469             }
1470         }
1471         j0 = i;
1472         e0 = e;
1473         t0 = e.type;
1474         if (e.op != TOK.error)
1475             exps[i] = e;
1476     }
1477 
1478     // [] is typed as void[]
1479     if (!t0)
1480         return Type.tvoid;
1481 
1482     // It's an error, don't do the cast
1483     if (t0.ty == Terror)
1484         return null;
1485 
1486     for (size_t i = 0; i < exps.dim; i++)
1487     {
1488         Expression e = exps[i];
1489         if (!e)
1490             continue;
1491 
1492         e = e.implicitCastTo(sc, t0);
1493         if (e.op == TOK.error)
1494         {
1495             /* https://issues.dlang.org/show_bug.cgi?id=13024
1496              * a workaround for the bug in typeMerge -
1497              * it should paint e1 and e2 by deduced common type,
1498              * but doesn't in this particular case.
1499              */
1500             return null;
1501         }
1502         exps[i] = e;
1503     }
1504     return t0;
1505 }
1506 
1507 private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2)
1508 {
1509     Expression e;
1510     switch (op)
1511     {
1512     case TOK.addAssign:
1513         e = new AddExp(loc, e1, e2);
1514         break;
1515 
1516     case TOK.minAssign:
1517         e = new MinExp(loc, e1, e2);
1518         break;
1519 
1520     case TOK.mulAssign:
1521         e = new MulExp(loc, e1, e2);
1522         break;
1523 
1524     case TOK.divAssign:
1525         e = new DivExp(loc, e1, e2);
1526         break;
1527 
1528     case TOK.modAssign:
1529         e = new ModExp(loc, e1, e2);
1530         break;
1531 
1532     case TOK.andAssign:
1533         e = new AndExp(loc, e1, e2);
1534         break;
1535 
1536     case TOK.orAssign:
1537         e = new OrExp(loc, e1, e2);
1538         break;
1539 
1540     case TOK.xorAssign:
1541         e = new XorExp(loc, e1, e2);
1542         break;
1543 
1544     case TOK.leftShiftAssign:
1545         e = new ShlExp(loc, e1, e2);
1546         break;
1547 
1548     case TOK.rightShiftAssign:
1549         e = new ShrExp(loc, e1, e2);
1550         break;
1551 
1552     case TOK.unsignedRightShiftAssign:
1553         e = new UshrExp(loc, e1, e2);
1554         break;
1555 
1556     default:
1557         assert(0);
1558     }
1559     return e;
1560 }
1561 
1562 /*********************
1563  * Rewrite:
1564  *    array.length op= e2
1565  * as:
1566  *    array.length = array.length op e2
1567  * or:
1568  *    auto tmp = &array;
1569  *    (*tmp).length = (*tmp).length op e2
1570  */
1571 private Expression rewriteOpAssign(BinExp exp)
1572 {
1573     Expression e;
1574 
1575     assert(exp.e1.op == TOK.arrayLength);
1576     ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
1577     if (ale.e1.op == TOK.variable)
1578     {
1579         e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1580         e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1581     }
1582     else
1583     {
1584         /*    auto tmp = &array;
1585          *    (*tmp).length = (*tmp).length op e2
1586          */
1587         auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1588 
1589         Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1590         Expression elvalue = e1.syntaxCopy();
1591         e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1592         e = new AssignExp(exp.loc, elvalue, e);
1593         e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1594     }
1595     return e;
1596 }
1597 
1598 /****************************************
1599  * Preprocess arguments to function.
1600  * Input:
1601  *      reportErrors    whether or not to report errors here.  Some callers are not
1602  *                      checking actual function params, so they'll do their own error reporting
1603  * Output:
1604  *      exps[]  tuples expanded, properties resolved, rewritten in place
1605  * Returns:
1606  *      true    a semantic error occurred
1607  */
1608 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1609 {
1610     bool err = false;
1611     if (exps)
1612     {
1613         expandTuples(exps);
1614 
1615         for (size_t i = 0; i < exps.dim; i++)
1616         {
1617             Expression arg = (*exps)[i];
1618             arg = resolveProperties(sc, arg);
1619             if (arg.op == TOK.type)
1620             {
1621                 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1622                 arg = resolveAliasThis(sc, arg);
1623 
1624                 if (arg.op == TOK.type)
1625                 {
1626                     if (reportErrors)
1627                     {
1628                         arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1629                         arg = ErrorExp.get();
1630                     }
1631                     err = true;
1632                 }
1633             }
1634             else if (arg.type.toBasetype().ty == Tfunction)
1635             {
1636                 if (reportErrors)
1637                 {
1638                     arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1639                     arg = ErrorExp.get();
1640                 }
1641                 err = true;
1642             }
1643             else if (checkNonAssignmentArrayOp(arg))
1644             {
1645                 arg = ErrorExp.get();
1646                 err = true;
1647             }
1648             (*exps)[i] = arg;
1649         }
1650     }
1651     return err;
1652 }
1653 
1654 /********************************************
1655  * Issue an error if default construction is disabled for type t.
1656  * Default construction is required for arrays and 'out' parameters.
1657  * Returns:
1658  *      true    an error was issued
1659  */
1660 private bool checkDefCtor(Loc loc, Type t)
1661 {
1662     t = t.baseElemOf();
1663     if (t.ty == Tstruct)
1664     {
1665         StructDeclaration sd = (cast(TypeStruct)t).sym;
1666         if (sd.noDefaultCtor)
1667         {
1668             sd.error(loc, "default construction is disabled");
1669             return true;
1670         }
1671     }
1672     return false;
1673 }
1674 
1675 /****************************************
1676  * Now that we know the exact type of the function we're calling,
1677  * the arguments[] need to be adjusted:
1678  *      1. implicitly convert argument to the corresponding parameter type
1679  *      2. add default arguments for any missing arguments
1680  *      3. do default promotions on arguments corresponding to ...
1681  *      4. add hidden _arguments[] argument
1682  *      5. call copy constructor for struct value arguments
1683  * Params:
1684  *      loc       = location of function call
1685  *      sc        = context
1686  *      tf        = type of the function
1687  *      ethis     = `this` argument, `null` if none or not known
1688  *      tthis     = type of `this` argument, `null` if no `this` argument
1689  *      arguments = array of actual arguments to function call
1690  *      fd        = the function being called, `null` if called indirectly
1691  *      prettype  = set to return type of function
1692  *      peprefix  = set to expression to execute before `arguments[]` are evaluated, `null` if none
1693  * Returns:
1694  *      true    errors happened
1695  */
1696 private bool functionParameters(const ref Loc loc, Scope* sc,
1697     TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1698     Type* prettype, Expression* peprefix)
1699 {
1700     //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1701     assert(arguments);
1702     assert(fd || tf.next);
1703     size_t nargs = arguments ? arguments.dim : 0;
1704     const size_t nparams = tf.parameterList.length;
1705     const olderrors = global.errors;
1706     bool err = false;
1707     *prettype = Type.terror;
1708     Expression eprefix = null;
1709     *peprefix = null;
1710 
1711     if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1712     {
1713         error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1714         return true;
1715     }
1716 
1717     // If inferring return type, and semantic3() needs to be run if not already run
1718     if (!tf.next && fd.inferRetType)
1719     {
1720         fd.functionSemantic();
1721     }
1722     else if (fd && fd.parent)
1723     {
1724         TemplateInstance ti = fd.parent.isTemplateInstance();
1725         if (ti && ti.tempdecl)
1726         {
1727             fd.functionSemantic3();
1728         }
1729     }
1730 
1731     /* If calling a pragma(inline, true) function,
1732      * set flag to later scan for inlines.
1733      */
1734     if (fd && fd.inlining == PINLINE.always)
1735     {
1736         if (sc._module)
1737             sc._module.hasAlwaysInlines = true;
1738         if (sc.func)
1739             sc.func.hasAlwaysInlines = true;
1740     }
1741 
1742     const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1743 
1744     const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1745 
1746     /* If the function return type has wildcards in it, we'll need to figure out the actual type
1747      * based on the actual argument types.
1748      * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1749      * of the arguments.
1750      */
1751     MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1752 
1753     bool done = false;
1754     foreach (const i; 0 .. n)
1755     {
1756         Expression arg = (i < nargs) ? (*arguments)[i] : null;
1757 
1758         if (i < nparams)
1759         {
1760             bool errorArgs()
1761             {
1762                 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1763                 return true;
1764             }
1765 
1766             Parameter p = tf.parameterList[i];
1767 
1768             if (!arg)
1769             {
1770                 if (!p.defaultArg)
1771                 {
1772                     if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1773                         goto L2;
1774                     return errorArgs();
1775                 }
1776                 arg = p.defaultArg;
1777                 arg = inlineCopy(arg, sc);
1778                 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1779                 arg = arg.resolveLoc(loc, sc);
1780                 arguments.push(arg);
1781                 nargs++;
1782             }
1783             else
1784             {
1785                 if (isDefaultInitOp(arg.op))
1786                 {
1787                     arg = arg.resolveLoc(loc, sc);
1788                     (*arguments)[i] = arg;
1789                 }
1790             }
1791 
1792 
1793             if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1794             {
1795                 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1796                 {
1797                     MATCH m;
1798                     if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1799                     {
1800                         if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1801                             goto L2;
1802                         else if (nargs != nparams)
1803                             return errorArgs();
1804                         goto L1;
1805                     }
1806                 }
1807             L2:
1808                 Type tb = p.type.toBasetype();
1809                 switch (tb.ty)
1810                 {
1811                 case Tsarray:
1812                 case Tarray:
1813                     {
1814                         /* Create a static array variable v of type arg.type:
1815                          *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1816                          *
1817                          * The array literal in the initializer of the hidden variable
1818                          * is now optimized.
1819                          * https://issues.dlang.org/show_bug.cgi?id=2356
1820                          */
1821                         Type tbn = (cast(TypeArray)tb).next;    // array element type
1822                         Type tret = p.isLazyArray();
1823 
1824                         auto elements = new Expressions(nargs - i);
1825                         foreach (u; 0 .. elements.dim)
1826                         {
1827                             Expression a = (*arguments)[i + u];
1828                             if (tret && a.implicitConvTo(tret))
1829                             {
1830                                 // p is a lazy array of delegates, tret is return type of the delegates
1831                                 a = a.implicitCastTo(sc, tret)
1832                                      .optimize(WANTvalue)
1833                                      .toDelegate(tret, sc);
1834                             }
1835                             else
1836                                 a = a.implicitCastTo(sc, tbn);
1837                             a = a.addDtorHook(sc);
1838                             (*elements)[u] = a;
1839                         }
1840                         // https://issues.dlang.org/show_bug.cgi?id=14395
1841                         // Convert to a static array literal, or its slice.
1842                         arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1843                         if (tb.ty == Tarray)
1844                         {
1845                             arg = new SliceExp(loc, arg, null, null);
1846                             arg.type = p.type;
1847                         }
1848                         break;
1849                     }
1850                 case Tclass:
1851                     {
1852                         /* Set arg to be:
1853                          *      new Tclass(arg0, arg1, ..., argn)
1854                          */
1855                         auto args = new Expressions(nargs - i);
1856                         foreach (u; i .. nargs)
1857                             (*args)[u - i] = (*arguments)[u];
1858                         arg = new NewExp(loc, null, null, p.type, args);
1859                         break;
1860                     }
1861                 default:
1862                     if (!arg)
1863                     {
1864                         error(loc, "not enough arguments");
1865                         return true;
1866                     }
1867                     break;
1868                 }
1869                 arg = arg.expressionSemantic(sc);
1870                 //printf("\targ = '%s'\n", arg.toChars());
1871                 arguments.setDim(i + 1);
1872                 (*arguments)[i] = arg;
1873                 nargs = i + 1;
1874                 done = true;
1875             }
1876 
1877         L1:
1878             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1879             {
1880                 const isRef = (p.storageClass & (STC.ref_ | STC.out_)) != 0;
1881                 if (ubyte wm = arg.type.deduceWild(p.type, isRef))
1882                 {
1883                     wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1884                     //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1885                 }
1886             }
1887         }
1888         if (done)
1889             break;
1890     }
1891     if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1892         tf.next && tf.next.hasWild() &&
1893         (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1894     {
1895         bool errorInout(MOD wildmatch)
1896         {
1897             const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1898             error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1899             return true;
1900         }
1901 
1902         if (fd)
1903         {
1904             /* If the called function may return the reference to
1905              * outer inout data, it should be rejected.
1906              *
1907              * void foo(ref inout(int) x) {
1908              *   ref inout(int) bar(inout(int)) { return x; }
1909              *   struct S {
1910              *      ref inout(int) bar() inout { return x; }
1911              *      ref inout(int) baz(alias a)() inout { return x; }
1912              *   }
1913              *   bar(int.init) = 1;  // bad!
1914              *   S().bar() = 1;      // bad!
1915              * }
1916              * void test() {
1917              *   int a;
1918              *   auto s = foo(a);
1919              *   s.baz!a() = 1;      // bad!
1920              * }
1921              *
1922              */
1923             bool checkEnclosingWild(Dsymbol s)
1924             {
1925                 bool checkWild(Dsymbol s)
1926                 {
1927                     if (!s)
1928                         return false;
1929                     if (auto ad = s.isAggregateDeclaration())
1930                     {
1931                         if (ad.isNested())
1932                             return checkEnclosingWild(s);
1933                     }
1934                     else if (auto ff = s.isFuncDeclaration())
1935                     {
1936                         if ((cast(TypeFunction)ff.type).iswild)
1937                             return errorInout(wildmatch);
1938 
1939                         if (ff.isNested() || ff.isThis())
1940                             return checkEnclosingWild(s);
1941                     }
1942                     return false;
1943                 }
1944 
1945                 Dsymbol ctx0 = s.toParent2();
1946                 Dsymbol ctx1 = s.toParentLocal();
1947                 if (checkWild(ctx0))
1948                     return true;
1949                 if (ctx0 != ctx1)
1950                     return checkWild(ctx1);
1951                 return false;
1952             }
1953             if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1954                 return true;
1955         }
1956         else if (tf.isWild())
1957             return errorInout(wildmatch);
1958     }
1959 
1960     Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1961                            tthis &&
1962                            tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1963                            tthis.hasPointers())
1964                           ? ethis : null;
1965 
1966     assert(nargs >= nparams);
1967     foreach (const i, arg; (*arguments)[0 .. nargs])
1968     {
1969         assert(arg);
1970         if (i < nparams)
1971         {
1972             Parameter p = tf.parameterList[i];
1973             Type targ = arg.type;               // keep original type for isCopyable() because alias this
1974                                                 // resolution may hide an uncopyable type
1975 
1976             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1977             {
1978                 Type tprm = p.type.hasWild()
1979                     ? p.type.substWildTo(wildmatch)
1980                     : p.type;
1981 
1982                 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
1983                 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1984                 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1985                 {
1986                     //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1987                     arg = arg.implicitCastTo(sc, tprm);
1988                     arg = arg.optimize(WANTvalue, p.isReference());
1989                 }
1990             }
1991 
1992             // Support passing rvalue to `in` parameters
1993             if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
1994             {
1995                 if (!arg.isLvalue())
1996                 {
1997                     auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
1998                     Expression ev = new DeclarationExp(arg.loc, v);
1999                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2000                     arg = ev.expressionSemantic(sc);
2001                 }
2002                 arg = arg.toLvalue(sc, arg);
2003 
2004                 // Look for mutable misaligned pointer, etc., in @safe mode
2005                 err |= checkUnsafeAccess(sc, arg, false, true);
2006             }
2007             else if (p.storageClass & STC.ref_)
2008             {
2009                 if (global.params.rvalueRefParam &&
2010                     !arg.isLvalue() &&
2011                     targ.isCopyable())
2012                 {   /* allow rvalues to be passed to ref parameters by copying
2013                      * them to a temp, then pass the temp as the argument
2014                      */
2015                     auto v = copyToTemp(0, "__rvalue", arg);
2016                     Expression ev = new DeclarationExp(arg.loc, v);
2017                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2018                     arg = ev.expressionSemantic(sc);
2019                 }
2020                 arg = arg.toLvalue(sc, arg);
2021 
2022                 // Look for mutable misaligned pointer, etc., in @safe mode
2023                 err |= checkUnsafeAccess(sc, arg, false, true);
2024             }
2025             else if (p.storageClass & STC.out_)
2026             {
2027                 Type t = arg.type;
2028                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2029                 {
2030                     arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2031                     err = true;
2032                 }
2033                 else
2034                 {
2035                     // Look for misaligned pointer, etc., in @safe mode
2036                     err |= checkUnsafeAccess(sc, arg, false, true);
2037                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
2038                 }
2039                 arg = arg.toLvalue(sc, arg);
2040             }
2041             else if (p.storageClass & STC.lazy_)
2042             {
2043                 // Convert lazy argument to a delegate
2044                 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2045                 arg = toDelegate(arg, t, sc);
2046             }
2047             //printf("arg: %s\n", arg.toChars());
2048             //printf("type: %s\n", arg.type.toChars());
2049             //printf("param: %s\n", p.toChars());
2050 
2051             if (firstArg && p.storageClass & STC.return_)
2052             {
2053                 /* Argument value can be assigned to firstArg.
2054                  * Check arg to see if it matters.
2055                  */
2056                 if (global.params.vsafe)
2057                     err |= checkParamArgumentReturn(sc, firstArg, arg, false);
2058             }
2059             else if (tf.parameterEscapes(tthis, p))
2060             {
2061                 /* Argument value can escape from the called function.
2062                  * Check arg to see if it matters.
2063                  */
2064                 if (global.params.vsafe)
2065                     err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2066             }
2067             else
2068             {
2069                 /* Argument value cannot escape from the called function.
2070                  */
2071                 Expression a = arg;
2072                 if (a.op == TOK.cast_)
2073                     a = (cast(CastExp)a).e1;
2074 
2075                 ArrayLiteralExp ale;
2076                 if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) &&
2077                     (ale = a.isArrayLiteralExp()) !is null)
2078                 {
2079                     // allocate the array literal as temporary static array on the stack
2080                     ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
2081                     auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2082                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
2083                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
2084                     arg = CommaExp.combine(declareTmp, castToSlice);
2085                     arg = arg.expressionSemantic(sc);
2086                 }
2087                 else if (a.op == TOK.function_)
2088                 {
2089                     /* Function literals can only appear once, so if this
2090                      * appearance was scoped, there cannot be any others.
2091                      */
2092                     FuncExp fe = cast(FuncExp)a;
2093                     fe.fd.tookAddressOf = 0;
2094                 }
2095                 else if (a.op == TOK.delegate_)
2096                 {
2097                     /* For passing a delegate to a scoped parameter,
2098                      * this doesn't count as taking the address of it.
2099                      * We only worry about 'escaping' references to the function.
2100                      */
2101                     DelegateExp de = cast(DelegateExp)a;
2102                     if (de.e1.op == TOK.variable)
2103                     {
2104                         VarExp ve = cast(VarExp)de.e1;
2105                         FuncDeclaration f = ve.var.isFuncDeclaration();
2106                         if (f)
2107                         {
2108                             if (f.tookAddressOf)
2109                                 --f.tookAddressOf;
2110                             //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2111                         }
2112                     }
2113                 }
2114             }
2115             if (!p.isReference())
2116                 err |= arg.checkSharedAccess(sc);
2117 
2118             arg = arg.optimize(WANTvalue, p.isReference());
2119 
2120             /* Determine if this parameter is the "first reference" parameter through which
2121              * later "return" arguments can be stored.
2122              */
2123             if (i == 0 && !tthis && p.isReference() && p.type &&
2124                 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2125             {
2126                 Type tb = p.type.baseElemOf();
2127                 if (tb.isMutable() && tb.hasPointers())
2128                 {
2129                     firstArg = arg;
2130                 }
2131             }
2132         }
2133         else
2134         {
2135             // These will be the trailing ... arguments
2136             // If not D linkage, do promotions
2137             if (tf.linkage != LINK.d)
2138             {
2139                 // Promote bytes, words, etc., to ints
2140                 arg = integralPromotions(arg, sc);
2141 
2142                 // Promote floats to doubles
2143                 switch (arg.type.ty)
2144                 {
2145                 case Tfloat32:
2146                     arg = arg.castTo(sc, Type.tfloat64);
2147                     break;
2148 
2149                 case Timaginary32:
2150                     arg = arg.castTo(sc, Type.timaginary64);
2151                     break;
2152 
2153                 default:
2154                     break;
2155                 }
2156                 if (tf.parameterList.varargs == VarArg.variadic)
2157                 {
2158                     const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2159                     if (arg.type.ty == Tarray)
2160                     {
2161                         arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2162                         err = true;
2163                     }
2164                     if (arg.type.ty == Tsarray)
2165                     {
2166                         arg.error("cannot pass static arrays to `%s` vararg functions", p);
2167                         err = true;
2168                     }
2169                 }
2170             }
2171 
2172             // Do not allow types that need destructors or copy constructors.
2173             if (arg.type.needsDestruction())
2174             {
2175                 arg.error("cannot pass types that need destruction as variadic arguments");
2176                 err = true;
2177             }
2178             if (arg.type.needsCopyOrPostblit())
2179             {
2180                 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2181                 err = true;
2182             }
2183 
2184             // Convert static arrays to dynamic arrays
2185             // BUG: I don't think this is right for D2
2186             Type tb = arg.type.toBasetype();
2187             if (tb.ty == Tsarray)
2188             {
2189                 TypeSArray ts = cast(TypeSArray)tb;
2190                 Type ta = ts.next.arrayOf();
2191                 if (ts.size(arg.loc) == 0)
2192                     arg = new NullExp(arg.loc, ta);
2193                 else
2194                     arg = arg.castTo(sc, ta);
2195             }
2196             if (tb.ty == Tstruct)
2197             {
2198                 //arg = callCpCtor(sc, arg);
2199             }
2200             // Give error for overloaded function addresses
2201             if (arg.op == TOK.symbolOffset)
2202             {
2203                 SymOffExp se = cast(SymOffExp)arg;
2204                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2205                 {
2206                     arg.error("function `%s` is overloaded", arg.toChars());
2207                     err = true;
2208                 }
2209             }
2210             err |= arg.checkValue();
2211             err |= arg.checkSharedAccess(sc);
2212             arg = arg.optimize(WANTvalue);
2213         }
2214         (*arguments)[i] = arg;
2215     }
2216 
2217     /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2218      */
2219     const isVa_list = tf.parameterList.varargs == VarArg.none;
2220     if (fd && fd.flags & FUNCFLAG.printf)
2221     {
2222         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2223         {
2224             checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2225         }
2226     }
2227     else if (fd && fd.flags & FUNCFLAG.scanf)
2228     {
2229         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2230         {
2231             checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2232         }
2233     }
2234     else
2235     {
2236         // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2237     }
2238 
2239     /* Remaining problems:
2240      * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2241      *    implemented by calling a function) we'll defer this for now.
2242      * 2. value structs (or static arrays of them) that need to be copy constructed
2243      * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2244      *    function gets called.
2245      * 4. value structs need to be destructed after the function call for platforms where the caller destroys the arguments.
2246      * 2, 3 and 4 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2247      * up properly. Pushing arguments on the stack then cannot fail.
2248      */
2249      {
2250         /* TODO: tackle problem 1)
2251          */
2252         const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2253         if (!leftToRight)
2254             assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2255 
2256         /* Does Problem (4) apply?
2257          */
2258         const bool callerDestroysArgs = !target.isCalleeDestroyingArgs(tf);
2259 
2260         const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2261         const ptrdiff_t end   = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2262         const ptrdiff_t step  = (leftToRight ? 1 : -1);
2263 
2264         /* Compute indices of last throwing argument and first arg needing destruction.
2265          * Used to not set up destructors unless an arg needs destruction on a throw
2266          * in a later argument.
2267          */
2268         ptrdiff_t lastthrow = -1;   // last argument that may throw
2269         ptrdiff_t firstdtor = -1;   // first argument that needs destruction
2270         ptrdiff_t lastdtor  = -1;   // last argument that needs destruction
2271         for (ptrdiff_t i = start; i != end; i += step)
2272         {
2273             Expression arg = (*arguments)[i];
2274             if (canThrow(arg, sc.func, false))
2275                 lastthrow = i;
2276             if (arg.type.needsDestruction())
2277             {
2278                 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2279                 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
2280                 {
2281                     if (firstdtor == -1)
2282                         firstdtor = i;
2283                     lastdtor = i;
2284                 }
2285             }
2286         }
2287 
2288         /* Do we need 'eprefix' for problems 3 or 4?
2289          */
2290         const bool needsPrefix = callerDestroysArgs
2291             ? firstdtor >= 0 // true if any argument needs destruction
2292             : firstdtor >= 0 && lastthrow >= 0 &&
2293               (lastthrow - firstdtor) * step > 0; // last throw after first destruction
2294         const ptrdiff_t lastPrefix = callerDestroysArgs
2295             ? lastdtor   // up to last argument requiring destruction
2296             : lastthrow; // up to last potentially throwing argument
2297 
2298         /* Problem 3: initialize 'eprefix' by declaring the gate
2299          */
2300         VarDeclaration gate;
2301         if (needsPrefix && !callerDestroysArgs)
2302         {
2303             // eprefix => bool __gate [= false]
2304             Identifier idtmp = Identifier.generateId("__gate");
2305             gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2306             gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2307             gate.dsymbolSemantic(sc);
2308 
2309             auto ae = new DeclarationExp(loc, gate);
2310             eprefix = ae.expressionSemantic(sc);
2311         }
2312 
2313         for (ptrdiff_t i = start; i != end; i += step)
2314         {
2315             Expression arg = (*arguments)[i];
2316             //printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
2317 
2318             Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2319             const bool isRef = parameter && parameter.isReference();
2320             const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2321 
2322             /* Skip lazy parameters
2323              */
2324             if (isLazy)
2325                 continue;
2326 
2327             /* Do we have 'eprefix' and aren't past 'lastPrefix' yet?
2328              * Then declare a temporary variable for this arg and append that declaration
2329              * to 'eprefix', which will implicitly take care of potential problem 2) for
2330              * this arg.
2331              * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
2332              * excluding all lazy parameters.
2333              */
2334             if (needsPrefix && (lastPrefix - i) * step >= 0)
2335             {
2336                 const bool needsDtor = !isRef && arg.type.needsDestruction() &&
2337                                        // Problem 3: last throwing arg doesn't require dtor patching
2338                                        (callerDestroysArgs || i != lastPrefix);
2339 
2340                 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2341                  */
2342                 auto tmp = copyToTemp(0,
2343                     needsDtor ? "__pfx" : "__pfy",
2344                     !isRef ? arg : arg.addressOf());
2345                 tmp.dsymbolSemantic(sc);
2346 
2347                 if (callerDestroysArgs)
2348                 {
2349                     /* Problem 4: Normal temporary, destructed after the call
2350                      */
2351                     if (needsDtor)
2352                         tmp.isArgDtorVar = true;   // mark it so that the backend passes it by ref to the function being called
2353                 }
2354                 else
2355                 {
2356                     /* Problem 3: Modify the destructor so it only runs if gate==false,
2357                      * i.e., only if there was a throw while constructing the args
2358                      */
2359                     if (!needsDtor)
2360                     {
2361                         if (tmp.edtor)
2362                         {
2363                             assert(i == lastPrefix);
2364                             tmp.edtor = null;
2365                         }
2366                     }
2367                     else
2368                     {
2369                         // edtor => (__gate || edtor)
2370                         assert(tmp.edtor);
2371                         Expression e = tmp.edtor;
2372                         e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e);
2373                         tmp.edtor = e.expressionSemantic(sc);
2374                         //printf("edtor: %s\n", tmp.edtor.toChars());
2375                     }
2376                 }
2377 
2378                 // eprefix => (eprefix, auto __pfx/y = arg)
2379                 auto ae = new DeclarationExp(loc, tmp);
2380                 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2381 
2382                 // arg => __pfx/y
2383                 arg = new VarExp(loc, tmp);
2384                 arg = arg.expressionSemantic(sc);
2385                 if (isRef)
2386                 {
2387                     arg = new PtrExp(loc, arg);
2388                     arg = arg.expressionSemantic(sc);
2389                 }
2390 
2391                 /* Problem 3: Last throwing arg?
2392                  * Then finalize eprefix => (eprefix, gate = true), i.e., disable the
2393                  * dtors right after constructing the last throwing arg.
2394                  * From now on, the callee will take care of destructing the args because
2395                  * the args are implicitly moved into function parameters.
2396                  */
2397                 if (!callerDestroysArgs && i == lastPrefix)
2398                 {
2399                     auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2400                     eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2401                 }
2402             }
2403             else // not part of 'eprefix'
2404             {
2405                 /* Handle problem 2) by calling the copy constructor for value structs
2406                  * (or static arrays of them) if appropriate.
2407                  */
2408                 Type tv = arg.type.baseElemOf();
2409                 if (!isRef && tv.ty == Tstruct)
2410                     arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2411             }
2412 
2413             (*arguments)[i] = arg;
2414         }
2415     }
2416     //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2417 
2418     /* Test compliance with DIP1021
2419      */
2420     if (global.params.useDIP1021 &&
2421         tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2422         err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2423 
2424     // If D linkage and variadic, add _arguments[] as first argument
2425     if (tf.isDstyleVariadic())
2426     {
2427         assert(arguments.dim >= nparams);
2428 
2429         auto args = new Parameters(arguments.dim - nparams);
2430         for (size_t i = 0; i < arguments.dim - nparams; i++)
2431         {
2432             auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2433             (*args)[i] = arg;
2434         }
2435         auto tup = new TypeTuple(args);
2436         Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2437         arguments.insert(0, e);
2438     }
2439 
2440     /* Determine function return type: tret
2441      */
2442     Type tret = tf.next;
2443     if (isCtorCall)
2444     {
2445         //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2446         //    wildmatch, tf.isWild(), fd.isReturnIsolated());
2447         if (!tthis)
2448         {
2449             assert(sc.intypeof || global.errors);
2450             tthis = fd.isThis().type.addMod(fd.type.mod);
2451         }
2452         if (tf.isWild() && !fd.isReturnIsolated())
2453         {
2454             if (wildmatch)
2455                 tret = tret.substWildTo(wildmatch);
2456             int offset;
2457             if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2458             {
2459                 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2460                 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2461                 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2462                 err = true;
2463             }
2464         }
2465         tret = tthis;
2466     }
2467     else if (wildmatch && tret)
2468     {
2469         /* Adjust function return type based on wildmatch
2470          */
2471         //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2472         tret = tret.substWildTo(wildmatch);
2473     }
2474 
2475     *prettype = tret;
2476     *peprefix = eprefix;
2477     return (err || olderrors != global.errors);
2478 }
2479 
2480 /**
2481  * Determines whether a symbol represents a module or package
2482  * (Used as a helper for is(type == module) and is(type == package))
2483  *
2484  * Params:
2485  *  sym = the symbol to be checked
2486  *
2487  * Returns:
2488  *  the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2489  */
2490 Package resolveIsPackage(Dsymbol sym)
2491 {
2492     Package pkg;
2493     if (Import imp = sym.isImport())
2494     {
2495         if (imp.pkg is null)
2496         {
2497             .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2498                     imp.toChars());
2499             assert(0);
2500         }
2501         pkg = imp.pkg;
2502     }
2503     else if (auto mod = sym.isModule())
2504         pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2505     else
2506         pkg = sym.isPackage();
2507     if (pkg)
2508         pkg.resolvePKGunknown();
2509     return pkg;
2510 }
2511 
2512 private Module loadStdMath()
2513 {
2514     __gshared Import impStdMath = null;
2515     __gshared Identifier[1] stdID;
2516     if (!impStdMath)
2517     {
2518         stdID[0] = Id.std;
2519         auto s = new Import(Loc.initial, stdID[], Id.math, null, false);
2520         // Module.load will call fatal() if there's no std.math available.
2521         // Gag the error here, pushing the error handling to the caller.
2522         uint errors = global.startGagging();
2523         s.load(null);
2524         if (s.mod)
2525         {
2526             s.mod.importAll(null);
2527             s.mod.dsymbolSemantic(null);
2528         }
2529         global.endGagging(errors);
2530         impStdMath = s;
2531     }
2532     return impStdMath.mod;
2533 }
2534 
2535 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2536 {
2537     alias visit = Visitor.visit;
2538 
2539     Scope* sc;
2540     Expression result;
2541 
2542     this(Scope* sc)
2543     {
2544         this.sc = sc;
2545     }
2546 
2547     private void setError()
2548     {
2549         result = ErrorExp.get();
2550     }
2551 
2552     /**************************
2553      * Semantically analyze Expression.
2554      * Determine types, fold constants, etc.
2555      */
2556     override void visit(Expression e)
2557     {
2558         static if (LOGSEMANTIC)
2559         {
2560             printf("Expression::semantic() %s\n", e.toChars());
2561         }
2562         if (e.type)
2563             e.type = e.type.typeSemantic(e.loc, sc);
2564         else
2565             e.type = Type.tvoid;
2566         result = e;
2567     }
2568 
2569     override void visit(IntegerExp e)
2570     {
2571         assert(e.type);
2572         if (e.type.ty == Terror)
2573             return setError();
2574 
2575         assert(e.type.deco);
2576         e.setInteger(e.getInteger());
2577         result = e;
2578     }
2579 
2580     override void visit(RealExp e)
2581     {
2582         if (!e.type)
2583             e.type = Type.tfloat64;
2584         else
2585             e.type = e.type.typeSemantic(e.loc, sc);
2586         result = e;
2587     }
2588 
2589     override void visit(ComplexExp e)
2590     {
2591         if (!e.type)
2592             e.type = Type.tcomplex80;
2593         else
2594             e.type = e.type.typeSemantic(e.loc, sc);
2595         result = e;
2596     }
2597 
2598     override void visit(IdentifierExp exp)
2599     {
2600         static if (LOGSEMANTIC)
2601         {
2602             printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2603         }
2604         if (exp.type) // This is used as the dummy expression
2605         {
2606             result = exp;
2607             return;
2608         }
2609 
2610         Dsymbol scopesym;
2611         Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2612         if (s)
2613         {
2614             if (s.errors)
2615                 return setError();
2616 
2617             Expression e;
2618 
2619             /* See if the symbol was a member of an enclosing 'with'
2620              */
2621             WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2622             if (withsym && withsym.withstate.wthis && symbolIsVisible(sc, s))
2623             {
2624                 /* Disallow shadowing
2625                  */
2626                 // First find the scope of the with
2627                 Scope* scwith = sc;
2628                 while (scwith.scopesym != scopesym)
2629                 {
2630                     scwith = scwith.enclosing;
2631                     assert(scwith);
2632                 }
2633                 // Look at enclosing scopes for symbols with the same name,
2634                 // in the same function
2635                 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2636                 {
2637                     Dsymbol s2;
2638                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2639                     {
2640                         exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2641                         return setError();
2642                     }
2643                 }
2644                 s = s.toAlias();
2645 
2646                 // Same as wthis.ident
2647                 //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2648                 //  The redudancy should be removed.
2649                 e = new VarExp(exp.loc, withsym.withstate.wthis);
2650                 e = new DotIdExp(exp.loc, e, exp.ident);
2651                 e = e.expressionSemantic(sc);
2652             }
2653             else
2654             {
2655                 if (withsym)
2656                 {
2657                     if (withsym.withstate.exp.type.ty != Tvoid)
2658                     {
2659                         // 'with (exp)' is a type expression
2660                         // or 's' is not visible there (for error message)
2661                         e = new TypeExp(exp.loc, withsym.withstate.exp.type);
2662                     }
2663                     else
2664                     {
2665                         // 'with (exp)' is a Package/Module
2666                         e = withsym.withstate.exp;
2667                     }
2668                     e = new DotIdExp(exp.loc, e, exp.ident);
2669                     result = e.expressionSemantic(sc);
2670                     return;
2671                 }
2672 
2673                 /* If f is really a function template,
2674                  * then replace f with the function template declaration.
2675                  */
2676                 FuncDeclaration f = s.isFuncDeclaration();
2677                 if (f)
2678                 {
2679                     TemplateDeclaration td = getFuncTemplateDecl(f);
2680                     if (td)
2681                     {
2682                         if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2683                             td = td.overroot; // then get the start
2684                         e = new TemplateExp(exp.loc, td, f);
2685                         e = e.expressionSemantic(sc);
2686                         result = e;
2687                         return;
2688                     }
2689                 }
2690 
2691                 if (global.params.fixAliasThis)
2692                 {
2693                     ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2694                     if (expDsym)
2695                     {
2696                         //printf("expDsym = %s\n", expDsym.exp.toChars());
2697                         result = expDsym.exp.expressionSemantic(sc);
2698                         return;
2699                     }
2700                 }
2701                 // Haven't done overload resolution yet, so pass 1
2702                 e = symbolToExp(s, exp.loc, sc, true);
2703             }
2704             result = e;
2705             return;
2706         }
2707 
2708         if (!global.params.fixAliasThis && hasThis(sc))
2709         {
2710             for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2711             {
2712                 if (ad.aliasthis)
2713                 {
2714                     Expression e;
2715                     e = new ThisExp(exp.loc);
2716                     e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2717                     e = new DotIdExp(exp.loc, e, exp.ident);
2718                     e = e.trySemantic(sc);
2719                     if (e)
2720                     {
2721                         result = e;
2722                         return;
2723                     }
2724                 }
2725 
2726                 auto cd = ad.isClassDeclaration();
2727                 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2728                 {
2729                     ad = cd.baseClass;
2730                     continue;
2731                 }
2732                 break;
2733             }
2734         }
2735 
2736         if (exp.ident == Id.ctfe)
2737         {
2738             if (sc.flags & SCOPE.ctfe)
2739             {
2740                 exp.error("variable `__ctfe` cannot be read at compile time");
2741                 return setError();
2742             }
2743 
2744             // Create the magic __ctfe bool variable
2745             auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2746             vd.storage_class |= STC.temp;
2747             vd.semanticRun = PASS.semanticdone;
2748             Expression e = new VarExp(exp.loc, vd);
2749             e = e.expressionSemantic(sc);
2750             result = e;
2751             return;
2752         }
2753 
2754         // If we've reached this point and are inside a with() scope then we may
2755         // try one last attempt by checking whether the 'wthis' object supports
2756         // dynamic dispatching via opDispatch.
2757         // This is done by rewriting this expression as wthis.ident.
2758         // The innermost with() scope of the hierarchy to satisfy the condition
2759         // above wins.
2760         // https://issues.dlang.org/show_bug.cgi?id=6400
2761         for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2762         {
2763             if (!sc2.scopesym)
2764                 continue;
2765 
2766             if (auto ss = sc2.scopesym.isWithScopeSymbol())
2767             {
2768                 if (ss.withstate.wthis)
2769                 {
2770                     Expression e;
2771                     e = new VarExp(exp.loc, ss.withstate.wthis);
2772                     e = new DotIdExp(exp.loc, e, exp.ident);
2773                     e = e.trySemantic(sc);
2774                     if (e)
2775                     {
2776                         result = e;
2777                         return;
2778                     }
2779                 }
2780                 // Try Type.opDispatch (so the static version)
2781                 else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type)
2782                 {
2783                     if (Type t = ss.withstate.exp.isTypeExp().type)
2784                     {
2785                         Expression e;
2786                         e = new TypeExp(exp.loc, t);
2787                         e = new DotIdExp(exp.loc, e, exp.ident);
2788                         e = e.trySemantic(sc);
2789                         if (e)
2790                         {
2791                             result = e;
2792                             return;
2793                         }
2794                     }
2795                 }
2796             }
2797         }
2798 
2799         /* Look for what user might have meant
2800          */
2801         if (const n = importHint(exp.ident.toString()))
2802             exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2803         else if (auto s2 = sc.search_correct(exp.ident))
2804             exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2805         else if (const p = Scope.search_correct_C(exp.ident))
2806             exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2807         else
2808             exp.error("undefined identifier `%s`", exp.ident.toChars());
2809 
2810         result = ErrorExp.get();
2811     }
2812 
2813     override void visit(DsymbolExp e)
2814     {
2815         result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2816     }
2817 
2818     override void visit(ThisExp e)
2819     {
2820         static if (LOGSEMANTIC)
2821         {
2822             printf("ThisExp::semantic()\n");
2823         }
2824         if (e.type)
2825         {
2826             result = e;
2827             return;
2828         }
2829 
2830         FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2831         AggregateDeclaration ad;
2832 
2833         /* Special case for typeof(this) and typeof(super) since both
2834          * should work even if they are not inside a non-static member function
2835          */
2836         if (!fd && sc.intypeof == 1)
2837         {
2838             // Find enclosing struct or class
2839             for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2840             {
2841                 if (!s)
2842                 {
2843                     e.error("`%s` is not in a class or struct scope", e.toChars());
2844                     goto Lerr;
2845                 }
2846                 ClassDeclaration cd = s.isClassDeclaration();
2847                 if (cd)
2848                 {
2849                     e.type = cd.type;
2850                     result = e;
2851                     return;
2852                 }
2853                 StructDeclaration sd = s.isStructDeclaration();
2854                 if (sd)
2855                 {
2856                     e.type = sd.type;
2857                     result = e;
2858                     return;
2859                 }
2860             }
2861         }
2862         if (!fd)
2863             goto Lerr;
2864 
2865         assert(fd.vthis);
2866         e.var = fd.vthis;
2867         assert(e.var.parent);
2868         ad = fd.isMemberLocal();
2869         if (!ad)
2870             ad = fd.isMember2();
2871         assert(ad);
2872         e.type = ad.type.addMod(e.var.type.mod);
2873 
2874         if (e.var.checkNestedReference(sc, e.loc))
2875             return setError();
2876 
2877         result = e;
2878         return;
2879 
2880     Lerr:
2881         e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2882         result = ErrorExp.get();
2883     }
2884 
2885     override void visit(SuperExp e)
2886     {
2887         static if (LOGSEMANTIC)
2888         {
2889             printf("SuperExp::semantic('%s')\n", e.toChars());
2890         }
2891         if (e.type)
2892         {
2893             result = e;
2894             return;
2895         }
2896 
2897         FuncDeclaration fd = hasThis(sc);
2898         ClassDeclaration cd;
2899         Dsymbol s;
2900 
2901         /* Special case for typeof(this) and typeof(super) since both
2902          * should work even if they are not inside a non-static member function
2903          */
2904         if (!fd && sc.intypeof == 1)
2905         {
2906             // Find enclosing class
2907             for (s = sc.getStructClassScope(); 1; s = s.parent)
2908             {
2909                 if (!s)
2910                 {
2911                     e.error("`%s` is not in a class scope", e.toChars());
2912                     goto Lerr;
2913                 }
2914                 cd = s.isClassDeclaration();
2915                 if (cd)
2916                 {
2917                     cd = cd.baseClass;
2918                     if (!cd)
2919                     {
2920                         e.error("class `%s` has no `super`", s.toChars());
2921                         goto Lerr;
2922                     }
2923                     e.type = cd.type;
2924                     result = e;
2925                     return;
2926                 }
2927             }
2928         }
2929         if (!fd)
2930             goto Lerr;
2931 
2932         e.var = fd.vthis;
2933         assert(e.var && e.var.parent);
2934 
2935         s = fd.toParentDecl();
2936         if (s.isTemplateDeclaration()) // allow inside template constraint
2937             s = s.toParent();
2938         assert(s);
2939         cd = s.isClassDeclaration();
2940         //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2941         if (!cd)
2942             goto Lerr;
2943         if (!cd.baseClass)
2944         {
2945             e.error("no base class for `%s`", cd.toChars());
2946             e.type = cd.type.addMod(e.var.type.mod);
2947         }
2948         else
2949         {
2950             e.type = cd.baseClass.type;
2951             e.type = e.type.castMod(e.var.type.mod);
2952         }
2953 
2954         if (e.var.checkNestedReference(sc, e.loc))
2955             return setError();
2956 
2957         result = e;
2958         return;
2959 
2960     Lerr:
2961         e.error("`super` is only allowed in non-static class member functions");
2962         result = ErrorExp.get();
2963     }
2964 
2965     override void visit(NullExp e)
2966     {
2967         static if (LOGSEMANTIC)
2968         {
2969             printf("NullExp::semantic('%s')\n", e.toChars());
2970         }
2971         // NULL is the same as (void *)0
2972         if (e.type)
2973         {
2974             result = e;
2975             return;
2976         }
2977         e.type = Type.tnull;
2978         result = e;
2979     }
2980 
2981     override void visit(StringExp e)
2982     {
2983         static if (LOGSEMANTIC)
2984         {
2985             printf("StringExp::semantic() %s\n", e.toChars());
2986         }
2987         if (e.type)
2988         {
2989             result = e;
2990             return;
2991         }
2992 
2993         OutBuffer buffer;
2994         size_t newlen = 0;
2995         size_t u;
2996         dchar c;
2997 
2998         switch (e.postfix)
2999         {
3000         case 'd':
3001             for (u = 0; u < e.len;)
3002             {
3003                 if (const p = utf_decodeChar(e.peekString(), u, c))
3004                 {
3005                     e.error("%.*s", cast(int)p.length, p.ptr);
3006                     return setError();
3007                 }
3008                 else
3009                 {
3010                     buffer.write4(c);
3011                     newlen++;
3012                 }
3013             }
3014             buffer.write4(0);
3015             e.setData(buffer.extractData(), newlen, 4);
3016             e.type = new TypeDArray(Type.tdchar.immutableOf());
3017             e.committed = 1;
3018             break;
3019 
3020         case 'w':
3021             for (u = 0; u < e.len;)
3022             {
3023                 if (const p = utf_decodeChar(e.peekString(), u, c))
3024                 {
3025                     e.error("%.*s", cast(int)p.length, p.ptr);
3026                     return setError();
3027                 }
3028                 else
3029                 {
3030                     buffer.writeUTF16(c);
3031                     newlen++;
3032                     if (c >= 0x10000)
3033                         newlen++;
3034                 }
3035             }
3036             buffer.writeUTF16(0);
3037             e.setData(buffer.extractData(), newlen, 2);
3038             e.type = new TypeDArray(Type.twchar.immutableOf());
3039             e.committed = 1;
3040             break;
3041 
3042         case 'c':
3043             e.committed = 1;
3044             goto default;
3045 
3046         default:
3047             e.type = new TypeDArray(Type.tchar.immutableOf());
3048             break;
3049         }
3050         e.type = e.type.typeSemantic(e.loc, sc);
3051         //type = type.immutableOf();
3052         //printf("type = %s\n", type.toChars());
3053 
3054         result = e;
3055     }
3056 
3057     override void visit(TupleExp exp)
3058     {
3059         static if (LOGSEMANTIC)
3060         {
3061             printf("+TupleExp::semantic(%s)\n", exp.toChars());
3062         }
3063         if (exp.type)
3064         {
3065             result = exp;
3066             return;
3067         }
3068 
3069         if (exp.e0)
3070             exp.e0 = exp.e0.expressionSemantic(sc);
3071 
3072         // Run semantic() on each argument
3073         bool err = false;
3074         for (size_t i = 0; i < exp.exps.dim; i++)
3075         {
3076             Expression e = (*exp.exps)[i];
3077             e = e.expressionSemantic(sc);
3078             if (!e.type)
3079             {
3080                 exp.error("`%s` has no value", e.toChars());
3081                 err = true;
3082             }
3083             else if (e.op == TOK.error)
3084                 err = true;
3085             else
3086                 (*exp.exps)[i] = e;
3087         }
3088         if (err)
3089             return setError();
3090 
3091         expandTuples(exp.exps);
3092 
3093         exp.type = new TypeTuple(exp.exps);
3094         exp.type = exp.type.typeSemantic(exp.loc, sc);
3095         //printf("-TupleExp::semantic(%s)\n", toChars());
3096         result = exp;
3097     }
3098 
3099     override void visit(ArrayLiteralExp e)
3100     {
3101         static if (LOGSEMANTIC)
3102         {
3103             printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3104         }
3105         if (e.type)
3106         {
3107             result = e;
3108             return;
3109         }
3110 
3111         /* Perhaps an empty array literal [ ] should be rewritten as null?
3112          */
3113 
3114         if (e.basis)
3115             e.basis = e.basis.expressionSemantic(sc);
3116         if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error))
3117             return setError();
3118 
3119         expandTuples(e.elements);
3120 
3121         if (e.basis)
3122             e.elements.push(e.basis);
3123         Type t0 = arrayExpressionToCommonType(sc, *e.elements);
3124         if (e.basis)
3125             e.basis = e.elements.pop();
3126         if (t0 is null)
3127             return setError();
3128 
3129         e.type = t0.arrayOf();
3130         e.type = e.type.typeSemantic(e.loc, sc);
3131 
3132         /* Disallow array literals of type void being used.
3133          */
3134         if (e.elements.dim > 0 && t0.ty == Tvoid)
3135         {
3136             e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3137             return setError();
3138         }
3139 
3140         if (global.params.useTypeInfo && Type.dtypeinfo)
3141             semanticTypeInfo(sc, e.type);
3142 
3143         result = e;
3144     }
3145 
3146     override void visit(AssocArrayLiteralExp e)
3147     {
3148         static if (LOGSEMANTIC)
3149         {
3150             printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3151         }
3152         if (e.type)
3153         {
3154             result = e;
3155             return;
3156         }
3157 
3158         // Run semantic() on each element
3159         bool err_keys = arrayExpressionSemantic(e.keys, sc);
3160         bool err_vals = arrayExpressionSemantic(e.values, sc);
3161         if (err_keys || err_vals)
3162             return setError();
3163 
3164         expandTuples(e.keys);
3165         expandTuples(e.values);
3166         if (e.keys.dim != e.values.dim)
3167         {
3168             e.error("number of keys is %llu, must match number of values %llu",
3169                         cast(ulong) e.keys.dim, cast(ulong) e.values.dim);
3170             return setError();
3171         }
3172 
3173         Type tkey = arrayExpressionToCommonType(sc, *e.keys);
3174         Type tvalue = arrayExpressionToCommonType(sc, *e.values);
3175         if (tkey is null || tvalue is null)
3176             return setError();
3177 
3178         e.type = new TypeAArray(tvalue, tkey);
3179         e.type = e.type.typeSemantic(e.loc, sc);
3180 
3181         semanticTypeInfo(sc, e.type);
3182 
3183         if (global.params.vsafe)
3184         {
3185             if (checkAssocArrayLiteralEscape(sc, e, false))
3186                 return setError();
3187         }
3188 
3189         result = e;
3190     }
3191 
3192     override void visit(StructLiteralExp e)
3193     {
3194         static if (LOGSEMANTIC)
3195         {
3196             printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3197         }
3198         if (e.type)
3199         {
3200             result = e;
3201             return;
3202         }
3203 
3204         e.sd.size(e.loc);
3205         if (e.sd.sizeok != Sizeok.done)
3206             return setError();
3207 
3208         // run semantic() on each element
3209         if (arrayExpressionSemantic(e.elements, sc))
3210             return setError();
3211 
3212         expandTuples(e.elements);
3213 
3214         /* Fit elements[] to the corresponding type of field[].
3215          */
3216         if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3217             return setError();
3218 
3219         /* Fill out remainder of elements[] with default initializers for fields[]
3220          */
3221         if (!e.sd.fill(e.loc, e.elements, false))
3222         {
3223             /* An error in the initializer needs to be recorded as an error
3224              * in the enclosing function or template, since the initializer
3225              * will be part of the stuct declaration.
3226              */
3227             global.increaseErrorCount();
3228             return setError();
3229         }
3230 
3231         if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
3232             return setError();
3233 
3234         e.type = e.stype ? e.stype : e.sd.type;
3235         result = e;
3236     }
3237 
3238     override void visit(TypeExp exp)
3239     {
3240         if (exp.type.ty == Terror)
3241             return setError();
3242 
3243         //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3244         Expression e;
3245         Type t;
3246         Dsymbol s;
3247 
3248         dmd.typesem.resolve(exp.type, exp.loc, sc, e, t, s, true);
3249         if (e)
3250         {
3251             // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3252             // then rewrite as `(this.var)` in case it would be followed by a DotVar
3253             // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3254             VarExp ve = e.isVarExp();
3255             if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3256                 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
3257             {
3258                 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3259                 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3260             }
3261             //printf("e = %s %s\n", Token::toChars(e.op), e.toChars());
3262             e = e.expressionSemantic(sc);
3263         }
3264         else if (t)
3265         {
3266             //printf("t = %d %s\n", t.ty, t.toChars());
3267             exp.type = t.typeSemantic(exp.loc, sc);
3268             e = exp;
3269         }
3270         else if (s)
3271         {
3272             //printf("s = %s %s\n", s.kind(), s.toChars());
3273             e = symbolToExp(s, exp.loc, sc, true);
3274         }
3275         else
3276             assert(0);
3277 
3278         if (global.params.vcomplex)
3279             exp.type.checkComplexTransition(exp.loc, sc);
3280 
3281         result = e;
3282     }
3283 
3284     override void visit(ScopeExp exp)
3285     {
3286         static if (LOGSEMANTIC)
3287         {
3288             printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3289         }
3290         if (exp.type)
3291         {
3292             result = exp;
3293             return;
3294         }
3295 
3296         ScopeDsymbol sds2 = exp.sds;
3297         TemplateInstance ti = sds2.isTemplateInstance();
3298         while (ti)
3299         {
3300             WithScopeSymbol withsym;
3301             if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3302                 return setError();
3303             if (withsym && withsym.withstate.wthis)
3304             {
3305                 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3306                 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3307                 result = e.expressionSemantic(sc);
3308                 return;
3309             }
3310             if (ti.needsTypeInference(sc))
3311             {
3312                 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3313                 {
3314                     Dsymbol p = td.toParentLocal();
3315                     FuncDeclaration fdthis = hasThis(sc);
3316                     AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3317                     if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3318                     {
3319                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3320                         result = e.expressionSemantic(sc);
3321                         return;
3322                     }
3323                 }
3324                 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3325                 {
3326                     FuncDeclaration fdthis = hasThis(sc);
3327                     AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3328                     if (fdthis && ad && fdthis.isMemberLocal() == ad)
3329                     {
3330                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3331                         result = e.expressionSemantic(sc);
3332                         return;
3333                     }
3334                 }
3335                 // ti is an instance which requires IFTI.
3336                 exp.sds = ti;
3337                 exp.type = Type.tvoid;
3338                 result = exp;
3339                 return;
3340             }
3341             ti.dsymbolSemantic(sc);
3342             if (!ti.inst || ti.errors)
3343                 return setError();
3344 
3345             Dsymbol s = ti.toAlias();
3346             if (s == ti)
3347             {
3348                 exp.sds = ti;
3349                 exp.type = Type.tvoid;
3350                 result = exp;
3351                 return;
3352             }
3353             sds2 = s.isScopeDsymbol();
3354             if (sds2)
3355             {
3356                 ti = sds2.isTemplateInstance();
3357                 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3358                 continue;
3359             }
3360 
3361             if (auto v = s.isVarDeclaration())
3362             {
3363                 if (!v.type)
3364                 {
3365                     exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3366                     return setError();
3367                 }
3368                 if ((v.storage_class & STC.manifest) && v._init)
3369                 {
3370                     /* When an instance that will be converted to a constant exists,
3371                      * the instance representation "foo!tiargs" is treated like a
3372                      * variable name, and its recursive appearance check (note that
3373                      * it's equivalent with a recursive instantiation of foo) is done
3374                      * separately from the circular initialization check for the
3375                      * eponymous enum variable declaration.
3376                      *
3377                      *  template foo(T) {
3378                      *    enum bool foo = foo;    // recursive definition check (v.inuse)
3379                      *  }
3380                      *  template bar(T) {
3381                      *    enum bool bar = bar!T;  // recursive instantiation check (ti.inuse)
3382                      *  }
3383                      */
3384                     if (ti.inuse)
3385                     {
3386                         exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3387                         return setError();
3388                     }
3389                     v.checkDeprecated(exp.loc, sc);
3390                     auto e = v.expandInitializer(exp.loc);
3391                     ti.inuse++;
3392                     e = e.expressionSemantic(sc);
3393                     ti.inuse--;
3394                     result = e;
3395                     return;
3396                 }
3397             }
3398 
3399             //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3400             auto e = symbolToExp(s, exp.loc, sc, true);
3401             //printf("-1ScopeExp::semantic()\n");
3402             result = e;
3403             return;
3404         }
3405 
3406         //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3407         //printf("\tparent = '%s'\n", sds2.parent.toChars());
3408         sds2.dsymbolSemantic(sc);
3409 
3410         // (Aggregate|Enum)Declaration
3411         if (auto t = sds2.getType())
3412         {
3413             result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3414             return;
3415         }
3416 
3417         if (auto td = sds2.isTemplateDeclaration())
3418         {
3419             result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3420             return;
3421         }
3422 
3423         exp.sds = sds2;
3424         exp.type = Type.tvoid;
3425         //printf("-2ScopeExp::semantic() %s\n", toChars());
3426         result = exp;
3427     }
3428 
3429     override void visit(NewExp exp)
3430     {
3431         static if (LOGSEMANTIC)
3432         {
3433             printf("NewExp::semantic() %s\n", exp.toChars());
3434             if (exp.thisexp)
3435                 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3436             printf("\tnewtype: %s\n", exp.newtype.toChars());
3437         }
3438         if (exp.type) // if semantic() already run
3439         {
3440             result = exp;
3441             return;
3442         }
3443 
3444         //for error messages if the argument in [] is not convertible to size_t
3445         const originalNewtype = exp.newtype;
3446 
3447         // https://issues.dlang.org/show_bug.cgi?id=11581
3448         // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3449         // T should be analyzed first and edim should go into arguments iff it's
3450         // not a tuple.
3451         Expression edim = null;
3452         if (!exp.arguments && exp.newtype.ty == Tsarray)
3453         {
3454             edim = (cast(TypeSArray)exp.newtype).dim;
3455             exp.newtype = (cast(TypeNext)exp.newtype).next;
3456         }
3457 
3458         ClassDeclaration cdthis = null;
3459         if (exp.thisexp)
3460         {
3461             exp.thisexp = exp.thisexp.expressionSemantic(sc);
3462             if (exp.thisexp.op == TOK.error)
3463                 return setError();
3464 
3465             cdthis = exp.thisexp.type.isClassHandle();
3466             if (!cdthis)
3467             {
3468                 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3469                 return setError();
3470             }
3471 
3472             sc = sc.push(cdthis);
3473             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3474             sc = sc.pop();
3475         }
3476         else
3477         {
3478             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3479         }
3480         if (exp.type.ty == Terror)
3481             return setError();
3482 
3483         if (edim)
3484         {
3485             if (exp.type.toBasetype().ty == Ttuple)
3486             {
3487                 // --> new T[edim]
3488                 exp.type = new TypeSArray(exp.type, edim);
3489                 exp.type = exp.type.typeSemantic(exp.loc, sc);
3490                 if (exp.type.ty == Terror)
3491                     return setError();
3492             }
3493             else
3494             {
3495                 // --> new T[](edim)
3496                 exp.arguments = new Expressions();
3497                 exp.arguments.push(edim);
3498                 exp.type = exp.type.arrayOf();
3499             }
3500         }
3501 
3502         exp.newtype = exp.type; // in case type gets cast to something else
3503         Type tb = exp.type.toBasetype();
3504         //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3505         if (arrayExpressionSemantic(exp.newargs, sc) ||
3506             preFunctionParameters(sc, exp.newargs))
3507         {
3508             return setError();
3509         }
3510         if (arrayExpressionSemantic(exp.arguments, sc))
3511         {
3512             return setError();
3513         }
3514         //https://issues.dlang.org/show_bug.cgi?id=20547
3515         //exp.arguments are the "parameters" to [], not to a real function
3516         //so the errors that come from preFunctionParameters are misleading
3517         if (originalNewtype.ty == Tsarray)
3518         {
3519             if (preFunctionParameters(sc, exp.arguments, false))
3520             {
3521                 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
3522                 return setError();
3523             }
3524         }
3525         else if (preFunctionParameters(sc, exp.arguments))
3526         {
3527             return setError();
3528         }
3529 
3530         if (exp.thisexp && tb.ty != Tclass)
3531         {
3532             exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3533             return setError();
3534         }
3535 
3536         const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
3537         Expression newprefix = null;
3538 
3539         if (tb.ty == Tclass)
3540         {
3541             auto cd = (cast(TypeClass)tb).sym;
3542             cd.size(exp.loc);
3543             if (cd.sizeok != Sizeok.done)
3544                 return setError();
3545             if (!cd.ctor)
3546                 cd.ctor = cd.searchCtor();
3547             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3548             {
3549                 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3550                 return setError();
3551             }
3552 
3553             if (cd.isInterfaceDeclaration())
3554             {
3555                 exp.error("cannot create instance of interface `%s`", cd.toChars());
3556                 return setError();
3557             }
3558 
3559             if (cd.isAbstract())
3560             {
3561                 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3562                 for (size_t i = 0; i < cd.vtbl.dim; i++)
3563                 {
3564                     FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3565                     if (fd && fd.isAbstract())
3566                     {
3567                         errorSupplemental(exp.loc, "function `%s` is not implemented",
3568                             fd.toFullSignature());
3569                     }
3570                 }
3571                 return setError();
3572             }
3573             // checkDeprecated() is already done in newtype.typeSemantic().
3574 
3575             if (cd.isNested())
3576             {
3577                 /* We need a 'this' pointer for the nested class.
3578                  * Ensure we have the right one.
3579                  */
3580                 Dsymbol s = cd.toParentLocal();
3581 
3582                 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3583                 if (auto cdn = s.isClassDeclaration())
3584                 {
3585                     if (!cdthis)
3586                     {
3587                         // Supply an implicit 'this' and try again
3588                         exp.thisexp = new ThisExp(exp.loc);
3589                         for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3590                         {
3591                             if (!sp)
3592                             {
3593                                 exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
3594                                     cdn.toChars(), cd.toChars());
3595                                 return setError();
3596                             }
3597                             ClassDeclaration cdp = sp.isClassDeclaration();
3598                             if (!cdp)
3599                                 continue;
3600                             if (cdp == cdn || cdn.isBaseOf(cdp, null))
3601                                 break;
3602                             // Add a '.outer' and try again
3603                             exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3604                         }
3605 
3606                         exp.thisexp = exp.thisexp.expressionSemantic(sc);
3607                         if (exp.thisexp.op == TOK.error)
3608                             return setError();
3609                         cdthis = exp.thisexp.type.isClassHandle();
3610                     }
3611                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3612                     {
3613                         //printf("cdthis = %s\n", cdthis.toChars());
3614                         exp.error("`this` for nested class must be of type `%s`, not `%s`",
3615                             cdn.toChars(), exp.thisexp.type.toChars());
3616                         return setError();
3617                     }
3618                     if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3619                     {
3620                         exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3621                             exp.newtype.toChars(), exp.thisexp.type.toChars());
3622                         return setError();
3623                     }
3624                 }
3625                 else if (exp.thisexp)
3626                 {
3627                     exp.error("`.new` is only for allocating nested classes");
3628                     return setError();
3629                 }
3630                 else if (auto fdn = s.isFuncDeclaration())
3631                 {
3632                     // make sure the parent context fdn of cd is reachable from sc
3633                     if (!ensureStaticLinkTo(sc.parent, fdn))
3634                     {
3635                         exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3636                             fdn.toPrettyChars(), cd.toPrettyChars());
3637                         return setError();
3638                     }
3639                 }
3640                 else
3641                     assert(0);
3642             }
3643             else if (exp.thisexp)
3644             {
3645                 exp.error("`.new` is only for allocating nested classes");
3646                 return setError();
3647             }
3648 
3649             if (cd.vthis2)
3650             {
3651                 if (AggregateDeclaration ad2 = cd.isMember2())
3652                 {
3653                     Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3654                     if (te.op != TOK.error)
3655                         te = getRightThis(exp.loc, sc, ad2, te, cd);
3656                     if (te.op == TOK.error)
3657                     {
3658                         exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3659                         return setError();
3660                     }
3661                 }
3662             }
3663 
3664             if (cd.aggNew)
3665             {
3666                 // Prepend the size argument to newargs[]
3667                 Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t);
3668                 if (!exp.newargs)
3669                     exp.newargs = new Expressions();
3670                 exp.newargs.shift(e);
3671 
3672                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3673                 if (!f || f.errors)
3674                     return setError();
3675 
3676                 checkFunctionAttributes(exp, sc, f);
3677                 checkAccess(cd, exp.loc, sc, f);
3678 
3679                 TypeFunction tf = cast(TypeFunction)f.type;
3680                 Type rettype;
3681                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3682                     return setError();
3683 
3684                 exp.allocator = f.isNewDeclaration();
3685                 assert(exp.allocator);
3686             }
3687             else
3688             {
3689                 if (exp.newargs && exp.newargs.dim)
3690                 {
3691                     exp.error("no allocator for `%s`", cd.toChars());
3692                     return setError();
3693                 }
3694             }
3695 
3696             if (cd.ctor)
3697             {
3698                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3699                 if (!f || f.errors)
3700                     return setError();
3701 
3702                 checkFunctionAttributes(exp, sc, f);
3703                 checkAccess(cd, exp.loc, sc, f);
3704 
3705                 TypeFunction tf = cast(TypeFunction)f.type;
3706                 if (!exp.arguments)
3707                     exp.arguments = new Expressions();
3708                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3709                     return setError();
3710 
3711                 exp.member = f.isCtorDeclaration();
3712                 assert(exp.member);
3713             }
3714             else
3715             {
3716                 if (nargs)
3717                 {
3718                     exp.error("no constructor for `%s`", cd.toChars());
3719                     return setError();
3720                 }
3721 
3722                 // https://issues.dlang.org/show_bug.cgi?id=19941
3723                 // Run semantic on all field initializers to resolve any forward
3724                 // references. This is the same as done for structs in sd.fill().
3725                 for (ClassDeclaration c = cd; c; c = c.baseClass)
3726                 {
3727                     foreach (v; c.fields)
3728                     {
3729                         if (v.inuse || v._scope is null || v._init is null ||
3730                             v._init.isVoidInitializer())
3731                             continue;
3732                         v.inuse++;
3733                         v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3734                         v.inuse--;
3735                     }
3736                 }
3737             }
3738         }
3739         else if (tb.ty == Tstruct)
3740         {
3741             auto sd = (cast(TypeStruct)tb).sym;
3742             sd.size(exp.loc);
3743             if (sd.sizeok != Sizeok.done)
3744                 return setError();
3745             if (!sd.ctor)
3746                 sd.ctor = sd.searchCtor();
3747             if (sd.noDefaultCtor && !nargs)
3748             {
3749                 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3750                 return setError();
3751             }
3752             // checkDeprecated() is already done in newtype.typeSemantic().
3753 
3754             if (sd.aggNew)
3755             {
3756                 // Prepend the uint size argument to newargs[]
3757                 Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t);
3758                 if (!exp.newargs)
3759                     exp.newargs = new Expressions();
3760                 exp.newargs.shift(e);
3761 
3762                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3763                 if (!f || f.errors)
3764                     return setError();
3765 
3766                 checkFunctionAttributes(exp, sc, f);
3767                 checkAccess(sd, exp.loc, sc, f);
3768 
3769                 TypeFunction tf = cast(TypeFunction)f.type;
3770                 Type rettype;
3771                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3772                     return setError();
3773 
3774                 exp.allocator = f.isNewDeclaration();
3775                 assert(exp.allocator);
3776             }
3777             else
3778             {
3779                 if (exp.newargs && exp.newargs.dim)
3780                 {
3781                     exp.error("no allocator for `%s`", sd.toChars());
3782                     return setError();
3783                 }
3784             }
3785 
3786             if (sd.ctor && nargs)
3787             {
3788                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3789                 if (!f || f.errors)
3790                     return setError();
3791 
3792                 checkFunctionAttributes(exp, sc, f);
3793                 checkAccess(sd, exp.loc, sc, f);
3794 
3795                 TypeFunction tf = cast(TypeFunction)f.type;
3796                 if (!exp.arguments)
3797                     exp.arguments = new Expressions();
3798                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3799                     return setError();
3800 
3801                 exp.member = f.isCtorDeclaration();
3802                 assert(exp.member);
3803 
3804                 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
3805                     return setError();
3806             }
3807             else
3808             {
3809                 if (!exp.arguments)
3810                     exp.arguments = new Expressions();
3811 
3812                 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3813                     return setError();
3814 
3815                 if (!sd.fill(exp.loc, exp.arguments, false))
3816                     return setError();
3817 
3818                 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
3819                     return setError();
3820 
3821                 /* Since a `new` allocation may escape, check each of the arguments for escaping
3822                  */
3823                 if (global.params.vsafe)
3824                 {
3825                     foreach (arg; *exp.arguments)
3826                     {
3827                         if (arg && checkNewEscape(sc, arg, false))
3828                             return setError();
3829                     }
3830                 }
3831             }
3832 
3833             exp.type = exp.type.pointerTo();
3834         }
3835         else if (tb.ty == Tarray)
3836         {
3837             if (!nargs)
3838             {
3839                 // https://issues.dlang.org/show_bug.cgi?id=20422
3840                 // Without this check the compiler would give a misleading error
3841                 exp.error("missing length argument for array");
3842                 return setError();
3843             }
3844 
3845             Type tn = tb.nextOf().baseElemOf();
3846             Dsymbol s = tn.toDsymbol(sc);
3847             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3848             if (ad && ad.noDefaultCtor)
3849             {
3850                 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3851                 return setError();
3852             }
3853             for (size_t i = 0; i < nargs; i++)
3854             {
3855                 if (tb.ty != Tarray)
3856                 {
3857                     exp.error("too many arguments for array");
3858                     return setError();
3859                 }
3860 
3861                 Expression arg = (*exp.arguments)[i];
3862                 arg = resolveProperties(sc, arg);
3863                 arg = arg.implicitCastTo(sc, Type.tsize_t);
3864                 if (arg.op == TOK.error)
3865                     return setError();
3866                 arg = arg.optimize(WANTvalue);
3867                 if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0)
3868                 {
3869                     exp.error("negative array index `%s`", arg.toChars());
3870                     return setError();
3871                 }
3872                 (*exp.arguments)[i] = arg;
3873                 tb = (cast(TypeDArray)tb).next.toBasetype();
3874             }
3875         }
3876         else if (tb.isscalar())
3877         {
3878             if (!nargs)
3879             {
3880             }
3881             else if (nargs == 1)
3882             {
3883                 Expression e = (*exp.arguments)[0];
3884                 e = e.implicitCastTo(sc, tb);
3885                 (*exp.arguments)[0] = e;
3886             }
3887             else
3888             {
3889                 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3890                 return setError();
3891             }
3892 
3893             exp.type = exp.type.pointerTo();
3894         }
3895         else
3896         {
3897             exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3898             return setError();
3899         }
3900 
3901         //printf("NewExp: '%s'\n", toChars());
3902         //printf("NewExp:type '%s'\n", type.toChars());
3903         semanticTypeInfo(sc, exp.type);
3904 
3905         if (newprefix)
3906         {
3907             result = Expression.combine(newprefix, exp);
3908             return;
3909         }
3910         result = exp;
3911     }
3912 
3913     override void visit(NewAnonClassExp e)
3914     {
3915         static if (LOGSEMANTIC)
3916         {
3917             printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3918             //printf("thisexp = %p\n", thisexp);
3919             //printf("type: %s\n", type.toChars());
3920         }
3921 
3922         Expression d = new DeclarationExp(e.loc, e.cd);
3923         sc = sc.push(); // just create new scope
3924         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3925         d = d.expressionSemantic(sc);
3926         sc = sc.pop();
3927 
3928         if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3929         {
3930             ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3931             if (!sds.members)
3932                 sds.members = new Dsymbols();
3933             sds.members.push(e.cd);
3934         }
3935 
3936         Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments);
3937 
3938         Expression c = new CommaExp(e.loc, d, n);
3939         result = c.expressionSemantic(sc);
3940     }
3941 
3942     override void visit(SymOffExp e)
3943     {
3944         static if (LOGSEMANTIC)
3945         {
3946             printf("SymOffExp::semantic('%s')\n", e.toChars());
3947         }
3948         //var.dsymbolSemantic(sc);
3949         if (!e.type)
3950             e.type = e.var.type.pointerTo();
3951 
3952         if (auto v = e.var.isVarDeclaration())
3953         {
3954             if (v.checkNestedReference(sc, e.loc))
3955                 return setError();
3956         }
3957         else if (auto f = e.var.isFuncDeclaration())
3958         {
3959             if (f.checkNestedReference(sc, e.loc))
3960                 return setError();
3961         }
3962 
3963         result = e;
3964     }
3965 
3966     override void visit(VarExp e)
3967     {
3968         static if (LOGSEMANTIC)
3969         {
3970             printf("VarExp::semantic(%s)\n", e.toChars());
3971         }
3972 
3973         auto vd = e.var.isVarDeclaration();
3974         auto fd = e.var.isFuncDeclaration();
3975 
3976         if (fd)
3977         {
3978             //printf("L%d fd = %s\n", __LINE__, f.toChars());
3979             if (!fd.functionSemantic())
3980                 return setError();
3981         }
3982 
3983         if (!e.type)
3984             e.type = e.var.type;
3985         if (e.type && !e.type.deco)
3986         {
3987             auto decl = e.var.isDeclaration();
3988             if (decl)
3989                 decl.inuse++;
3990             e.type = e.type.typeSemantic(e.loc, sc);
3991             if (decl)
3992                 decl.inuse--;
3993         }
3994 
3995         /* Fix for 1161 doesn't work because it causes visibility
3996          * problems when instantiating imported templates passing private
3997          * variables as alias template parameters.
3998          */
3999         //checkAccess(loc, sc, NULL, var);
4000 
4001         if (vd)
4002         {
4003             if (vd.checkNestedReference(sc, e.loc))
4004                 return setError();
4005 
4006             // https://issues.dlang.org/show_bug.cgi?id=12025
4007             // If the variable is not actually used in runtime code,
4008             // the purity violation error is redundant.
4009             //checkPurity(sc, vd);
4010         }
4011         else if (fd)
4012         {
4013             // TODO: If fd isn't yet resolved its overload, the checkNestedReference
4014             // call would cause incorrect validation.
4015             // Maybe here should be moved in CallExp, or AddrExp for functions.
4016             if (fd.checkNestedReference(sc, e.loc))
4017                 return setError();
4018         }
4019         else if (auto od = e.var.isOverDeclaration())
4020         {
4021             e.type = Type.tvoid; // ambiguous type?
4022         }
4023 
4024         result = e;
4025     }
4026 
4027     override void visit(FuncExp exp)
4028     {
4029         static if (LOGSEMANTIC)
4030         {
4031             printf("FuncExp::semantic(%s)\n", exp.toChars());
4032             if (exp.fd.treq)
4033                 printf("  treq = %s\n", exp.fd.treq.toChars());
4034         }
4035 
4036         if (exp.type)
4037         {
4038             result = exp;
4039             return;
4040         }
4041 
4042         Expression e = exp;
4043         uint olderrors;
4044 
4045         sc = sc.push(); // just create new scope
4046         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4047         sc.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4048 
4049         /* fd.treq might be incomplete type,
4050             * so should not semantic it.
4051             * void foo(T)(T delegate(int) dg){}
4052             * foo(a=>a); // in IFTI, treq == T delegate(int)
4053             */
4054         //if (fd.treq)
4055         //    fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4056 
4057         exp.genIdent(sc);
4058 
4059         // Set target of return type inference
4060         if (exp.fd.treq && !exp.fd.type.nextOf())
4061         {
4062             TypeFunction tfv = null;
4063             if (exp.fd.treq.ty == Tdelegate || (exp.fd.treq.ty == Tpointer && exp.fd.treq.nextOf().ty == Tfunction))
4064                 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4065             if (tfv)
4066             {
4067                 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4068                 tfl.next = tfv.nextOf();
4069             }
4070         }
4071 
4072         //printf("td = %p, treq = %p\n", td, fd.treq);
4073         if (exp.td)
4074         {
4075             assert(exp.td.parameters && exp.td.parameters.dim);
4076             exp.td.dsymbolSemantic(sc);
4077             exp.type = Type.tvoid; // temporary type
4078 
4079             if (exp.fd.treq) // defer type determination
4080             {
4081                 FuncExp fe;
4082                 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4083                     e = fe;
4084                 else
4085                     e = ErrorExp.get();
4086             }
4087             goto Ldone;
4088         }
4089 
4090         olderrors = global.errors;
4091         exp.fd.dsymbolSemantic(sc);
4092         if (olderrors == global.errors)
4093         {
4094             exp.fd.semantic2(sc);
4095             if (olderrors == global.errors)
4096                 exp.fd.semantic3(sc);
4097         }
4098         if (olderrors != global.errors)
4099         {
4100             if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4101                 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4102             e = ErrorExp.get();
4103             goto Ldone;
4104         }
4105 
4106         // Type is a "delegate to" or "pointer to" the function literal
4107         if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4108         {
4109             exp.type = new TypeDelegate(exp.fd.type);
4110             exp.type = exp.type.typeSemantic(exp.loc, sc);
4111 
4112             exp.fd.tok = TOK.delegate_;
4113         }
4114         else
4115         {
4116             exp.type = new TypePointer(exp.fd.type);
4117             exp.type = exp.type.typeSemantic(exp.loc, sc);
4118             //type = fd.type.pointerTo();
4119 
4120             /* A lambda expression deduced to function pointer might become
4121                 * to a delegate literal implicitly.
4122                 *
4123                 *   auto foo(void function() fp) { return 1; }
4124                 *   assert(foo({}) == 1);
4125                 *
4126                 * So, should keep fd.tok == TOKreserve if fd.treq == NULL.
4127                 */
4128             if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4129             {
4130                 // change to non-nested
4131                 exp.fd.tok = TOK.function_;
4132                 exp.fd.vthis = null;
4133             }
4134         }
4135         exp.fd.tookAddressOf++;
4136 
4137     Ldone:
4138         sc = sc.pop();
4139         result = e;
4140     }
4141 
4142     /**
4143      * Perform semantic analysis on function literals
4144      *
4145      * Test the following construct:
4146      * ---
4147      * (x, y, z) { return x + y + z; }(42, 84, 1992);
4148      * ---
4149      */
4150     Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4151     {
4152         if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
4153         {
4154             for (size_t k = 0; k < arguments.dim; k++)
4155             {
4156                 Expression checkarg = (*arguments)[k];
4157                 if (checkarg.op == TOK.error)
4158                     return checkarg;
4159             }
4160 
4161             exp.genIdent(sc);
4162 
4163             assert(exp.td.parameters && exp.td.parameters.dim);
4164             exp.td.dsymbolSemantic(sc);
4165 
4166             TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4167             size_t dim = tfl.parameterList.length;
4168             if (arguments.dim < dim)
4169             {
4170                 // Default arguments are always typed, so they don't need inference.
4171                 Parameter p = tfl.parameterList[arguments.dim];
4172                 if (p.defaultArg)
4173                     dim = arguments.dim;
4174             }
4175 
4176             if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
4177                 arguments.dim < dim)
4178             {
4179                 OutBuffer buf;
4180                 foreach (idx, ref arg; *arguments)
4181                     buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4182                 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4183                           exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4184                           buf.peekChars());
4185                 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
4186                                       arguments.dim < dim ? "few".ptr : "many".ptr,
4187                                       cast(int)dim, cast(int)arguments.dim);
4188                 return ErrorExp.get();
4189             }
4190 
4191             auto tiargs = new Objects();
4192             tiargs.reserve(exp.td.parameters.dim);
4193 
4194             for (size_t i = 0; i < exp.td.parameters.dim; i++)
4195             {
4196                 TemplateParameter tp = (*exp.td.parameters)[i];
4197                 assert(dim <= tfl.parameterList.length);
4198                 foreach (u, p; tfl.parameterList)
4199                 {
4200                     if (u == dim)
4201                         break;
4202 
4203                     if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4204                     {
4205                         Expression e = (*arguments)[u];
4206                         tiargs.push(e.type);
4207                         break;
4208                     }
4209                 }
4210             }
4211 
4212             auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4213             return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4214         }
4215         return exp.expressionSemantic(sc);
4216     }
4217 
4218     override void visit(CallExp exp)
4219     {
4220         static if (LOGSEMANTIC)
4221         {
4222             printf("CallExp::semantic() %s\n", exp.toChars());
4223         }
4224         if (exp.type)
4225         {
4226             result = exp;
4227             return; // semantic() already run
4228         }
4229 
4230         Objects* tiargs = null; // initial list of template arguments
4231         Expression ethis = null;
4232         Type tthis = null;
4233         Expression e1org = exp.e1;
4234 
4235         if (exp.e1.op == TOK.comma)
4236         {
4237             /* Rewrite (a,b)(args) as (a,(b(args)))
4238              */
4239             auto ce = cast(CommaExp)exp.e1;
4240             exp.e1 = ce.e2;
4241             ce.e2 = exp;
4242             result = ce.expressionSemantic(sc);
4243             return;
4244         }
4245         if (exp.e1.op == TOK.delegate_)
4246         {
4247             DelegateExp de = cast(DelegateExp)exp.e1;
4248             exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4249             visit(exp);
4250             return;
4251         }
4252         if (exp.e1.op == TOK.function_)
4253         {
4254             if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4255                 return setError();
4256 
4257             // Run e1 semantic even if arguments have any errors
4258             FuncExp fe = cast(FuncExp)exp.e1;
4259             exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4260             if (exp.e1.op == TOK.error)
4261             {
4262                 result = exp.e1;
4263                 return;
4264             }
4265         }
4266 
4267         if (Expression ex = resolveUFCS(sc, exp))
4268         {
4269             result = ex;
4270             return;
4271         }
4272 
4273         /* This recognizes:
4274          *  foo!(tiargs)(funcargs)
4275          */
4276         if (exp.e1.op == TOK.scope_)
4277         {
4278             ScopeExp se = cast(ScopeExp)exp.e1;
4279             TemplateInstance ti = se.sds.isTemplateInstance();
4280             if (ti)
4281             {
4282                 /* Attempt to instantiate ti. If that works, go with it.
4283                  * If not, go with partial explicit specialization.
4284                  */
4285                 WithScopeSymbol withsym;
4286                 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4287                     return setError();
4288                 if (withsym && withsym.withstate.wthis)
4289                 {
4290                     exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4291                     exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4292                     goto Ldotti;
4293                 }
4294                 if (ti.needsTypeInference(sc, 1))
4295                 {
4296                     /* Go with partial explicit specialization
4297                      */
4298                     tiargs = ti.tiargs;
4299                     assert(ti.tempdecl);
4300                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4301                         exp.e1 = new TemplateExp(exp.loc, td);
4302                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4303                         exp.e1 = new VarExp(exp.loc, od);
4304                     else
4305                         exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4306                 }
4307                 else
4308                 {
4309                     Expression e1x = exp.e1.expressionSemantic(sc);
4310                     if (e1x.op == TOK.error)
4311                     {
4312                         result = e1x;
4313                         return;
4314                     }
4315                     exp.e1 = e1x;
4316                 }
4317             }
4318         }
4319 
4320         /* This recognizes:
4321          *  expr.foo!(tiargs)(funcargs)
4322          */
4323     Ldotti:
4324         if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4325         {
4326             DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
4327             TemplateInstance ti = se.ti;
4328             {
4329                 /* Attempt to instantiate ti. If that works, go with it.
4330                  * If not, go with partial explicit specialization.
4331                  */
4332                 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4333                     return setError();
4334                 if (ti.needsTypeInference(sc, 1))
4335                 {
4336                     /* Go with partial explicit specialization
4337                      */
4338                     tiargs = ti.tiargs;
4339                     assert(ti.tempdecl);
4340                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4341                         exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4342                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4343                     {
4344                         exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4345                     }
4346                     else
4347                         exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4348                 }
4349                 else
4350                 {
4351                     Expression e1x = exp.e1.expressionSemantic(sc);
4352                     if (e1x.op == TOK.error)
4353                     {
4354                         result = e1x;
4355                         return;
4356                     }
4357                     exp.e1 = e1x;
4358                 }
4359             }
4360         }
4361 
4362     Lagain:
4363         //printf("Lagain: %s\n", toChars());
4364         exp.f = null;
4365         if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_)
4366         {
4367             // semantic() run later for these
4368         }
4369         else
4370         {
4371             if (exp.e1.op == TOK.dotIdentifier)
4372             {
4373                 DotIdExp die = cast(DotIdExp)exp.e1;
4374                 exp.e1 = die.expressionSemantic(sc);
4375                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4376                  * We handle such earlier, so go back.
4377                  * Note that in the rewrite, we carefully did not run semantic() on e1
4378                  */
4379                 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4380                 {
4381                     goto Ldotti;
4382                 }
4383             }
4384             else
4385             {
4386                 __gshared int nest;
4387                 if (++nest > global.recursionLimit)
4388                 {
4389                     exp.error("recursive evaluation of `%s`", exp.toChars());
4390                     --nest;
4391                     return setError();
4392                 }
4393                 Expression ex = unaSemantic(exp, sc);
4394                 --nest;
4395                 if (ex)
4396                 {
4397                     result = ex;
4398                     return;
4399                 }
4400             }
4401 
4402             /* Look for e1 being a lazy parameter
4403              */
4404             if (exp.e1.op == TOK.variable)
4405             {
4406                 VarExp ve = cast(VarExp)exp.e1;
4407                 if (ve.var.storage_class & STC.lazy_)
4408                 {
4409                     // lazy parameters can be called without violating purity and safety
4410                     Type tw = ve.var.type;
4411                     Type tc = ve.var.type.substWildTo(MODFlags.const_);
4412                     auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4413                     (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4414                     auto t = new TypeDelegate(tf);
4415                     ve.type = t.typeSemantic(exp.loc, sc);
4416                 }
4417                 VarDeclaration v = ve.var.isVarDeclaration();
4418                 if (v && ve.checkPurity(sc, v))
4419                     return setError();
4420             }
4421 
4422             if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4423             {
4424                 SymOffExp se = cast(SymOffExp)exp.e1;
4425                 exp.e1 = new VarExp(se.loc, se.var, true);
4426                 exp.e1 = exp.e1.expressionSemantic(sc);
4427             }
4428             else if (exp.e1.op == TOK.dot)
4429             {
4430                 DotExp de = cast(DotExp)exp.e1;
4431 
4432                 if (de.e2.op == TOK.overloadSet)
4433                 {
4434                     ethis = de.e1;
4435                     tthis = de.e1.type;
4436                     exp.e1 = de.e2;
4437                 }
4438             }
4439             else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction)
4440             {
4441                 // Rewrite (*fp)(arguments) to fp(arguments)
4442                 exp.e1 = (cast(PtrExp)exp.e1).e1;
4443             }
4444         }
4445 
4446         Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4447 
4448         if (exp.e1.op == TOK.error)
4449         {
4450             result = exp.e1;
4451             return;
4452         }
4453         if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4454             return setError();
4455 
4456         // Check for call operator overload
4457         if (t1)
4458         {
4459             if (t1.ty == Tstruct)
4460             {
4461                 auto sd = (cast(TypeStruct)t1).sym;
4462                 sd.size(exp.loc); // Resolve forward references to construct object
4463                 if (sd.sizeok != Sizeok.done)
4464                     return setError();
4465                 if (!sd.ctor)
4466                     sd.ctor = sd.searchCtor();
4467                 /* If `sd.ctor` is a generated copy constructor, this means that it
4468                    is the single constructor that this struct has. In order to not
4469                    disable default construction, the ctor is nullified. The side effect
4470                    of this is that the generated copy constructor cannot be called
4471                    explicitly, but that is ok, because when calling a constructor the
4472                    default constructor should have priority over the generated copy
4473                    constructor.
4474                 */
4475                 if (sd.ctor)
4476                 {
4477                     auto ctor = sd.ctor.isCtorDeclaration();
4478                     if (ctor && ctor.isCpCtor && ctor.generated)
4479                         sd.ctor = null;
4480                 }
4481 
4482                 // First look for constructor
4483                 if (exp.e1.op == TOK.type && sd.ctor)
4484                 {
4485                     if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
4486                         goto Lx;
4487 
4488                     /* https://issues.dlang.org/show_bug.cgi?id=20695
4489                        If all constructors are copy constructors, then
4490                        try default construction.
4491                      */
4492                     if (!sd.hasRegularCtor)
4493                         goto Lx;
4494 
4495                     auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4496                     if (!sd.fill(exp.loc, sle.elements, true))
4497                         return setError();
4498                     if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
4499                         return setError();
4500 
4501                     // https://issues.dlang.org/show_bug.cgi?id=14556
4502                     // Set concrete type to avoid further redundant semantic().
4503                     sle.type = exp.e1.type;
4504 
4505                     /* Constructor takes a mutable object, so don't use
4506                      * the immutable initializer symbol.
4507                      */
4508                     sle.useStaticInit = false;
4509 
4510                     Expression e = sle;
4511                     if (auto cf = sd.ctor.isCtorDeclaration())
4512                     {
4513                         e = new DotVarExp(exp.loc, e, cf, true);
4514                     }
4515                     else if (auto td = sd.ctor.isTemplateDeclaration())
4516                     {
4517                         e = new DotIdExp(exp.loc, e, td.ident);
4518                     }
4519                     else if (auto os = sd.ctor.isOverloadSet())
4520                     {
4521                         e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4522                     }
4523                     else
4524                         assert(0);
4525                     e = new CallExp(exp.loc, e, exp.arguments);
4526                     e = e.expressionSemantic(sc);
4527                     result = e;
4528                     return;
4529                 }
4530                 // No constructor, look for overload of opCall
4531                 if (search_function(sd, Id.call))
4532                     goto L1;
4533                 // overload of opCall, therefore it's a call
4534                 if (exp.e1.op != TOK.type)
4535                 {
4536                     if (sd.aliasthis && !(exp.att1 && exp.e1.type.equivalent(exp.att1)))
4537                     {
4538                         if (!exp.att1 && exp.e1.type.checkAliasThisRec())
4539                             exp.att1 = exp.e1.type;
4540                         exp.e1 = resolveAliasThis(sc, exp.e1);
4541                         goto Lagain;
4542                     }
4543                     exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4544                     return setError();
4545                 }
4546 
4547                 /* It's a struct literal
4548                  */
4549             Lx:
4550                 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4551                 e = e.expressionSemantic(sc);
4552                 result = e;
4553                 return;
4554             }
4555             else if (t1.ty == Tclass)
4556             {
4557             L1:
4558                 // Rewrite as e1.call(arguments)
4559                 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4560                 e = new CallExp(exp.loc, e, exp.arguments);
4561                 e = e.expressionSemantic(sc);
4562                 result = e;
4563                 return;
4564             }
4565             else if (exp.e1.op == TOK.type && t1.isscalar())
4566             {
4567                 Expression e;
4568 
4569                 // Make sure to use the the enum type itself rather than its
4570                 // base type
4571                 // https://issues.dlang.org/show_bug.cgi?id=16346
4572                 if (exp.e1.type.ty == Tenum)
4573                 {
4574                     t1 = exp.e1.type;
4575                 }
4576 
4577                 if (!exp.arguments || exp.arguments.dim == 0)
4578                 {
4579                     e = t1.defaultInitLiteral(exp.loc);
4580                 }
4581                 else if (exp.arguments.dim == 1)
4582                 {
4583                     e = (*exp.arguments)[0];
4584                     e = e.implicitCastTo(sc, t1);
4585                     e = new CastExp(exp.loc, e, t1);
4586                 }
4587                 else
4588                 {
4589                     exp.error("more than one argument for construction of `%s`", t1.toChars());
4590                     return setError();
4591                 }
4592                 e = e.expressionSemantic(sc);
4593                 result = e;
4594                 return;
4595             }
4596         }
4597 
4598         static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4599             OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4600         {
4601             FuncDeclaration f = null;
4602             foreach (s; os.a)
4603             {
4604                 if (tiargs && s.isFuncDeclaration())
4605                     continue;
4606                 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4607                 {
4608                     if (f2.errors)
4609                         return null;
4610                     if (f)
4611                     {
4612                         /* Error if match in more than one overload set,
4613                          * even if one is a 'better' match than the other.
4614                          */
4615                         ScopeDsymbol.multiplyDefined(loc, f, f2);
4616                     }
4617                     else
4618                         f = f2;
4619                 }
4620             }
4621             if (!f)
4622                 .error(loc, "no overload matches for `%s`", os.toChars());
4623             else if (f.errors)
4624                 f = null;
4625             return f;
4626         }
4627 
4628         bool isSuper = false;
4629         if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration)
4630         {
4631             UnaExp ue = cast(UnaExp)exp.e1;
4632 
4633             Expression ue1 = ue.e1;
4634             Expression ue1old = ue1; // need for 'right this' check
4635             VarDeclaration v;
4636             if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
4637             {
4638                 ue.e1 = new TypeExp(ue1.loc, ue1.type);
4639                 ue1 = null;
4640             }
4641 
4642             DotVarExp dve;
4643             DotTemplateExp dte;
4644             Dsymbol s;
4645             if (exp.e1.op == TOK.dotVariable)
4646             {
4647                 dve = cast(DotVarExp)exp.e1;
4648                 dte = null;
4649                 s = dve.var;
4650                 tiargs = null;
4651             }
4652             else
4653             {
4654                 dve = null;
4655                 dte = cast(DotTemplateExp)exp.e1;
4656                 s = dte.td;
4657             }
4658 
4659             // Do overload resolution
4660             exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard);
4661             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4662                 return setError();
4663 
4664             if (exp.f.interfaceVirtual)
4665             {
4666                 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4667                  */
4668                 auto b = exp.f.interfaceVirtual;
4669                 auto ad2 = b.sym;
4670                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4671                 ue.e1 = ue.e1.expressionSemantic(sc);
4672                 ue1 = ue.e1;
4673                 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
4674                 assert(vi >= 0);
4675                 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4676                 assert(exp.f);
4677             }
4678             if (exp.f.needThis())
4679             {
4680                 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
4681                 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4682                 if (ue.e1.op == TOK.error)
4683                 {
4684                     result = ue.e1;
4685                     return;
4686                 }
4687                 ethis = ue.e1;
4688                 tthis = ue.e1.type;
4689                 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4690                 {
4691                     if (global.params.vsafe && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
4692                         return setError();
4693                 }
4694             }
4695 
4696             /* Cannot call public functions from inside invariant
4697              * (because then the invariant would have infinite recursion)
4698              */
4699             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant())
4700             {
4701                 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4702                 return setError();
4703             }
4704 
4705             if (!exp.ignoreAttributes)
4706                 checkFunctionAttributes(exp, sc, exp.f);
4707             checkAccess(exp.loc, sc, ue.e1, exp.f);
4708             if (!exp.f.needThis())
4709             {
4710                 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4711             }
4712             else
4713             {
4714                 if (ue1old.checkRightThis(sc))
4715                     return setError();
4716                 if (exp.e1.op == TOK.dotVariable)
4717                 {
4718                     dve.var = exp.f;
4719                     exp.e1.type = exp.f.type;
4720                 }
4721                 else
4722                 {
4723                     exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4724                     exp.e1 = exp.e1.expressionSemantic(sc);
4725                     if (exp.e1.op == TOK.error)
4726                         return setError();
4727                     ue = cast(UnaExp)exp.e1;
4728                 }
4729                 version (none)
4730                 {
4731                     printf("ue.e1 = %s\n", ue.e1.toChars());
4732                     printf("f = %s\n", exp.f.toChars());
4733                     printf("t1 = %s\n", t1.toChars());
4734                     printf("e1 = %s\n", exp.e1.toChars());
4735                     printf("e1.type = %s\n", exp.e1.type.toChars());
4736                 }
4737 
4738                 // See if we need to adjust the 'this' pointer
4739                 AggregateDeclaration ad = exp.f.isThis();
4740                 ClassDeclaration cd = ue.e1.type.isClassHandle();
4741                 if (ad && cd && ad.isClassDeclaration())
4742                 {
4743                     if (ue.e1.op == TOK.dotType)
4744                     {
4745                         ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4746                         exp.directcall = true;
4747                     }
4748                     else if (ue.e1.op == TOK.super_)
4749                         exp.directcall = true;
4750                     else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4751                         exp.directcall = true;
4752 
4753                     if (ad != cd)
4754                     {
4755                         ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4756                         ue.e1 = ue.e1.expressionSemantic(sc);
4757                     }
4758                 }
4759             }
4760             // If we've got a pointer to a function then deference it
4761             // https://issues.dlang.org/show_bug.cgi?id=16483
4762             if (exp.e1.type.ty == Tpointer && exp.e1.type.nextOf().ty == Tfunction)
4763             {
4764                 Expression e = new PtrExp(exp.loc, exp.e1);
4765                 e.type = exp.e1.type.nextOf();
4766                 exp.e1 = e;
4767             }
4768             t1 = exp.e1.type;
4769         }
4770         else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_)
4771         {
4772             auto ad = sc.func ? sc.func.isThis() : null;
4773             auto cd = ad ? ad.isClassDeclaration() : null;
4774 
4775             isSuper = exp.e1.op == TOK.super_;
4776             if (isSuper)
4777             {
4778                 // Base class constructor call
4779                 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4780                 {
4781                     exp.error("super class constructor call must be in a constructor");
4782                     return setError();
4783                 }
4784                 if (!cd.baseClass.ctor)
4785                 {
4786                     exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4787                     return setError();
4788                 }
4789             }
4790             else
4791             {
4792                 // `this` call expression must be inside a
4793                 // constructor
4794                 if (!ad || !sc.func.isCtorDeclaration())
4795                 {
4796                     exp.error("constructor call must be in a constructor");
4797                     return setError();
4798                 }
4799 
4800                 // https://issues.dlang.org/show_bug.cgi?id=18719
4801                 // If `exp` is a call expression to another constructor
4802                 // then it means that all struct/class fields will be
4803                 // initialized after this call.
4804                 foreach (ref field; sc.ctorflow.fieldinit)
4805                 {
4806                     field.csx |= CSX.this_ctor;
4807                 }
4808             }
4809 
4810             if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4811             {
4812                 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4813                     exp.error("constructor calls not allowed in loops or after labels");
4814                 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4815                     exp.error("multiple constructor calls");
4816                 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4817                     exp.error("an earlier `return` statement skips constructor");
4818                 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4819             }
4820 
4821             tthis = ad.type.addMod(sc.func.type.mod);
4822             auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4823             if (auto os = ctor.isOverloadSet())
4824                 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4825             else
4826                 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4827 
4828             if (!exp.f || exp.f.errors)
4829                 return setError();
4830 
4831             checkFunctionAttributes(exp, sc, exp.f);
4832             checkAccess(exp.loc, sc, null, exp.f);
4833 
4834             exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4835             exp.e1 = exp.e1.expressionSemantic(sc);
4836             // https://issues.dlang.org/show_bug.cgi?id=21095
4837             if (exp.e1.op == TOK.error)
4838                 return setError();
4839             t1 = exp.e1.type;
4840 
4841             // BUG: this should really be done by checking the static
4842             // call graph
4843             if (exp.f == sc.func)
4844             {
4845                 exp.error("cyclic constructor call");
4846                 return setError();
4847             }
4848         }
4849         else if (exp.e1.op == TOK.overloadSet)
4850         {
4851             auto os = (cast(OverExp)exp.e1).vars;
4852             exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
4853             if (!exp.f)
4854                 return setError();
4855             if (ethis)
4856                 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4857             else
4858                 exp.e1 = new VarExp(exp.loc, exp.f, false);
4859             goto Lagain;
4860         }
4861         else if (!t1)
4862         {
4863             exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4864             return setError();
4865         }
4866         else if (t1.ty == Terror)
4867         {
4868             return setError();
4869         }
4870         else if (t1.ty != Tfunction)
4871         {
4872             TypeFunction tf;
4873             const(char)* p;
4874             Dsymbol s;
4875             exp.f = null;
4876             if (exp.e1.op == TOK.function_)
4877             {
4878                 // function literal that direct called is always inferred.
4879                 assert((cast(FuncExp)exp.e1).fd);
4880                 exp.f = (cast(FuncExp)exp.e1).fd;
4881                 tf = cast(TypeFunction)exp.f.type;
4882                 p = "function literal";
4883             }
4884             else if (t1.ty == Tdelegate)
4885             {
4886                 TypeDelegate td = cast(TypeDelegate)t1;
4887                 assert(td.next.ty == Tfunction);
4888                 tf = cast(TypeFunction)td.next;
4889                 p = "delegate";
4890             }
4891             else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction)
4892             {
4893                 tf = cast(TypeFunction)(cast(TypePointer)t1).next;
4894                 p = "function pointer";
4895             }
4896             else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4897             {
4898                 DotVarExp dve = cast(DotVarExp)exp.e1;
4899                 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4900                 if (!exp.f)
4901                     return setError();
4902                 if (exp.f.needThis())
4903                 {
4904                     dve.var = exp.f;
4905                     dve.type = exp.f.type;
4906                     dve.hasOverloads = false;
4907                     goto Lagain;
4908                 }
4909                 exp.e1 = new VarExp(dve.loc, exp.f, false);
4910                 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4911                 result = e.expressionSemantic(sc);
4912                 return;
4913             }
4914             else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4915             {
4916                 s = (cast(VarExp)exp.e1).var;
4917                 goto L2;
4918             }
4919             else if (exp.e1.op == TOK.template_)
4920             {
4921                 s = (cast(TemplateExp)exp.e1).td;
4922             L2:
4923                 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
4924                 if (!exp.f || exp.f.errors)
4925                     return setError();
4926                 if (exp.f.needThis())
4927                 {
4928                     if (hasThis(sc))
4929                     {
4930                         // Supply an implicit 'this', as in
4931                         //    this.ident
4932                         exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
4933                         goto Lagain;
4934                     }
4935                     else if (isNeedThisScope(sc, exp.f))
4936                     {
4937                         exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4938                         return setError();
4939                     }
4940                 }
4941                 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
4942                 goto Lagain;
4943             }
4944             else
4945             {
4946                 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
4947                 return setError();
4948             }
4949 
4950             const(char)* failMessage;
4951             Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4952             if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4953             {
4954                 OutBuffer buf;
4955                 buf.writeByte('(');
4956                 argExpTypesToCBuffer(&buf, exp.arguments);
4957                 buf.writeByte(')');
4958                 if (tthis)
4959                     tthis.modToBuffer(&buf);
4960 
4961                 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4962                 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4963                     p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4964                 if (failMessage)
4965                     errorSupplemental(exp.loc, "%s", failMessage);
4966                 return setError();
4967             }
4968             // Purity and safety check should run after testing arguments matching
4969             if (exp.f)
4970             {
4971                 exp.checkPurity(sc, exp.f);
4972                 exp.checkSafety(sc, exp.f);
4973                 exp.checkNogc(sc, exp.f);
4974                 if (exp.f.checkNestedReference(sc, exp.loc))
4975                     return setError();
4976             }
4977             else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
4978             {
4979                 bool err = false;
4980                 if (!tf.purity && sc.func.setImpure())
4981                 {
4982                     exp.error("`pure` %s `%s` cannot call impure %s `%s`",
4983                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4984                     err = true;
4985                 }
4986                 if (!tf.isnogc && sc.func.setGC())
4987                 {
4988                     exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
4989                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4990                     err = true;
4991                 }
4992                 if (tf.trust <= TRUST.system && sc.func.setUnsafe())
4993                 {
4994                     exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
4995                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4996                     err = true;
4997                 }
4998                 if (err)
4999                     return setError();
5000             }
5001 
5002             if (t1.ty == Tpointer)
5003             {
5004                 Expression e = new PtrExp(exp.loc, exp.e1);
5005                 e.type = tf;
5006                 exp.e1 = e;
5007             }
5008             t1 = tf;
5009         }
5010         else if (exp.e1.op == TOK.variable)
5011         {
5012             // Do overload resolution
5013             VarExp ve = cast(VarExp)exp.e1;
5014 
5015             exp.f = ve.var.isFuncDeclaration();
5016             assert(exp.f);
5017             tiargs = null;
5018 
5019             if (exp.f.overnext)
5020                 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
5021             else
5022             {
5023                 exp.f = exp.f.toAliasFunc();
5024                 TypeFunction tf = cast(TypeFunction)exp.f.type;
5025                 const(char)* failMessage;
5026                 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5027                 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5028                 {
5029                     OutBuffer buf;
5030                     buf.writeByte('(');
5031                     argExpTypesToCBuffer(&buf, exp.arguments);
5032                     buf.writeByte(')');
5033 
5034                     //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5035                     .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5036                         exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5037                     if (failMessage)
5038                         errorSupplemental(exp.loc, "%s", failMessage);
5039                     exp.f = null;
5040                 }
5041             }
5042             if (!exp.f || exp.f.errors)
5043                 return setError();
5044 
5045             if (exp.f.needThis())
5046             {
5047                 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5048                 if (exp.f.checkNestedReference(sc, exp.loc))
5049                     return setError();
5050 
5051                 if (hasThis(sc))
5052                 {
5053                     // Supply an implicit 'this', as in
5054                     //    this.ident
5055                     exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5056                     // Note: we cannot use f directly, because further overload resolution
5057                     // through the supplied 'this' may cause different result.
5058                     goto Lagain;
5059                 }
5060                 else if (isNeedThisScope(sc, exp.f))
5061                 {
5062                     exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5063                     return setError();
5064                 }
5065             }
5066 
5067             checkFunctionAttributes(exp, sc, exp.f);
5068             checkAccess(exp.loc, sc, null, exp.f);
5069             if (exp.f.checkNestedReference(sc, exp.loc))
5070                 return setError();
5071 
5072             ethis = null;
5073             tthis = null;
5074 
5075             if (ve.hasOverloads)
5076             {
5077                 exp.e1 = new VarExp(ve.loc, exp.f, false);
5078                 exp.e1.type = exp.f.type;
5079             }
5080             t1 = exp.f.type;
5081         }
5082         assert(t1.ty == Tfunction);
5083 
5084         Expression argprefix;
5085         if (!exp.arguments)
5086             exp.arguments = new Expressions();
5087         if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5088             return setError();
5089 
5090         if (!exp.type)
5091         {
5092             exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5093                         // avoid recursive expression printing
5094             exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5095             return setError();
5096         }
5097 
5098         if (exp.f && exp.f.tintro)
5099         {
5100             Type t = exp.type;
5101             int offset = 0;
5102             TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5103             if (tf.next.isBaseOf(t, &offset) && offset)
5104             {
5105                 exp.type = tf.next;
5106                 result = Expression.combine(argprefix, exp.castTo(sc, t));
5107                 return;
5108             }
5109         }
5110 
5111         // Handle the case of a direct lambda call
5112         if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5113         {
5114             exp.f.tookAddressOf = 0;
5115         }
5116 
5117         result = Expression.combine(argprefix, exp);
5118 
5119         if (isSuper)
5120         {
5121             auto ad = sc.func ? sc.func.isThis() : null;
5122             auto cd = ad ? ad.isClassDeclaration() : null;
5123             if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5124             {
5125                 // if super is defined in C++, it sets the vtable pointer to the base class
5126                 // so we have to restore it, but still return 'this' from super() call:
5127                 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5128                 Loc loc = exp.loc;
5129 
5130                 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5131                 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5132                 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5133 
5134                 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5135                 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5136 
5137                 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5138 
5139                 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5140 
5141                 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5142                 result = e.expressionSemantic(sc);
5143             }
5144         }
5145 
5146         // declare dual-context container
5147         if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func)
5148         {
5149             // check access to second `this`
5150             if (AggregateDeclaration ad2 = exp.f.isMember2())
5151             {
5152                 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5153                 if (te.op != TOK.error)
5154                     te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5155                 if (te.op == TOK.error)
5156                 {
5157                     exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5158                     return setError();
5159                 }
5160             }
5161             VarDeclaration vthis2 = makeThis2Argument(exp.loc, sc, exp.f);            exp.vthis2 = vthis2;
5162             Expression de = new DeclarationExp(exp.loc, vthis2);
5163             result = Expression.combine(de, result);
5164             result = result.expressionSemantic(sc);
5165         }
5166     }
5167 
5168     override void visit(DeclarationExp e)
5169     {
5170         if (e.type)
5171         {
5172             result = e;
5173             return;
5174         }
5175         static if (LOGSEMANTIC)
5176         {
5177             printf("DeclarationExp::semantic() %s\n", e.toChars());
5178         }
5179 
5180         uint olderrors = global.errors;
5181 
5182         /* This is here to support extern(linkage) declaration,
5183          * where the extern(linkage) winds up being an AttribDeclaration
5184          * wrapper.
5185          */
5186         Dsymbol s = e.declaration;
5187 
5188         while (1)
5189         {
5190             AttribDeclaration ad = s.isAttribDeclaration();
5191             if (ad)
5192             {
5193                 if (ad.decl && ad.decl.dim == 1)
5194                 {
5195                     s = (*ad.decl)[0];
5196                     continue;
5197                 }
5198             }
5199             break;
5200         }
5201 
5202         VarDeclaration v = s.isVarDeclaration();
5203         if (v)
5204         {
5205             // Do semantic() on initializer first, so:
5206             //      int a = a;
5207             // will be illegal.
5208             e.declaration.dsymbolSemantic(sc);
5209             s.parent = sc.parent;
5210         }
5211 
5212         //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5213         // Insert into both local scope and function scope.
5214         // Must be unique in both.
5215         if (s.ident)
5216         {
5217             if (!sc.insert(s))
5218             {
5219                 auto conflict = sc.search(Loc.initial, s.ident, null);
5220                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5221                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5222                                   conflict.kind(), conflict.toChars());
5223                 return setError();
5224             }
5225             else if (sc.func)
5226             {
5227                 // https://issues.dlang.org/show_bug.cgi?id=11720
5228                 // include Dataseg variables
5229                 if ((s.isFuncDeclaration() ||
5230                      s.isAggregateDeclaration() ||
5231                      s.isEnumDeclaration() ||
5232                      s.isTemplateDeclaration() ||
5233                      v && v.isDataseg()) && !sc.func.localsymtab.insert(s))
5234                 {
5235                     // Get the previous symbol
5236                     Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5237 
5238                     // Perturb the name mangling so that the symbols can co-exist
5239                     // instead of colliding
5240                     s.localNum = cast(ushort)(originalSymbol.localNum + 1);
5241                     assert(s.localNum);         // 65535 should be enough for anyone
5242 
5243                     // Replace originalSymbol with s, which updates the localCount
5244                     sc.func.localsymtab.update(s);
5245 
5246                     // The mangling change only works for D mangling
5247                 }
5248 //              else
5249                 {
5250                     /* https://issues.dlang.org/show_bug.cgi?id=21272
5251                      * If we are in a foreach body we need to extract the
5252                      * function containing the foreach
5253                      */
5254                     FuncDeclaration fes_enclosing_func;
5255                     if (sc.func && sc.func.fes)
5256                         fes_enclosing_func = sc.enclosing.enclosing.func;
5257 
5258                     // Disallow shadowing
5259                     for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5260                     {
5261                         Dsymbol s2;
5262                         if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5263                         {
5264                             // allow STC.local symbols to be shadowed
5265                             // TODO: not really an optimal design
5266                             auto decl = s2.isDeclaration();
5267                             if (!decl || !(decl.storage_class & STC.local))
5268                             {
5269                                 if (sc.func.fes)
5270                                 {
5271                                     e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5272                                 }
5273                                 else
5274                                 {
5275                                     e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5276                                     return setError();
5277                                 }
5278                             }
5279                         }
5280                     }
5281                 }
5282             }
5283         }
5284         if (!s.isVarDeclaration())
5285         {
5286             Scope* sc2 = sc;
5287             if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5288                 sc2 = sc.push();
5289             sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5290             e.declaration.dsymbolSemantic(sc2);
5291             if (sc2 != sc)
5292                 sc2.pop();
5293             s.parent = sc.parent;
5294         }
5295         if (global.errors == olderrors)
5296         {
5297             e.declaration.semantic2(sc);
5298             if (global.errors == olderrors)
5299             {
5300                 e.declaration.semantic3(sc);
5301             }
5302         }
5303         // todo: error in declaration should be propagated.
5304 
5305         e.type = Type.tvoid;
5306         result = e;
5307     }
5308 
5309     override void visit(TypeidExp exp)
5310     {
5311         static if (LOGSEMANTIC)
5312         {
5313             printf("TypeidExp::semantic() %s\n", exp.toChars());
5314         }
5315         Type ta = isType(exp.obj);
5316         Expression ea = isExpression(exp.obj);
5317         Dsymbol sa = isDsymbol(exp.obj);
5318         //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5319 
5320         if (ta)
5321         {
5322             dmd.typesem.resolve(ta, exp.loc, sc, ea, ta, sa, true);
5323         }
5324 
5325         if (ea)
5326         {
5327             if (auto sym = getDsymbol(ea))
5328                 ea = symbolToExp(sym, exp.loc, sc, false);
5329             else
5330                 ea = ea.expressionSemantic(sc);
5331             ea = resolveProperties(sc, ea);
5332             ta = ea.type;
5333             if (ea.op == TOK.type)
5334                 ea = null;
5335         }
5336 
5337         if (!ta)
5338         {
5339             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5340             exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5341             return setError();
5342         }
5343 
5344         if (global.params.vcomplex)
5345             ta.checkComplexTransition(exp.loc, sc);
5346 
5347         Expression e;
5348         auto tb = ta.toBasetype();
5349         if (ea && tb.ty == Tclass)
5350         {
5351             if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5352             {
5353                 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
5354                 e = ErrorExp.get();
5355             }
5356             else if (!Type.typeinfoclass)
5357             {
5358                 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5359                 e = ErrorExp.get();
5360             }
5361             else
5362             {
5363                 /* Get the dynamic type, which is .classinfo
5364                 */
5365                 ea = ea.expressionSemantic(sc);
5366                 e = new TypeidExp(ea.loc, ea);
5367                 e.type = Type.typeinfoclass.type;
5368             }
5369         }
5370         else if (ta.ty == Terror)
5371         {
5372             e = ErrorExp.get();
5373         }
5374         else
5375         {
5376             // Handle this in the glue layer
5377             e = new TypeidExp(exp.loc, ta);
5378             e.type = getTypeInfoType(exp.loc, ta, sc);
5379 
5380             semanticTypeInfo(sc, ta);
5381 
5382             if (ea)
5383             {
5384                 e = new CommaExp(exp.loc, ea, e); // execute ea
5385                 e = e.expressionSemantic(sc);
5386             }
5387         }
5388         result = e;
5389     }
5390 
5391     override void visit(TraitsExp e)
5392     {
5393         result = semanticTraits(e, sc);
5394     }
5395 
5396     override void visit(HaltExp e)
5397     {
5398         static if (LOGSEMANTIC)
5399         {
5400             printf("HaltExp::semantic()\n");
5401         }
5402         e.type = Type.tvoid;
5403         result = e;
5404     }
5405 
5406     override void visit(IsExp e)
5407     {
5408         /* is(targ id tok tspec)
5409          * is(targ id :  tok2)
5410          * is(targ id == tok2)
5411          */
5412         Type tded = null;
5413 
5414         void yes()
5415         {
5416             //printf("yes\n");
5417             if (!e.id)
5418             {
5419                 result = IntegerExp.createBool(true);
5420                 return;
5421             }
5422 
5423             Dsymbol s;
5424             Tuple tup = isTuple(tded);
5425             if (tup)
5426                 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5427             else
5428                 s = new AliasDeclaration(e.loc, e.id, tded);
5429             s.dsymbolSemantic(sc);
5430 
5431             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5432              * More investigation is needed.
5433              */
5434             if (!tup && !sc.insert(s))
5435             {
5436                 auto conflict = sc.search(Loc.initial, s.ident, null);
5437                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5438                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5439                                   conflict.kind(), conflict.toChars());
5440             }
5441 
5442             unSpeculative(sc, s);
5443 
5444             result = IntegerExp.createBool(true);
5445         }
5446         void no()
5447         {
5448             result = IntegerExp.createBool(false);
5449             //printf("no\n");
5450         }
5451 
5452         static if (LOGSEMANTIC)
5453         {
5454             printf("IsExp::semantic(%s)\n", e.toChars());
5455         }
5456         if (e.id && !(sc.flags & SCOPE.condition))
5457         {
5458             e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5459             return setError();
5460         }
5461 
5462         if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5463         {
5464             const oldErrors = global.startGagging();
5465             Dsymbol sym = e.targ.toDsymbol(sc);
5466             global.endGagging(oldErrors);
5467 
5468             if (sym is null)
5469                 return no();
5470             Package p = resolveIsPackage(sym);
5471             if (p is null)
5472                 return no();
5473             if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5474                 return no();
5475             else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5476                 return no();
5477             tded = e.targ;
5478             return yes();
5479         }
5480 
5481         {
5482             Scope* sc2 = sc.copy(); // keep sc.flags
5483             sc2.tinst = null;
5484             sc2.minst = null;
5485             sc2.flags |= SCOPE.fullinst;
5486             Type t = e.targ.trySemantic(e.loc, sc2);
5487             sc2.pop();
5488             if (!t) // errors, so condition is false
5489                 return no();
5490             e.targ = t;
5491         }
5492 
5493         if (e.tok2 != TOK.reserved)
5494         {
5495             switch (e.tok2)
5496             {
5497             case TOK.struct_:
5498                 if (e.targ.ty != Tstruct)
5499                     return no();
5500                 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5501                     return no();
5502                 tded = e.targ;
5503                 break;
5504 
5505             case TOK.union_:
5506                 if (e.targ.ty != Tstruct)
5507                     return no();
5508                 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5509                     return no();
5510                 tded = e.targ;
5511                 break;
5512 
5513             case TOK.class_:
5514                 if (e.targ.ty != Tclass)
5515                     return no();
5516                 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5517                     return no();
5518                 tded = e.targ;
5519                 break;
5520 
5521             case TOK.interface_:
5522                 if (e.targ.ty != Tclass)
5523                     return no();
5524                 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5525                     return no();
5526                 tded = e.targ;
5527                 break;
5528 
5529             case TOK.const_:
5530                 if (!e.targ.isConst())
5531                     return no();
5532                 tded = e.targ;
5533                 break;
5534 
5535             case TOK.immutable_:
5536                 if (!e.targ.isImmutable())
5537                     return no();
5538                 tded = e.targ;
5539                 break;
5540 
5541             case TOK.shared_:
5542                 if (!e.targ.isShared())
5543                     return no();
5544                 tded = e.targ;
5545                 break;
5546 
5547             case TOK.inout_:
5548                 if (!e.targ.isWild())
5549                     return no();
5550                 tded = e.targ;
5551                 break;
5552 
5553             case TOK.super_:
5554                 // If class or interface, get the base class and interfaces
5555                 if (e.targ.ty != Tclass)
5556                     return no();
5557                 else
5558                 {
5559                     ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5560                     auto args = new Parameters();
5561                     args.reserve(cd.baseclasses.dim);
5562                     if (cd.semanticRun < PASS.semanticdone)
5563                         cd.dsymbolSemantic(null);
5564                     for (size_t i = 0; i < cd.baseclasses.dim; i++)
5565                     {
5566                         BaseClass* b = (*cd.baseclasses)[i];
5567                         args.push(new Parameter(STC.in_, b.type, null, null, null));
5568                     }
5569                     tded = new TypeTuple(args);
5570                 }
5571                 break;
5572 
5573             case TOK.enum_:
5574                 if (e.targ.ty != Tenum)
5575                     return no();
5576                 if (e.id)
5577                     tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5578                 else
5579                     tded = e.targ;
5580 
5581                 if (tded.ty == Terror)
5582                     return setError();
5583                 break;
5584 
5585             case TOK.delegate_:
5586                 if (e.targ.ty != Tdelegate)
5587                     return no();
5588                 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5589                 break;
5590 
5591             case TOK.function_:
5592             case TOK.parameters:
5593                 {
5594                     if (e.targ.ty != Tfunction)
5595                         return no();
5596                     tded = e.targ;
5597 
5598                     /* Generate tuple from function parameter types.
5599                      */
5600                     assert(tded.ty == Tfunction);
5601                     auto tdedf = tded.isTypeFunction();
5602                     auto args = new Parameters();
5603                     foreach (i, arg; tdedf.parameterList)
5604                     {
5605                         assert(arg && arg.type);
5606                         /* If one of the default arguments was an error,
5607                            don't return an invalid tuple
5608                          */
5609                         if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error)
5610                             return setError();
5611                         args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5612                     }
5613                     tded = new TypeTuple(args);
5614                     break;
5615                 }
5616             case TOK.return_:
5617                 /* Get the 'return type' for the function,
5618                  * delegate, or pointer to function.
5619                  */
5620                 if (e.targ.ty == Tfunction)
5621                     tded = (cast(TypeFunction)e.targ).next;
5622                 else if (e.targ.ty == Tdelegate)
5623                 {
5624                     tded = (cast(TypeDelegate)e.targ).next;
5625                     tded = (cast(TypeFunction)tded).next;
5626                 }
5627                 else if (e.targ.ty == Tpointer && (cast(TypePointer)e.targ).next.ty == Tfunction)
5628                 {
5629                     tded = (cast(TypePointer)e.targ).next;
5630                     tded = (cast(TypeFunction)tded).next;
5631                 }
5632                 else
5633                     return no();
5634                 break;
5635 
5636             case TOK.argumentTypes:
5637                 /* Generate a type tuple of the equivalent types used to determine if a
5638                  * function argument of this type can be passed in registers.
5639                  * The results of this are highly platform dependent, and intended
5640                  * primarly for use in implementing va_arg().
5641                  */
5642                 tded = target.toArgTypes(e.targ);
5643                 if (!tded)
5644                     return no();
5645                 // not valid for a parameter
5646                 break;
5647 
5648             case TOK.vector:
5649                 if (e.targ.ty != Tvector)
5650                     return no();
5651                 tded = (cast(TypeVector)e.targ).basetype;
5652                 break;
5653 
5654             default:
5655                 assert(0);
5656             }
5657 
5658             // https://issues.dlang.org/show_bug.cgi?id=18753
5659             if (tded)
5660                 return yes();
5661             return no();
5662         }
5663         else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
5664         {
5665             /* Evaluate to true if targ matches tspec
5666              * is(targ == tspec)
5667              * is(targ : tspec)
5668              */
5669             e.tspec = e.tspec.typeSemantic(e.loc, sc);
5670             //printf("targ  = %s, %s\n", e.targ.toChars(), e.targ.deco);
5671             //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5672 
5673             if (e.tok == TOK.colon)
5674             {
5675                 // current scope is itself deprecated, or deprecations are not errors
5676                 const bool deprecationAllowed = sc.isDeprecated
5677                     || global.params.useDeprecated != DiagnosticReporting.error;
5678                 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5679 
5680                 if (preventAliasThis && e.targ.ty == Tstruct)
5681                 {
5682                     if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5683                         return yes();
5684                     else
5685                         return no();
5686                 }
5687                 else if (preventAliasThis && e.targ.ty == Tclass)
5688                 {
5689                     if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5690                         return yes();
5691                     else
5692                         return no();
5693                 }
5694                 else if (e.targ.implicitConvTo(e.tspec))
5695                     return yes();
5696                 else
5697                     return no();
5698             }
5699             else /* == */
5700             {
5701                 if (e.targ.equals(e.tspec))
5702                     return yes();
5703                 else
5704                     return no();
5705             }
5706         }
5707         else if (e.tspec)
5708         {
5709             /* Evaluate to true if targ matches tspec.
5710              * If true, declare id as an alias for the specialized type.
5711              * is(targ == tspec, tpl)
5712              * is(targ : tspec, tpl)
5713              * is(targ id == tspec)
5714              * is(targ id : tspec)
5715              * is(targ id == tspec, tpl)
5716              * is(targ id : tspec, tpl)
5717              */
5718             Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5719             e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5720 
5721             Objects dedtypes = Objects(e.parameters.dim);
5722             dedtypes.zero();
5723 
5724             MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5725             //printf("targ: %s\n", targ.toChars());
5726             //printf("tspec: %s\n", tspec.toChars());
5727             if (m <= MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5728             {
5729                 return no();
5730             }
5731             else
5732             {
5733                 tded = cast(Type)dedtypes[0];
5734                 if (!tded)
5735                     tded = e.targ;
5736                 Objects tiargs = Objects(1);
5737                 tiargs[0] = e.targ;
5738 
5739                 /* Declare trailing parameters
5740                  */
5741                 for (size_t i = 1; i < e.parameters.dim; i++)
5742                 {
5743                     TemplateParameter tp = (*e.parameters)[i];
5744                     Declaration s = null;
5745 
5746                     m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5747                     if (m <= MATCH.nomatch)
5748                         return no();
5749                     s.dsymbolSemantic(sc);
5750                     if (!sc.insert(s))
5751                     {
5752                         auto conflict = sc.search(Loc.initial, s.ident, null);
5753                         e.error("declaration `%s` is already defined", s.toPrettyChars());
5754                         errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5755                                           conflict.kind(), conflict.toChars());
5756                     }
5757 
5758                     unSpeculative(sc, s);
5759                 }
5760                 return yes();
5761             }
5762         }
5763         else if (e.id)
5764         {
5765             /* Declare id as an alias for type targ. Evaluate to true
5766              * is(targ id)
5767              */
5768             tded = e.targ;
5769         }
5770         return yes();
5771     }
5772 
5773     override void visit(BinAssignExp exp)
5774     {
5775         if (exp.type)
5776         {
5777             result = exp;
5778             return;
5779         }
5780 
5781         Expression e = exp.op_overload(sc);
5782         if (e)
5783         {
5784             result = e;
5785             return;
5786         }
5787 
5788         if (exp.e1.op == TOK.arrayLength)
5789         {
5790             // arr.length op= e2;
5791             e = rewriteOpAssign(exp);
5792             e = e.expressionSemantic(sc);
5793             result = e;
5794             return;
5795         }
5796         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5797         {
5798             if (checkNonAssignmentArrayOp(exp.e1))
5799                 return setError();
5800 
5801             if (exp.e1.op == TOK.slice)
5802                 (cast(SliceExp)exp.e1).arrayop = true;
5803 
5804             // T[] op= ...
5805             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5806             {
5807                 // T[] op= T
5808                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5809             }
5810             else if (Expression ex = typeCombine(exp, sc))
5811             {
5812                 result = ex;
5813                 return;
5814             }
5815             exp.type = exp.e1.type;
5816             result = arrayOp(exp, sc);
5817             return;
5818         }
5819 
5820         exp.e1 = exp.e1.expressionSemantic(sc);
5821         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
5822         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5823         exp.type = exp.e1.type;
5824 
5825         if (auto ad = isAggregate(exp.e1.type))
5826         {
5827             if (const s = search_function(ad, Id.opOpAssign))
5828             {
5829                 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());
5830                 return setError();
5831             }
5832         }
5833         if (exp.e1.checkScalar() ||
5834             exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5835             exp.e1.checkSharedAccess(sc))
5836             return setError();
5837 
5838         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);
5839         int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign);
5840         int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign);
5841 
5842         if (bitwise && exp.type.toBasetype().ty == Tbool)
5843             exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5844         else if (exp.checkNoBool())
5845             return setError();
5846 
5847         if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5848         {
5849             result = scaleFactor(exp, sc);
5850             return;
5851         }
5852 
5853         if (Expression ex = typeCombine(exp, sc))
5854         {
5855             result = ex;
5856             return;
5857         }
5858 
5859         if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5860             return setError();
5861         if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5862             return setError();
5863 
5864         if (shift)
5865         {
5866             if (exp.e2.type.toBasetype().ty != Tvector)
5867                 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5868         }
5869 
5870         if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5871         {
5872             result = exp.incompatibleTypes();
5873             return;
5874         }
5875 
5876         if (exp.e1.op == TOK.error || exp.e2.op == TOK.error)
5877             return setError();
5878 
5879         e = exp.checkOpAssignTypes(sc);
5880         if (e.op == TOK.error)
5881         {
5882             result = e;
5883             return;
5884         }
5885 
5886         assert(e.op == TOK.assign || e == exp);
5887         result = (cast(BinExp)e).reorderSettingAAElem(sc);
5888     }
5889 
5890     private Expression compileIt(MixinExp exp)
5891     {
5892         OutBuffer buf;
5893         if (expressionsToString(buf, sc, exp.exps))
5894             return null;
5895 
5896         uint errors = global.errors;
5897         const len = buf.length;
5898         const str = buf.extractChars()[0 .. len];
5899         scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
5900         p.nextToken();
5901         //printf("p.loc.linnum = %d\n", p.loc.linnum);
5902 
5903         Expression e = p.parseExpression();
5904         p.reportDiagnostics();
5905         if (global.errors != errors)
5906             return null;
5907 
5908         if (p.token.value != TOK.endOfFile)
5909         {
5910             exp.error("incomplete mixin expression `%s`", str.ptr);
5911             return null;
5912         }
5913         return e;
5914     }
5915 
5916     override void visit(MixinExp exp)
5917     {
5918         /* https://dlang.org/spec/expression.html#mixin_expressions
5919          */
5920 
5921         static if (LOGSEMANTIC)
5922         {
5923             printf("MixinExp::semantic('%s')\n", exp.toChars());
5924         }
5925 
5926         auto e = compileIt(exp);
5927         if (!e)
5928             return setError();
5929         result = e.expressionSemantic(sc);
5930     }
5931 
5932     override void visit(ImportExp e)
5933     {
5934         static if (LOGSEMANTIC)
5935         {
5936             printf("ImportExp::semantic('%s')\n", e.toChars());
5937         }
5938 
5939         auto se = semanticString(sc, e.e1, "file name argument");
5940         if (!se)
5941             return setError();
5942         se = se.toUTF8(sc);
5943 
5944         auto namez = se.toStringz().ptr;
5945         if (!global.filePath)
5946         {
5947             e.error("need `-J` switch to import text file `%s`", namez);
5948             return setError();
5949         }
5950 
5951         /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5952          * ('Path Traversal') attacks.
5953          * http://cwe.mitre.org/data/definitions/22.html
5954          */
5955 
5956         if (FileName.absolute(namez))
5957         {
5958             e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
5959             return setError();
5960         }
5961 
5962         auto idxReserved = FileName.findReservedChar(namez);
5963         if (idxReserved != size_t.max)
5964         {
5965             e.error("`%s` is  not a valid filename on this platform", se.toChars());
5966             e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
5967             return setError();
5968         }
5969 
5970         if (FileName.refersToParentDir(namez))
5971         {
5972             e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
5973             return setError();
5974         }
5975 
5976         auto name = FileName.searchPath(global.filePath, namez, false);
5977         if (!name)
5978         {
5979             e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
5980             e.errorSupplemental("Path(s) searched (as provided by `-J`):");
5981             foreach (idx, path; *global.filePath)
5982             {
5983                 const attr = FileName.exists(path);
5984                 const(char)* err = attr == 2 ? "" :
5985                     (attr == 1 ? " (not a directory)" : " (path not found)");
5986                 e.errorSupplemental("[%zu]: `%s`%s", idx, path, err);
5987             }
5988             return setError();
5989         }
5990 
5991         sc._module.contentImportedFiles.push(name);
5992         if (global.params.verbose)
5993         {
5994             const slice = se.peekString();
5995             message("file      %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
5996         }
5997         if (global.params.moduleDeps !is null)
5998         {
5999             OutBuffer* ob = global.params.moduleDeps;
6000             Module imod = sc.instantiatingModule();
6001 
6002             if (!global.params.moduleDepsFile)
6003                 ob.writestring("depsFile ");
6004             ob.writestring(imod.toPrettyChars());
6005             ob.writestring(" (");
6006             escapePath(ob, imod.srcfile.toChars());
6007             ob.writestring(") : ");
6008             if (global.params.moduleDepsFile)
6009                 ob.writestring("string : ");
6010             ob.write(se.peekString());
6011             ob.writestring(" (");
6012             escapePath(ob, name);
6013             ob.writestring(")");
6014             ob.writenl();
6015         }
6016         if (global.params.emitMakeDeps)
6017         {
6018             global.params.makeDeps.push(name);
6019         }
6020 
6021         {
6022             auto readResult = File.read(name);
6023             if (!readResult.success)
6024             {
6025                 e.error("cannot read file `%s`", name);
6026                 return setError();
6027             }
6028             else
6029             {
6030                 // take ownership of buffer (probably leaking)
6031                 auto data = readResult.extractSlice();
6032                 se = new StringExp(e.loc, data);
6033             }
6034         }
6035         result = se.expressionSemantic(sc);
6036     }
6037 
6038     override void visit(AssertExp exp)
6039     {
6040         // https://dlang.org/spec/expression.html#assert_expressions
6041         static if (LOGSEMANTIC)
6042         {
6043             printf("AssertExp::semantic('%s')\n", exp.toChars());
6044         }
6045 
6046         const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context;
6047         Expression temporariesPrefix;
6048 
6049         if (generateMsg)
6050         // no message - use assert expression as msg
6051         {
6052             if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
6053                 return setError();
6054 
6055             /*
6056             {
6057               auto a = e1, b = e2;
6058               assert(a == b, _d_assert_fail!"=="(a, b));
6059             }()
6060             */
6061 
6062             /*
6063             Stores the result of an operand expression into a temporary
6064             if necessary, e.g. if it is an impure fuction call containing side
6065             effects as in https://issues.dlang.org/show_bug.cgi?id=20114
6066 
6067             Params:
6068                 op = an expression which may require a temporary (added to
6069                      `temporariesPrefix`: `auto tmp = op`) and will be replaced
6070                      by `tmp` if necessary
6071 
6072             Returns: (possibly replaced) `op`
6073             */
6074             Expression maybePromoteToTmp(ref Expression op)
6075             {
6076                 // https://issues.dlang.org/show_bug.cgi?id=20989
6077                 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6078                 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6079                 {
6080                     auto die = op.isDotIdExp();
6081                     if (die && die.ident == Id.ptr)
6082                         die.noderef = true;
6083                 }
6084 
6085                 op = op.expressionSemantic(sc);
6086                 op = resolveProperties(sc, op);
6087 
6088                 // Create a temporary for expressions with side effects
6089                 // Defensively assume that function calls may have side effects even
6090                 // though it's not detected by hasSideEffect (e.g. `debug puts("Hello")` )
6091                 // Rewriting CallExp's also avoids some issues with the inliner/debug generation
6092                 if (op.hasSideEffect(true))
6093                 {
6094                     // https://issues.dlang.org/show_bug.cgi?id=21590
6095                     // Don't create unnecessary temporaries and detect `assert(a = b)`
6096                     if (op.isAssignExp() || op.isBinAssignExp())
6097                     {
6098                         auto left = (cast(BinExp) op).e1;
6099 
6100                         // Find leftmost expression to handle other rewrites,
6101                         // e.g. --(++a) => a += 1 -= 1
6102                         while (left.isAssignExp() || left.isBinAssignExp())
6103                             left = (cast(BinExp) left).e1;
6104 
6105                         // Only use the assignee if it's a variable and skip
6106                         // other lvalues (e.g. ref's returned by functions)
6107                         if (left.isVarExp())
6108                             return left;
6109 
6110                         // Sanity check that `op` can be converted to boolean
6111                         op.toBoolean(sc);
6112                     }
6113 
6114                     const stc = op.isLvalue() ? STC.ref_ : 0;
6115                     auto tmp = copyToTemp(stc, "__assertOp", op);
6116                     tmp.dsymbolSemantic(sc);
6117 
6118                     auto decl = new DeclarationExp(op.loc, tmp);
6119                     temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6120 
6121                     op = new VarExp(op.loc, tmp);
6122                     op = op.expressionSemantic(sc);
6123                 }
6124                 return op;
6125             }
6126 
6127             // if the assert condition is a mixin expression, try to compile it
6128             if (auto ce = exp.e1.isMixinExp())
6129             {
6130                 if (auto e1 = compileIt(ce))
6131                     exp.e1 = e1;
6132             }
6133 
6134             Expressions* es;
6135             Objects* tiargs;
6136             Loc loc = exp.e1.loc;
6137 
6138             const tok = exp.e1.op;
6139             bool isEqualsCallExpression;
6140             if (tok == TOK.call)
6141             {
6142                 const callExp = cast(CallExp) exp.e1;
6143 
6144                 // https://issues.dlang.org/show_bug.cgi?id=20331
6145                 // callExp.f may be null if the assert contains a call to
6146                 // a function pointer or literal
6147                 if (const callExpFunc = callExp.f)
6148                 {
6149                     const callExpIdent = callExpFunc.ident;
6150                     isEqualsCallExpression = callExpIdent == Id.__equals ||
6151                                              callExpIdent == Id.eq;
6152                 }
6153             }
6154             if (tok == TOK.equal || tok == TOK.notEqual ||
6155                 tok == TOK.lessThan || tok == TOK.greaterThan ||
6156                 tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual ||
6157                 tok == TOK.identity || tok == TOK.notIdentity ||
6158                 tok == TOK.in_ ||
6159                 isEqualsCallExpression)
6160             {
6161                 es = new Expressions(3);
6162                 tiargs = new Objects(1);
6163 
6164                 if (isEqualsCallExpression)
6165                 {
6166                     auto callExp = cast(CallExp) exp.e1;
6167                     auto args = callExp.arguments;
6168 
6169                     // structs with opEquals get rewritten to a DotVarExp:
6170                     // a.opEquals(b)
6171                     // https://issues.dlang.org/show_bug.cgi?id=20100
6172                     if (args.length == 1)
6173                     {
6174                         auto dv = callExp.e1.isDotVarExp();
6175                         assert(dv);
6176 
6177                         // runtime args
6178                         (*es)[1] = maybePromoteToTmp(dv.e1);
6179                         (*es)[2] = maybePromoteToTmp((*args)[0]);
6180                     }
6181                     else
6182                     {
6183                         // runtime args
6184                         (*es)[1] = maybePromoteToTmp((*args)[0]);
6185                         (*es)[2] = maybePromoteToTmp((*args)[1]);
6186                     }
6187                 }
6188                 else
6189                 {
6190                     auto binExp = cast(EqualExp) exp.e1;
6191 
6192                     // runtime args
6193                     (*es)[1] = maybePromoteToTmp(binExp.e1);
6194                     (*es)[2] = maybePromoteToTmp(binExp.e2);
6195                 }
6196 
6197                 // template args
6198                 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op));
6199                 comp = comp.expressionSemantic(sc);
6200                 (*es)[0] = comp;
6201                 (*tiargs)[0] = (*es)[1].type;
6202             }
6203 
6204             // Format exp.e1 before any additional boolean conversion
6205             // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
6206             else if (tok != TOK.andAnd && tok != TOK.orOr)
6207             {
6208                 es = new Expressions(2);
6209                 tiargs = new Objects(1);
6210 
6211                 if (auto ne = exp.e1.isNotExp())
6212                 {
6213                     // Fetch the (potential non-bool) expression and fold
6214                     // (n) negations into (n % 2) negations, e.g. !!a => a
6215                     for (bool neg = true; ; neg = !neg)
6216                     {
6217                         if (auto ne2 = ne.e1.isNotExp())
6218                             ne = ne2;
6219                         else
6220                         {
6221                             (*es)[0] = new StringExp(loc, neg ? "!" : "");
6222                             (*es)[1] = maybePromoteToTmp(ne.e1);
6223                             break;
6224                         }
6225                     }
6226                 }
6227                 else
6228                 {   // Simply format exp.e1
6229                     (*es)[0] = new StringExp(loc, "");
6230                     (*es)[1] = maybePromoteToTmp(exp.e1);
6231                 }
6232 
6233                 (*tiargs)[0] = (*es)[1].type;
6234 
6235                 // Passing __ctfe to auto ref infers ref and aborts compilation:
6236                 // "cannot modify compiler-generated variable __ctfe"
6237                 auto ve = (*es)[1].isVarExp();
6238                 if (ve && ve.var.ident == Id.ctfe)
6239                 {
6240                     exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6241                     goto LSkip;
6242                 }
6243             }
6244             else
6245             {
6246                 OutBuffer buf;
6247                 buf.printf("%s failed", exp.toChars());
6248                 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6249                 goto LSkip;
6250             }
6251 
6252             Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6253             auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6254 
6255             auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6256             auto ec = CallExp.create(loc, dt, es);
6257             exp.msg = ec;
6258         }
6259 
6260         LSkip:
6261         if (Expression ex = unaSemantic(exp, sc))
6262         {
6263             result = ex;
6264             return;
6265         }
6266 
6267         exp.e1 = resolveProperties(sc, exp.e1);
6268         // BUG: see if we can do compile time elimination of the Assert
6269         exp.e1 = exp.e1.optimize(WANTvalue);
6270         exp.e1 = exp.e1.toBoolean(sc);
6271 
6272         if (exp.e1.op == TOK.error)
6273         {
6274             result = exp.e1;
6275             return;
6276         }
6277 
6278         if (exp.msg)
6279         {
6280             exp.msg = expressionSemantic(exp.msg, sc);
6281             exp.msg = resolveProperties(sc, exp.msg);
6282             exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6283             exp.msg = exp.msg.optimize(WANTvalue);
6284             checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
6285         }
6286 
6287         if (exp.msg && exp.msg.op == TOK.error)
6288         {
6289             result = exp.msg;
6290             return;
6291         }
6292 
6293         auto f1 = checkNonAssignmentArrayOp(exp.e1);
6294         auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6295         if (f1 || f2)
6296             return setError();
6297 
6298         if (exp.e1.isBool(false))
6299         {
6300             /* This is an `assert(0)` which means halt program execution
6301              */
6302             FuncDeclaration fd = sc.parent.isFuncDeclaration();
6303             if (fd)
6304                 fd.hasReturnExp |= 4;
6305             sc.ctorflow.orCSX(CSX.halt);
6306 
6307             if (global.params.useAssert == CHECKENABLE.off)
6308             {
6309                 Expression e = new HaltExp(exp.loc);
6310                 e = e.expressionSemantic(sc);
6311                 result = e;
6312                 return;
6313             }
6314         }
6315 
6316         exp.type = Type.tvoid;
6317 
6318         result = !temporariesPrefix
6319             ? exp
6320             : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6321     }
6322 
6323     override void visit(DotIdExp exp)
6324     {
6325         static if (LOGSEMANTIC)
6326         {
6327             printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6328             //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
6329         }
6330         Expression e = exp.semanticY(sc, 1);
6331         if (e && isDotOpDispatch(e))
6332         {
6333             uint errors = global.startGagging();
6334             e = resolvePropertiesX(sc, e);
6335             if (global.endGagging(errors))
6336                 e = null; /* fall down to UFCS */
6337             else
6338             {
6339                 result = e;
6340                 return;
6341             }
6342         }
6343         if (!e) // if failed to find the property
6344         {
6345             /* If ident is not a valid property, rewrite:
6346              *   e1.ident
6347              * as:
6348              *   .ident(e1)
6349              */
6350             e = resolveUFCSProperties(sc, exp);
6351         }
6352         result = e;
6353     }
6354 
6355     override void visit(DotTemplateExp e)
6356     {
6357         if (Expression ex = unaSemantic(e, sc))
6358         {
6359             result = ex;
6360             return;
6361         }
6362         result = e;
6363     }
6364 
6365     override void visit(DotVarExp exp)
6366     {
6367         static if (LOGSEMANTIC)
6368         {
6369             printf("DotVarExp::semantic('%s')\n", exp.toChars());
6370         }
6371         if (exp.type)
6372         {
6373             result = exp;
6374             return;
6375         }
6376 
6377         exp.var = exp.var.toAlias().isDeclaration();
6378 
6379         exp.e1 = exp.e1.expressionSemantic(sc);
6380 
6381         if (auto tup = exp.var.isTupleDeclaration())
6382         {
6383             /* Replace:
6384              *  e1.tuple(a, b, c)
6385              * with:
6386              *  tuple(e1.a, e1.b, e1.c)
6387              */
6388             Expression e0;
6389             Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6390 
6391             auto exps = new Expressions();
6392             exps.reserve(tup.objects.dim);
6393             for (size_t i = 0; i < tup.objects.dim; i++)
6394             {
6395                 RootObject o = (*tup.objects)[i];
6396                 Expression e;
6397                 Declaration var;
6398                 if (o.dyncast() == DYNCAST.expression)
6399                 {
6400                     e = cast(Expression)o;
6401                     if (auto se = e.isDsymbolExp())
6402                         var = se.s.isDeclaration();
6403                     else if (auto ve = e.isVarExp())
6404                         if (!ve.var.isFuncDeclaration())
6405                             // Exempt functions for backwards compatibility reasons.
6406                             // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6407                             var = ve.var;
6408                 }
6409                 else if (o.dyncast() == DYNCAST.dsymbol)
6410                 {
6411                     Dsymbol s = cast(Dsymbol) o;
6412                     Declaration d = s.isDeclaration();
6413                     if (!d || d.isFuncDeclaration())
6414                         // Exempt functions for backwards compatibility reasons.
6415                         // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6416                         e = new DsymbolExp(exp.loc, s);
6417                     else
6418                         var = d;
6419                 }
6420                 else if (o.dyncast() == DYNCAST.type)
6421                 {
6422                     e = new TypeExp(exp.loc, cast(Type)o);
6423                 }
6424                 else
6425                 {
6426                     exp.error("`%s` is not an expression", o.toChars());
6427                     return setError();
6428                 }
6429                 if (var)
6430                     e = new DotVarExp(exp.loc, ev, var);
6431                 exps.push(e);
6432             }
6433 
6434             Expression e = new TupleExp(exp.loc, e0, exps);
6435             e = e.expressionSemantic(sc);
6436             result = e;
6437             return;
6438         }
6439 
6440         exp.e1 = exp.e1.addDtorHook(sc);
6441 
6442         Type t1 = exp.e1.type;
6443 
6444         if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6445         {
6446             // for functions, do checks after overload resolution
6447             if (!fd.functionSemantic())
6448                 return setError();
6449 
6450             /* https://issues.dlang.org/show_bug.cgi?id=13843
6451              * If fd obviously has no overloads, we should
6452              * normalize AST, and it will give a chance to wrap fd with FuncExp.
6453              */
6454             if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6455             {
6456                 // (e1, fd)
6457                 auto e = symbolToExp(fd, exp.loc, sc, false);
6458                 result = Expression.combine(exp.e1, e);
6459                 return;
6460             }
6461 
6462             exp.type = fd.type;
6463             assert(exp.type);
6464         }
6465         else if (OverDeclaration od = exp.var.isOverDeclaration())
6466         {
6467             exp.type = Type.tvoid; // ambiguous type?
6468         }
6469         else
6470         {
6471             exp.type = exp.var.type;
6472             if (!exp.type && global.errors) // var is goofed up, just return error.
6473                 return setError();
6474             assert(exp.type);
6475 
6476             if (t1.ty == Tpointer)
6477                 t1 = t1.nextOf();
6478 
6479             exp.type = exp.type.addMod(t1.mod);
6480 
6481             Dsymbol vparent = exp.var.toParent();
6482             AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6483             if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6484                 exp.e1 = e1x;
6485             else
6486             {
6487                 /* Later checkRightThis will report correct error for invalid field variable access.
6488                  */
6489                 Expression e = new VarExp(exp.loc, exp.var);
6490                 e = e.expressionSemantic(sc);
6491                 result = e;
6492                 return;
6493             }
6494             checkAccess(exp.loc, sc, exp.e1, exp.var);
6495 
6496             VarDeclaration v = exp.var.isVarDeclaration();
6497             if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6498             {
6499                 Expression e = expandVar(WANTvalue, v);
6500                 if (e)
6501                 {
6502                     result = e;
6503                     return;
6504                 }
6505             }
6506 
6507             if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6508                       (!v.needThis() && v.semanticRun > PASS.init)))  // fix https://issues.dlang.org/show_bug.cgi?id=17258
6509             {
6510                 // (e1, v)
6511                 checkAccess(exp.loc, sc, exp.e1, v);
6512                 Expression e = new VarExp(exp.loc, v);
6513                 e = new CommaExp(exp.loc, exp.e1, e);
6514                 e = e.expressionSemantic(sc);
6515                 result = e;
6516                 return;
6517             }
6518         }
6519         //printf("-DotVarExp::semantic('%s')\n", toChars());
6520         result = exp;
6521     }
6522 
6523     override void visit(DotTemplateInstanceExp exp)
6524     {
6525         static if (LOGSEMANTIC)
6526         {
6527             printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6528         }
6529         // Indicate we need to resolve by UFCS.
6530         Expression e = exp.semanticY(sc, 1);
6531         if (!e)
6532             e = resolveUFCSProperties(sc, exp);
6533         result = e;
6534     }
6535 
6536     override void visit(DelegateExp e)
6537     {
6538         static if (LOGSEMANTIC)
6539         {
6540             printf("DelegateExp::semantic('%s')\n", e.toChars());
6541         }
6542         if (e.type)
6543         {
6544             result = e;
6545             return;
6546         }
6547 
6548         e.e1 = e.e1.expressionSemantic(sc);
6549 
6550         e.type = new TypeDelegate(e.func.type);
6551         e.type = e.type.typeSemantic(e.loc, sc);
6552 
6553         FuncDeclaration f = e.func.toAliasFunc();
6554         AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
6555         if (f.needThis())
6556             e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6557         if (e.e1.op == TOK.error)
6558             return setError();
6559 
6560         /* A delegate takes the address of e.e1 in order to set the .ptr field
6561          * https://issues.dlang.org/show_bug.cgi?id=18575
6562          */
6563         if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct)
6564         {
6565             if (auto v = expToVariable(e.e1))
6566             {
6567                 if (!checkAddressVar(sc, e.e1, v))
6568                     return setError();
6569             }
6570         }
6571 
6572         if (f.type.ty == Tfunction)
6573         {
6574             TypeFunction tf = cast(TypeFunction)f.type;
6575             if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6576             {
6577                 OutBuffer thisBuf, funcBuf;
6578                 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6579                 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6580                 e.error("%smethod `%s` is not callable using a %s`%s`",
6581                     funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6582                 return setError();
6583             }
6584         }
6585         if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6586         {
6587             // A downcast is required for interfaces
6588             // https://issues.dlang.org/show_bug.cgi?id=3706
6589             e.e1 = new CastExp(e.loc, e.e1, ad.type);
6590             e.e1 = e.e1.expressionSemantic(sc);
6591         }
6592         result = e;
6593         // declare dual-context container
6594         if (f.isThis2 && !sc.intypeof && sc.func)
6595         {
6596             // check access to second `this`
6597             if (AggregateDeclaration ad2 = f.isMember2())
6598             {
6599                 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6600                 if (te.op != TOK.error)
6601                     te = getRightThis(e.loc, sc, ad2, te, f);
6602                 if (te.op == TOK.error)
6603                 {
6604                     e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6605                     return setError();
6606                 }
6607             }
6608             VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6609             e.vthis2 = vthis2;
6610             Expression de = new DeclarationExp(e.loc, vthis2);
6611             result = Expression.combine(de, result);
6612             result = result.expressionSemantic(sc);
6613         }
6614     }
6615 
6616     override void visit(DotTypeExp exp)
6617     {
6618         static if (LOGSEMANTIC)
6619         {
6620             printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6621         }
6622         if (exp.type)
6623         {
6624             result = exp;
6625             return;
6626         }
6627 
6628         if (auto e = unaSemantic(exp, sc))
6629         {
6630             result = e;
6631             return;
6632         }
6633 
6634         exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6635         result = exp;
6636     }
6637 
6638     override void visit(AddrExp exp)
6639     {
6640         static if (LOGSEMANTIC)
6641         {
6642             printf("AddrExp::semantic('%s')\n", exp.toChars());
6643         }
6644         if (exp.type)
6645         {
6646             result = exp;
6647             return;
6648         }
6649 
6650         if (Expression ex = unaSemantic(exp, sc))
6651         {
6652             result = ex;
6653             return;
6654         }
6655 
6656         int wasCond = exp.e1.op == TOK.question;
6657 
6658         if (exp.e1.op == TOK.dotTemplateInstance)
6659         {
6660             DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6661             TemplateInstance ti = dti.ti;
6662             {
6663                 //assert(ti.needsTypeInference(sc));
6664                 ti.dsymbolSemantic(sc);
6665                 if (!ti.inst || ti.errors) // if template failed to expand
6666                     return setError();
6667 
6668                 Dsymbol s = ti.toAlias();
6669                 FuncDeclaration f = s.isFuncDeclaration();
6670                 if (f)
6671                 {
6672                     exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6673                     exp.e1 = exp.e1.expressionSemantic(sc);
6674                 }
6675             }
6676         }
6677         else if (exp.e1.op == TOK.scope_)
6678         {
6679             TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6680             if (ti)
6681             {
6682                 //assert(ti.needsTypeInference(sc));
6683                 ti.dsymbolSemantic(sc);
6684                 if (!ti.inst || ti.errors) // if template failed to expand
6685                     return setError();
6686 
6687                 Dsymbol s = ti.toAlias();
6688                 FuncDeclaration f = s.isFuncDeclaration();
6689                 if (f)
6690                 {
6691                     exp.e1 = new VarExp(exp.e1.loc, f);
6692                     exp.e1 = exp.e1.expressionSemantic(sc);
6693                 }
6694             }
6695         }
6696         /* https://issues.dlang.org/show_bug.cgi?id=809
6697          *
6698          * If the address of a lazy variable is taken,
6699          * the expression is rewritten so that the type
6700          * of it is the delegate type. This means that
6701          * the symbol is not going to represent a call
6702          * to the delegate anymore, but rather, the
6703          * actual symbol.
6704          */
6705         if (auto ve = exp.e1.isVarExp())
6706         {
6707             if (ve.var.storage_class & STC.lazy_)
6708             {
6709                 exp.e1 = exp.e1.expressionSemantic(sc);
6710                 exp.e1 = resolveProperties(sc, exp.e1);
6711                 if (auto callExp = exp.e1.isCallExp())
6712                 {
6713                     if (callExp.e1.type.toBasetype().ty == Tdelegate)
6714                     {
6715                         /* https://issues.dlang.org/show_bug.cgi?id=20551
6716                          *
6717                          * Cannot take address of lazy parameter in @safe code
6718                          * because it might end up being a pointer to undefined
6719                          * memory.
6720                          */
6721                         if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6722                         {
6723                             exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
6724                                      ve.toChars(), sc.func.toChars());
6725                             setError();
6726                         }
6727                         else
6728                         {
6729                             VarExp ve2 = callExp.e1.isVarExp();
6730                             ve2.delegateWasExtracted = true;
6731                             ve2.var.storage_class |= STC.scope_;
6732                             result = ve2;
6733                         }
6734                         return;
6735                     }
6736                 }
6737             }
6738         }
6739 
6740         exp.e1 = exp.e1.toLvalue(sc, null);
6741         if (exp.e1.op == TOK.error)
6742         {
6743             result = exp.e1;
6744             return;
6745         }
6746         if (checkNonAssignmentArrayOp(exp.e1))
6747             return setError();
6748 
6749         if (!exp.e1.type)
6750         {
6751             exp.error("cannot take address of `%s`", exp.e1.toChars());
6752             return setError();
6753         }
6754 
6755         bool hasOverloads;
6756         if (auto f = isFuncAddress(exp, &hasOverloads))
6757         {
6758             if (!hasOverloads && f.checkForwardRef(exp.loc))
6759                 return setError();
6760         }
6761         else if (!exp.e1.type.deco)
6762         {
6763             if (exp.e1.op == TOK.variable)
6764             {
6765                 VarExp ve = cast(VarExp)exp.e1;
6766                 Declaration d = ve.var;
6767                 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
6768             }
6769             else
6770                 exp.error("forward reference to `%s`", exp.e1.toChars());
6771             return setError();
6772         }
6773 
6774         exp.type = exp.e1.type.pointerTo();
6775 
6776         // See if this should really be a delegate
6777         if (exp.e1.op == TOK.dotVariable)
6778         {
6779             DotVarExp dve = cast(DotVarExp)exp.e1;
6780             FuncDeclaration f = dve.var.isFuncDeclaration();
6781             if (f)
6782             {
6783                 f = f.toAliasFunc(); // FIXME, should see overloads
6784                                      // https://issues.dlang.org/show_bug.cgi?id=1983
6785                 if (!dve.hasOverloads)
6786                     f.tookAddressOf++;
6787 
6788                 Expression e;
6789                 if (f.needThis())
6790                     e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
6791                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
6792                     e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
6793                 e = e.expressionSemantic(sc);
6794                 result = e;
6795                 return;
6796             }
6797 
6798             // Look for misaligned pointer in @safe mode
6799             if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
6800                 return setError();
6801 
6802             if (global.params.vsafe)
6803             {
6804                 if (VarDeclaration v = expToVariable(dve.e1))
6805                 {
6806                     if (!checkAddressVar(sc, exp.e1, v))
6807                         return setError();
6808                 }
6809             }
6810         }
6811         else if (exp.e1.op == TOK.variable)
6812         {
6813             VarExp ve = cast(VarExp)exp.e1;
6814             VarDeclaration v = ve.var.isVarDeclaration();
6815             if (v)
6816             {
6817                 if (!checkAddressVar(sc, exp.e1, v))
6818                     return setError();
6819 
6820                 ve.checkPurity(sc, v);
6821             }
6822             FuncDeclaration f = ve.var.isFuncDeclaration();
6823             if (f)
6824             {
6825                 /* Because nested functions cannot be overloaded,
6826                  * mark here that we took its address because castTo()
6827                  * may not be called with an exact match.
6828                  */
6829                 if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
6830                     f.tookAddressOf++;
6831                 if (f.isNested() && !f.needThis())
6832                 {
6833                     if (f.isFuncLiteralDeclaration())
6834                     {
6835                         if (!f.FuncDeclaration.isNested())
6836                         {
6837                             /* Supply a 'null' for a this pointer if no this is available
6838                              */
6839                             Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
6840                             e = e.expressionSemantic(sc);
6841                             result = e;
6842                             return;
6843                         }
6844                     }
6845                     Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
6846                     e = e.expressionSemantic(sc);
6847                     result = e;
6848                     return;
6849                 }
6850                 if (f.needThis())
6851                 {
6852                     if (hasThis(sc))
6853                     {
6854                         /* Should probably supply 'this' after overload resolution,
6855                          * not before.
6856                          */
6857                         Expression ethis = new ThisExp(exp.loc);
6858                         Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
6859                         e = e.expressionSemantic(sc);
6860                         result = e;
6861                         return;
6862                     }
6863                     if (sc.func && !sc.intypeof)
6864                     {
6865                         if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6866                         {
6867                             exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
6868                         }
6869                     }
6870                 }
6871             }
6872         }
6873         else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe)
6874         {
6875             if (VarDeclaration v = expToVariable(exp.e1))
6876             {
6877                 if (!checkAddressVar(sc, exp.e1, v))
6878                     return setError();
6879             }
6880         }
6881         else if (exp.e1.op == TOK.call)
6882         {
6883             CallExp ce = cast(CallExp)exp.e1;
6884             if (ce.e1.type.ty == Tfunction)
6885             {
6886                 TypeFunction tf = cast(TypeFunction)ce.e1.type;
6887                 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6888                 {
6889                     exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
6890                         ce.e1.toChars(), sc.func.toChars());
6891                 }
6892             }
6893         }
6894         else if (exp.e1.op == TOK.index)
6895         {
6896             /* For:
6897              *   int[3] a;
6898              *   &a[i]
6899              * check 'a' the same as for a regular variable
6900              */
6901             if (VarDeclaration v = expToVariable(exp.e1))
6902             {
6903                 if (global.params.vsafe && !checkAddressVar(sc, exp.e1, v))
6904                     return setError();
6905 
6906                 exp.e1.checkPurity(sc, v);
6907             }
6908         }
6909         else if (wasCond)
6910         {
6911             /* a ? b : c was transformed to *(a ? &b : &c), but we still
6912              * need to do safety checks
6913              */
6914             assert(exp.e1.op == TOK.star);
6915             PtrExp pe = cast(PtrExp)exp.e1;
6916             assert(pe.e1.op == TOK.question);
6917             CondExp ce = cast(CondExp)pe.e1;
6918             assert(ce.e1.op == TOK.address);
6919             assert(ce.e2.op == TOK.address);
6920 
6921             // Re-run semantic on the address expressions only
6922             ce.e1.type = null;
6923             ce.e1 = ce.e1.expressionSemantic(sc);
6924             ce.e2.type = null;
6925             ce.e2 = ce.e2.expressionSemantic(sc);
6926         }
6927         result = exp.optimize(WANTvalue);
6928     }
6929 
6930     override void visit(PtrExp exp)
6931     {
6932         static if (LOGSEMANTIC)
6933         {
6934             printf("PtrExp::semantic('%s')\n", exp.toChars());
6935         }
6936         if (exp.type)
6937         {
6938             result = exp;
6939             return;
6940         }
6941 
6942         Expression e = exp.op_overload(sc);
6943         if (e)
6944         {
6945             result = e;
6946             return;
6947         }
6948 
6949         Type tb = exp.e1.type.toBasetype();
6950         switch (tb.ty)
6951         {
6952         case Tpointer:
6953             exp.type = (cast(TypePointer)tb).next;
6954             break;
6955 
6956         case Tsarray:
6957         case Tarray:
6958             if (isNonAssignmentArrayOp(exp.e1))
6959                 goto default;
6960             exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
6961             exp.type = (cast(TypeArray)tb).next;
6962             exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
6963             break;
6964 
6965         case Terror:
6966             return setError();
6967 
6968         case Tnull:
6969             exp.type = Type.tnoreturn;  // typeof(*null) is bottom type
6970             break;
6971 
6972         default:
6973             exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
6974             goto case Terror;
6975         }
6976 
6977         if (exp.checkValue())
6978             return setError();
6979 
6980         result = exp;
6981     }
6982 
6983     override void visit(NegExp exp)
6984     {
6985         static if (LOGSEMANTIC)
6986         {
6987             printf("NegExp::semantic('%s')\n", exp.toChars());
6988         }
6989         if (exp.type)
6990         {
6991             result = exp;
6992             return;
6993         }
6994 
6995         Expression e = exp.op_overload(sc);
6996         if (e)
6997         {
6998             result = e;
6999             return;
7000         }
7001 
7002         fix16997(sc, exp);
7003         exp.type = exp.e1.type;
7004         Type tb = exp.type.toBasetype();
7005         if (tb.ty == Tarray || tb.ty == Tsarray)
7006         {
7007             if (!isArrayOpValid(exp.e1))
7008             {
7009                 result = arrayOpInvalidError(exp);
7010                 return;
7011             }
7012             result = exp;
7013             return;
7014         }
7015         if (!target.isVectorOpSupported(tb, exp.op))
7016         {
7017             result = exp.incompatibleTypes();
7018             return;
7019         }
7020         if (exp.e1.checkNoBool())
7021             return setError();
7022         if (exp.e1.checkArithmetic() ||
7023             exp.e1.checkSharedAccess(sc))
7024             return setError();
7025 
7026         result = exp;
7027     }
7028 
7029     override void visit(UAddExp exp)
7030     {
7031         static if (LOGSEMANTIC)
7032         {
7033             printf("UAddExp::semantic('%s')\n", exp.toChars());
7034         }
7035         assert(!exp.type);
7036 
7037         Expression e = exp.op_overload(sc);
7038         if (e)
7039         {
7040             result = e;
7041             return;
7042         }
7043 
7044         fix16997(sc, exp);
7045         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
7046         {
7047             result = exp.incompatibleTypes();
7048             return;
7049         }
7050         if (exp.e1.checkNoBool())
7051             return setError();
7052         if (exp.e1.checkArithmetic())
7053             return setError();
7054         if (exp.e1.checkSharedAccess(sc))
7055             return setError();
7056 
7057         result = exp.e1;
7058     }
7059 
7060     override void visit(ComExp exp)
7061     {
7062         if (exp.type)
7063         {
7064             result = exp;
7065             return;
7066         }
7067 
7068         Expression e = exp.op_overload(sc);
7069         if (e)
7070         {
7071             result = e;
7072             return;
7073         }
7074 
7075         fix16997(sc, exp);
7076         exp.type = exp.e1.type;
7077         Type tb = exp.type.toBasetype();
7078         if (tb.ty == Tarray || tb.ty == Tsarray)
7079         {
7080             if (!isArrayOpValid(exp.e1))
7081             {
7082                 result = arrayOpInvalidError(exp);
7083                 return;
7084             }
7085             result = exp;
7086             return;
7087         }
7088         if (!target.isVectorOpSupported(tb, exp.op))
7089         {
7090             result = exp.incompatibleTypes();
7091             return;
7092         }
7093         if (exp.e1.checkNoBool())
7094             return setError();
7095         if (exp.e1.checkIntegral() ||
7096             exp.e1.checkSharedAccess(sc))
7097             return setError();
7098 
7099         result = exp;
7100     }
7101 
7102     override void visit(NotExp e)
7103     {
7104         if (e.type)
7105         {
7106             result = e;
7107             return;
7108         }
7109 
7110         e.setNoderefOperand();
7111 
7112         // Note there is no operator overload
7113         if (Expression ex = unaSemantic(e, sc))
7114         {
7115             result = ex;
7116             return;
7117         }
7118 
7119         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7120         if (e.e1.op == TOK.type)
7121             e.e1 = resolveAliasThis(sc, e.e1);
7122 
7123         e.e1 = resolveProperties(sc, e.e1);
7124         e.e1 = e.e1.toBoolean(sc);
7125         if (e.e1.type == Type.terror)
7126         {
7127             result = e.e1;
7128             return;
7129         }
7130 
7131         if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7132         {
7133             result = e.incompatibleTypes();
7134         }
7135         // https://issues.dlang.org/show_bug.cgi?id=13910
7136         // Today NotExp can take an array as its operand.
7137         if (checkNonAssignmentArrayOp(e.e1))
7138             return setError();
7139 
7140         e.type = Type.tbool;
7141         result = e;
7142     }
7143 
7144     override void visit(DeleteExp exp)
7145     {
7146         if (!sc.isDeprecated)
7147         {
7148             // @@@DEPRECATED_2019-02@@@
7149             // 1. Deprecation for 1 year
7150             // 2. Error for 1 year
7151             // 3. Removal of keyword, "delete" can be used for other identities
7152             if (!exp.isRAII)
7153                 deprecation(exp.loc, "The `delete` keyword has been deprecated.  Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
7154         }
7155 
7156         if (Expression ex = unaSemantic(exp, sc))
7157         {
7158             result = ex;
7159             return;
7160         }
7161         exp.e1 = resolveProperties(sc, exp.e1);
7162         exp.e1 = exp.e1.modifiableLvalue(sc, null);
7163         if (exp.e1.op == TOK.error)
7164         {
7165             result = exp.e1;
7166             return;
7167         }
7168         exp.type = Type.tvoid;
7169 
7170         AggregateDeclaration ad = null;
7171         Type tb = exp.e1.type.toBasetype();
7172         switch (tb.ty)
7173         {
7174         case Tclass:
7175             {
7176                 auto cd = (cast(TypeClass)tb).sym;
7177                 if (cd.isCOMinterface())
7178                 {
7179                     /* Because COM classes are deleted by IUnknown.Release()
7180                      */
7181                     exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7182                     return setError();
7183                 }
7184                 ad = cd;
7185                 break;
7186             }
7187         case Tpointer:
7188             tb = (cast(TypePointer)tb).next.toBasetype();
7189             if (tb.ty == Tstruct)
7190             {
7191                 ad = (cast(TypeStruct)tb).sym;
7192                 semanticTypeInfo(sc, tb);
7193             }
7194             break;
7195 
7196         case Tarray:
7197             {
7198                 Type tv = tb.nextOf().baseElemOf();
7199                 if (tv.ty == Tstruct)
7200                 {
7201                     ad = (cast(TypeStruct)tv).sym;
7202                     if (ad.dtor)
7203                         semanticTypeInfo(sc, ad.type);
7204                 }
7205                 break;
7206             }
7207         default:
7208             exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7209             return setError();
7210         }
7211 
7212         bool err = false;
7213         if (ad)
7214         {
7215             if (ad.dtor)
7216             {
7217                 err |= !ad.dtor.functionSemantic();
7218                 err |= exp.checkPurity(sc, ad.dtor);
7219                 err |= exp.checkSafety(sc, ad.dtor);
7220                 err |= exp.checkNogc(sc, ad.dtor);
7221             }
7222             if (err)
7223                 return setError();
7224         }
7225 
7226         if (!sc.intypeof && sc.func &&
7227             !exp.isRAII &&
7228             !(sc.flags & SCOPE.debug_) &&
7229             sc.func.setUnsafe())
7230         {
7231             exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars());
7232             err = true;
7233         }
7234         if (err)
7235             return setError();
7236 
7237         result = exp;
7238     }
7239 
7240     override void visit(CastExp exp)
7241     {
7242         static if (LOGSEMANTIC)
7243         {
7244             printf("CastExp::semantic('%s')\n", exp.toChars());
7245         }
7246         //static int x; assert(++x < 10);
7247         if (exp.type)
7248         {
7249             result = exp;
7250             return;
7251         }
7252 
7253         if (exp.to)
7254         {
7255             exp.to = exp.to.typeSemantic(exp.loc, sc);
7256             if (exp.to == Type.terror)
7257                 return setError();
7258 
7259             if (!exp.to.hasPointers())
7260                 exp.setNoderefOperand();
7261 
7262             // When e1 is a template lambda, this cast may instantiate it with
7263             // the type 'to'.
7264             exp.e1 = inferType(exp.e1, exp.to);
7265         }
7266 
7267         if (auto e = unaSemantic(exp, sc))
7268         {
7269             result = e;
7270             return;
7271         }
7272 
7273         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7274         if (exp.e1.op == TOK.type)
7275             exp.e1 = resolveAliasThis(sc, exp.e1);
7276 
7277         auto e1x = resolveProperties(sc, exp.e1);
7278         if (e1x.op == TOK.error)
7279         {
7280             result = e1x;
7281             return;
7282         }
7283         if (e1x.checkType())
7284             return setError();
7285         exp.e1 = e1x;
7286 
7287         if (!exp.e1.type)
7288         {
7289             exp.error("cannot cast `%s`", exp.e1.toChars());
7290             return setError();
7291         }
7292 
7293         // https://issues.dlang.org/show_bug.cgi?id=19954
7294         if (exp.e1.type.ty == Ttuple)
7295         {
7296             TupleExp te = exp.e1.isTupleExp();
7297             if (te.exps.dim == 1)
7298                 exp.e1 = (*te.exps)[0];
7299         }
7300 
7301         // only allow S(x) rewrite if cast specified S explicitly.
7302         // See https://issues.dlang.org/show_bug.cgi?id=18545
7303         const bool allowImplicitConstruction = exp.to !is null;
7304 
7305         if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7306         {
7307             exp.to = exp.e1.type.castMod(exp.mod);
7308             exp.to = exp.to.typeSemantic(exp.loc, sc);
7309 
7310             if (exp.to == Type.terror)
7311                 return setError();
7312         }
7313 
7314         if (exp.to.ty == Ttuple)
7315         {
7316             exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
7317             return setError();
7318         }
7319 
7320         // cast(void) is used to mark e1 as unused, so it is safe
7321         if (exp.to.ty == Tvoid)
7322         {
7323             exp.type = exp.to;
7324             result = exp;
7325             return;
7326         }
7327 
7328         if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7329         {
7330             if (Expression e = exp.op_overload(sc))
7331             {
7332                 result = e.implicitCastTo(sc, exp.to);
7333                 return;
7334             }
7335         }
7336 
7337         Type t1b = exp.e1.type.toBasetype();
7338         Type tob = exp.to.toBasetype();
7339 
7340         if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7341         {
7342             /* Look to replace:
7343              *  cast(S)t
7344              * with:
7345              *  S(t)
7346              */
7347 
7348             // Rewrite as to.call(e1)
7349             Expression e = new TypeExp(exp.loc, exp.to);
7350             e = new CallExp(exp.loc, e, exp.e1);
7351             e = e.trySemantic(sc);
7352             if (e)
7353             {
7354                 result = e;
7355                 return;
7356             }
7357         }
7358 
7359         if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7360         {
7361             if (checkNonAssignmentArrayOp(exp.e1))
7362                 return setError();
7363         }
7364 
7365         // Look for casting to a vector type
7366         if (tob.ty == Tvector && t1b.ty != Tvector)
7367         {
7368             result = new VectorExp(exp.loc, exp.e1, exp.to);
7369             result = result.expressionSemantic(sc);
7370             return;
7371         }
7372 
7373         Expression ex = exp.e1.castTo(sc, exp.to);
7374         if (ex.op == TOK.error)
7375         {
7376             result = ex;
7377             return;
7378         }
7379 
7380         // Check for unsafe casts
7381         if (!sc.intypeof &&
7382             !(sc.flags & SCOPE.debug_) &&
7383             !isSafeCast(ex, t1b, tob) &&
7384             (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe()))
7385         {
7386             exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
7387             return setError();
7388         }
7389 
7390         // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7391         // to handle certain casts.  Those casts which `object.__ArrayCast` does not support are filtered out.
7392         // See `e2ir.toElemCast` for other types of casts.  If `object.__ArrayCast` is improved to support more
7393         // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7394         if (tob.ty == Tarray)
7395         {
7396             // https://issues.dlang.org/show_bug.cgi?id=19840
7397             if (auto ad = isAggregate(t1b))
7398             {
7399                 if (ad.aliasthis)
7400                 {
7401                     Expression e = resolveAliasThis(sc, exp.e1);
7402                     e = new CastExp(exp.loc, e, exp.to);
7403                     result = e.expressionSemantic(sc);
7404                     return;
7405                 }
7406             }
7407 
7408             if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7409             {
7410                 auto tFrom = t1b.nextOf();
7411                 auto tTo = tob.nextOf();
7412 
7413                 // https://issues.dlang.org/show_bug.cgi?id=20130
7414                 if (exp.e1.op != TOK.string_ || !ex.isStringExp)
7415                 {
7416                     const uint fromSize = cast(uint)tFrom.size();
7417                     const uint toSize = cast(uint)tTo.size();
7418 
7419                     // If array element sizes do not match, we must adjust the dimensions
7420                     if (fromSize != toSize)
7421                     {
7422                         if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7423                             return setError();
7424 
7425                         // A runtime check is needed in case arrays don't line up.  That check should
7426                         // be done in the implementation of `object.__ArrayCast`
7427                         if (toSize == 0 || (fromSize % toSize) != 0)
7428                         {
7429                             // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7430 
7431                             // fully qualify as `object.__ArrayCast`
7432                             Expression id = new IdentifierExp(exp.loc, Id.empty);
7433                             auto dotid = new DotIdExp(exp.loc, id, Id.object);
7434 
7435                             auto tiargs = new Objects();
7436                             tiargs.push(tFrom);
7437                             tiargs.push(tTo);
7438                             auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7439 
7440                             auto arguments = new Expressions();
7441                             arguments.push(exp.e1);
7442                             Expression ce = new CallExp(exp.loc, dt, arguments);
7443 
7444                             result = expressionSemantic(ce, sc);
7445                             return;
7446                         }
7447                     }
7448                 }
7449             }
7450         }
7451 
7452         result = ex;
7453     }
7454 
7455     override void visit(VectorExp exp)
7456     {
7457         static if (LOGSEMANTIC)
7458         {
7459             printf("VectorExp::semantic('%s')\n", exp.toChars());
7460         }
7461         if (exp.type)
7462         {
7463             result = exp;
7464             return;
7465         }
7466 
7467         exp.e1 = exp.e1.expressionSemantic(sc);
7468         exp.type = exp.to.typeSemantic(exp.loc, sc);
7469         if (exp.e1.op == TOK.error || exp.type.ty == Terror)
7470         {
7471             result = exp.e1;
7472             return;
7473         }
7474 
7475         Type tb = exp.type.toBasetype();
7476         assert(tb.ty == Tvector);
7477         TypeVector tv = cast(TypeVector)tb;
7478         Type te = tv.elementType();
7479         exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7480 
7481         bool checkElem(Expression elem)
7482         {
7483             if (elem.isConst() == 1)
7484                 return false;
7485 
7486              exp.error("constant expression expected, not `%s`", elem.toChars());
7487              return true;
7488         }
7489 
7490         exp.e1 = exp.e1.optimize(WANTvalue);
7491         bool res;
7492         if (exp.e1.op == TOK.arrayLiteral)
7493         {
7494             foreach (i; 0 .. exp.dim)
7495             {
7496                 // Do not stop on first error - check all AST nodes even if error found
7497                 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7498             }
7499         }
7500         else if (exp.e1.type.ty == Tvoid)
7501             checkElem(exp.e1);
7502 
7503         result = res ? ErrorExp.get() : exp;
7504     }
7505 
7506     override void visit(VectorArrayExp e)
7507     {
7508         static if (LOGSEMANTIC)
7509         {
7510             printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7511         }
7512         if (!e.type)
7513         {
7514             unaSemantic(e, sc);
7515             e.e1 = resolveProperties(sc, e.e1);
7516 
7517             if (e.e1.op == TOK.error)
7518             {
7519                 result = e.e1;
7520                 return;
7521             }
7522             assert(e.e1.type.ty == Tvector);
7523             e.type = e.e1.type.isTypeVector().basetype;
7524         }
7525         result = e;
7526     }
7527 
7528     override void visit(SliceExp exp)
7529     {
7530         static if (LOGSEMANTIC)
7531         {
7532             printf("SliceExp::semantic('%s')\n", exp.toChars());
7533         }
7534         if (exp.type)
7535         {
7536             result = exp;
7537             return;
7538         }
7539 
7540         // operator overloading should be handled in ArrayExp already.
7541         if (Expression ex = unaSemantic(exp, sc))
7542         {
7543             result = ex;
7544             return;
7545         }
7546         exp.e1 = resolveProperties(sc, exp.e1);
7547         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7548         {
7549             if (exp.lwr || exp.upr)
7550             {
7551                 exp.error("cannot slice type `%s`", exp.e1.toChars());
7552                 return setError();
7553             }
7554             Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7555             result = e.expressionSemantic(sc);
7556             return;
7557         }
7558         if (!exp.lwr && !exp.upr)
7559         {
7560             if (exp.e1.op == TOK.arrayLiteral)
7561             {
7562                 // Convert [a,b,c][] to [a,b,c]
7563                 Type t1b = exp.e1.type.toBasetype();
7564                 Expression e = exp.e1;
7565                 if (t1b.ty == Tsarray)
7566                 {
7567                     e = e.copy();
7568                     e.type = t1b.nextOf().arrayOf();
7569                 }
7570                 result = e;
7571                 return;
7572             }
7573             if (exp.e1.op == TOK.slice)
7574             {
7575                 // Convert e[][] to e[]
7576                 SliceExp se = cast(SliceExp)exp.e1;
7577                 if (!se.lwr && !se.upr)
7578                 {
7579                     result = se;
7580                     return;
7581                 }
7582             }
7583             if (isArrayOpOperand(exp.e1))
7584             {
7585                 // Convert (a[]+b[])[] to a[]+b[]
7586                 result = exp.e1;
7587                 return;
7588             }
7589         }
7590         if (exp.e1.op == TOK.error)
7591         {
7592             result = exp.e1;
7593             return;
7594         }
7595         if (exp.e1.type.ty == Terror)
7596             return setError();
7597 
7598         Type t1b = exp.e1.type.toBasetype();
7599         if (t1b.ty == Tpointer)
7600         {
7601             if ((cast(TypePointer)t1b).next.ty == Tfunction)
7602             {
7603                 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7604                 return setError();
7605             }
7606             if (!exp.lwr || !exp.upr)
7607             {
7608                 exp.error("need upper and lower bound to slice pointer");
7609                 return setError();
7610             }
7611             if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7612             {
7613                 exp.error("pointer slicing not allowed in safe functions");
7614                 return setError();
7615             }
7616         }
7617         else if (t1b.ty == Tarray)
7618         {
7619         }
7620         else if (t1b.ty == Tsarray)
7621         {
7622             if (!exp.arrayop && global.params.vsafe)
7623             {
7624                 /* Slicing a static array is like taking the address of it.
7625                  * Perform checks as if e[] was &e
7626                  */
7627                 if (VarDeclaration v = expToVariable(exp.e1))
7628                 {
7629                     if (exp.e1.op == TOK.dotVariable)
7630                     {
7631                         DotVarExp dve = cast(DotVarExp)exp.e1;
7632                         if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) &&
7633                             !(v.storage_class & STC.ref_))
7634                         {
7635                             // because it's a class
7636                             v = null;
7637                         }
7638                     }
7639 
7640                     if (v && !checkAddressVar(sc, exp.e1, v))
7641                         return setError();
7642                 }
7643             }
7644         }
7645         else if (t1b.ty == Ttuple)
7646         {
7647             if (!exp.lwr && !exp.upr)
7648             {
7649                 result = exp.e1;
7650                 return;
7651             }
7652             if (!exp.lwr || !exp.upr)
7653             {
7654                 exp.error("need upper and lower bound to slice tuple");
7655                 return setError();
7656             }
7657         }
7658         else if (t1b.ty == Tvector)
7659         {
7660             // Convert e1 to corresponding static array
7661             TypeVector tv1 = cast(TypeVector)t1b;
7662             t1b = tv1.basetype;
7663             t1b = t1b.castMod(tv1.mod);
7664             exp.e1.type = t1b;
7665         }
7666         else
7667         {
7668             exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7669             return setError();
7670         }
7671 
7672         /* Run semantic on lwr and upr.
7673          */
7674         Scope* scx = sc;
7675         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7676         {
7677             // Create scope for 'length' variable
7678             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7679             sym.parent = sc.scopesym;
7680             sc = sc.push(sym);
7681         }
7682         if (exp.lwr)
7683         {
7684             if (t1b.ty == Ttuple)
7685                 sc = sc.startCTFE();
7686             exp.lwr = exp.lwr.expressionSemantic(sc);
7687             exp.lwr = resolveProperties(sc, exp.lwr);
7688             if (t1b.ty == Ttuple)
7689                 sc = sc.endCTFE();
7690             exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7691         }
7692         if (exp.upr)
7693         {
7694             if (t1b.ty == Ttuple)
7695                 sc = sc.startCTFE();
7696             exp.upr = exp.upr.expressionSemantic(sc);
7697             exp.upr = resolveProperties(sc, exp.upr);
7698             if (t1b.ty == Ttuple)
7699                 sc = sc.endCTFE();
7700             exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7701         }
7702         if (sc != scx)
7703             sc = sc.pop();
7704         if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7705             return setError();
7706 
7707         if (t1b.ty == Ttuple)
7708         {
7709             exp.lwr = exp.lwr.ctfeInterpret();
7710             exp.upr = exp.upr.ctfeInterpret();
7711             uinteger_t i1 = exp.lwr.toUInteger();
7712             uinteger_t i2 = exp.upr.toUInteger();
7713 
7714             TupleExp te;
7715             TypeTuple tup;
7716             size_t length;
7717             if (exp.e1.op == TOK.tuple) // slicing an expression tuple
7718             {
7719                 te = cast(TupleExp)exp.e1;
7720                 tup = null;
7721                 length = te.exps.dim;
7722             }
7723             else if (exp.e1.op == TOK.type) // slicing a type tuple
7724             {
7725                 te = null;
7726                 tup = cast(TypeTuple)t1b;
7727                 length = Parameter.dim(tup.arguments);
7728             }
7729             else
7730                 assert(0);
7731 
7732             if (i2 < i1 || length < i2)
7733             {
7734                 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7735                 return setError();
7736             }
7737 
7738             size_t j1 = cast(size_t)i1;
7739             size_t j2 = cast(size_t)i2;
7740             Expression e;
7741             if (exp.e1.op == TOK.tuple)
7742             {
7743                 auto exps = new Expressions(j2 - j1);
7744                 for (size_t i = 0; i < j2 - j1; i++)
7745                 {
7746                     (*exps)[i] = (*te.exps)[j1 + i];
7747                 }
7748                 e = new TupleExp(exp.loc, te.e0, exps);
7749             }
7750             else
7751             {
7752                 auto args = new Parameters();
7753                 args.reserve(j2 - j1);
7754                 for (size_t i = j1; i < j2; i++)
7755                 {
7756                     Parameter arg = Parameter.getNth(tup.arguments, i);
7757                     args.push(arg);
7758                 }
7759                 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
7760             }
7761             e = e.expressionSemantic(sc);
7762             result = e;
7763             return;
7764         }
7765 
7766         exp.type = t1b.nextOf().arrayOf();
7767         // Allow typedef[] -> typedef[]
7768         if (exp.type.equals(t1b))
7769             exp.type = exp.e1.type;
7770 
7771         // We might know $ now
7772         setLengthVarIfKnown(exp.lengthVar, t1b);
7773 
7774         if (exp.lwr && exp.upr)
7775         {
7776             exp.lwr = exp.lwr.optimize(WANTvalue);
7777             exp.upr = exp.upr.optimize(WANTvalue);
7778 
7779             IntRange lwrRange = getIntRange(exp.lwr);
7780             IntRange uprRange = getIntRange(exp.upr);
7781 
7782             if (t1b.ty == Tsarray || t1b.ty == Tarray)
7783             {
7784                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
7785                 el = el.expressionSemantic(sc);
7786                 el = el.optimize(WANTvalue);
7787                 if (el.op == TOK.int64)
7788                 {
7789                     // Array length is known at compile-time. Upper is in bounds if it fits length.
7790                     dinteger_t length = el.toInteger();
7791                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
7792                     exp.upperIsInBounds = bounds.contains(uprRange);
7793                 }
7794                 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
7795                 {
7796                     // Upper slice expression is '0'. Value is always in bounds.
7797                     exp.upperIsInBounds = true;
7798                 }
7799                 else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
7800                 {
7801                     // Upper slice expression is '$'. Value is always in bounds.
7802                     exp.upperIsInBounds = true;
7803                 }
7804             }
7805             else if (t1b.ty == Tpointer)
7806             {
7807                 exp.upperIsInBounds = true;
7808             }
7809             else
7810                 assert(0);
7811 
7812             exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
7813 
7814             //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
7815         }
7816 
7817         result = exp;
7818     }
7819 
7820     override void visit(ArrayLengthExp e)
7821     {
7822         static if (LOGSEMANTIC)
7823         {
7824             printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
7825         }
7826         if (e.type)
7827         {
7828             result = e;
7829             return;
7830         }
7831 
7832         if (Expression ex = unaSemantic(e, sc))
7833         {
7834             result = ex;
7835             return;
7836         }
7837         e.e1 = resolveProperties(sc, e.e1);
7838 
7839         e.type = Type.tsize_t;
7840         result = e;
7841     }
7842 
7843     override void visit(ArrayExp exp)
7844     {
7845         static if (LOGSEMANTIC)
7846         {
7847             printf("ArrayExp::semantic('%s')\n", exp.toChars());
7848         }
7849         assert(!exp.type);
7850         Expression e = exp.op_overload(sc);
7851         if (e)
7852         {
7853             result = e;
7854             return;
7855         }
7856 
7857         if (isAggregate(exp.e1.type))
7858             exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
7859         else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7860             exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
7861         else if (isIndexableNonAggregate(exp.e1.type))
7862             exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
7863         else
7864             exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
7865 
7866         result = ErrorExp.get();
7867     }
7868 
7869     override void visit(DotExp exp)
7870     {
7871         static if (LOGSEMANTIC)
7872         {
7873             printf("DotExp::semantic('%s')\n", exp.toChars());
7874             if (exp.type)
7875                 printf("\ttype = %s\n", exp.type.toChars());
7876         }
7877         exp.e1 = exp.e1.expressionSemantic(sc);
7878         exp.e2 = exp.e2.expressionSemantic(sc);
7879 
7880         if (exp.e1.op == TOK.type)
7881         {
7882             result = exp.e2;
7883             return;
7884         }
7885         if (exp.e2.op == TOK.type)
7886         {
7887             result = exp.e2;
7888             return;
7889         }
7890         if (exp.e2.op == TOK.template_)
7891         {
7892             auto td = (cast(TemplateExp)exp.e2).td;
7893             Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
7894             result = e.expressionSemantic(sc);
7895             return;
7896         }
7897         if (!exp.type || exp.e1.op == TOK.this_)
7898             exp.type = exp.e2.type;
7899         result = exp;
7900     }
7901 
7902     override void visit(CommaExp e)
7903     {
7904         if (e.type)
7905         {
7906             result = e;
7907             return;
7908         }
7909 
7910         // Allow `((a,b),(x,y))`
7911         if (e.allowCommaExp)
7912         {
7913             CommaExp.allow(e.e1);
7914             CommaExp.allow(e.e2);
7915         }
7916 
7917         if (Expression ex = binSemanticProp(e, sc))
7918         {
7919             result = ex;
7920             return;
7921         }
7922         e.e1 = e.e1.addDtorHook(sc);
7923 
7924         if (checkNonAssignmentArrayOp(e.e1))
7925             return setError();
7926 
7927         e.type = e.e2.type;
7928         if (e.type is Type.tvoid)
7929             discardValue(e.e1);
7930         else if (!e.allowCommaExp && !e.isGenerated)
7931             e.error("Using the result of a comma expression is not allowed");
7932         result = e;
7933     }
7934 
7935     override void visit(IntervalExp e)
7936     {
7937         static if (LOGSEMANTIC)
7938         {
7939             printf("IntervalExp::semantic('%s')\n", e.toChars());
7940         }
7941         if (e.type)
7942         {
7943             result = e;
7944             return;
7945         }
7946 
7947         Expression le = e.lwr;
7948         le = le.expressionSemantic(sc);
7949         le = resolveProperties(sc, le);
7950 
7951         Expression ue = e.upr;
7952         ue = ue.expressionSemantic(sc);
7953         ue = resolveProperties(sc, ue);
7954 
7955         if (le.op == TOK.error)
7956         {
7957             result = le;
7958             return;
7959         }
7960         if (ue.op == TOK.error)
7961         {
7962             result = ue;
7963             return;
7964         }
7965 
7966         e.lwr = le;
7967         e.upr = ue;
7968 
7969         e.type = Type.tvoid;
7970         result = e;
7971     }
7972 
7973     override void visit(DelegatePtrExp e)
7974     {
7975         static if (LOGSEMANTIC)
7976         {
7977             printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
7978         }
7979         if (!e.type)
7980         {
7981             unaSemantic(e, sc);
7982             e.e1 = resolveProperties(sc, e.e1);
7983 
7984             if (e.e1.op == TOK.error)
7985             {
7986                 result = e.e1;
7987                 return;
7988             }
7989             e.type = Type.tvoidptr;
7990         }
7991         result = e;
7992     }
7993 
7994     override void visit(DelegateFuncptrExp e)
7995     {
7996         static if (LOGSEMANTIC)
7997         {
7998             printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
7999         }
8000         if (!e.type)
8001         {
8002             unaSemantic(e, sc);
8003             e.e1 = resolveProperties(sc, e.e1);
8004             if (e.e1.op == TOK.error)
8005             {
8006                 result = e.e1;
8007                 return;
8008             }
8009             e.type = e.e1.type.nextOf().pointerTo();
8010         }
8011         result = e;
8012     }
8013 
8014     override void visit(IndexExp exp)
8015     {
8016         static if (LOGSEMANTIC)
8017         {
8018             printf("IndexExp::semantic('%s')\n", exp.toChars());
8019         }
8020         if (exp.type)
8021         {
8022             result = exp;
8023             return;
8024         }
8025 
8026         // operator overloading should be handled in ArrayExp already.
8027         if (!exp.e1.type)
8028             exp.e1 = exp.e1.expressionSemantic(sc);
8029         assert(exp.e1.type); // semantic() should already be run on it
8030         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
8031         {
8032             exp.e2 = exp.e2.expressionSemantic(sc);
8033             exp.e2 = resolveProperties(sc, exp.e2);
8034             Type nt;
8035             if (exp.e2.op == TOK.type)
8036                 nt = new TypeAArray(exp.e1.type, exp.e2.type);
8037             else
8038                 nt = new TypeSArray(exp.e1.type, exp.e2);
8039             Expression e = new TypeExp(exp.loc, nt);
8040             result = e.expressionSemantic(sc);
8041             return;
8042         }
8043         if (exp.e1.op == TOK.error)
8044         {
8045             result = exp.e1;
8046             return;
8047         }
8048         if (exp.e1.type.ty == Terror)
8049             return setError();
8050 
8051         // Note that unlike C we do not implement the int[ptr]
8052 
8053         Type t1b = exp.e1.type.toBasetype();
8054 
8055         if (t1b.ty == Tvector)
8056         {
8057             // Convert e1 to corresponding static array
8058             TypeVector tv1 = cast(TypeVector)t1b;
8059             t1b = tv1.basetype;
8060             t1b = t1b.castMod(tv1.mod);
8061             exp.e1.type = t1b;
8062         }
8063 
8064         /* Run semantic on e2
8065          */
8066         Scope* scx = sc;
8067         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
8068         {
8069             // Create scope for 'length' variable
8070             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
8071             sym.parent = sc.scopesym;
8072             sc = sc.push(sym);
8073         }
8074         if (t1b.ty == Ttuple)
8075             sc = sc.startCTFE();
8076         exp.e2 = exp.e2.expressionSemantic(sc);
8077         exp.e2 = resolveProperties(sc, exp.e2);
8078         if (t1b.ty == Ttuple)
8079             sc = sc.endCTFE();
8080         if (exp.e2.op == TOK.tuple)
8081         {
8082             TupleExp te = cast(TupleExp)exp.e2;
8083             if (te.exps && te.exps.dim == 1)
8084                 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
8085         }
8086         if (sc != scx)
8087             sc = sc.pop();
8088         if (exp.e2.type == Type.terror)
8089             return setError();
8090 
8091         if (checkNonAssignmentArrayOp(exp.e1))
8092             return setError();
8093 
8094         switch (t1b.ty)
8095         {
8096         case Tpointer:
8097             if ((cast(TypePointer)t1b).next.ty == Tfunction)
8098             {
8099                 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
8100                 return setError();
8101             }
8102             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8103             if (exp.e2.type == Type.terror)
8104                 return setError();
8105             exp.e2 = exp.e2.optimize(WANTvalue);
8106             if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0)
8107             {
8108             }
8109             else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
8110             {
8111                 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
8112                 return setError();
8113             }
8114             exp.type = (cast(TypeNext)t1b).next;
8115             break;
8116 
8117         case Tarray:
8118             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8119             if (exp.e2.type == Type.terror)
8120                 return setError();
8121             exp.type = (cast(TypeNext)t1b).next;
8122             break;
8123 
8124         case Tsarray:
8125             {
8126                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8127                 if (exp.e2.type == Type.terror)
8128                     return setError();
8129                 exp.type = t1b.nextOf();
8130                 break;
8131             }
8132         case Taarray:
8133             {
8134                 TypeAArray taa = cast(TypeAArray)t1b;
8135                 /* We can skip the implicit conversion if they differ only by
8136                  * constness
8137                  * https://issues.dlang.org/show_bug.cgi?id=2684
8138                  * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8139                  */
8140                 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8141                 {
8142                     exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8143                     if (exp.e2.type == Type.terror)
8144                         return setError();
8145                 }
8146 
8147                 semanticTypeInfo(sc, taa);
8148 
8149                 exp.type = taa.next;
8150                 break;
8151             }
8152         case Ttuple:
8153             {
8154                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8155                 if (exp.e2.type == Type.terror)
8156                     return setError();
8157 
8158                 exp.e2 = exp.e2.ctfeInterpret();
8159                 uinteger_t index = exp.e2.toUInteger();
8160 
8161                 TupleExp te;
8162                 TypeTuple tup;
8163                 size_t length;
8164                 if (exp.e1.op == TOK.tuple)
8165                 {
8166                     te = cast(TupleExp)exp.e1;
8167                     tup = null;
8168                     length = te.exps.dim;
8169                 }
8170                 else if (exp.e1.op == TOK.type)
8171                 {
8172                     te = null;
8173                     tup = cast(TypeTuple)t1b;
8174                     length = Parameter.dim(tup.arguments);
8175                 }
8176                 else
8177                     assert(0);
8178 
8179                 if (length <= index)
8180                 {
8181                     exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8182                     return setError();
8183                 }
8184                 Expression e;
8185                 if (exp.e1.op == TOK.tuple)
8186                 {
8187                     e = (*te.exps)[cast(size_t)index];
8188                     e = Expression.combine(te.e0, e);
8189                 }
8190                 else
8191                     e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8192                 result = e;
8193                 return;
8194             }
8195         default:
8196             exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8197             return setError();
8198         }
8199 
8200         // We might know $ now
8201         setLengthVarIfKnown(exp.lengthVar, t1b);
8202 
8203         if (t1b.ty == Tsarray || t1b.ty == Tarray)
8204         {
8205             Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8206             el = el.expressionSemantic(sc);
8207             el = el.optimize(WANTvalue);
8208             if (el.op == TOK.int64)
8209             {
8210                 exp.e2 = exp.e2.optimize(WANTvalue);
8211                 dinteger_t length = el.toInteger();
8212                 if (length)
8213                 {
8214                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8215                     exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2));
8216                 }
8217             }
8218         }
8219 
8220         result = exp;
8221     }
8222 
8223     override void visit(PostExp exp)
8224     {
8225         static if (LOGSEMANTIC)
8226         {
8227             printf("PostExp::semantic('%s')\n", exp.toChars());
8228         }
8229         if (exp.type)
8230         {
8231             result = exp;
8232             return;
8233         }
8234 
8235         if (Expression ex = binSemantic(exp, sc))
8236         {
8237             result = ex;
8238             return;
8239         }
8240         Expression e1x = resolveProperties(sc, exp.e1);
8241         if (e1x.op == TOK.error)
8242         {
8243             result = e1x;
8244             return;
8245         }
8246         exp.e1 = e1x;
8247 
8248         Expression e = exp.op_overload(sc);
8249         if (e)
8250         {
8251             result = e;
8252             return;
8253         }
8254 
8255         if (exp.e1.checkReadModifyWrite(exp.op))
8256             return setError();
8257 
8258         if (exp.e1.op == TOK.slice)
8259         {
8260             const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement";
8261             exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8262             return setError();
8263         }
8264 
8265         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
8266 
8267         Type t1 = exp.e1.type.toBasetype();
8268         if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength)
8269         {
8270             /* Check for operator overloading,
8271              * but rewrite in terms of ++e instead of e++
8272              */
8273 
8274             /* If e1 is not trivial, take a reference to it
8275              */
8276             Expression de = null;
8277             if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength)
8278             {
8279                 // ref v = e1;
8280                 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8281                 de = new DeclarationExp(exp.loc, v);
8282                 exp.e1 = new VarExp(exp.e1.loc, v);
8283             }
8284 
8285             /* Rewrite as:
8286              * auto tmp = e1; ++e1; tmp
8287              */
8288             auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8289             Expression ea = new DeclarationExp(exp.loc, tmp);
8290 
8291             Expression eb = exp.e1.syntaxCopy();
8292             eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb);
8293 
8294             Expression ec = new VarExp(exp.loc, tmp);
8295 
8296             // Combine de,ea,eb,ec
8297             if (de)
8298                 ea = new CommaExp(exp.loc, de, ea);
8299             e = new CommaExp(exp.loc, ea, eb);
8300             e = new CommaExp(exp.loc, e, ec);
8301             e = e.expressionSemantic(sc);
8302             result = e;
8303             return;
8304         }
8305 
8306         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8307 
8308         e = exp;
8309         if (exp.e1.checkScalar() ||
8310             exp.e1.checkSharedAccess(sc))
8311             return setError();
8312         if (exp.e1.checkNoBool())
8313             return setError();
8314 
8315         if (exp.e1.type.ty == Tpointer)
8316             e = scaleFactor(exp, sc);
8317         else
8318             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8319         e.type = exp.e1.type;
8320         result = e;
8321     }
8322 
8323     override void visit(PreExp exp)
8324     {
8325         Expression e = exp.op_overload(sc);
8326         // printf("PreExp::semantic('%s')\n", toChars());
8327         if (e)
8328         {
8329             result = e;
8330             return;
8331         }
8332 
8333         // Rewrite as e1+=1 or e1-=1
8334         if (exp.op == TOK.prePlusPlus)
8335             e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8336         else
8337             e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8338         result = e.expressionSemantic(sc);
8339     }
8340 
8341     /*
8342      * Get the expression initializer for a specific struct
8343      *
8344      * Params:
8345      *  sd = the struct for which the expression initializer is needed
8346      *  loc = the location of the initializer
8347      *  sc = the scope where the expression is located
8348      *  t = the type of the expression
8349      *
8350      * Returns:
8351      *  The expression initializer or error expression if any errors occured
8352      */
8353     private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8354     {
8355         if (sd.zeroInit && !sd.isNested())
8356         {
8357             // https://issues.dlang.org/show_bug.cgi?id=14606
8358             // Always use BlitExp for the special expression: (struct = 0)
8359             return IntegerExp.literal!0;
8360         }
8361 
8362         if (sd.isNested())
8363         {
8364             auto sle = new StructLiteralExp(loc, sd, null, t);
8365             if (!sd.fill(loc, sle.elements, true))
8366                 return ErrorExp.get();
8367             if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
8368                 return ErrorExp.get();
8369 
8370             sle.type = t;
8371             return sle;
8372         }
8373 
8374         return t.defaultInit(loc);
8375     }
8376 
8377     override void visit(AssignExp exp)
8378     {
8379         static if (LOGSEMANTIC)
8380         {
8381             printf("AssignExp::semantic('%s')\n", exp.toChars());
8382         }
8383         //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op));
8384         //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op));
8385 
8386         void setResult(Expression e, int line = __LINE__)
8387         {
8388             //printf("line %d\n", line);
8389             result = e;
8390         }
8391 
8392         if (exp.type)
8393         {
8394             return setResult(exp);
8395         }
8396 
8397         Expression e1old = exp.e1;
8398 
8399         if (auto e2comma = exp.e2.isCommaExp())
8400         {
8401             if (!e2comma.isGenerated)
8402                 exp.error("Using the result of a comma expression is not allowed");
8403 
8404             /* Rewrite to get rid of the comma from rvalue
8405              *   e1=(e0,e2) => e0,(e1=e2)
8406              */
8407             Expression e0;
8408             exp.e2 = Expression.extractLast(e2comma, e0);
8409             Expression e = Expression.combine(e0, exp);
8410             return setResult(e.expressionSemantic(sc));
8411         }
8412 
8413         /* Look for operator overloading of a[arguments] = e2.
8414          * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8415          * converted to unary operator overloading already.
8416          */
8417         if (auto ae = exp.e1.isArrayExp())
8418         {
8419             Expression res;
8420 
8421             ae.e1 = ae.e1.expressionSemantic(sc);
8422             ae.e1 = resolveProperties(sc, ae.e1);
8423             Expression ae1old = ae.e1;
8424 
8425             const(bool) maybeSlice =
8426                 (ae.arguments.dim == 0 ||
8427                  ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval);
8428 
8429             IntervalExp ie = null;
8430             if (maybeSlice && ae.arguments.dim)
8431             {
8432                 assert((*ae.arguments)[0].op == TOK.interval);
8433                 ie = cast(IntervalExp)(*ae.arguments)[0];
8434             }
8435             while (true)
8436             {
8437                 if (ae.e1.op == TOK.error)
8438                     return setResult(ae.e1);
8439 
8440                 Expression e0 = null;
8441                 Expression ae1save = ae.e1;
8442                 ae.lengthVar = null;
8443 
8444                 Type t1b = ae.e1.type.toBasetype();
8445                 AggregateDeclaration ad = isAggregate(t1b);
8446                 if (!ad)
8447                     break;
8448                 if (search_function(ad, Id.indexass))
8449                 {
8450                     // Deal with $
8451                     res = resolveOpDollar(sc, ae, &e0);
8452                     if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8453                         goto Lfallback;
8454                     if (res.op == TOK.error)
8455                         return setResult(res);
8456 
8457                     res = exp.e2.expressionSemantic(sc);
8458                     if (res.op == TOK.error)
8459                         return setResult(res);
8460                     exp.e2 = res;
8461 
8462                     /* Rewrite (a[arguments] = e2) as:
8463                      *      a.opIndexAssign(e2, arguments)
8464                      */
8465                     Expressions* a = ae.arguments.copy();
8466                     a.insert(0, exp.e2);
8467                     res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8468                     res = new CallExp(exp.loc, res, a);
8469                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8470                         res = res.trySemantic(sc);
8471                     else
8472                         res = res.expressionSemantic(sc);
8473                     if (res)
8474                         return setResult(Expression.combine(e0, res));
8475                 }
8476 
8477             Lfallback:
8478                 if (maybeSlice && search_function(ad, Id.sliceass))
8479                 {
8480                     // Deal with $
8481                     res = resolveOpDollar(sc, ae, ie, &e0);
8482                     if (res.op == TOK.error)
8483                         return setResult(res);
8484 
8485                     res = exp.e2.expressionSemantic(sc);
8486                     if (res.op == TOK.error)
8487                         return setResult(res);
8488 
8489                     exp.e2 = res;
8490 
8491                     /* Rewrite (a[i..j] = e2) as:
8492                      *      a.opSliceAssign(e2, i, j)
8493                      */
8494                     auto a = new Expressions();
8495                     a.push(exp.e2);
8496                     if (ie)
8497                     {
8498                         a.push(ie.lwr);
8499                         a.push(ie.upr);
8500                     }
8501                     res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8502                     res = new CallExp(exp.loc, res, a);
8503                     res = res.expressionSemantic(sc);
8504                     return setResult(Expression.combine(e0, res));
8505                 }
8506 
8507                 // No operator overloading member function found yet, but
8508                 // there might be an alias this to try.
8509                 if (ad.aliasthis && !(ae.att1 && t1b.equivalent(ae.att1)))
8510                 {
8511                     if (!ae.att1 && t1b.checkAliasThisRec())
8512                         ae.att1 = t1b;
8513 
8514                     /* Rewrite (a[arguments] op e2) as:
8515                      *      a.aliasthis[arguments] op e2
8516                      */
8517                     ae.e1 = resolveAliasThis(sc, ae1save, true);
8518                     if (ae.e1)
8519                         continue;
8520                 }
8521                 break;
8522             }
8523             ae.e1 = ae1old; // recovery
8524             ae.lengthVar = null;
8525         }
8526 
8527         /* Run this.e1 semantic.
8528          */
8529         {
8530             Expression e1x = exp.e1;
8531 
8532             /* With UFCS, e.f = value
8533              * Could mean:
8534              *      .f(e, value)
8535              * or:
8536              *      .f(e) = value
8537              */
8538             if (auto dti = e1x.isDotTemplateInstanceExp())
8539             {
8540                 Expression e = dti.semanticY(sc, 1);
8541                 if (!e)
8542                 {
8543                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8544                 }
8545 
8546                 e1x = e;
8547             }
8548             else if (auto die = e1x.isDotIdExp())
8549             {
8550                 Expression e = die.semanticY(sc, 1);
8551                 if (e && isDotOpDispatch(e))
8552                 {
8553                     /* https://issues.dlang.org/show_bug.cgi?id=19687
8554                      *
8555                      * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8556                      * but that call is done with gagged errors. That is the only time when
8557                      * semantic gets ran on e2, that is why the error never gets to be printed.
8558                      * In order to make sure that UFCS is tried with correct parameters, e2
8559                      * needs to have semantic ran on it.
8560                      */
8561                     exp.e2 = exp.e2.expressionSemantic(sc);
8562                     uint errors = global.startGagging();
8563                     e = resolvePropertiesX(sc, e, exp.e2);
8564                     if (global.endGagging(errors))
8565                         e = null; /* fall down to UFCS */
8566                     else
8567                         return setResult(e);
8568                 }
8569                 if (!e)
8570                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8571                 e1x = e;
8572             }
8573             else
8574             {
8575                 if (auto se = e1x.isSliceExp())
8576                     se.arrayop = true;
8577 
8578                 e1x = e1x.expressionSemantic(sc);
8579             }
8580 
8581             /* We have f = value.
8582              * Could mean:
8583              *      f(value)
8584              * or:
8585              *      f() = value
8586              */
8587             if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8588                 return setResult(e);
8589 
8590             if (e1x.checkRightThis(sc))
8591             {
8592                 return setError();
8593             }
8594             exp.e1 = e1x;
8595             assert(exp.e1.type);
8596         }
8597         Type t1 = exp.e1.type.toBasetype();
8598 
8599         /* Run this.e2 semantic.
8600          * Different from other binary expressions, the analysis of e2
8601          * depends on the result of e1 in assignments.
8602          */
8603         {
8604             Expression e2x = inferType(exp.e2, t1.baseElemOf());
8605             e2x = e2x.expressionSemantic(sc);
8606             e2x = resolveProperties(sc, e2x);
8607             if (e2x.op == TOK.type)
8608                 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8609             if (e2x.op == TOK.error)
8610                 return setResult(e2x);
8611             if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8612                 return setError();
8613             exp.e2 = e2x;
8614         }
8615 
8616         /* Rewrite tuple assignment as a tuple of assignments.
8617          */
8618         {
8619             Expression e2x = exp.e2;
8620 
8621         Ltupleassign:
8622             if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple)
8623             {
8624                 TupleExp tup1 = cast(TupleExp)exp.e1;
8625                 TupleExp tup2 = cast(TupleExp)e2x;
8626                 size_t dim = tup1.exps.dim;
8627                 Expression e = null;
8628                 if (dim != tup2.exps.dim)
8629                 {
8630                     exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
8631                     return setError();
8632                 }
8633                 if (dim == 0)
8634                 {
8635                     e = IntegerExp.literal!0;
8636                     e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8637                     e = Expression.combine(tup1.e0, tup2.e0, e);
8638                 }
8639                 else
8640                 {
8641                     auto exps = new Expressions(dim);
8642                     for (size_t i = 0; i < dim; i++)
8643                     {
8644                         Expression ex1 = (*tup1.exps)[i];
8645                         Expression ex2 = (*tup2.exps)[i];
8646                         (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8647                     }
8648                     e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8649                 }
8650                 return setResult(e.expressionSemantic(sc));
8651             }
8652 
8653             /* Look for form: e1 = e2.aliasthis.
8654              */
8655             if (exp.e1.op == TOK.tuple)
8656             {
8657                 TupleDeclaration td = isAliasThisTuple(e2x);
8658                 if (!td)
8659                     goto Lnomatch;
8660 
8661                 assert(exp.e1.type.ty == Ttuple);
8662                 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8663 
8664                 Expression e0;
8665                 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8666 
8667                 auto iexps = new Expressions();
8668                 iexps.push(ev);
8669                 for (size_t u = 0; u < iexps.dim; u++)
8670                 {
8671                 Lexpand:
8672                     Expression e = (*iexps)[u];
8673 
8674                     Parameter arg = Parameter.getNth(tt.arguments, u);
8675                     //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
8676                     //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars());
8677                     //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
8678 
8679                     if (!arg || !e.type.implicitConvTo(arg.type))
8680                     {
8681                         // expand initializer to tuple
8682                         if (expandAliasThisTuples(iexps, u) != -1)
8683                         {
8684                             if (iexps.dim <= u)
8685                                 break;
8686                             goto Lexpand;
8687                         }
8688                         goto Lnomatch;
8689                     }
8690                 }
8691                 e2x = new TupleExp(e2x.loc, e0, iexps);
8692                 e2x = e2x.expressionSemantic(sc);
8693                 if (e2x.op == TOK.error)
8694                 {
8695                     result = e2x;
8696                     return;
8697                 }
8698                 // Do not need to overwrite this.e2
8699                 goto Ltupleassign;
8700             }
8701         Lnomatch:
8702         }
8703 
8704         if (exp.op == TOK.assign)  // skip TOK.blit and TOK.construct, which are initializations
8705             exp.e1.checkSharedAccess(sc);
8706 
8707         /* Inside constructor, if this is the first assignment of object field,
8708          * rewrite this to initializing the field.
8709          */
8710         if (exp.op == TOK.assign
8711             && exp.e1.checkModifiable(sc) == Modifiable.initialization)
8712         {
8713             //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
8714             auto t = exp.type;
8715             exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
8716             exp.type = t;
8717 
8718             // @@@DEPRECATED_2020-06@@@
8719             // When removing, alter `checkModifiable` to return the correct value.
8720             if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() &&
8721                 exp.e1.type.isImmutable())
8722             {
8723                 deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated.");
8724                 deprecationSupplemental(exp.loc, "Use `shared static this` instead.");
8725             }
8726 
8727             // https://issues.dlang.org/show_bug.cgi?id=13515
8728             // set Index::modifiable flag for complex AA element initialization
8729             if (auto ie1 = exp.e1.isIndexExp())
8730             {
8731                 Expression e1x = ie1.markSettingAAElem();
8732                 if (e1x.op == TOK.error)
8733                 {
8734                     result = e1x;
8735                     return;
8736                 }
8737             }
8738         }
8739         else if (exp.op == TOK.construct && exp.e1.op == TOK.variable &&
8740                  (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
8741         {
8742             exp.memset = MemorySet.referenceInit;
8743         }
8744 
8745         /* If it is an assignment from a 'foreign' type,
8746          * check for operator overloading.
8747          */
8748         if (exp.memset == MemorySet.referenceInit)
8749         {
8750             // If this is an initialization of a reference,
8751             // do nothing
8752         }
8753         else if (t1.ty == Tstruct)
8754         {
8755             auto e1x = exp.e1;
8756             auto e2x = exp.e2;
8757             auto sd = (cast(TypeStruct)t1).sym;
8758 
8759             if (exp.op == TOK.construct)
8760             {
8761                 Type t2 = e2x.type.toBasetype();
8762                 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
8763                 {
8764                     sd.size(exp.loc);
8765                     if (sd.sizeok != Sizeok.done)
8766                         return setError();
8767                     if (!sd.ctor)
8768                         sd.ctor = sd.searchCtor();
8769 
8770                     // https://issues.dlang.org/show_bug.cgi?id=15661
8771                     // Look for the form from last of comma chain.
8772                     auto e2y = lastComma(e2x);
8773 
8774                     CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null;
8775                     DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable)
8776                         ? cast(DotVarExp)ce.e1 : null;
8777                     if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
8778                         // https://issues.dlang.org/show_bug.cgi?id=19389
8779                         dve.e1.op != TOK.dotVariable &&
8780                         e2y.type.implicitConvTo(t1))
8781                     {
8782                         /* Look for form of constructor call which is:
8783                          *    __ctmp.ctor(arguments...)
8784                          */
8785 
8786                         /* Before calling the constructor, initialize
8787                          * variable with a bit copy of the default
8788                          * initializer
8789                          */
8790                         Expression einit = getInitExp(sd, exp.loc, sc, t1);
8791                         if (einit.op == TOK.error)
8792                         {
8793                             result = einit;
8794                             return;
8795                         }
8796 
8797                         auto ae = new BlitExp(exp.loc, exp.e1, einit);
8798                         ae.type = e1x.type;
8799 
8800                         /* Replace __ctmp being constructed with e1.
8801                          * We need to copy constructor call expression,
8802                          * because it may be used in other place.
8803                          */
8804                         auto dvx = cast(DotVarExp)dve.copy();
8805                         dvx.e1 = e1x;
8806                         auto cx = cast(CallExp)ce.copy();
8807                         cx.e1 = dvx;
8808                         if (checkConstructorEscape(sc, cx, false))
8809                             return setError();
8810 
8811                         Expression e0;
8812                         Expression.extractLast(e2x, e0);
8813 
8814                         auto e = Expression.combine(e0, ae, cx);
8815                         e = e.expressionSemantic(sc);
8816                         result = e;
8817                         return;
8818                     }
8819                     // https://issues.dlang.org/show_bug.cgi?id=21586
8820                     // Rewrite CondExp or e1 will miss direct construction, e.g.
8821                     // e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
8822                     // a temporary created and an extra destructor call.
8823                     // AST will be rewritten to:
8824                     // a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
8825                     if (e2x.op == TOK.question)
8826                     {
8827                         /* Rewrite as:
8828                          *  a ? e1 = b : e1 = c;
8829                          */
8830                         CondExp econd = cast(CondExp)e2x;
8831                         Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
8832                         Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
8833                         Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
8834                         result = e.expressionSemantic(sc);
8835                         return;
8836                     }
8837                     if (sd.postblit || sd.hasCopyCtor)
8838                     {
8839                         /* We have a copy constructor for this
8840                          */
8841 
8842                         if (e2x.isLvalue())
8843                         {
8844                             if (sd.hasCopyCtor)
8845                             {
8846                                 /* Rewrite as:
8847                                  * e1 = init, e1.copyCtor(e2);
8848                                  */
8849                                 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
8850                                 einit.type = e1x.type;
8851 
8852                                 Expression e;
8853                                 e = new DotIdExp(exp.loc, e1x, Id.ctor);
8854                                 e = new CallExp(exp.loc, e, e2x);
8855                                 e = new CommaExp(exp.loc, einit, e);
8856 
8857                                 //printf("e: %s\n", e.toChars());
8858 
8859                                 result = e.expressionSemantic(sc);
8860                                 return;
8861                             }
8862                             else
8863                             {
8864                                 if (!e2x.type.implicitConvTo(e1x.type))
8865                                 {
8866                                     exp.error("conversion error from `%s` to `%s`",
8867                                         e2x.type.toChars(), e1x.type.toChars());
8868                                     return setError();
8869                                 }
8870 
8871                                 /* Rewrite as:
8872                                  *  (e1 = e2).postblit();
8873                                  *
8874                                  * Blit assignment e1 = e2 returns a reference to the original e1,
8875                                  * then call the postblit on it.
8876                                  */
8877                                 Expression e = e1x.copy();
8878                                 e.type = e.type.mutableOf();
8879                                 if (e.type.isShared && !sd.type.isShared)
8880                                     e.type = e.type.unSharedOf();
8881                                 e = new BlitExp(exp.loc, e, e2x);
8882                                 e = new DotVarExp(exp.loc, e, sd.postblit, false);
8883                                 e = new CallExp(exp.loc, e);
8884                                 result = e.expressionSemantic(sc);
8885                                 return;
8886                             }
8887                         }
8888                         else
8889                         {
8890                             /* The struct value returned from the function is transferred
8891                              * so should not call the destructor on it.
8892                              */
8893                             e2x = valueNoDtor(e2x);
8894                         }
8895                     }
8896 
8897                     // https://issues.dlang.org/show_bug.cgi?id=19251
8898                     // if e2 cannot be converted to e1.type, maybe there is an alias this
8899                     if (!e2x.implicitConvTo(t1))
8900                     {
8901                         AggregateDeclaration ad2 = isAggregate(e2x.type);
8902                         if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type.equivalent(exp.att2)))
8903                         {
8904                             if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8905                                 exp.att2 = exp.e2.type;
8906                             /* Rewrite (e1 op e2) as:
8907                              *      (e1 op e2.aliasthis)
8908                              */
8909                             exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8910                             result = exp.expressionSemantic(sc);
8911                             return;
8912                         }
8913                     }
8914                 }
8915                 else if (!e2x.implicitConvTo(t1))
8916                 {
8917                     sd.size(exp.loc);
8918                     if (sd.sizeok != Sizeok.done)
8919                         return setError();
8920                     if (!sd.ctor)
8921                         sd.ctor = sd.searchCtor();
8922 
8923                     if (sd.ctor)
8924                     {
8925                         /* Look for implicit constructor call
8926                          * Rewrite as:
8927                          *  e1 = init, e1.ctor(e2)
8928                          */
8929 
8930                         /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
8931                          * Using `new` to initialize a struct object is a common mistake, but
8932                          * the error message from the compiler is not very helpful in that
8933                          * case. If exp.e2 is a NewExp and the type of new is the same as
8934                          * the type as exp.e1 (struct in this case), then we know for sure
8935                          * that the user wants to instantiate a struct. This is done to avoid
8936                          * issuing an error when the user actually wants to call a constructor
8937                          * which receives a class object.
8938                          *
8939                          * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
8940                          * which receives an instance of a Foo2 class
8941                          */
8942                         if (exp.e2.op == TOK.new_)
8943                         {
8944                             auto newExp = cast(NewExp)(exp.e2);
8945                             if (newExp.newtype && newExp.newtype == t1)
8946                             {
8947                                 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
8948                                       newExp.toChars(), newExp.type.toChars(), t1.toChars());
8949                                 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
8950                                 return setError();
8951                             }
8952                         }
8953 
8954                         Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
8955                         einit.type = e1x.type;
8956 
8957                         Expression e;
8958                         e = new DotIdExp(exp.loc, e1x, Id.ctor);
8959                         e = new CallExp(exp.loc, e, e2x);
8960                         e = new CommaExp(exp.loc, einit, e);
8961                         e = e.expressionSemantic(sc);
8962                         result = e;
8963                         return;
8964                     }
8965                     if (search_function(sd, Id.call))
8966                     {
8967                         /* Look for static opCall
8968                          * https://issues.dlang.org/show_bug.cgi?id=2702
8969                          * Rewrite as:
8970                          *  e1 = typeof(e1).opCall(arguments)
8971                          */
8972                         e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
8973                         e2x = new CallExp(exp.loc, e2x, exp.e2);
8974 
8975                         e2x = e2x.expressionSemantic(sc);
8976                         e2x = resolveProperties(sc, e2x);
8977                         if (e2x.op == TOK.error)
8978                         {
8979                             result = e2x;
8980                             return;
8981                         }
8982                         if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8983                             return setError();
8984                     }
8985                 }
8986                 else // https://issues.dlang.org/show_bug.cgi?id=11355
8987                 {
8988                     AggregateDeclaration ad2 = isAggregate(e2x.type);
8989                     if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type.equivalent(exp.att2)))
8990                     {
8991                         if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8992                             exp.att2 = exp.e2.type;
8993                         /* Rewrite (e1 op e2) as:
8994                          *      (e1 op e2.aliasthis)
8995                          */
8996                         exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8997                         result = exp.expressionSemantic(sc);
8998                         return;
8999                     }
9000                 }
9001             }
9002             else if (exp.op == TOK.assign)
9003             {
9004                 if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
9005                 {
9006                     /*
9007                      * Rewrite:
9008                      *      aa[key] = e2;
9009                      * as:
9010                      *      ref __aatmp = aa;
9011                      *      ref __aakey = key;
9012                      *      ref __aaval = e2;
9013                      *      (__aakey in __aatmp
9014                      *          ? __aatmp[__aakey].opAssign(__aaval)
9015                      *          : ConstructExp(__aatmp[__aakey], __aaval));
9016                      */
9017                     // ensure we keep the expr modifiable
9018                     Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
9019                     if (esetting.op == TOK.error)
9020                     {
9021                         result = esetting;
9022                         return;
9023                     }
9024                     assert(esetting.op == TOK.index);
9025                     IndexExp ie = cast(IndexExp) esetting;
9026                     Type t2 = e2x.type.toBasetype();
9027 
9028                     Expression e0 = null;
9029                     Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
9030                     Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
9031                     Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
9032 
9033                     AssignExp ae = cast(AssignExp)exp.copy();
9034                     ae.e1 = new IndexExp(exp.loc, ea, ek);
9035                     ae.e1 = ae.e1.expressionSemantic(sc);
9036                     ae.e1 = ae.e1.optimize(WANTvalue);
9037                     ae.e2 = ev;
9038                     Expression e = ae.op_overload(sc);
9039                     if (e)
9040                     {
9041                         Expression ey = null;
9042                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
9043                         {
9044                             ey = ev;
9045                         }
9046                         else if (!ev.implicitConvTo(ie.type) && sd.ctor)
9047                         {
9048                             // Look for implicit constructor call
9049                             // Rewrite as S().ctor(e2)
9050                             ey = new StructLiteralExp(exp.loc, sd, null);
9051                             ey = new DotIdExp(exp.loc, ey, Id.ctor);
9052                             ey = new CallExp(exp.loc, ey, ev);
9053                             ey = ey.trySemantic(sc);
9054                         }
9055                         if (ey)
9056                         {
9057                             Expression ex;
9058                             ex = new IndexExp(exp.loc, ea, ek);
9059                             ex = ex.expressionSemantic(sc);
9060                             ex = ex.optimize(WANTvalue);
9061                             ex = ex.modifiableLvalue(sc, ex); // allocate new slot
9062 
9063                             ey = new ConstructExp(exp.loc, ex, ey);
9064                             ey = ey.expressionSemantic(sc);
9065                             if (ey.op == TOK.error)
9066                             {
9067                                 result = ey;
9068                                 return;
9069                             }
9070                             ex = e;
9071 
9072                             // https://issues.dlang.org/show_bug.cgi?id=14144
9073                             // The whole expression should have the common type
9074                             // of opAssign() return and assigned AA entry.
9075                             // Even if there's no common type, expression should be typed as void.
9076                             if (!typeMerge(sc, TOK.question, ex, ey))
9077                             {
9078                                 ex = new CastExp(ex.loc, ex, Type.tvoid);
9079                                 ey = new CastExp(ey.loc, ey, Type.tvoid);
9080                             }
9081                             e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
9082                         }
9083                         e = Expression.combine(e0, e);
9084                         e = e.expressionSemantic(sc);
9085                         result = e;
9086                         return;
9087                     }
9088                 }
9089                 else
9090                 {
9091                     Expression e = exp.op_overload(sc);
9092                     if (e)
9093                     {
9094                         result = e;
9095                         return;
9096                     }
9097                 }
9098             }
9099             else
9100                 assert(exp.op == TOK.blit);
9101 
9102             exp.e1 = e1x;
9103             exp.e2 = e2x;
9104         }
9105         else if (t1.ty == Tclass)
9106         {
9107             // Disallow assignment operator overloads for same type
9108             if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type))
9109             {
9110                 Expression e = exp.op_overload(sc);
9111                 if (e)
9112                 {
9113                     result = e;
9114                     return;
9115                 }
9116             }
9117         }
9118         else if (t1.ty == Tsarray)
9119         {
9120             // SliceExp cannot have static array type without context inference.
9121             assert(exp.e1.op != TOK.slice);
9122             Expression e1x = exp.e1;
9123             Expression e2x = exp.e2;
9124 
9125             if (e2x.implicitConvTo(e1x.type))
9126             {
9127                 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()))
9128                 {
9129                     if (e1x.checkPostblit(sc, t1))
9130                         return setError();
9131                 }
9132 
9133                 // e2 matches to t1 because of the implicit length match, so
9134                 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9135                 {
9136                     // convert e1 to e1[]
9137                     // e.g. e1[] = a[] + b[];
9138                     auto sle = new SliceExp(e1x.loc, e1x, null, null);
9139                     sle.arrayop = true;
9140                     e1x = sle.expressionSemantic(sc);
9141                 }
9142                 else
9143                 {
9144                     // convert e2 to t1 later
9145                     // e.g. e1 = [1, 2, 3];
9146                 }
9147             }
9148             else
9149             {
9150                 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9151                 {
9152                     uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9153                     uinteger_t dim2 = dim1;
9154                     if (auto ale = e2x.isArrayLiteralExp())
9155                     {
9156                         dim2 = ale.elements ? ale.elements.dim : 0;
9157                     }
9158                     else if (auto se = e2x.isSliceExp())
9159                     {
9160                         Type tx = toStaticArrayType(se);
9161                         if (tx)
9162                             dim2 = (cast(TypeSArray)tx).dim.toInteger();
9163                     }
9164                     if (dim1 != dim2)
9165                     {
9166                         exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9167                         return setError();
9168                     }
9169                 }
9170 
9171                 // May be block or element-wise assignment, so
9172                 // convert e1 to e1[]
9173                 if (exp.op != TOK.assign)
9174                 {
9175                     // If multidimensional static array, treat as one large array
9176                     //
9177                     // Find the appropriate array type depending on the assignment, e.g.
9178                     // int[3] = int => int[3]
9179                     // int[3][2] = int => int[6]
9180                     // int[3][2] = int[] => int[3][2]
9181                     // int[3][2][4] + int => int[24]
9182                     // int[3][2][4] + int[] => int[3][8]
9183                     ulong dim = t1.isTypeSArray().dim.toUInteger();
9184                     auto type = t1.nextOf();
9185 
9186                     for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9187                     {
9188                         import core.checkedint : mulu;
9189 
9190                         // Accumulate skipped dimensions
9191                         bool overflow = false;
9192                         dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9193                         if (overflow || dim >= uint.max)
9194                         {
9195                             // dym exceeds maximum array size
9196                             exp.error("static array `%s` size overflowed to %llu",
9197                                         e1x.type.toChars(), cast(ulong) dim);
9198                             return setError();
9199                         }
9200 
9201                         // Move to the element type
9202                         type = tsa.nextOf().toBasetype();
9203 
9204                         // Rewrite ex1 as a static array if a matching type was found
9205                         if (e2x.implicitConvTo(type) > MATCH.nomatch)
9206                         {
9207                             e1x.type = type.sarrayOf(dim);
9208                             break;
9209                         }
9210                     }
9211                 }
9212                 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9213                 sle.arrayop = true;
9214                 e1x = sle.expressionSemantic(sc);
9215             }
9216             if (e1x.op == TOK.error)
9217                 return setResult(e1x);
9218             if (e2x.op == TOK.error)
9219                 return setResult(e2x);
9220 
9221             exp.e1 = e1x;
9222             exp.e2 = e2x;
9223             t1 = e1x.type.toBasetype();
9224         }
9225         /* Check the mutability of e1.
9226          */
9227         if (auto ale = exp.e1.isArrayLengthExp())
9228         {
9229             // e1 is not an lvalue, but we let code generator handle it
9230 
9231             auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9232             if (ale1x.op == TOK.error)
9233                 return setResult(ale1x);
9234             ale.e1 = ale1x;
9235 
9236             Type tn = ale.e1.type.toBasetype().nextOf();
9237             checkDefCtor(ale.loc, tn);
9238 
9239             Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9240             if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9241                 return setError();
9242 
9243             // use slice expression when arr.length = 0 to avoid runtime call
9244             if(exp.e2.isConst() && exp.e2.toUInteger() == 0)
9245             {
9246                 IntervalExp ie = new IntervalExp(ale.loc, exp.e2, exp.e2);
9247                 Expression se = new SliceExp(ale.loc, ale.e1, ie);
9248                 Expression as = new AssignExp(ale.loc, ale.e1, se);
9249                 auto res = as.expressionSemantic(sc);
9250                 return setResult(res);
9251             }
9252 
9253             // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9254             Expression id = new IdentifierExp(ale.loc, Id.empty);
9255             id = new DotIdExp(ale.loc, id, Id.object);
9256             auto tiargs = new Objects();
9257             tiargs.push(ale.e1.type);
9258             id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9259             id = new DotIdExp(ale.loc, id, hook);
9260             id = id.expressionSemantic(sc);
9261 
9262             auto arguments = new Expressions();
9263             arguments.reserve(5);
9264             if (global.params.tracegc)
9265             {
9266                 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9267                 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9268                 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9269                 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9270             }
9271             arguments.push(ale.e1);
9272             arguments.push(exp.e2);
9273 
9274             Expression ce = new CallExp(ale.loc, id, arguments);
9275             auto res = ce.expressionSemantic(sc);
9276             // if (global.params.verbose)
9277             //     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
9278             return setResult(res);
9279         }
9280         else if (auto se = exp.e1.isSliceExp())
9281         {
9282             Type tn = se.type.nextOf();
9283             const fun = sc.func;
9284             if (exp.op == TOK.assign && !tn.isMutable() &&
9285                 // allow modifiation in module ctor, see
9286                 // https://issues.dlang.org/show_bug.cgi?id=9884
9287                 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9288             {
9289                 exp.error("slice `%s` is not mutable", se.toChars());
9290                 return setError();
9291             }
9292 
9293             if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable())
9294             {
9295                 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9296                     exp.e1.toChars(), tn.baseElemOf().toChars());
9297                 result = ErrorExp.get();
9298                 return;
9299             }
9300 
9301             // For conditional operator, both branches need conversion.
9302             while (se.e1.op == TOK.slice)
9303                 se = cast(SliceExp)se.e1;
9304             if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray)
9305             {
9306                 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9307                 if (se.e1.op == TOK.error)
9308                     return setResult(se.e1);
9309             }
9310         }
9311         else
9312         {
9313             if (t1.ty == Tsarray && exp.op == TOK.assign)
9314             {
9315                 Type tn = exp.e1.type.nextOf();
9316                 if (tn && !tn.baseElemOf().isAssignable())
9317                 {
9318                     exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9319                         exp.e1.toChars(), tn.baseElemOf().toChars());
9320                     result = ErrorExp.get();
9321                     return;
9322                 }
9323             }
9324 
9325             Expression e1x = exp.e1;
9326 
9327             // Try to do a decent error message with the expression
9328             // before it got constant folded
9329 
9330             e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
9331 
9332             if (exp.op == TOK.assign)
9333                 e1x = e1x.modifiableLvalue(sc, e1old);
9334 
9335             if (e1x.op == TOK.error)
9336             {
9337                 result = e1x;
9338                 return;
9339             }
9340             exp.e1 = e1x;
9341         }
9342 
9343         /* Tweak e2 based on the type of e1.
9344          */
9345         Expression e2x = exp.e2;
9346         Type t2 = e2x.type.toBasetype();
9347 
9348         // If it is a array, get the element type. Note that it may be
9349         // multi-dimensional.
9350         Type telem = t1;
9351         while (telem.ty == Tarray)
9352             telem = telem.nextOf();
9353 
9354         if (exp.e1.op == TOK.slice && t1.nextOf() &&
9355             (telem.ty != Tvoid || e2x.op == TOK.null_) &&
9356             e2x.implicitConvTo(t1.nextOf()))
9357         {
9358             // Check for block assignment. If it is of type void[], void[][], etc,
9359             // '= null' is the only allowable block assignment (Bug 7493)
9360             exp.memset = MemorySet.blockAssign;    // make it easy for back end to tell what this is
9361             e2x = e2x.implicitCastTo(sc, t1.nextOf());
9362             if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9363                 return setError();
9364         }
9365         else if (exp.e1.op == TOK.slice &&
9366                  (t2.ty == Tarray || t2.ty == Tsarray) &&
9367                  t2.nextOf().implicitConvTo(t1.nextOf()))
9368         {
9369             // Check element-wise assignment.
9370 
9371             /* If assigned elements number is known at compile time,
9372              * check the mismatch.
9373              */
9374             SliceExp se1 = cast(SliceExp)exp.e1;
9375             TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9376             TypeSArray tsa2 = null;
9377             if (auto ale = e2x.isArrayLiteralExp())
9378                 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
9379             else if (auto se = e2x.isSliceExp())
9380                 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9381             else
9382                 tsa2 = t2.isTypeSArray();
9383             if (tsa1 && tsa2)
9384             {
9385                 uinteger_t dim1 = tsa1.dim.toInteger();
9386                 uinteger_t dim2 = tsa2.dim.toInteger();
9387                 if (dim1 != dim2)
9388                 {
9389                     exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9390                     return setError();
9391                 }
9392             }
9393 
9394             if (exp.op != TOK.blit &&
9395                 (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9396                  e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9397                  e2x.op != TOK.slice && e2x.isLvalue()))
9398             {
9399                 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9400                     return setError();
9401             }
9402 
9403             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9404                 e2x.op != TOK.slice && e2x.op != TOK.assign &&
9405                 e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ &&
9406                 !(e2x.op == TOK.add || e2x.op == TOK.min ||
9407                   e2x.op == TOK.mul || e2x.op == TOK.div ||
9408                   e2x.op == TOK.mod || e2x.op == TOK.xor ||
9409                   e2x.op == TOK.and || e2x.op == TOK.or ||
9410                   e2x.op == TOK.pow ||
9411                   e2x.op == TOK.tilde || e2x.op == TOK.negate))
9412             {
9413                 const(char)* e1str = exp.e1.toChars();
9414                 const(char)* e2str = e2x.toChars();
9415                 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9416             }
9417 
9418             Type t2n = t2.nextOf();
9419             Type t1n = t1.nextOf();
9420             int offset;
9421             if (t2n.equivalent(t1n) ||
9422                 t1n.isBaseOf(t2n, &offset) && offset == 0)
9423             {
9424                 /* Allow copy of distinct qualifier elements.
9425                  * eg.
9426                  *  char[] dst;  const(char)[] src;
9427                  *  dst[] = src;
9428                  *
9429                  *  class C {}   class D : C {}
9430                  *  C[2] ca;  D[] da;
9431                  *  ca[] = da;
9432                  */
9433                 if (isArrayOpValid(e2x))
9434                 {
9435                     // Don't add CastExp to keep AST for array operations
9436                     e2x = e2x.copy();
9437                     e2x.type = exp.e1.type.constOf();
9438                 }
9439                 else
9440                     e2x = e2x.castTo(sc, exp.e1.type.constOf());
9441             }
9442             else
9443             {
9444                 /* https://issues.dlang.org/show_bug.cgi?id=15778
9445                  * A string literal has an array type of immutable
9446                  * elements by default, and normally it cannot be convertible to
9447                  * array type of mutable elements. But for element-wise assignment,
9448                  * elements need to be const at best. So we should give a chance
9449                  * to change code unit size for polysemous string literal.
9450                  */
9451                 if (e2x.op == TOK.string_)
9452                     e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9453                 else
9454                     e2x = e2x.implicitCastTo(sc, exp.e1.type);
9455             }
9456             if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9457             {
9458                 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
9459                 {
9460                     exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
9461                     return setError();
9462                 }
9463             }
9464         }
9465         else
9466         {
9467             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9468                 t1.ty == Tarray && t2.ty == Tsarray &&
9469                 e2x.op != TOK.slice &&
9470                 t2.implicitConvTo(t1))
9471             {
9472                 // Disallow ar[] = sa (Converted to ar[] = sa[])
9473                 // Disallow da   = sa (Converted to da   = sa[])
9474                 const(char)* e1str = exp.e1.toChars();
9475                 const(char)* e2str = e2x.toChars();
9476                 const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice";
9477                 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9478             }
9479             if (exp.op == TOK.blit)
9480                 e2x = e2x.castTo(sc, exp.e1.type);
9481             else
9482             {
9483                 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9484 
9485                 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9486 
9487                 // If the implicit cast has failed and the assign expression is
9488                 // the initialization of a struct member field
9489                 if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct)
9490                 {
9491                     scope sd = (cast(TypeStruct)t1).sym;
9492                     Dsymbol opAssign = search_function(sd, Id.assign);
9493 
9494                     // and the struct defines an opAssign
9495                     if (opAssign)
9496                     {
9497                         // offer more information about the cause of the problem
9498                         errorSupplemental(exp.loc,
9499                                           "`%s` is the first assignment of `%s` therefore it represents its initialization",
9500                                           exp.toChars(), exp.e1.toChars());
9501                         errorSupplemental(exp.loc,
9502                                           "`opAssign` methods are not used for initialization, but for subsequent assignments");
9503                     }
9504                 }
9505             }
9506         }
9507         if (e2x.op == TOK.error)
9508         {
9509             result = e2x;
9510             return;
9511         }
9512         exp.e2 = e2x;
9513         t2 = exp.e2.type.toBasetype();
9514 
9515         /* Look for array operations
9516          */
9517         if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9518         {
9519             // Look for valid array operations
9520             if (exp.memset != MemorySet.blockAssign &&
9521                 exp.e1.op == TOK.slice &&
9522                 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9523             {
9524                 exp.type = exp.e1.type;
9525                 if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9526                                         // tweak mutability of e1 element
9527                     exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9528                 result = arrayOp(exp, sc);
9529                 return;
9530             }
9531 
9532             // Drop invalid array operations in e2
9533             //  d = a[] + b[], d = (a[] + b[])[0..2], etc
9534             if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == TOK.assign))
9535                 return setError();
9536 
9537             // Remains valid array assignments
9538             //  d = d[], d = [1,2,3], etc
9539         }
9540 
9541         /* Don't allow assignment to classes that were allocated on the stack with:
9542          *      scope Class c = new Class();
9543          */
9544         if (exp.e1.op == TOK.variable && exp.op == TOK.assign)
9545         {
9546             VarExp ve = cast(VarExp)exp.e1;
9547             VarDeclaration vd = ve.var.isVarDeclaration();
9548             if (vd && (vd.onstack || vd.mynew))
9549             {
9550                 assert(t1.ty == Tclass);
9551                 exp.error("cannot rebind scope variables");
9552             }
9553         }
9554 
9555         if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9556         {
9557             exp.error("cannot modify compiler-generated variable `__ctfe`");
9558         }
9559 
9560         exp.type = exp.e1.type;
9561         assert(exp.type);
9562         auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
9563         checkAssignEscape(sc, res, false);
9564         return setResult(res);
9565     }
9566 
9567     override void visit(PowAssignExp exp)
9568     {
9569         if (exp.type)
9570         {
9571             result = exp;
9572             return;
9573         }
9574 
9575         Expression e = exp.op_overload(sc);
9576         if (e)
9577         {
9578             result = e;
9579             return;
9580         }
9581 
9582         if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
9583             return setError();
9584 
9585         assert(exp.e1.type && exp.e2.type);
9586         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
9587         {
9588             if (checkNonAssignmentArrayOp(exp.e1))
9589                 return setError();
9590 
9591             // T[] ^^= ...
9592             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
9593             {
9594                 // T[] ^^= T
9595                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
9596             }
9597             else if (Expression ex = typeCombine(exp, sc))
9598             {
9599                 result = ex;
9600                 return;
9601             }
9602 
9603             // Check element types are arithmetic
9604             Type tb1 = exp.e1.type.nextOf().toBasetype();
9605             Type tb2 = exp.e2.type.toBasetype();
9606             if (tb2.ty == Tarray || tb2.ty == Tsarray)
9607                 tb2 = tb2.nextOf().toBasetype();
9608             if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
9609             {
9610                 exp.type = exp.e1.type;
9611                 result = arrayOp(exp, sc);
9612                 return;
9613             }
9614         }
9615         else
9616         {
9617             exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9618         }
9619 
9620         if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
9621         {
9622             Expression e0 = null;
9623             e = exp.reorderSettingAAElem(sc);
9624             e = Expression.extractLast(e, e0);
9625             assert(e == exp);
9626 
9627             if (exp.e1.op == TOK.variable)
9628             {
9629                 // Rewrite: e1 = e1 ^^ e2
9630                 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
9631                 e = new AssignExp(exp.loc, exp.e1, e);
9632             }
9633             else
9634             {
9635                 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
9636                 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
9637                 auto de = new DeclarationExp(exp.e1.loc, v);
9638                 auto ve = new VarExp(exp.e1.loc, v);
9639                 e = new PowExp(exp.loc, ve, exp.e2);
9640                 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
9641                 e = new CommaExp(exp.loc, de, e);
9642             }
9643             e = Expression.combine(e0, e);
9644             e = e.expressionSemantic(sc);
9645             result = e;
9646             return;
9647         }
9648         result = exp.incompatibleTypes();
9649     }
9650 
9651     override void visit(CatAssignExp exp)
9652     {
9653         if (exp.type)
9654         {
9655             result = exp;
9656             return;
9657         }
9658 
9659         //printf("CatAssignExp::semantic() %s\n", exp.toChars());
9660         Expression e = exp.op_overload(sc);
9661         if (e)
9662         {
9663             result = e;
9664             return;
9665         }
9666 
9667         if (exp.e1.op == TOK.slice)
9668         {
9669             SliceExp se = cast(SliceExp)exp.e1;
9670             if (se.e1.type.toBasetype().ty == Tsarray)
9671             {
9672                 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
9673                 return setError();
9674             }
9675         }
9676 
9677         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9678         if (exp.e1.op == TOK.error)
9679         {
9680             result = exp.e1;
9681             return;
9682         }
9683         if (exp.e2.op == TOK.error)
9684         {
9685             result = exp.e2;
9686             return;
9687         }
9688 
9689         if (checkNonAssignmentArrayOp(exp.e2))
9690             return setError();
9691 
9692         Type tb1 = exp.e1.type.toBasetype();
9693         Type tb1next = tb1.nextOf();
9694         Type tb2 = exp.e2.type.toBasetype();
9695 
9696         /* Possibilities:
9697          * TOK.concatenateAssign: appending T[] to T[]
9698          * TOK.concatenateElemAssign: appending T to T[]
9699          * TOK.concatenateDcharAssign: appending dchar to T[]
9700          */
9701         if ((tb1.ty == Tarray) &&
9702             (tb2.ty == Tarray || tb2.ty == Tsarray) &&
9703             (exp.e2.implicitConvTo(exp.e1.type) ||
9704              (tb2.nextOf().implicitConvTo(tb1next) &&
9705               (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
9706         {
9707             // TOK.concatenateAssign
9708             assert(exp.op == TOK.concatenateAssign);
9709             if (exp.e1.checkPostblit(sc, tb1next))
9710                 return setError();
9711 
9712             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
9713         }
9714         else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
9715         {
9716             /* https://issues.dlang.org/show_bug.cgi?id=19782
9717              *
9718              * If e2 is implicitly convertible to tb1next, the conversion
9719              * might be done through alias this, in which case, e2 needs to
9720              * be modified accordingly (e2 => e2.aliasthis).
9721              */
9722             if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
9723                 goto Laliasthis;
9724             if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
9725                 goto Laliasthis;
9726             // Append element
9727             if (exp.e2.checkPostblit(sc, tb2))
9728                 return setError();
9729 
9730             if (checkNewEscape(sc, exp.e2, false))
9731                 return setError();
9732 
9733             exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
9734             exp.e2 = doCopyOrMove(sc, exp.e2);
9735         }
9736         else if (tb1.ty == Tarray &&
9737                  (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
9738                  exp.e2.type.ty != tb1next.ty &&
9739                  exp.e2.implicitConvTo(Type.tdchar))
9740         {
9741             // Append dchar to char[] or wchar[]
9742             exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
9743 
9744             /* Do not allow appending wchar to char[] because if wchar happens
9745              * to be a surrogate pair, nothing good can result.
9746              */
9747         }
9748         else
9749         {
9750             // Try alias this on first operand
9751             static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
9752             {
9753                 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
9754                 if (!ad1 || !ad1.aliasthis)
9755                     return null;
9756 
9757                 /* Rewrite (e1 op e2) as:
9758                  *      (e1.aliasthis op e2)
9759                  */
9760                 if (exp.att1 && exp.e1.type.equivalent(exp.att1))
9761                     return null;
9762                 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
9763                 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
9764                 BinExp be = cast(BinExp)exp.copy();
9765                 if (!be.att1 && exp.e1.type.checkAliasThisRec())
9766                     be.att1 = exp.e1.type;
9767                 be.e1 = e1;
9768                 return be.trySemantic(sc);
9769             }
9770 
9771             // Try alias this on second operand
9772             static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
9773             {
9774                 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
9775                 if (!ad2 || !ad2.aliasthis)
9776                     return null;
9777                 /* Rewrite (e1 op e2) as:
9778                  *      (e1 op e2.aliasthis)
9779                  */
9780                 if (exp.att2 && exp.e2.type.equivalent(exp.att2))
9781                     return null;
9782                 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
9783                 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
9784                 BinExp be = cast(BinExp)exp.copy();
9785                 if (!be.att2 && exp.e2.type.checkAliasThisRec())
9786                     be.att2 = exp.e2.type;
9787                 be.e2 = e2;
9788                 return be.trySemantic(sc);
9789             }
9790 
9791     Laliasthis:
9792             result = tryAliasThisForLhs(exp, sc);
9793             if (result)
9794                 return;
9795 
9796             result = tryAliasThisForRhs(exp, sc);
9797             if (result)
9798                 return;
9799 
9800             exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
9801             return setError();
9802         }
9803 
9804         if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
9805             return setError();
9806 
9807         exp.type = exp.e1.type;
9808         auto res = exp.reorderSettingAAElem(sc);
9809         if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) && global.params.vsafe)
9810             checkAssignEscape(sc, res, false);
9811         result = res;
9812     }
9813 
9814     override void visit(AddExp exp)
9815     {
9816         static if (LOGSEMANTIC)
9817         {
9818             printf("AddExp::semantic('%s')\n", exp.toChars());
9819         }
9820         if (exp.type)
9821         {
9822             result = exp;
9823             return;
9824         }
9825 
9826         if (Expression ex = binSemanticProp(exp, sc))
9827         {
9828             result = ex;
9829             return;
9830         }
9831         Expression e = exp.op_overload(sc);
9832         if (e)
9833         {
9834             result = e;
9835             return;
9836         }
9837 
9838         Type tb1 = exp.e1.type.toBasetype();
9839         Type tb2 = exp.e2.type.toBasetype();
9840 
9841         bool err = false;
9842         if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction)
9843         {
9844             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9845         }
9846         if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction)
9847         {
9848             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9849         }
9850         if (err)
9851             return setError();
9852 
9853         if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
9854         {
9855             result = scaleFactor(exp, sc);
9856             return;
9857         }
9858 
9859         if (tb1.ty == Tpointer && tb2.ty == Tpointer)
9860         {
9861             result = exp.incompatibleTypes();
9862             return;
9863         }
9864 
9865         if (Expression ex = typeCombine(exp, sc))
9866         {
9867             result = ex;
9868             return;
9869         }
9870 
9871         Type tb = exp.type.toBasetype();
9872         if (tb.ty == Tarray || tb.ty == Tsarray)
9873         {
9874             if (!isArrayOpValid(exp))
9875             {
9876                 result = arrayOpInvalidError(exp);
9877                 return;
9878             }
9879             result = exp;
9880             return;
9881         }
9882 
9883         tb1 = exp.e1.type.toBasetype();
9884         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
9885         {
9886             result = exp.incompatibleTypes();
9887             return;
9888         }
9889         if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
9890         {
9891             switch (exp.type.toBasetype().ty)
9892             {
9893             case Tfloat32:
9894             case Timaginary32:
9895                 exp.type = Type.tcomplex32;
9896                 break;
9897 
9898             case Tfloat64:
9899             case Timaginary64:
9900                 exp.type = Type.tcomplex64;
9901                 break;
9902 
9903             case Tfloat80:
9904             case Timaginary80:
9905                 exp.type = Type.tcomplex80;
9906                 break;
9907 
9908             default:
9909                 assert(0);
9910             }
9911         }
9912         result = exp;
9913     }
9914 
9915     override void visit(MinExp exp)
9916     {
9917         static if (LOGSEMANTIC)
9918         {
9919             printf("MinExp::semantic('%s')\n", exp.toChars());
9920         }
9921         if (exp.type)
9922         {
9923             result = exp;
9924             return;
9925         }
9926 
9927         if (Expression ex = binSemanticProp(exp, sc))
9928         {
9929             result = ex;
9930             return;
9931         }
9932         Expression e = exp.op_overload(sc);
9933         if (e)
9934         {
9935             result = e;
9936             return;
9937         }
9938 
9939         Type t1 = exp.e1.type.toBasetype();
9940         Type t2 = exp.e2.type.toBasetype();
9941 
9942         bool err = false;
9943         if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction)
9944         {
9945             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9946         }
9947         if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction)
9948         {
9949             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9950         }
9951         if (err)
9952             return setError();
9953 
9954         if (t1.ty == Tpointer)
9955         {
9956             if (t2.ty == Tpointer)
9957             {
9958                 // https://dlang.org/spec/expression.html#add_expressions
9959                 // "If both operands are pointers, and the operator is -, the pointers are
9960                 // subtracted and the result is divided by the size of the type pointed to
9961                 // by the operands. It is an error if the pointers point to different types."
9962                 Type p1 = t1.nextOf();
9963                 Type p2 = t2.nextOf();
9964 
9965                 if (!p1.equivalent(p2))
9966                 {
9967                     // Deprecation to remain for at least a year, after which this should be
9968                     // changed to an error
9969                     // See https://github.com/dlang/dmd/pull/7332
9970                     deprecation(exp.loc,
9971                         "cannot subtract pointers to different types: `%s` and `%s`.",
9972                         t1.toChars(), t2.toChars());
9973                 }
9974 
9975                 // Need to divide the result by the stride
9976                 // Replace (ptr - ptr) with (ptr - ptr) / stride
9977                 d_int64 stride;
9978 
9979                 // make sure pointer types are compatible
9980                 if (Expression ex = typeCombine(exp, sc))
9981                 {
9982                     result = ex;
9983                     return;
9984                 }
9985 
9986                 exp.type = Type.tptrdiff_t;
9987                 stride = t2.nextOf().size();
9988                 if (stride == 0)
9989                 {
9990                     e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
9991                 }
9992                 else
9993                 {
9994                     e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
9995                     e.type = Type.tptrdiff_t;
9996                 }
9997             }
9998             else if (t2.isintegral())
9999                 e = scaleFactor(exp, sc);
10000             else
10001             {
10002                 exp.error("can't subtract `%s` from pointer", t2.toChars());
10003                 e = ErrorExp.get();
10004             }
10005             result = e;
10006             return;
10007         }
10008         if (t2.ty == Tpointer)
10009         {
10010             exp.type = exp.e2.type;
10011             exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
10012             return setError();
10013         }
10014 
10015         if (Expression ex = typeCombine(exp, sc))
10016         {
10017             result = ex;
10018             return;
10019         }
10020 
10021         Type tb = exp.type.toBasetype();
10022         if (tb.ty == Tarray || tb.ty == Tsarray)
10023         {
10024             if (!isArrayOpValid(exp))
10025             {
10026                 result = arrayOpInvalidError(exp);
10027                 return;
10028             }
10029             result = exp;
10030             return;
10031         }
10032 
10033         t1 = exp.e1.type.toBasetype();
10034         t2 = exp.e2.type.toBasetype();
10035         if (!target.isVectorOpSupported(t1, exp.op, t2))
10036         {
10037             result = exp.incompatibleTypes();
10038             return;
10039         }
10040         if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
10041         {
10042             switch (exp.type.ty)
10043             {
10044             case Tfloat32:
10045             case Timaginary32:
10046                 exp.type = Type.tcomplex32;
10047                 break;
10048 
10049             case Tfloat64:
10050             case Timaginary64:
10051                 exp.type = Type.tcomplex64;
10052                 break;
10053 
10054             case Tfloat80:
10055             case Timaginary80:
10056                 exp.type = Type.tcomplex80;
10057                 break;
10058 
10059             default:
10060                 assert(0);
10061             }
10062         }
10063         result = exp;
10064         return;
10065     }
10066 
10067     override void visit(CatExp exp)
10068     {
10069         // https://dlang.org/spec/expression.html#cat_expressions
10070         //printf("CatExp.semantic() %s\n", toChars());
10071         if (exp.type)
10072         {
10073             result = exp;
10074             return;
10075         }
10076 
10077         if (Expression ex = binSemanticProp(exp, sc))
10078         {
10079             result = ex;
10080             return;
10081         }
10082         Expression e = exp.op_overload(sc);
10083         if (e)
10084         {
10085             result = e;
10086             return;
10087         }
10088 
10089         Type tb1 = exp.e1.type.toBasetype();
10090         Type tb2 = exp.e2.type.toBasetype();
10091 
10092         auto f1 = checkNonAssignmentArrayOp(exp.e1);
10093         auto f2 = checkNonAssignmentArrayOp(exp.e2);
10094         if (f1 || f2)
10095             return setError();
10096 
10097         /* BUG: Should handle things like:
10098          *      char c;
10099          *      c ~ ' '
10100          *      ' ' ~ c;
10101          */
10102 
10103         Type tb1next = tb1.nextOf();
10104         Type tb2next = tb2.nextOf();
10105 
10106         // Check for: array ~ array
10107         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)))
10108         {
10109             /* https://issues.dlang.org/show_bug.cgi?id=9248
10110              * Here to avoid the case of:
10111              *    void*[] a = [cast(void*)1];
10112              *    void*[] b = [cast(void*)2];
10113              *    a ~ b;
10114              * becoming:
10115              *    a ~ [cast(void*)b];
10116              */
10117 
10118             /* https://issues.dlang.org/show_bug.cgi?id=14682
10119              * Also to avoid the case of:
10120              *    int[][] a;
10121              *    a ~ [];
10122              * becoming:
10123              *    a ~ cast(int[])[];
10124              */
10125             goto Lpeer;
10126         }
10127 
10128         // Check for: array ~ element
10129         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10130         {
10131             if (exp.e1.op == TOK.arrayLiteral)
10132             {
10133                 exp.e2 = doCopyOrMove(sc, exp.e2);
10134                 // https://issues.dlang.org/show_bug.cgi?id=14686
10135                 // Postblit call appears in AST, and this is
10136                 // finally translated  to an ArrayLiteralExp in below optimize().
10137             }
10138             else if (exp.e1.op == TOK.string_)
10139             {
10140                 // No postblit call exists on character (integer) value.
10141             }
10142             else
10143             {
10144                 if (exp.e2.checkPostblit(sc, tb2))
10145                     return setError();
10146                 // Postblit call will be done in runtime helper function
10147             }
10148 
10149             if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
10150             {
10151                 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10152                 exp.type = tb2.arrayOf();
10153                 goto L2elem;
10154             }
10155             if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10156             {
10157                 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10158                 exp.type = tb1next.arrayOf();
10159             L2elem:
10160                 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10161                 {
10162                     // Make e2 into [e2]
10163                     exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10164                 }
10165                 else if (checkNewEscape(sc, exp.e2, false))
10166                     return setError();
10167                 result = exp.optimize(WANTvalue);
10168                 return;
10169             }
10170         }
10171         // Check for: element ~ array
10172         if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10173         {
10174             if (exp.e2.op == TOK.arrayLiteral)
10175             {
10176                 exp.e1 = doCopyOrMove(sc, exp.e1);
10177             }
10178             else if (exp.e2.op == TOK.string_)
10179             {
10180             }
10181             else
10182             {
10183                 if (exp.e1.checkPostblit(sc, tb1))
10184                     return setError();
10185             }
10186 
10187             if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
10188             {
10189                 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10190                 exp.type = tb1.arrayOf();
10191                 goto L1elem;
10192             }
10193             if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10194             {
10195                 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10196                 exp.type = tb2next.arrayOf();
10197             L1elem:
10198                 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10199                 {
10200                     // Make e1 into [e1]
10201                     exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10202                 }
10203                 else if (checkNewEscape(sc, exp.e1, false))
10204                     return setError();
10205                 result = exp.optimize(WANTvalue);
10206                 return;
10207             }
10208         }
10209 
10210     Lpeer:
10211         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10212         {
10213             Type t1 = tb1next.mutableOf().constOf().arrayOf();
10214             Type t2 = tb2next.mutableOf().constOf().arrayOf();
10215             if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed)
10216                 exp.e1.type = t1;
10217             else
10218                 exp.e1 = exp.e1.castTo(sc, t1);
10219             if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed)
10220                 exp.e2.type = t2;
10221             else
10222                 exp.e2 = exp.e2.castTo(sc, t2);
10223         }
10224 
10225         if (Expression ex = typeCombine(exp, sc))
10226         {
10227             result = ex;
10228             return;
10229         }
10230         exp.type = exp.type.toHeadMutable();
10231 
10232         Type tb = exp.type.toBasetype();
10233         if (tb.ty == Tsarray)
10234             exp.type = tb.nextOf().arrayOf();
10235         if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10236         {
10237             exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10238         }
10239         if (Type tbn = tb.nextOf())
10240         {
10241             if (exp.checkPostblit(sc, tbn))
10242                 return setError();
10243         }
10244         Type t1 = exp.e1.type.toBasetype();
10245         Type t2 = exp.e2.type.toBasetype();
10246         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10247             (t2.ty == Tarray || t2.ty == Tsarray))
10248         {
10249             // Normalize to ArrayLiteralExp or StringExp as far as possible
10250             e = exp.optimize(WANTvalue);
10251         }
10252         else
10253         {
10254             //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10255             result = exp.incompatibleTypes();
10256             return;
10257         }
10258 
10259         result = e;
10260     }
10261 
10262     override void visit(MulExp exp)
10263     {
10264         version (none)
10265         {
10266             printf("MulExp::semantic() %s\n", exp.toChars());
10267         }
10268         if (exp.type)
10269         {
10270             result = exp;
10271             return;
10272         }
10273 
10274         if (Expression ex = binSemanticProp(exp, sc))
10275         {
10276             result = ex;
10277             return;
10278         }
10279         Expression e = exp.op_overload(sc);
10280         if (e)
10281         {
10282             result = e;
10283             return;
10284         }
10285 
10286         if (Expression ex = typeCombine(exp, sc))
10287         {
10288             result = ex;
10289             return;
10290         }
10291 
10292         Type tb = exp.type.toBasetype();
10293         if (tb.ty == Tarray || tb.ty == Tsarray)
10294         {
10295             if (!isArrayOpValid(exp))
10296             {
10297                 result = arrayOpInvalidError(exp);
10298                 return;
10299             }
10300             result = exp;
10301             return;
10302         }
10303 
10304         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10305             return setError();
10306 
10307         if (exp.type.isfloating())
10308         {
10309             Type t1 = exp.e1.type;
10310             Type t2 = exp.e2.type;
10311 
10312             if (t1.isreal())
10313             {
10314                 exp.type = t2;
10315             }
10316             else if (t2.isreal())
10317             {
10318                 exp.type = t1;
10319             }
10320             else if (t1.isimaginary())
10321             {
10322                 if (t2.isimaginary())
10323                 {
10324                     switch (t1.toBasetype().ty)
10325                     {
10326                     case Timaginary32:
10327                         exp.type = Type.tfloat32;
10328                         break;
10329 
10330                     case Timaginary64:
10331                         exp.type = Type.tfloat64;
10332                         break;
10333 
10334                     case Timaginary80:
10335                         exp.type = Type.tfloat80;
10336                         break;
10337 
10338                     default:
10339                         assert(0);
10340                     }
10341 
10342                     // iy * iv = -yv
10343                     exp.e1.type = exp.type;
10344                     exp.e2.type = exp.type;
10345                     e = new NegExp(exp.loc, exp);
10346                     e = e.expressionSemantic(sc);
10347                     result = e;
10348                     return;
10349                 }
10350                 else
10351                     exp.type = t2; // t2 is complex
10352             }
10353             else if (t2.isimaginary())
10354             {
10355                 exp.type = t1; // t1 is complex
10356             }
10357         }
10358         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10359         {
10360             result = exp.incompatibleTypes();
10361             return;
10362         }
10363         result = exp;
10364     }
10365 
10366     override void visit(DivExp exp)
10367     {
10368         if (exp.type)
10369         {
10370             result = exp;
10371             return;
10372         }
10373 
10374         if (Expression ex = binSemanticProp(exp, sc))
10375         {
10376             result = ex;
10377             return;
10378         }
10379         Expression e = exp.op_overload(sc);
10380         if (e)
10381         {
10382             result = e;
10383             return;
10384         }
10385 
10386         if (Expression ex = typeCombine(exp, sc))
10387         {
10388             result = ex;
10389             return;
10390         }
10391 
10392         Type tb = exp.type.toBasetype();
10393         if (tb.ty == Tarray || tb.ty == Tsarray)
10394         {
10395             if (!isArrayOpValid(exp))
10396             {
10397                 result = arrayOpInvalidError(exp);
10398                 return;
10399             }
10400             result = exp;
10401             return;
10402         }
10403 
10404         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10405             return setError();
10406 
10407         if (exp.type.isfloating())
10408         {
10409             Type t1 = exp.e1.type;
10410             Type t2 = exp.e2.type;
10411 
10412             if (t1.isreal())
10413             {
10414                 exp.type = t2;
10415                 if (t2.isimaginary())
10416                 {
10417                     // x/iv = i(-x/v)
10418                     exp.e2.type = t1;
10419                     e = new NegExp(exp.loc, exp);
10420                     e = e.expressionSemantic(sc);
10421                     result = e;
10422                     return;
10423                 }
10424             }
10425             else if (t2.isreal())
10426             {
10427                 exp.type = t1;
10428             }
10429             else if (t1.isimaginary())
10430             {
10431                 if (t2.isimaginary())
10432                 {
10433                     switch (t1.toBasetype().ty)
10434                     {
10435                     case Timaginary32:
10436                         exp.type = Type.tfloat32;
10437                         break;
10438 
10439                     case Timaginary64:
10440                         exp.type = Type.tfloat64;
10441                         break;
10442 
10443                     case Timaginary80:
10444                         exp.type = Type.tfloat80;
10445                         break;
10446 
10447                     default:
10448                         assert(0);
10449                     }
10450                 }
10451                 else
10452                     exp.type = t2; // t2 is complex
10453             }
10454             else if (t2.isimaginary())
10455             {
10456                 exp.type = t1; // t1 is complex
10457             }
10458         }
10459         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10460         {
10461             result = exp.incompatibleTypes();
10462             return;
10463         }
10464         result = exp;
10465     }
10466 
10467     override void visit(ModExp exp)
10468     {
10469         if (exp.type)
10470         {
10471             result = exp;
10472             return;
10473         }
10474 
10475         if (Expression ex = binSemanticProp(exp, sc))
10476         {
10477             result = ex;
10478             return;
10479         }
10480         Expression e = exp.op_overload(sc);
10481         if (e)
10482         {
10483             result = e;
10484             return;
10485         }
10486 
10487         if (Expression ex = typeCombine(exp, sc))
10488         {
10489             result = ex;
10490             return;
10491         }
10492 
10493         Type tb = exp.type.toBasetype();
10494         if (tb.ty == Tarray || tb.ty == Tsarray)
10495         {
10496             if (!isArrayOpValid(exp))
10497             {
10498                 result = arrayOpInvalidError(exp);
10499                 return;
10500             }
10501             result = exp;
10502             return;
10503         }
10504         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10505         {
10506             result = exp.incompatibleTypes();
10507             return;
10508         }
10509 
10510         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10511             return setError();
10512 
10513         if (exp.type.isfloating())
10514         {
10515             exp.type = exp.e1.type;
10516             if (exp.e2.type.iscomplex())
10517             {
10518                 exp.error("cannot perform modulo complex arithmetic");
10519                 return setError();
10520             }
10521         }
10522         result = exp;
10523     }
10524 
10525     override void visit(PowExp exp)
10526     {
10527         if (exp.type)
10528         {
10529             result = exp;
10530             return;
10531         }
10532 
10533         //printf("PowExp::semantic() %s\n", toChars());
10534         if (Expression ex = binSemanticProp(exp, sc))
10535         {
10536             result = ex;
10537             return;
10538         }
10539         Expression e = exp.op_overload(sc);
10540         if (e)
10541         {
10542             result = e;
10543             return;
10544         }
10545 
10546         if (Expression ex = typeCombine(exp, sc))
10547         {
10548             result = ex;
10549             return;
10550         }
10551 
10552         Type tb = exp.type.toBasetype();
10553         if (tb.ty == Tarray || tb.ty == Tsarray)
10554         {
10555             if (!isArrayOpValid(exp))
10556             {
10557                 result = arrayOpInvalidError(exp);
10558                 return;
10559             }
10560             result = exp;
10561             return;
10562         }
10563 
10564         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10565             return setError();
10566 
10567         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10568         {
10569             result = exp.incompatibleTypes();
10570             return;
10571         }
10572 
10573         // First, attempt to fold the expression.
10574         e = exp.optimize(WANTvalue);
10575         if (e.op != TOK.pow)
10576         {
10577             e = e.expressionSemantic(sc);
10578             result = e;
10579             return;
10580         }
10581 
10582         Module mmath = loadStdMath();
10583         if (!mmath)
10584         {
10585             e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
10586             return setError();
10587         }
10588         e = new ScopeExp(exp.loc, mmath);
10589 
10590         if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half)
10591         {
10592             // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
10593             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
10594         }
10595         else
10596         {
10597             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
10598             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
10599         }
10600         e = e.expressionSemantic(sc);
10601         result = e;
10602         return;
10603     }
10604 
10605     override void visit(ShlExp exp)
10606     {
10607         //printf("ShlExp::semantic(), type = %p\n", type);
10608         if (exp.type)
10609         {
10610             result = exp;
10611             return;
10612         }
10613 
10614         if (Expression ex = binSemanticProp(exp, sc))
10615         {
10616             result = ex;
10617             return;
10618         }
10619         Expression e = exp.op_overload(sc);
10620         if (e)
10621         {
10622             result = e;
10623             return;
10624         }
10625 
10626         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10627             return setError();
10628 
10629         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10630         {
10631             result = exp.incompatibleTypes();
10632             return;
10633         }
10634         exp.e1 = integralPromotions(exp.e1, sc);
10635         if (exp.e2.type.toBasetype().ty != Tvector)
10636             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10637 
10638         exp.type = exp.e1.type;
10639         result = exp;
10640     }
10641 
10642     override void visit(ShrExp exp)
10643     {
10644         if (exp.type)
10645         {
10646             result = exp;
10647             return;
10648         }
10649 
10650         if (Expression ex = binSemanticProp(exp, sc))
10651         {
10652             result = ex;
10653             return;
10654         }
10655         Expression e = exp.op_overload(sc);
10656         if (e)
10657         {
10658             result = e;
10659             return;
10660         }
10661 
10662         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10663             return setError();
10664 
10665         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10666         {
10667             result = exp.incompatibleTypes();
10668             return;
10669         }
10670         exp.e1 = integralPromotions(exp.e1, sc);
10671         if (exp.e2.type.toBasetype().ty != Tvector)
10672             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10673 
10674         exp.type = exp.e1.type;
10675         result = exp;
10676     }
10677 
10678     override void visit(UshrExp exp)
10679     {
10680         if (exp.type)
10681         {
10682             result = exp;
10683             return;
10684         }
10685 
10686         if (Expression ex = binSemanticProp(exp, sc))
10687         {
10688             result = ex;
10689             return;
10690         }
10691         Expression e = exp.op_overload(sc);
10692         if (e)
10693         {
10694             result = e;
10695             return;
10696         }
10697 
10698         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10699             return setError();
10700 
10701         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10702         {
10703             result = exp.incompatibleTypes();
10704             return;
10705         }
10706         exp.e1 = integralPromotions(exp.e1, sc);
10707         if (exp.e2.type.toBasetype().ty != Tvector)
10708             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10709 
10710         exp.type = exp.e1.type;
10711         result = exp;
10712     }
10713 
10714     override void visit(AndExp exp)
10715     {
10716         if (exp.type)
10717         {
10718             result = exp;
10719             return;
10720         }
10721 
10722         if (Expression ex = binSemanticProp(exp, sc))
10723         {
10724             result = ex;
10725             return;
10726         }
10727         Expression e = exp.op_overload(sc);
10728         if (e)
10729         {
10730             result = e;
10731             return;
10732         }
10733 
10734         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10735         {
10736             exp.type = exp.e1.type;
10737             result = exp;
10738             return;
10739         }
10740 
10741         if (Expression ex = typeCombine(exp, sc))
10742         {
10743             result = ex;
10744             return;
10745         }
10746 
10747         Type tb = exp.type.toBasetype();
10748         if (tb.ty == Tarray || tb.ty == Tsarray)
10749         {
10750             if (!isArrayOpValid(exp))
10751             {
10752                 result = arrayOpInvalidError(exp);
10753                 return;
10754             }
10755             result = exp;
10756             return;
10757         }
10758         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10759         {
10760             result = exp.incompatibleTypes();
10761             return;
10762         }
10763         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10764             return setError();
10765 
10766         result = exp;
10767     }
10768 
10769     override void visit(OrExp exp)
10770     {
10771         if (exp.type)
10772         {
10773             result = exp;
10774             return;
10775         }
10776 
10777         if (Expression ex = binSemanticProp(exp, sc))
10778         {
10779             result = ex;
10780             return;
10781         }
10782         Expression e = exp.op_overload(sc);
10783         if (e)
10784         {
10785             result = e;
10786             return;
10787         }
10788 
10789         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10790         {
10791             exp.type = exp.e1.type;
10792             result = exp;
10793             return;
10794         }
10795 
10796         if (Expression ex = typeCombine(exp, sc))
10797         {
10798             result = ex;
10799             return;
10800         }
10801 
10802         Type tb = exp.type.toBasetype();
10803         if (tb.ty == Tarray || tb.ty == Tsarray)
10804         {
10805             if (!isArrayOpValid(exp))
10806             {
10807                 result = arrayOpInvalidError(exp);
10808                 return;
10809             }
10810             result = exp;
10811             return;
10812         }
10813         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10814         {
10815             result = exp.incompatibleTypes();
10816             return;
10817         }
10818         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10819             return setError();
10820 
10821         result = exp;
10822     }
10823 
10824     override void visit(XorExp exp)
10825     {
10826         if (exp.type)
10827         {
10828             result = exp;
10829             return;
10830         }
10831 
10832         if (Expression ex = binSemanticProp(exp, sc))
10833         {
10834             result = ex;
10835             return;
10836         }
10837         Expression e = exp.op_overload(sc);
10838         if (e)
10839         {
10840             result = e;
10841             return;
10842         }
10843 
10844         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10845         {
10846             exp.type = exp.e1.type;
10847             result = exp;
10848             return;
10849         }
10850 
10851         if (Expression ex = typeCombine(exp, sc))
10852         {
10853             result = ex;
10854             return;
10855         }
10856 
10857         Type tb = exp.type.toBasetype();
10858         if (tb.ty == Tarray || tb.ty == Tsarray)
10859         {
10860             if (!isArrayOpValid(exp))
10861             {
10862                 result = arrayOpInvalidError(exp);
10863                 return;
10864             }
10865             result = exp;
10866             return;
10867         }
10868         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10869         {
10870             result = exp.incompatibleTypes();
10871             return;
10872         }
10873         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10874             return setError();
10875 
10876         result = exp;
10877     }
10878 
10879     override void visit(LogicalExp exp)
10880     {
10881         static if (LOGSEMANTIC)
10882         {
10883             printf("LogicalExp::semantic() %s\n", exp.toChars());
10884         }
10885 
10886         if (exp.type)
10887         {
10888             result = exp;
10889             return;
10890         }
10891 
10892         exp.setNoderefOperands();
10893 
10894         Expression e1x = exp.e1.expressionSemantic(sc);
10895 
10896         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10897         if (e1x.op == TOK.type)
10898             e1x = resolveAliasThis(sc, e1x);
10899 
10900         e1x = resolveProperties(sc, e1x);
10901         e1x = e1x.toBoolean(sc);
10902 
10903         if (sc.flags & SCOPE.condition)
10904         {
10905             /* If in static if, don't evaluate e2 if we don't have to.
10906              */
10907             e1x = e1x.optimize(WANTvalue);
10908             if (e1x.isBool(exp.op == TOK.orOr))
10909             {
10910                 result = IntegerExp.createBool(exp.op == TOK.orOr);
10911                 return;
10912             }
10913         }
10914 
10915         CtorFlow ctorflow = sc.ctorflow.clone();
10916         Expression e2x = exp.e2.expressionSemantic(sc);
10917         sc.merge(exp.loc, ctorflow);
10918         ctorflow.freeFieldinit();
10919 
10920         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10921         if (e2x.op == TOK.type)
10922             e2x = resolveAliasThis(sc, e2x);
10923 
10924         e2x = resolveProperties(sc, e2x);
10925 
10926         auto f1 = checkNonAssignmentArrayOp(e1x);
10927         auto f2 = checkNonAssignmentArrayOp(e2x);
10928         if (f1 || f2)
10929             return setError();
10930 
10931         // Unless the right operand is 'void', the expression is converted to 'bool'.
10932         if (e2x.type.ty != Tvoid)
10933             e2x = e2x.toBoolean(sc);
10934 
10935         if (e2x.op == TOK.type || e2x.op == TOK.scope_)
10936         {
10937             exp.error("`%s` is not an expression", exp.e2.toChars());
10938             return setError();
10939         }
10940         if (e1x.op == TOK.error)
10941         {
10942             result = e1x;
10943             return;
10944         }
10945         if (e2x.op == TOK.error)
10946         {
10947             result = e2x;
10948             return;
10949         }
10950 
10951         // The result type is 'bool', unless the right operand has type 'void'.
10952         if (e2x.type.ty == Tvoid)
10953             exp.type = Type.tvoid;
10954         else
10955             exp.type = Type.tbool;
10956 
10957         exp.e1 = e1x;
10958         exp.e2 = e2x;
10959         result = exp;
10960     }
10961 
10962 
10963     override void visit(CmpExp exp)
10964     {
10965         static if (LOGSEMANTIC)
10966         {
10967             printf("CmpExp::semantic('%s')\n", exp.toChars());
10968         }
10969         if (exp.type)
10970         {
10971             result = exp;
10972             return;
10973         }
10974 
10975         exp.setNoderefOperands();
10976 
10977         if (Expression ex = binSemanticProp(exp, sc))
10978         {
10979             result = ex;
10980             return;
10981         }
10982         Type t1 = exp.e1.type.toBasetype();
10983         Type t2 = exp.e2.type.toBasetype();
10984         if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_)
10985         {
10986             exp.error("do not use `null` when comparing class types");
10987             return setError();
10988         }
10989 
10990         TOK cmpop;
10991         if (auto e = exp.op_overload(sc, &cmpop))
10992         {
10993             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
10994             {
10995                 exp.error("recursive `opCmp` expansion");
10996                 return setError();
10997             }
10998             if (e.op == TOK.call)
10999             {
11000                 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
11001                 e = e.expressionSemantic(sc);
11002             }
11003             result = e;
11004             return;
11005         }
11006 
11007         if (Expression ex = typeCombine(exp, sc))
11008         {
11009             result = ex;
11010             return;
11011         }
11012 
11013         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11014         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11015         if (f1 || f2)
11016             return setError();
11017 
11018         exp.type = Type.tbool;
11019 
11020         // Special handling for array comparisons
11021         Expression arrayLowering = null;
11022         t1 = exp.e1.type.toBasetype();
11023         t2 = exp.e2.type.toBasetype();
11024         if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
11025         {
11026             Type t1next = t1.nextOf();
11027             Type t2next = t2.nextOf();
11028             if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
11029             {
11030                 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
11031                 return setError();
11032             }
11033             if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
11034             {
11035                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
11036                     return setError();
11037 
11038                 // Lower to object.__cmp(e1, e2)
11039                 Expression al = new IdentifierExp(exp.loc, Id.empty);
11040                 al = new DotIdExp(exp.loc, al, Id.object);
11041                 al = new DotIdExp(exp.loc, al, Id.__cmp);
11042                 al = al.expressionSemantic(sc);
11043 
11044                 auto arguments = new Expressions(2);
11045                 (*arguments)[0] = exp.e1;
11046                 (*arguments)[1] = exp.e2;
11047 
11048                 al = new CallExp(exp.loc, al, arguments);
11049                 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
11050 
11051                 arrayLowering = al;
11052             }
11053         }
11054         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
11055         {
11056             if (t2.ty == Tstruct)
11057                 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
11058             else
11059                 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
11060             return setError();
11061         }
11062         else if (t1.iscomplex() || t2.iscomplex())
11063         {
11064             exp.error("compare not defined for complex operands");
11065             return setError();
11066         }
11067         else if (t1.ty == Taarray || t2.ty == Taarray)
11068         {
11069             exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op));
11070             return setError();
11071         }
11072         else if (!target.isVectorOpSupported(t1, exp.op, t2))
11073         {
11074             result = exp.incompatibleTypes();
11075             return;
11076         }
11077         else
11078         {
11079             bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
11080             bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
11081             if (r1 || r2)
11082                 return setError();
11083         }
11084 
11085         //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
11086         if (arrayLowering)
11087         {
11088             arrayLowering = arrayLowering.expressionSemantic(sc);
11089             result = arrayLowering;
11090             return;
11091         }
11092         result = exp;
11093         return;
11094     }
11095 
11096     override void visit(InExp exp)
11097     {
11098         if (exp.type)
11099         {
11100             result = exp;
11101             return;
11102         }
11103 
11104         if (Expression ex = binSemanticProp(exp, sc))
11105         {
11106             result = ex;
11107             return;
11108         }
11109         Expression e = exp.op_overload(sc);
11110         if (e)
11111         {
11112             result = e;
11113             return;
11114         }
11115 
11116         Type t2b = exp.e2.type.toBasetype();
11117         switch (t2b.ty)
11118         {
11119         case Taarray:
11120             {
11121                 TypeAArray ta = cast(TypeAArray)t2b;
11122 
11123                 // Special handling for array keys
11124                 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11125                 {
11126                     // Convert key to type of key
11127                     exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11128                 }
11129 
11130                 semanticTypeInfo(sc, ta.index);
11131 
11132                 // Return type is pointer to value
11133                 exp.type = ta.nextOf().pointerTo();
11134                 break;
11135             }
11136 
11137         case Terror:
11138             return setError();
11139 
11140         default:
11141             result = exp.incompatibleTypes();
11142             return;
11143         }
11144         result = exp;
11145     }
11146 
11147     override void visit(RemoveExp e)
11148     {
11149         if (Expression ex = binSemantic(e, sc))
11150         {
11151             result = ex;
11152             return;
11153         }
11154         result = e;
11155     }
11156 
11157     override void visit(EqualExp exp)
11158     {
11159         //printf("EqualExp::semantic('%s')\n", exp.toChars());
11160         if (exp.type)
11161         {
11162             result = exp;
11163             return;
11164         }
11165 
11166         exp.setNoderefOperands();
11167 
11168         if (auto e = binSemanticProp(exp, sc))
11169         {
11170             result = e;
11171             return;
11172         }
11173         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
11174         {
11175             /* https://issues.dlang.org/show_bug.cgi?id=12520
11176              * empty tuples are represented as types so special cases are added
11177              * so that they can be compared for equality with tuples of values.
11178              */
11179             static auto extractTypeTupAndExpTup(Expression e)
11180             {
11181                 static struct Result { bool ttEmpty; bool te; }
11182                 auto tt = e.op == TOK.type ? e.isTypeExp().type.isTypeTuple() : null;
11183                 return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
11184             }
11185             auto tups1 = extractTypeTupAndExpTup(exp.e1);
11186             auto tups2 = extractTypeTupAndExpTup(exp.e2);
11187             // AliasSeq!() == AliasSeq!(<at least a value>)
11188             if (tups1.ttEmpty && tups2.te)
11189             {
11190                 result = IntegerExp.createBool(exp.op != TOK.equal);
11191                 return;
11192             }
11193             // AliasSeq!(<at least a value>) == AliasSeq!()
11194             else if (tups1.te && tups2.ttEmpty)
11195             {
11196                 result = IntegerExp.createBool(exp.op != TOK.equal);
11197                 return;
11198             }
11199             // AliasSeq!() == AliasSeq!()
11200             else if (tups1.ttEmpty && tups2.ttEmpty)
11201             {
11202                 result = IntegerExp.createBool(exp.op == TOK.equal);
11203                 return;
11204             }
11205             // otherwise, two types are really not comparable
11206             result = exp.incompatibleTypes();
11207             return;
11208         }
11209 
11210         {
11211             auto t1 = exp.e1.type;
11212             auto t2 = exp.e2.type;
11213             if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11214                 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11215                     t1.toChars(), t2.toChars());
11216         }
11217 
11218         /* Before checking for operator overloading, check to see if we're
11219          * comparing the addresses of two statics. If so, we can just see
11220          * if they are the same symbol.
11221          */
11222         if (exp.e1.op == TOK.address && exp.e2.op == TOK.address)
11223         {
11224             AddrExp ae1 = cast(AddrExp)exp.e1;
11225             AddrExp ae2 = cast(AddrExp)exp.e2;
11226             if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable)
11227             {
11228                 VarExp ve1 = cast(VarExp)ae1.e1;
11229                 VarExp ve2 = cast(VarExp)ae2.e1;
11230                 if (ve1.var == ve2.var)
11231                 {
11232                     // They are the same, result is 'true' for ==, 'false' for !=
11233                     result = IntegerExp.createBool(exp.op == TOK.equal);
11234                     return;
11235                 }
11236             }
11237         }
11238 
11239         Type t1 = exp.e1.type.toBasetype();
11240         Type t2 = exp.e2.type.toBasetype();
11241 
11242         // Indicates whether the comparison of the 2 specified array types
11243         // requires an object.__equals() lowering.
11244         static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11245         {
11246             Type t1n = t1.nextOf().toBasetype();
11247             Type t2n = t2.nextOf().toBasetype();
11248             if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11249                 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11250             {
11251                 return false;
11252             }
11253             if (t1n.constOf() != t2n.constOf())
11254                 return true;
11255 
11256             Type t = t1n;
11257             while (t.toBasetype().nextOf())
11258                 t = t.nextOf().toBasetype();
11259             if (auto ts = t.isTypeStruct())
11260             {
11261                 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11262                 if (global.params.useTypeInfo && Type.dtypeinfo)
11263                     semanticTypeInfo(sc, ts);
11264 
11265                 return ts.sym.hasIdentityEquals; // has custom opEquals
11266             }
11267 
11268             return false;
11269         }
11270 
11271         if (auto e = exp.op_overload(sc))
11272         {
11273             result = e;
11274             return;
11275         }
11276 
11277 
11278         const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11279                                   (t2.ty == Tarray || t2.ty == Tsarray);
11280         const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11281 
11282         if (!needsArrayLowering)
11283         {
11284             if (auto e = typeCombine(exp, sc))
11285             {
11286                 result = e;
11287                 return;
11288             }
11289         }
11290 
11291         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11292         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11293         if (f1 || f2)
11294             return setError();
11295 
11296         exp.type = Type.tbool;
11297 
11298         if (!isArrayComparison)
11299         {
11300             if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11301             {
11302                 // Cast both to complex
11303                 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11304                 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11305             }
11306         }
11307 
11308         // lower some array comparisons to object.__equals(e1, e2)
11309         if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
11310         {
11311             //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
11312 
11313             if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
11314                 return setError();
11315 
11316             Expression __equals = new IdentifierExp(exp.loc, Id.empty);
11317             Identifier id = Identifier.idPool("__equals");
11318             __equals = new DotIdExp(exp.loc, __equals, Id.object);
11319             __equals = new DotIdExp(exp.loc, __equals, id);
11320 
11321             auto arguments = new Expressions(2);
11322             (*arguments)[0] = exp.e1;
11323             (*arguments)[1] = exp.e2;
11324 
11325             __equals = new CallExp(exp.loc, __equals, arguments);
11326             if (exp.op == TOK.notEqual)
11327             {
11328                 __equals = new NotExp(exp.loc, __equals);
11329             }
11330             __equals = __equals.trySemantic(sc); // for better error message
11331             if (!__equals)
11332             {
11333                 exp.error("incompatible types for array comparison: `%s` and `%s`",
11334                           exp.e1.type.toChars(), exp.e2.type.toChars());
11335                 __equals = ErrorExp.get();
11336             }
11337 
11338             result = __equals;
11339             return;
11340         }
11341 
11342         if (exp.e1.type.toBasetype().ty == Taarray)
11343             semanticTypeInfo(sc, exp.e1.type.toBasetype());
11344 
11345 
11346         if (!target.isVectorOpSupported(t1, exp.op, t2))
11347         {
11348             result = exp.incompatibleTypes();
11349             return;
11350         }
11351 
11352         result = exp;
11353     }
11354 
11355     override void visit(IdentityExp exp)
11356     {
11357         if (exp.type)
11358         {
11359             result = exp;
11360             return;
11361         }
11362 
11363         exp.setNoderefOperands();
11364 
11365         if (auto e = binSemanticProp(exp, sc))
11366         {
11367             result = e;
11368             return;
11369         }
11370 
11371         if (auto e = typeCombine(exp, sc))
11372         {
11373             result = e;
11374             return;
11375         }
11376 
11377         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11378         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11379         if (f1 || f2)
11380             return setError();
11381 
11382         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
11383         {
11384             result = exp.incompatibleTypes();
11385             return;
11386         }
11387 
11388         exp.type = Type.tbool;
11389 
11390         if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11391         {
11392             // Cast both to complex
11393             exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11394             exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11395         }
11396 
11397         auto tb1 = exp.e1.type.toBasetype();
11398         auto tb2 = exp.e2.type.toBasetype();
11399         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
11400         {
11401             result = exp.incompatibleTypes();
11402             return;
11403         }
11404 
11405         if (exp.e1.op == TOK.call)
11406             exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
11407         if (exp.e2.op == TOK.call)
11408             exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
11409 
11410         if (exp.e1.type.toBasetype().ty == Tsarray ||
11411             exp.e2.type.toBasetype().ty == Tsarray)
11412             exp.deprecation("identity comparison of static arrays "
11413                 ~ "implicitly coerces them to slices, "
11414                 ~ "which are compared by reference");
11415 
11416         result = exp;
11417     }
11418 
11419     override void visit(CondExp exp)
11420     {
11421         static if (LOGSEMANTIC)
11422         {
11423             printf("CondExp::semantic('%s')\n", exp.toChars());
11424         }
11425         if (exp.type)
11426         {
11427             result = exp;
11428             return;
11429         }
11430 
11431         if (exp.econd.op == TOK.dotIdentifier)
11432             (cast(DotIdExp)exp.econd).noderef = true;
11433 
11434         Expression ec = exp.econd.expressionSemantic(sc);
11435         ec = resolveProperties(sc, ec);
11436         ec = ec.toBoolean(sc);
11437 
11438         CtorFlow ctorflow_root = sc.ctorflow.clone();
11439         Expression e1x = exp.e1.expressionSemantic(sc);
11440         e1x = resolveProperties(sc, e1x);
11441 
11442         CtorFlow ctorflow1 = sc.ctorflow;
11443         sc.ctorflow = ctorflow_root;
11444         Expression e2x = exp.e2.expressionSemantic(sc);
11445         e2x = resolveProperties(sc, e2x);
11446 
11447         sc.merge(exp.loc, ctorflow1);
11448         ctorflow1.freeFieldinit();
11449 
11450         if (ec.op == TOK.error)
11451         {
11452             result = ec;
11453             return;
11454         }
11455         if (ec.type == Type.terror)
11456             return setError();
11457         exp.econd = ec;
11458 
11459         if (e1x.op == TOK.error)
11460         {
11461             result = e1x;
11462             return;
11463         }
11464         if (e1x.type == Type.terror)
11465             return setError();
11466         exp.e1 = e1x;
11467 
11468         if (e2x.op == TOK.error)
11469         {
11470             result = e2x;
11471             return;
11472         }
11473         if (e2x.type == Type.terror)
11474             return setError();
11475         exp.e2 = e2x;
11476 
11477         auto f0 = checkNonAssignmentArrayOp(exp.econd);
11478         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11479         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11480         if (f0 || f1 || f2)
11481             return setError();
11482 
11483         Type t1 = exp.e1.type;
11484         Type t2 = exp.e2.type;
11485         // If either operand is void the result is void, we have to cast both
11486         // the expression to void so that we explicitly discard the expression
11487         // value if any
11488         // https://issues.dlang.org/show_bug.cgi?id=16598
11489         if (t1.ty == Tvoid || t2.ty == Tvoid)
11490         {
11491             exp.type = Type.tvoid;
11492             exp.e1 = exp.e1.castTo(sc, exp.type);
11493             exp.e2 = exp.e2.castTo(sc, exp.type);
11494         }
11495         else if (t1 == t2)
11496             exp.type = t1;
11497         else
11498         {
11499             if (Expression ex = typeCombine(exp, sc))
11500             {
11501                 result = ex;
11502                 return;
11503             }
11504 
11505             switch (exp.e1.type.toBasetype().ty)
11506             {
11507             case Tcomplex32:
11508             case Tcomplex64:
11509             case Tcomplex80:
11510                 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
11511                 break;
11512             default:
11513                 break;
11514             }
11515             switch (exp.e2.type.toBasetype().ty)
11516             {
11517             case Tcomplex32:
11518             case Tcomplex64:
11519             case Tcomplex80:
11520                 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
11521                 break;
11522             default:
11523                 break;
11524             }
11525             if (exp.type.toBasetype().ty == Tarray)
11526             {
11527                 exp.e1 = exp.e1.castTo(sc, exp.type);
11528                 exp.e2 = exp.e2.castTo(sc, exp.type);
11529             }
11530         }
11531         exp.type = exp.type.merge2();
11532         version (none)
11533         {
11534             printf("res: %s\n", exp.type.toChars());
11535             printf("e1 : %s\n", exp.e1.type.toChars());
11536             printf("e2 : %s\n", exp.e2.type.toChars());
11537         }
11538 
11539         /* https://issues.dlang.org/show_bug.cgi?id=14696
11540          * If either e1 or e2 contain temporaries which need dtor,
11541          * make them conditional.
11542          * Rewrite:
11543          *      cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
11544          * to:
11545          *      (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
11546          * and replace edtors of __tmp1 and __tmp2 with:
11547          *      __tmp1.edtor --> __cond && __tmp1.dtor()
11548          *      __tmp2.edtor --> __cond || __tmp2.dtor()
11549          */
11550         exp.hookDtors(sc);
11551 
11552         result = exp;
11553     }
11554 
11555     override void visit(FileInitExp e)
11556     {
11557         //printf("FileInitExp::semantic()\n");
11558         e.type = Type.tstring;
11559         result = e;
11560     }
11561 
11562     override void visit(LineInitExp e)
11563     {
11564         e.type = Type.tint32;
11565         result = e;
11566     }
11567 
11568     override void visit(ModuleInitExp e)
11569     {
11570         //printf("ModuleInitExp::semantic()\n");
11571         e.type = Type.tstring;
11572         result = e;
11573     }
11574 
11575     override void visit(FuncInitExp e)
11576     {
11577         //printf("FuncInitExp::semantic()\n");
11578         e.type = Type.tstring;
11579         if (sc.func)
11580         {
11581             result = e.resolveLoc(Loc.initial, sc);
11582             return;
11583         }
11584         result = e;
11585     }
11586 
11587     override void visit(PrettyFuncInitExp e)
11588     {
11589         //printf("PrettyFuncInitExp::semantic()\n");
11590         e.type = Type.tstring;
11591         if (sc.func)
11592         {
11593             result = e.resolveLoc(Loc.initial, sc);
11594             return;
11595         }
11596 
11597         result = e;
11598     }
11599 }
11600 
11601 /**********************************
11602  * Try to run semantic routines.
11603  * If they fail, return NULL.
11604  */
11605 Expression trySemantic(Expression exp, Scope* sc)
11606 {
11607     //printf("+trySemantic(%s)\n", exp.toChars());
11608     uint errors = global.startGagging();
11609     Expression e = expressionSemantic(exp, sc);
11610     if (global.endGagging(errors))
11611     {
11612         e = null;
11613     }
11614     //printf("-trySemantic(%s)\n", exp.toChars());
11615     return e;
11616 }
11617 
11618 /**************************
11619  * Helper function for easy error propagation.
11620  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11621  */
11622 Expression unaSemantic(UnaExp e, Scope* sc)
11623 {
11624     static if (LOGSEMANTIC)
11625     {
11626         printf("UnaExp::semantic('%s')\n", e.toChars());
11627     }
11628     Expression e1x = e.e1.expressionSemantic(sc);
11629     if (e1x.op == TOK.error)
11630         return e1x;
11631     e.e1 = e1x;
11632     return null;
11633 }
11634 
11635 /**************************
11636  * Helper function for easy error propagation.
11637  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11638  */
11639 Expression binSemantic(BinExp e, Scope* sc)
11640 {
11641     static if (LOGSEMANTIC)
11642     {
11643         printf("BinExp::semantic('%s')\n", e.toChars());
11644     }
11645     Expression e1x = e.e1.expressionSemantic(sc);
11646     Expression e2x = e.e2.expressionSemantic(sc);
11647 
11648     // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11649     if (e1x.op == TOK.type)
11650         e1x = resolveAliasThis(sc, e1x);
11651     if (e2x.op == TOK.type)
11652         e2x = resolveAliasThis(sc, e2x);
11653 
11654     if (e1x.op == TOK.error)
11655         return e1x;
11656     if (e2x.op == TOK.error)
11657         return e2x;
11658     e.e1 = e1x;
11659     e.e2 = e2x;
11660     return null;
11661 }
11662 
11663 Expression binSemanticProp(BinExp e, Scope* sc)
11664 {
11665     if (Expression ex = binSemantic(e, sc))
11666         return ex;
11667     Expression e1x = resolveProperties(sc, e.e1);
11668     Expression e2x = resolveProperties(sc, e.e2);
11669     if (e1x.op == TOK.error)
11670         return e1x;
11671     if (e2x.op == TOK.error)
11672         return e2x;
11673     e.e1 = e1x;
11674     e.e2 = e2x;
11675     return null;
11676 }
11677 
11678 // entrypoint for semantic ExpressionSemanticVisitor
11679 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
11680 {
11681     scope v = new ExpressionSemanticVisitor(sc);
11682     e.accept(v);
11683     return v.result;
11684 }
11685 
11686 Expression semanticX(DotIdExp exp, Scope* sc)
11687 {
11688     //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
11689     if (Expression ex = unaSemantic(exp, sc))
11690         return ex;
11691 
11692     if (exp.ident == Id._mangleof)
11693     {
11694         // symbol.mangleof
11695         Dsymbol ds;
11696         switch (exp.e1.op)
11697         {
11698         case TOK.scope_:
11699             ds = (cast(ScopeExp)exp.e1).sds;
11700             goto L1;
11701         case TOK.variable:
11702             ds = (cast(VarExp)exp.e1).var;
11703             goto L1;
11704         case TOK.dotVariable:
11705             ds = (cast(DotVarExp)exp.e1).var;
11706             goto L1;
11707         case TOK.overloadSet:
11708             ds = (cast(OverExp)exp.e1).vars;
11709             goto L1;
11710         case TOK.template_:
11711             {
11712                 TemplateExp te = cast(TemplateExp)exp.e1;
11713                 ds = te.fd ? cast(Dsymbol)te.fd : te.td;
11714             }
11715         L1:
11716             {
11717                 assert(ds);
11718                 if (auto f = ds.isFuncDeclaration())
11719                 {
11720                     if (f.checkForwardRef(exp.loc))
11721                     {
11722                         return ErrorExp.get();
11723                     }
11724                     if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
11725                                    FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
11726                     {
11727                         f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes");
11728                         return ErrorExp.get();
11729                     }
11730                 }
11731                 OutBuffer buf;
11732                 mangleToBuffer(ds, &buf);
11733                 Expression e = new StringExp(exp.loc, buf.extractSlice());
11734                 e = e.expressionSemantic(sc);
11735                 return e;
11736             }
11737         default:
11738             break;
11739         }
11740     }
11741 
11742     if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length)
11743     {
11744         // bypass checkPurity
11745         return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
11746     }
11747 
11748     if (exp.e1.op == TOK.dot)
11749     {
11750     }
11751     else
11752     {
11753         exp.e1 = resolvePropertiesX(sc, exp.e1);
11754     }
11755     if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof)
11756     {
11757         /* 'distribute' the .offsetof to each of the tuple elements.
11758          */
11759         TupleExp te = cast(TupleExp)exp.e1;
11760         auto exps = new Expressions(te.exps.dim);
11761         for (size_t i = 0; i < exps.dim; i++)
11762         {
11763             Expression e = (*te.exps)[i];
11764             e = e.expressionSemantic(sc);
11765             e = new DotIdExp(e.loc, e, Id.offsetof);
11766             (*exps)[i] = e;
11767         }
11768         // Don't evaluate te.e0 in runtime
11769         Expression e = new TupleExp(exp.loc, null, exps);
11770         e = e.expressionSemantic(sc);
11771         return e;
11772     }
11773     if (exp.e1.op == TOK.tuple && exp.ident == Id.length)
11774     {
11775         TupleExp te = cast(TupleExp)exp.e1;
11776         // Don't evaluate te.e0 in runtime
11777         Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
11778         return e;
11779     }
11780 
11781     // https://issues.dlang.org/show_bug.cgi?id=14416
11782     // Template has no built-in properties except for 'stringof'.
11783     if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof)
11784     {
11785         exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11786         return ErrorExp.get();
11787     }
11788     if (!exp.e1.type)
11789     {
11790         exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11791         return ErrorExp.get();
11792     }
11793 
11794     return exp;
11795 }
11796 
11797 // Resolve e1.ident without seeing UFCS.
11798 // If flag == 1, stop "not a property" error and return NULL.
11799 Expression semanticY(DotIdExp exp, Scope* sc, int flag)
11800 {
11801     //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
11802 
11803     //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
11804 
11805     /* Special case: rewrite this.id and super.id
11806      * to be classtype.id and baseclasstype.id
11807      * if we have no this pointer.
11808      */
11809     if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc))
11810     {
11811         if (AggregateDeclaration ad = sc.getStructClassScope())
11812         {
11813             if (exp.e1.op == TOK.this_)
11814             {
11815                 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
11816             }
11817             else
11818             {
11819                 ClassDeclaration cd = ad.isClassDeclaration();
11820                 if (cd && cd.baseClass)
11821                     exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
11822             }
11823         }
11824     }
11825 
11826     Expression e = semanticX(exp, sc);
11827     if (e != exp)
11828         return e;
11829 
11830     Expression eleft;
11831     Expression eright;
11832     if (exp.e1.op == TOK.dot)
11833     {
11834         DotExp de = cast(DotExp)exp.e1;
11835         eleft = de.e1;
11836         eright = de.e2;
11837     }
11838     else
11839     {
11840         eleft = null;
11841         eright = exp.e1;
11842     }
11843 
11844     Type t1b = exp.e1.type.toBasetype();
11845 
11846     if (eright.op == TOK.scope_) // also used for template alias's
11847     {
11848         ScopeExp ie = cast(ScopeExp)eright;
11849 
11850         int flags = SearchLocalsOnly;
11851         /* Disable access to another module's private imports.
11852          * The check for 'is sds our current module' is because
11853          * the current module should have access to its own imports.
11854          */
11855         if (ie.sds.isModule() && ie.sds != sc._module)
11856             flags |= IgnorePrivateImports;
11857         if (sc.flags & SCOPE.ignoresymbolvisibility)
11858             flags |= IgnoreSymbolVisibility;
11859         Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
11860         /* Check for visibility before resolving aliases because public
11861          * aliases to private symbols are public.
11862          */
11863         if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
11864         {
11865             s = null;
11866         }
11867         if (s)
11868         {
11869             auto p = s.isPackage();
11870             if (p && checkAccess(sc, p))
11871             {
11872                 s = null;
11873             }
11874         }
11875         if (s)
11876         {
11877             // if 's' is a tuple variable, the tuple is returned.
11878             s = s.toAlias();
11879 
11880             exp.checkDeprecated(sc, s);
11881             exp.checkDisabled(sc, s);
11882 
11883             EnumMember em = s.isEnumMember();
11884             if (em)
11885             {
11886                 return em.getVarExp(exp.loc, sc);
11887             }
11888             VarDeclaration v = s.isVarDeclaration();
11889             if (v)
11890             {
11891                 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
11892                 if (!v.type ||
11893                     !v.type.deco && v.inuse)
11894                 {
11895                     if (v.inuse)
11896                         exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
11897                     else
11898                         exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
11899                     return ErrorExp.get();
11900                 }
11901                 if (v.type.ty == Terror)
11902                     return ErrorExp.get();
11903 
11904                 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
11905                 {
11906                     /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
11907                      * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
11908                      * be reverted. `wantsym` is the hack to work around the problem.
11909                      */
11910                     if (v.inuse)
11911                     {
11912                         error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
11913                         return ErrorExp.get();
11914                     }
11915                     e = v.expandInitializer(exp.loc);
11916                     v.inuse++;
11917                     e = e.expressionSemantic(sc);
11918                     v.inuse--;
11919                     return e;
11920                 }
11921 
11922                 if (v.needThis())
11923                 {
11924                     if (!eleft)
11925                         eleft = new ThisExp(exp.loc);
11926                     e = new DotVarExp(exp.loc, eleft, v);
11927                     e = e.expressionSemantic(sc);
11928                 }
11929                 else
11930                 {
11931                     e = new VarExp(exp.loc, v);
11932                     if (eleft)
11933                     {
11934                         e = new CommaExp(exp.loc, eleft, e);
11935                         e.type = v.type;
11936                     }
11937                 }
11938                 e = e.deref();
11939                 return e.expressionSemantic(sc);
11940             }
11941 
11942             FuncDeclaration f = s.isFuncDeclaration();
11943             if (f)
11944             {
11945                 //printf("it's a function\n");
11946                 if (!f.functionSemantic())
11947                     return ErrorExp.get();
11948                 if (f.needThis())
11949                 {
11950                     if (!eleft)
11951                         eleft = new ThisExp(exp.loc);
11952                     e = new DotVarExp(exp.loc, eleft, f, true);
11953                     e = e.expressionSemantic(sc);
11954                 }
11955                 else
11956                 {
11957                     e = new VarExp(exp.loc, f, true);
11958                     if (eleft)
11959                     {
11960                         e = new CommaExp(exp.loc, eleft, e);
11961                         e.type = f.type;
11962                     }
11963                 }
11964                 return e;
11965             }
11966             if (auto td = s.isTemplateDeclaration())
11967             {
11968                 if (eleft)
11969                     e = new DotTemplateExp(exp.loc, eleft, td);
11970                 else
11971                     e = new TemplateExp(exp.loc, td);
11972                 e = e.expressionSemantic(sc);
11973                 return e;
11974             }
11975             if (OverDeclaration od = s.isOverDeclaration())
11976             {
11977                 e = new VarExp(exp.loc, od, true);
11978                 if (eleft)
11979                 {
11980                     e = new CommaExp(exp.loc, eleft, e);
11981                     e.type = Type.tvoid; // ambiguous type?
11982                 }
11983                 return e;
11984             }
11985             OverloadSet o = s.isOverloadSet();
11986             if (o)
11987             {
11988                 //printf("'%s' is an overload set\n", o.toChars());
11989                 return new OverExp(exp.loc, o);
11990             }
11991 
11992             if (auto t = s.getType())
11993             {
11994                 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
11995             }
11996 
11997             TupleDeclaration tup = s.isTupleDeclaration();
11998             if (tup)
11999             {
12000                 if (eleft)
12001                 {
12002                     e = new DotVarExp(exp.loc, eleft, tup);
12003                     e = e.expressionSemantic(sc);
12004                     return e;
12005                 }
12006                 e = new TupleExp(exp.loc, tup);
12007                 e = e.expressionSemantic(sc);
12008                 return e;
12009             }
12010 
12011             ScopeDsymbol sds = s.isScopeDsymbol();
12012             if (sds)
12013             {
12014                 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
12015                 e = new ScopeExp(exp.loc, sds);
12016                 e = e.expressionSemantic(sc);
12017                 if (eleft)
12018                     e = new DotExp(exp.loc, eleft, e);
12019                 return e;
12020             }
12021 
12022             Import imp = s.isImport();
12023             if (imp)
12024             {
12025                 ie = new ScopeExp(exp.loc, imp.pkg);
12026                 return ie.expressionSemantic(sc);
12027             }
12028             // BUG: handle other cases like in IdentifierExp::semantic()
12029             debug
12030             {
12031                 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
12032             }
12033             assert(0);
12034         }
12035         else if (exp.ident == Id.stringof)
12036         {
12037             e = new StringExp(exp.loc, ie.toString());
12038             e = e.expressionSemantic(sc);
12039             return e;
12040         }
12041         if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
12042         {
12043             flag = 0;
12044         }
12045         if (flag)
12046             return null;
12047         s = ie.sds.search_correct(exp.ident);
12048         if (s && symbolIsVisible(sc, s))
12049         {
12050             if (s.isPackage())
12051                 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
12052             else
12053                 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());
12054         }
12055         else
12056             exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
12057         return ErrorExp.get();
12058     }
12059     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)
12060     {
12061         Type t1bn = t1b.nextOf();
12062         if (flag)
12063         {
12064             AggregateDeclaration ad = isAggregate(t1bn);
12065             if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
12066                 return null;
12067         }
12068 
12069         /* Rewrite:
12070          *   p.ident
12071          * as:
12072          *   (*p).ident
12073          */
12074         if (flag && t1bn.ty == Tvoid)
12075             return null;
12076         e = new PtrExp(exp.loc, exp.e1);
12077         e = e.expressionSemantic(sc);
12078         return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12079     }
12080     else
12081     {
12082         if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_)
12083             flag = 0;
12084         e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12085         if (e)
12086             e = e.expressionSemantic(sc);
12087         return e;
12088     }
12089 }
12090 
12091 // Resolve e1.ident!tiargs without seeing UFCS.
12092 // If flag == 1, stop "not a property" error and return NULL.
12093 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
12094 {
12095     static if (LOGSEMANTIC)
12096     {
12097         printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
12098     }
12099 
12100     static Expression errorExp()
12101     {
12102         return ErrorExp.get();
12103     }
12104 
12105     Expression e1 = exp.e1;
12106 
12107     if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
12108     {
12109         // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
12110         // and do the symbol search in that context (Issue: 19476)
12111         auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
12112         e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12113     }
12114 
12115     auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12116 
12117     Expression e = die.semanticX(sc);
12118     if (e == die)
12119     {
12120         exp.e1 = die.e1; // take back
12121         Type t1b = exp.e1.type.toBasetype();
12122         if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12123         {
12124             /* No built-in type has templatized properties, so do shortcut.
12125              * It is necessary in: 1024.max!"a < b"
12126              */
12127             if (flag)
12128                 return null;
12129         }
12130         e = die.semanticY(sc, flag);
12131         if (flag)
12132         {
12133             if (!e ||
12134                 isDotOpDispatch(e))
12135             {
12136                 /* opDispatch!tiargs would be a function template that needs IFTI,
12137                  * so it's not a template
12138                  */
12139                 return null;
12140             }
12141         }
12142     }
12143     assert(e);
12144 
12145     if (e.op == TOK.error)
12146         return e;
12147     if (e.op == TOK.dotVariable)
12148     {
12149         DotVarExp dve = cast(DotVarExp)e;
12150         if (FuncDeclaration fd = dve.var.isFuncDeclaration())
12151         {
12152             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12153             {
12154                 e = new DotTemplateExp(dve.loc, dve.e1, td);
12155                 e = e.expressionSemantic(sc);
12156             }
12157         }
12158         else if (OverDeclaration od = dve.var.isOverDeclaration())
12159         {
12160             exp.e1 = dve.e1; // pull semantic() result
12161 
12162             if (!exp.findTempDecl(sc))
12163                 goto Lerr;
12164             if (exp.ti.needsTypeInference(sc))
12165                 return exp;
12166             exp.ti.dsymbolSemantic(sc);
12167             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12168                 return errorExp();
12169 
12170             if (Declaration v = exp.ti.toAlias().isDeclaration())
12171             {
12172                 if (v.type && !v.type.deco)
12173                     v.type = v.type.typeSemantic(v.loc, sc);
12174                 return new DotVarExp(exp.loc, exp.e1, v)
12175                        .expressionSemantic(sc);
12176             }
12177             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12178                    .expressionSemantic(sc);
12179         }
12180     }
12181     else if (e.op == TOK.variable)
12182     {
12183         VarExp ve = cast(VarExp)e;
12184         if (FuncDeclaration fd = ve.var.isFuncDeclaration())
12185         {
12186             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12187             {
12188                 e = new TemplateExp(ve.loc, td)
12189                     .expressionSemantic(sc);
12190             }
12191         }
12192         else if (OverDeclaration od = ve.var.isOverDeclaration())
12193         {
12194             exp.ti.tempdecl = od;
12195             return new ScopeExp(exp.loc, exp.ti)
12196                    .expressionSemantic(sc);
12197         }
12198     }
12199 
12200     if (e.op == TOK.dotTemplateDeclaration)
12201     {
12202         DotTemplateExp dte = cast(DotTemplateExp)e;
12203         exp.e1 = dte.e1; // pull semantic() result
12204 
12205         exp.ti.tempdecl = dte.td;
12206         if (!exp.ti.semanticTiargs(sc))
12207             return errorExp();
12208         if (exp.ti.needsTypeInference(sc))
12209             return exp;
12210         exp.ti.dsymbolSemantic(sc);
12211         if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12212             return errorExp();
12213 
12214         if (Declaration v = exp.ti.toAlias().isDeclaration())
12215         {
12216             if (v.isFuncDeclaration() || v.isVarDeclaration())
12217             {
12218                 return new DotVarExp(exp.loc, exp.e1, v)
12219                        .expressionSemantic(sc);
12220             }
12221         }
12222         return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12223                .expressionSemantic(sc);
12224     }
12225     else if (e.op == TOK.template_)
12226     {
12227         exp.ti.tempdecl = (cast(TemplateExp)e).td;
12228         return new ScopeExp(exp.loc, exp.ti)
12229                .expressionSemantic(sc);
12230     }
12231     else if (e.op == TOK.dot)
12232     {
12233         DotExp de = cast(DotExp)e;
12234 
12235         if (de.e2.op == TOK.overloadSet)
12236         {
12237             if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
12238             {
12239                 return errorExp();
12240             }
12241             if (exp.ti.needsTypeInference(sc))
12242                 return exp;
12243             exp.ti.dsymbolSemantic(sc);
12244             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12245                 return errorExp();
12246 
12247             if (Declaration v = exp.ti.toAlias().isDeclaration())
12248             {
12249                 if (v.type && !v.type.deco)
12250                     v.type = v.type.typeSemantic(v.loc, sc);
12251                 return new DotVarExp(exp.loc, exp.e1, v)
12252                        .expressionSemantic(sc);
12253             }
12254             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12255                    .expressionSemantic(sc);
12256         }
12257     }
12258     else if (e.op == TOK.overloadSet)
12259     {
12260         OverExp oe = cast(OverExp)e;
12261         exp.ti.tempdecl = oe.vars;
12262         return new ScopeExp(exp.loc, exp.ti)
12263                .expressionSemantic(sc);
12264     }
12265 
12266 Lerr:
12267     exp.error("`%s` isn't a template", e.toChars());
12268     return errorExp();
12269 }
12270 
12271 /***************************************
12272  * If expression is shared, check that we can access it.
12273  * Give error message if not.
12274  *
12275  * Params:
12276  *      e = expression to check
12277  *      sc = context
12278  *      returnRef = Whether this expression is for a `return` statement
12279  *                  off a `ref` function, in which case a single level
12280  *                  of dereference is allowed (e.g. `shared(int)*`).
12281  * Returns:
12282  *      true on error
12283  */
12284 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
12285 {
12286     if (!global.params.noSharedAccess ||
12287         sc.intypeof ||
12288         sc.flags & SCOPE.ctfe)
12289     {
12290         return false;
12291     }
12292 
12293     //printf("checkSharedAccess() %s\n", e.toChars());
12294 
12295     static extern(C++) final class SharedCheckVisitor : SemanticTimeTransitiveVisitor
12296     {
12297         /// In case we don't know which expression triggered it,
12298         /// e.g. for `visit(Type)` overload
12299         Expression original;
12300         /// Where the result is stored (`true` == error)
12301         bool result;
12302         /// Whether we should allow one level of dereferencing
12303         bool allowRef;
12304 
12305         /// Ctor
12306         this(Expression oe, bool allowRef_)
12307         {
12308             this.original = oe;
12309             this.allowRef = allowRef_;
12310         }
12311 
12312         void sharedError(Expression e)
12313         {
12314             // https://dlang.org/phobos/core_atomic.html
12315             e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
12316             this.result = true;
12317         }
12318 
12319         /// Introduce base class overrides
12320         alias visit = SemanticTimeTransitiveVisitor.visit;
12321 
12322         // Error by default
12323         override void visit(Expression e)
12324         {
12325             if (e.type.isShared())
12326                 this.sharedError(e);
12327         }
12328 
12329         /// Ditto
12330         override void visit(Type t)
12331         {
12332             // Note: This handles things like `new shared(Throwable).msg`,
12333             // where accessing `msg` would violate `shared`.
12334             if (t.isShared())
12335                 this.sharedError(this.original);
12336         }
12337 
12338         // Those have no indirections / can be ignored
12339         override void visit(ErrorExp e) {}
12340         override void visit(ComplexExp e) {}
12341         override void visit(IntegerExp e) {}
12342         override void visit(NullExp e) {}
12343 
12344         override void visit(VarExp e)
12345         {
12346             if (!this.allowRef && e.var.type.isShared())
12347                 this.sharedError(e);
12348         }
12349 
12350         override void visit(AddrExp e)
12351         {
12352             this.allowRef = true;
12353             e.e1.accept(this);
12354         }
12355 
12356         override void visit(PtrExp e)
12357         {
12358             if (!this.allowRef && e.type.isShared())
12359                 return this.sharedError(e);
12360 
12361             if (e.e1.type.isShared())
12362                 return this.sharedError(e);
12363 
12364             this.allowRef = false;
12365             e.e1.accept(this);
12366         }
12367 
12368         override void visit(DotVarExp e)
12369         {
12370             if (!this.allowRef && e.type.isShared())
12371                 return this.sharedError(e);
12372 
12373             // Allow to use `DotVarExp` within value types
12374             if (e.e1.type.ty == Tsarray || e.e1.type.ty == Tstruct)
12375                 return e.e1.accept(this);
12376 
12377             // If we end up with a single `VarExp`, it might be a `ref` param
12378             // `shared ref T` param == `shared(T)*`.
12379             if (auto ve = e.e1.isVarExp())
12380             {
12381                 this.allowRef = this.allowRef && (ve.var.storage_class & STC.ref_);
12382                 return e.e1.accept(this);
12383             }
12384 
12385             this.allowRef = false;
12386             return e.e1.accept(this);
12387         }
12388 
12389         override void visit(IndexExp e)
12390         {
12391             if (!this.allowRef && e.type.isShared())
12392                 return this.sharedError(e);
12393 
12394             if (e.e1.type.isShared())
12395                 return this.sharedError(e);
12396 
12397             this.allowRef = false;
12398             e.e1.accept(this);
12399         }
12400 
12401         override void visit(CommaExp e)
12402         {
12403             // Cannot be `return ref` since we can't use the return,
12404             // but it's better to show that error than an unrelated `shared` one
12405             this.allowRef = true;
12406             e.e2.accept(this);
12407         }
12408     }
12409 
12410     scope visitor = new SharedCheckVisitor(e, returnRef);
12411     e.accept(visitor);
12412     return visitor.result;
12413 }
12414 
12415 
12416 
12417 /****************************************************
12418  * Determine if `exp`, which gets its address taken, can do so safely.
12419  * Params:
12420  *      sc = context
12421  *      exp = expression having its address taken
12422  *      v = the variable getting its address taken
12423  * Returns:
12424  *      `true` if ok, `false` for error
12425  */
12426 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
12427 {
12428     //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
12429     if (v)
12430     {
12431         if (!v.canTakeAddressOf())
12432         {
12433             exp.error("cannot take address of `%s`", exp.toChars());
12434             return false;
12435         }
12436         if (sc.func && !sc.intypeof && !v.isDataseg())
12437         {
12438             const(char)* p = v.isParameter() ? "parameter" : "local";
12439             if (global.params.vsafe)
12440             {
12441                 // Taking the address of v means it cannot be set to 'scope' later
12442                 v.storage_class &= ~STC.maybescope;
12443                 v.doNotInferScope = true;
12444                 if (exp.type.hasPointers() && v.storage_class & STC.scope_ &&
12445                     !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
12446                 {
12447                     exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12448                     return false;
12449                 }
12450             }
12451             else if (!(sc.flags & SCOPE.debug_) &&
12452                      sc.func.setUnsafe())
12453             {
12454                 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12455                 return false;
12456             }
12457         }
12458     }
12459     return true;
12460 }
12461 
12462 /*******************************
12463  * Checks the attributes of a function.
12464  * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
12465  * and usage of `deprecated` and `@disabled`-ed symbols are checked.
12466  *
12467  * Params:
12468  *  exp = expression to check attributes for
12469  *  sc  = scope of the function
12470  *  f   = function to be checked
12471  * Returns: `true` if error occur.
12472  */
12473 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
12474 {
12475     with(exp)
12476     {
12477         bool error = checkDisabled(sc, f);
12478         error |= checkDeprecated(sc, f);
12479         error |= checkPurity(sc, f);
12480         error |= checkSafety(sc, f);
12481         error |= checkNogc(sc, f);
12482         return error;
12483     }
12484 }
12485 
12486 /*******************************
12487  * Helper function for `getRightThis()`.
12488  * Gets `this` of the next outer aggregate.
12489  * Params:
12490  *      loc = location to use for error messages
12491  *      sc = context
12492  *      s = the parent symbol of the existing `this`
12493  *      ad = struct or class we need the correct `this` for
12494  *      e1 = existing `this`
12495  *      t = type of the existing `this`
12496  *      var = the specific member of ad we're accessing
12497  *      flag = if true, return `null` instead of throwing an error
12498  * Returns:
12499  *      Expression representing the `this` for the var
12500  */
12501 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
12502 {
12503     int n = 0;
12504     while (s && s.isFuncDeclaration())
12505     {
12506         FuncDeclaration f = s.isFuncDeclaration();
12507         if (f.vthis)
12508         {
12509             n++;
12510             e1 = new VarExp(loc, f.vthis);
12511             if (f.isThis2)
12512             {
12513                 // (*__this)[i]
12514                 if (n > 1)
12515                     e1 = e1.expressionSemantic(sc);
12516                 e1 = new PtrExp(loc, e1);
12517                 uint i = f.followInstantiationContext(ad);
12518                 e1 = new IndexExp(loc, e1, new IntegerExp(i));
12519                 s = f.toParentP(ad);
12520                 continue;
12521             }
12522         }
12523         else
12524         {
12525             if (flag)
12526                 return null;
12527             e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
12528             e1 = ErrorExp.get();
12529             return e1;
12530         }
12531         s = s.toParent2();
12532     }
12533     if (n > 1 || e1.op == TOK.index)
12534         e1 = e1.expressionSemantic(sc);
12535     if (s && e1.type.equivalent(Type.tvoidptr))
12536     {
12537         if (auto sad = s.isAggregateDeclaration())
12538         {
12539             Type ta = sad.handleType();
12540             if (ta.ty == Tstruct)
12541                 ta = ta.pointerTo();
12542             e1.type = ta;
12543         }
12544     }
12545     e1.type = e1.type.addMod(t.mod);
12546     return e1;
12547 }
12548 
12549 /*******************************
12550  * Make a dual-context container for use as a `this` argument.
12551  * Params:
12552  *      loc = location to use for error messages
12553  *      sc = current scope
12554  *      fd = target function that will take the `this` argument
12555  * Returns:
12556  *      Temporary closure variable.
12557  * Note:
12558  *      The function `fd` is added to the nested references of the
12559  *      newly created variable such that a closure is made for the variable when
12560  *      the address of `fd` is taken.
12561  */
12562 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
12563 {
12564     Type tthis2 = Type.tvoidptr.sarrayOf(2);
12565     VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
12566     vthis2.storage_class |= STC.temp;
12567     vthis2.dsymbolSemantic(sc);
12568     vthis2.parent = sc.parent;
12569     // make it a closure var
12570     assert(sc.func);
12571     sc.func.closureVars.push(vthis2);
12572     // add `fd` to the nested refs
12573     vthis2.nestedrefs.push(fd);
12574     return vthis2;
12575 }
12576 
12577 /*******************************
12578  * Make sure that the runtime hook `id` exists.
12579  * Params:
12580  *      loc = location to use for error messages
12581  *      sc = current scope
12582  *      id = the hook identifier
12583  *      description = what the hook does
12584  *      module_ = what module the hook is located in
12585  * Returns:
12586  *      a `bool` indicating if the hook is present.
12587  */
12588 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
12589 {
12590     auto rootSymbol = sc.search(loc, Id.empty, null);
12591     if (auto moduleSymbol = rootSymbol.search(loc, module_))
12592         if (moduleSymbol.search(loc, id))
12593           return true;
12594     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);
12595     return false;
12596 }