1 /**
2  * Semantic analysis of expressions.
3  *
4  * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5  *
6  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d)
10  * Documentation:  https://dlang.org/phobos/dmd_expressionsem.html
11  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d
12  */
13 
14 module dmd.expressionsem;
15 
16 import core.stdc.stdio;
17 
18 import dmd.access;
19 import dmd.aggregate;
20 import dmd.aliasthis;
21 import dmd.arrayop;
22 import dmd.arraytypes;
23 import dmd.attrib;
24 import dmd.astcodegen;
25 import dmd.canthrow;
26 import dmd.chkformat;
27 import dmd.ctorflow;
28 import dmd.dscope;
29 import dmd.dsymbol;
30 import dmd.declaration;
31 import dmd.dclass;
32 import dmd.dcast;
33 import dmd.delegatize;
34 import dmd.denum;
35 import dmd.dimport;
36 import dmd.dinterpret;
37 import dmd.dmangle;
38 import dmd.dmodule;
39 import dmd.dstruct;
40 import dmd.dsymbolsem;
41 import dmd.dtemplate;
42 import dmd.errors;
43 import dmd.escape;
44 import dmd.expression;
45 import dmd.func;
46 import dmd.globals;
47 import dmd.hdrgen;
48 import dmd.id;
49 import dmd.identifier;
50 import dmd.imphint;
51 import dmd.init;
52 import dmd.initsem;
53 import dmd.inline;
54 import dmd.intrange;
55 import dmd.mtype;
56 import dmd.nspace;
57 import dmd.opover;
58 import dmd.optimize;
59 import dmd.parse;
60 import dmd.root.ctfloat;
61 import dmd.root.file;
62 import dmd.root.filename;
63 import dmd.root.outbuffer;
64 import dmd.root.rmem;
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 = Pool!TemplateInstance.make(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 = cast(CallExp)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)
1247     {
1248         DotVarExp dve = cast(DotVarExp)e1;
1249         s = dve.var.isFuncDeclaration();
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)
1255     {
1256         s = (cast(VarExp)e1).var.isFuncDeclaration();
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                 assert(fd.type.ty == Tfunction);
1277                 Expression e = new CallExp(loc, e1, e2);
1278                 return e.expressionSemantic(sc);
1279             }
1280         }
1281         {
1282             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1283             if (fd && fd.type)
1284             {
1285                 if (fd.errors)
1286                     return ErrorExp.get();
1287                 assert(fd.type.ty == Tfunction);
1288                 TypeFunction tf = cast(TypeFunction)fd.type;
1289                 if (!e2 || tf.isref)
1290                 {
1291                     Expression e = new CallExp(loc, e1);
1292                     if (e2)
1293                         e = new AssignExp(loc, e, e2);
1294                     return e.expressionSemantic(sc);
1295                 }
1296             }
1297         }
1298         if (FuncDeclaration fd = s.isFuncDeclaration())
1299         {
1300             // Keep better diagnostic message for invalid property usage of functions
1301             assert(fd.type.ty == Tfunction);
1302             Expression e = new CallExp(loc, e1, e2);
1303             return e.expressionSemantic(sc);
1304         }
1305         if (e2)
1306             goto Leprop;
1307     }
1308     if (e1.op == TOK.variable)
1309     {
1310         VarExp ve = cast(VarExp)e1;
1311         VarDeclaration v = ve.var.isVarDeclaration();
1312         if (v && ve.checkPurity(sc, v))
1313             return ErrorExp.get();
1314     }
1315     if (e2)
1316         return null;
1317 
1318     if (e1.type && e1.op != TOK.type) // function type is not a property
1319     {
1320         /* Look for e1 being a lazy parameter; rewrite as delegate call
1321          * only if the symbol wasn't already treated as a delegate
1322          */
1323         auto ve = e1.isVarExp();
1324         if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1325         {
1326                 Expression e = new CallExp(loc, e1);
1327                 return e.expressionSemantic(sc);
1328         }
1329         else if (e1.op == TOK.dotVariable)
1330         {
1331             // Check for reading overlapped pointer field in @safe code.
1332             if (checkUnsafeAccess(sc, e1, true, true))
1333                 return ErrorExp.get();
1334         }
1335         else if (e1.op == TOK.dot)
1336         {
1337             e1.error("expression has no value");
1338             return ErrorExp.get();
1339         }
1340         else if (e1.op == TOK.call)
1341         {
1342             CallExp ce = cast(CallExp)e1;
1343             // Check for reading overlapped pointer field in @safe code.
1344             if (checkUnsafeAccess(sc, ce.e1, true, true))
1345                 return ErrorExp.get();
1346         }
1347     }
1348 
1349     if (!e1.type)
1350     {
1351         error(loc, "cannot resolve type for %s", e1.toChars());
1352         e1 = ErrorExp.get();
1353     }
1354     return e1;
1355 
1356 Leprop:
1357     error(loc, "not a property %s", e1.toChars());
1358     return ErrorExp.get();
1359 }
1360 
1361 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1362 {
1363     //printf("resolveProperties(%s)\n", e.toChars());
1364     e = resolvePropertiesX(sc, e);
1365     if (e.checkRightThis(sc))
1366         return ErrorExp.get();
1367     return e;
1368 }
1369 
1370 /****************************************
1371  * The common type is determined by applying ?: to each pair.
1372  * Output:
1373  *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1374  *      *pt     if pt is not NULL, set to the common type
1375  * Returns:
1376  *      true    a semantic error was detected
1377  */
1378 private bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt)
1379 {
1380     /* Still have a problem with:
1381      *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1382      * which works if the array literal is initialized top down with the ubyte[][]
1383      * type, but fails with this function doing bottom up typing.
1384      */
1385 
1386     //printf("arrayExpressionToCommonType()\n");
1387     scope IntegerExp integerexp = IntegerExp.literal!0;
1388     scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1389 
1390     Type t0 = null;
1391     Expression e0 = null;
1392     size_t j0 = ~0;
1393     bool foundType;
1394 
1395     for (size_t i = 0; i < exps.dim; i++)
1396     {
1397         Expression e = (*exps)[i];
1398         if (!e)
1399             continue;
1400 
1401         e = resolveProperties(sc, e);
1402         if (!e.type)
1403         {
1404             e.error("`%s` has no value", e.toChars());
1405             t0 = Type.terror;
1406             continue;
1407         }
1408         if (e.op == TOK.type)
1409         {
1410             foundType = true; // do not break immediately, there might be more errors
1411             e.checkValue(); // report an error "type T has no value"
1412             t0 = Type.terror;
1413             continue;
1414         }
1415         if (e.type.ty == Tvoid)
1416         {
1417             // void expressions do not concur to the determination of the common
1418             // type.
1419             continue;
1420         }
1421         if (checkNonAssignmentArrayOp(e))
1422         {
1423             t0 = Type.terror;
1424             continue;
1425         }
1426 
1427         e = doCopyOrMove(sc, e);
1428 
1429         if (!foundType && t0 && !t0.equals(e.type))
1430         {
1431             /* This applies ?: to merge the types. It's backwards;
1432              * ?: should call this function to merge types.
1433              */
1434             condexp.type = null;
1435             condexp.e1 = e0;
1436             condexp.e2 = e;
1437             condexp.loc = e.loc;
1438             Expression ex = condexp.expressionSemantic(sc);
1439             if (ex.op == TOK.error)
1440                 e = ex;
1441             else
1442             {
1443                 // Convert to common type
1444                 (*exps)[j0] = condexp.e1.castTo(sc, condexp.type);
1445                 e = condexp.e2.castTo(sc, condexp.type);
1446             }
1447         }
1448         j0 = i;
1449         e0 = e;
1450         t0 = e.type;
1451         if (e.op != TOK.error)
1452             (*exps)[i] = e;
1453     }
1454 
1455     if (!t0)
1456         t0 = Type.tvoid; // [] is typed as void[]
1457     else if (t0.ty != Terror)
1458     {
1459         for (size_t i = 0; i < exps.dim; i++)
1460         {
1461             Expression e = (*exps)[i];
1462             if (!e)
1463                 continue;
1464 
1465             e = e.implicitCastTo(sc, t0);
1466             //assert(e.op != TOK.error);
1467             if (e.op == TOK.error)
1468             {
1469                 /* https://issues.dlang.org/show_bug.cgi?id=13024
1470                  * a workaround for the bug in typeMerge -
1471                  * it should paint e1 and e2 by deduced common type,
1472                  * but doesn't in this particular case.
1473                  */
1474                 t0 = Type.terror;
1475                 break;
1476             }
1477             (*exps)[i] = e;
1478         }
1479     }
1480     if (pt)
1481         *pt = t0;
1482 
1483     return (t0 == Type.terror);
1484 }
1485 
1486 private Expression opAssignToOp(const ref Loc loc, TOK op, Expression e1, Expression e2)
1487 {
1488     Expression e;
1489     switch (op)
1490     {
1491     case TOK.addAssign:
1492         e = new AddExp(loc, e1, e2);
1493         break;
1494 
1495     case TOK.minAssign:
1496         e = new MinExp(loc, e1, e2);
1497         break;
1498 
1499     case TOK.mulAssign:
1500         e = new MulExp(loc, e1, e2);
1501         break;
1502 
1503     case TOK.divAssign:
1504         e = new DivExp(loc, e1, e2);
1505         break;
1506 
1507     case TOK.modAssign:
1508         e = new ModExp(loc, e1, e2);
1509         break;
1510 
1511     case TOK.andAssign:
1512         e = new AndExp(loc, e1, e2);
1513         break;
1514 
1515     case TOK.orAssign:
1516         e = new OrExp(loc, e1, e2);
1517         break;
1518 
1519     case TOK.xorAssign:
1520         e = new XorExp(loc, e1, e2);
1521         break;
1522 
1523     case TOK.leftShiftAssign:
1524         e = new ShlExp(loc, e1, e2);
1525         break;
1526 
1527     case TOK.rightShiftAssign:
1528         e = new ShrExp(loc, e1, e2);
1529         break;
1530 
1531     case TOK.unsignedRightShiftAssign:
1532         e = new UshrExp(loc, e1, e2);
1533         break;
1534 
1535     default:
1536         assert(0);
1537     }
1538     return e;
1539 }
1540 
1541 /*********************
1542  * Rewrite:
1543  *    array.length op= e2
1544  * as:
1545  *    array.length = array.length op e2
1546  * or:
1547  *    auto tmp = &array;
1548  *    (*tmp).length = (*tmp).length op e2
1549  */
1550 private Expression rewriteOpAssign(BinExp exp)
1551 {
1552     Expression e;
1553 
1554     assert(exp.e1.op == TOK.arrayLength);
1555     ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
1556     if (ale.e1.op == TOK.variable)
1557     {
1558         e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1559         e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1560     }
1561     else
1562     {
1563         /*    auto tmp = &array;
1564          *    (*tmp).length = (*tmp).length op e2
1565          */
1566         auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1567 
1568         Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1569         Expression elvalue = e1.syntaxCopy();
1570         e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1571         e = new AssignExp(exp.loc, elvalue, e);
1572         e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1573     }
1574     return e;
1575 }
1576 
1577 /****************************************
1578  * Preprocess arguments to function.
1579  * Input:
1580  *      reportErrors    whether or not to report errors here.  Some callers are not
1581  *                      checking actual function params, so they'll do their own error reporting
1582  * Output:
1583  *      exps[]  tuples expanded, properties resolved, rewritten in place
1584  * Returns:
1585  *      true    a semantic error occurred
1586  */
1587 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1588 {
1589     bool err = false;
1590     if (exps)
1591     {
1592         expandTuples(exps);
1593 
1594         for (size_t i = 0; i < exps.dim; i++)
1595         {
1596             Expression arg = (*exps)[i];
1597             arg = resolveProperties(sc, arg);
1598             if (arg.op == TOK.type)
1599             {
1600                 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1601                 arg = resolveAliasThis(sc, arg);
1602 
1603                 if (arg.op == TOK.type)
1604                 {
1605                     if (reportErrors)
1606                     {
1607                         arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1608                         arg = ErrorExp.get();
1609                     }
1610                     err = true;
1611                 }
1612             }
1613             else if (arg.type.toBasetype().ty == Tfunction)
1614             {
1615                 if (reportErrors)
1616                 {
1617                     arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1618                     arg = ErrorExp.get();
1619                 }
1620                 err = true;
1621             }
1622             else if (checkNonAssignmentArrayOp(arg))
1623             {
1624                 arg = ErrorExp.get();
1625                 err = true;
1626             }
1627             (*exps)[i] = arg;
1628         }
1629     }
1630     return err;
1631 }
1632 
1633 /********************************************
1634  * Issue an error if default construction is disabled for type t.
1635  * Default construction is required for arrays and 'out' parameters.
1636  * Returns:
1637  *      true    an error was issued
1638  */
1639 private bool checkDefCtor(Loc loc, Type t)
1640 {
1641     t = t.baseElemOf();
1642     if (t.ty == Tstruct)
1643     {
1644         StructDeclaration sd = (cast(TypeStruct)t).sym;
1645         if (sd.noDefaultCtor)
1646         {
1647             sd.error(loc, "default construction is disabled");
1648             return true;
1649         }
1650     }
1651     return false;
1652 }
1653 
1654 /****************************************
1655  * Now that we know the exact type of the function we're calling,
1656  * the arguments[] need to be adjusted:
1657  *      1. implicitly convert argument to the corresponding parameter type
1658  *      2. add default arguments for any missing arguments
1659  *      3. do default promotions on arguments corresponding to ...
1660  *      4. add hidden _arguments[] argument
1661  *      5. call copy constructor for struct value arguments
1662  * Params:
1663  *      loc       = location of function call
1664  *      sc        = context
1665  *      tf        = type of the function
1666  *      ethis     = `this` argument, `null` if none or not known
1667  *      tthis     = type of `this` argument, `null` if no `this` argument
1668  *      arguments = array of actual arguments to function call
1669  *      fd        = the function being called, `null` if called indirectly
1670  *      prettype  = set to return type of function
1671  *      peprefix  = set to expression to execute before `arguments[]` are evaluated, `null` if none
1672  * Returns:
1673  *      true    errors happened
1674  */
1675 private bool functionParameters(const ref Loc loc, Scope* sc,
1676     TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1677     Type* prettype, Expression* peprefix)
1678 {
1679     //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1680     assert(arguments);
1681     assert(fd || tf.next);
1682     size_t nargs = arguments ? arguments.dim : 0;
1683     const size_t nparams = tf.parameterList.length;
1684     const olderrors = global.errors;
1685     bool err = false;
1686     *prettype = Type.terror;
1687     Expression eprefix = null;
1688     *peprefix = null;
1689 
1690     if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1691     {
1692         error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1693         return true;
1694     }
1695 
1696     // If inferring return type, and semantic3() needs to be run if not already run
1697     if (!tf.next && fd.inferRetType)
1698     {
1699         fd.functionSemantic();
1700     }
1701     else if (fd && fd.parent)
1702     {
1703         TemplateInstance ti = fd.parent.isTemplateInstance();
1704         if (ti && ti.tempdecl)
1705         {
1706             fd.functionSemantic3();
1707         }
1708     }
1709 
1710     /* If calling a pragma(inline, true) function,
1711      * set flag to later scan for inlines.
1712      */
1713     if (fd && fd.inlining == PINLINE.always)
1714     {
1715         if (sc._module)
1716             sc._module.hasAlwaysInlines = true;
1717         if (sc.func)
1718             sc.func.hasAlwaysInlines = true;
1719     }
1720 
1721     const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1722 
1723     const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1724 
1725     /* If the function return type has wildcards in it, we'll need to figure out the actual type
1726      * based on the actual argument types.
1727      * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1728      * of the arguments.
1729      */
1730     MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1731 
1732     bool done = false;
1733     foreach (const i; 0 .. n)
1734     {
1735         Expression arg = (i < nargs) ? (*arguments)[i] : null;
1736 
1737         if (i < nparams)
1738         {
1739             bool errorArgs()
1740             {
1741                 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1742                 return true;
1743             }
1744 
1745             Parameter p = tf.parameterList[i];
1746             const bool isRef = p.isReference();
1747 
1748             if (!arg)
1749             {
1750                 if (!p.defaultArg)
1751                 {
1752                     if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1753                         goto L2;
1754                     return errorArgs();
1755                 }
1756                 arg = p.defaultArg;
1757                 arg = inlineCopy(arg, sc);
1758                 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1759                 arg = arg.resolveLoc(loc, sc);
1760                 arguments.push(arg);
1761                 nargs++;
1762             }
1763             else
1764             {
1765                 if (isDefaultInitOp(arg.op))
1766                 {
1767                     arg = arg.resolveLoc(loc, sc);
1768                     (*arguments)[i] = arg;
1769                 }
1770             }
1771 
1772 
1773             if (isRef && !p.type.isConst && !p.type.isImmutable
1774                 && (p.storageClass & STC.const_) != STC.const_
1775                 && (p.storageClass & STC.immutable_) != STC.immutable_
1776                 && checkIfIsStructLiteralDotExpr(arg))
1777                     break;
1778 
1779             if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1780             {
1781                 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1782                 {
1783                     MATCH m;
1784                     if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1785                     {
1786                         if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1787                             goto L2;
1788                         else if (nargs != nparams)
1789                             return errorArgs();
1790                         goto L1;
1791                     }
1792                 }
1793             L2:
1794                 Type tb = p.type.toBasetype();
1795                 switch (tb.ty)
1796                 {
1797                 case Tsarray:
1798                 case Tarray:
1799                     {
1800                         /* Create a static array variable v of type arg.type:
1801                          *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1802                          *
1803                          * The array literal in the initializer of the hidden variable
1804                          * is now optimized.
1805                          * https://issues.dlang.org/show_bug.cgi?id=2356
1806                          */
1807                         Type tbn = (cast(TypeArray)tb).next;    // array element type
1808                         Type tret = p.isLazyArray();
1809 
1810                         auto elements = new Expressions(nargs - i);
1811                         foreach (u; 0 .. elements.dim)
1812                         {
1813                             Expression a = (*arguments)[i + u];
1814                             if (tret && a.implicitConvTo(tret))
1815                             {
1816                                 // p is a lazy array of delegates, tret is return type of the delegates
1817                                 a = a.implicitCastTo(sc, tret)
1818                                      .optimize(WANTvalue)
1819                                      .toDelegate(tret, sc);
1820                             }
1821                             else
1822                                 a = a.implicitCastTo(sc, tbn);
1823                             a = a.addDtorHook(sc);
1824                             (*elements)[u] = a;
1825                         }
1826                         // https://issues.dlang.org/show_bug.cgi?id=14395
1827                         // Convert to a static array literal, or its slice.
1828                         arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1829                         if (tb.ty == Tarray)
1830                         {
1831                             arg = new SliceExp(loc, arg, null, null);
1832                             arg.type = p.type;
1833                         }
1834                         break;
1835                     }
1836                 case Tclass:
1837                     {
1838                         /* Set arg to be:
1839                          *      new Tclass(arg0, arg1, ..., argn)
1840                          */
1841                         auto args = new Expressions(nargs - i);
1842                         foreach (u; i .. nargs)
1843                             (*args)[u - i] = (*arguments)[u];
1844                         arg = new NewExp(loc, null, null, p.type, args);
1845                         break;
1846                     }
1847                 default:
1848                     if (!arg)
1849                     {
1850                         error(loc, "not enough arguments");
1851                         return true;
1852                     }
1853                     break;
1854                 }
1855                 arg = arg.expressionSemantic(sc);
1856                 //printf("\targ = '%s'\n", arg.toChars());
1857                 arguments.setDim(i + 1);
1858                 (*arguments)[i] = arg;
1859                 nargs = i + 1;
1860                 done = true;
1861             }
1862 
1863         L1:
1864             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1865             {
1866 
1867                 if (ubyte wm = arg.type.deduceWild(p.type, isRef))
1868                 {
1869                     wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1870                     //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1871                 }
1872             }
1873         }
1874         if (done)
1875             break;
1876     }
1877     if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1878         tf.next && tf.next.hasWild() &&
1879         (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1880     {
1881         bool errorInout(MOD wildmatch)
1882         {
1883             const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1884             error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1885             return true;
1886         }
1887 
1888         if (fd)
1889         {
1890             /* If the called function may return the reference to
1891              * outer inout data, it should be rejected.
1892              *
1893              * void foo(ref inout(int) x) {
1894              *   ref inout(int) bar(inout(int)) { return x; }
1895              *   struct S {
1896              *      ref inout(int) bar() inout { return x; }
1897              *      ref inout(int) baz(alias a)() inout { return x; }
1898              *   }
1899              *   bar(int.init) = 1;  // bad!
1900              *   S().bar() = 1;      // bad!
1901              * }
1902              * void test() {
1903              *   int a;
1904              *   auto s = foo(a);
1905              *   s.baz!a() = 1;      // bad!
1906              * }
1907              *
1908              */
1909             bool checkEnclosingWild(Dsymbol s)
1910             {
1911                 bool checkWild(Dsymbol s)
1912                 {
1913                     if (!s)
1914                         return false;
1915                     if (auto ad = s.isAggregateDeclaration())
1916                     {
1917                         if (ad.isNested())
1918                             return checkEnclosingWild(s);
1919                     }
1920                     else if (auto ff = s.isFuncDeclaration())
1921                     {
1922                         if ((cast(TypeFunction)ff.type).iswild)
1923                             return errorInout(wildmatch);
1924 
1925                         if (ff.isNested() || ff.isThis())
1926                             return checkEnclosingWild(s);
1927                     }
1928                     return false;
1929                 }
1930 
1931                 Dsymbol ctx0 = s.toParent2();
1932                 Dsymbol ctx1 = s.toParentLocal();
1933                 if (checkWild(ctx0))
1934                     return true;
1935                 if (ctx0 != ctx1)
1936                     return checkWild(ctx1);
1937                 return false;
1938             }
1939             if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1940                 return true;
1941         }
1942         else if (tf.isWild())
1943             return errorInout(wildmatch);
1944     }
1945 
1946     Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1947                            tthis &&
1948                            tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1949                            tthis.hasPointers())
1950                           ? ethis : null;
1951 
1952     assert(nargs >= nparams);
1953     foreach (const i, arg; (*arguments)[0 .. nargs])
1954     {
1955         assert(arg);
1956         if (i < nparams)
1957         {
1958             Parameter p = tf.parameterList[i];
1959             Type targ = arg.type;               // keep original type for isCopyable() because alias this
1960                                                 // resolution may hide an uncopyable type
1961 
1962             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1963             {
1964                 Type tprm = p.type.hasWild()
1965                     ? p.type.substWildTo(wildmatch)
1966                     : p.type;
1967 
1968                 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
1969                 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1970                 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1971                 {
1972                     //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1973                     arg = arg.implicitCastTo(sc, tprm);
1974                     arg = arg.optimize(WANTvalue, p.isReference());
1975                 }
1976             }
1977 
1978             // Support passing rvalue to `in` parameters
1979             if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
1980             {
1981                 if (!arg.isLvalue())
1982                 {
1983                     auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
1984                     Expression ev = new DeclarationExp(arg.loc, v);
1985                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1986                     arg = ev.expressionSemantic(sc);
1987                 }
1988                 arg = arg.toLvalue(sc, arg);
1989 
1990                 // Look for mutable misaligned pointer, etc., in @safe mode
1991                 err |= checkUnsafeAccess(sc, arg, false, true);
1992             }
1993             else if (p.storageClass & STC.ref_)
1994             {
1995                 if (global.params.rvalueRefParam &&
1996                     !arg.isLvalue() &&
1997                     targ.isCopyable())
1998                 {   /* allow rvalues to be passed to ref parameters by copying
1999                      * them to a temp, then pass the temp as the argument
2000                      */
2001                     auto v = copyToTemp(0, "__rvalue", arg);
2002                     Expression ev = new DeclarationExp(arg.loc, v);
2003                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2004                     arg = ev.expressionSemantic(sc);
2005                 }
2006                 arg = arg.toLvalue(sc, arg);
2007 
2008                 // Look for mutable misaligned pointer, etc., in @safe mode
2009                 err |= checkUnsafeAccess(sc, arg, false, true);
2010             }
2011             else if (p.storageClass & STC.out_)
2012             {
2013                 Type t = arg.type;
2014                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2015                 {
2016                     arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2017                     err = true;
2018                 }
2019                 else
2020                 {
2021                     // Look for misaligned pointer, etc., in @safe mode
2022                     err |= checkUnsafeAccess(sc, arg, false, true);
2023                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
2024                 }
2025                 arg = arg.toLvalue(sc, arg);
2026             }
2027             else if (p.storageClass & STC.lazy_)
2028             {
2029                 // Convert lazy argument to a delegate
2030                 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2031                 arg = toDelegate(arg, t, sc);
2032             }
2033             //printf("arg: %s\n", arg.toChars());
2034             //printf("type: %s\n", arg.type.toChars());
2035             //printf("param: %s\n", p.toChars());
2036 
2037             if (firstArg && p.storageClass & STC.return_)
2038             {
2039                 /* Argument value can be assigned to firstArg.
2040                  * Check arg to see if it matters.
2041                  */
2042                 if (global.params.vsafe)
2043                     err |= checkParamArgumentReturn(sc, firstArg, arg, false);
2044             }
2045             else if (tf.parameterEscapes(tthis, p))
2046             {
2047                 /* Argument value can escape from the called function.
2048                  * Check arg to see if it matters.
2049                  */
2050                 if (global.params.vsafe)
2051                     err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2052             }
2053             else
2054             {
2055                 /* Argument value cannot escape from the called function.
2056                  */
2057                 Expression a = arg;
2058                 if (a.op == TOK.cast_)
2059                     a = (cast(CastExp)a).e1;
2060 
2061                 ArrayLiteralExp ale;
2062                 if (p.type.toBasetype().ty == Tarray && !(p.storageClass & STC.return_) &&
2063                     (ale = a.isArrayLiteralExp()) !is null)
2064                 {
2065                     // allocate the array literal as temporary static array on the stack
2066                     ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
2067                     auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2068                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
2069                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
2070                     arg = CommaExp.combine(declareTmp, castToSlice);
2071                     arg = arg.expressionSemantic(sc);
2072                 }
2073                 else if (a.op == TOK.function_)
2074                 {
2075                     /* Function literals can only appear once, so if this
2076                      * appearance was scoped, there cannot be any others.
2077                      */
2078                     FuncExp fe = cast(FuncExp)a;
2079                     fe.fd.tookAddressOf = 0;
2080                 }
2081                 else if (a.op == TOK.delegate_)
2082                 {
2083                     /* For passing a delegate to a scoped parameter,
2084                      * this doesn't count as taking the address of it.
2085                      * We only worry about 'escaping' references to the function.
2086                      */
2087                     DelegateExp de = cast(DelegateExp)a;
2088                     if (de.e1.op == TOK.variable)
2089                     {
2090                         VarExp ve = cast(VarExp)de.e1;
2091                         FuncDeclaration f = ve.var.isFuncDeclaration();
2092                         if (f)
2093                         {
2094                             if (f.tookAddressOf)
2095                                 --f.tookAddressOf;
2096                             //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2097                         }
2098                     }
2099                 }
2100             }
2101             if (!p.isReference())
2102                 err |= arg.checkSharedAccess(sc);
2103 
2104             arg = arg.optimize(WANTvalue, p.isReference());
2105 
2106             /* Determine if this parameter is the "first reference" parameter through which
2107              * later "return" arguments can be stored.
2108              */
2109             if (i == 0 && !tthis && p.isReference() && p.type &&
2110                 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2111             {
2112                 Type tb = p.type.baseElemOf();
2113                 if (tb.isMutable() && tb.hasPointers())
2114                 {
2115                     firstArg = arg;
2116                 }
2117             }
2118         }
2119         else
2120         {
2121             // These will be the trailing ... arguments
2122             // If not D linkage, do promotions
2123             if (tf.linkage != LINK.d)
2124             {
2125                 // Promote bytes, words, etc., to ints
2126                 arg = integralPromotions(arg, sc);
2127 
2128                 // Promote floats to doubles
2129                 switch (arg.type.ty)
2130                 {
2131                 case Tfloat32:
2132                     arg = arg.castTo(sc, Type.tfloat64);
2133                     break;
2134 
2135                 case Timaginary32:
2136                     arg = arg.castTo(sc, Type.timaginary64);
2137                     break;
2138 
2139                 default:
2140                     break;
2141                 }
2142                 if (tf.parameterList.varargs == VarArg.variadic)
2143                 {
2144                     const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2145                     if (arg.type.ty == Tarray)
2146                     {
2147                         arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2148                         err = true;
2149                     }
2150                     if (arg.type.ty == Tsarray)
2151                     {
2152                         arg.error("cannot pass static arrays to `%s` vararg functions", p);
2153                         err = true;
2154                     }
2155                 }
2156             }
2157 
2158             // Do not allow types that need destructors or copy constructors.
2159             if (arg.type.needsDestruction())
2160             {
2161                 arg.error("cannot pass types that need destruction as variadic arguments");
2162                 err = true;
2163             }
2164             if (arg.type.needsCopyOrPostblit())
2165             {
2166                 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2167                 err = true;
2168             }
2169 
2170             // Convert static arrays to dynamic arrays
2171             // BUG: I don't think this is right for D2
2172             Type tb = arg.type.toBasetype();
2173             if (tb.ty == Tsarray)
2174             {
2175                 TypeSArray ts = cast(TypeSArray)tb;
2176                 Type ta = ts.next.arrayOf();
2177                 if (ts.size(arg.loc) == 0)
2178                     arg = new NullExp(arg.loc, ta);
2179                 else
2180                     arg = arg.castTo(sc, ta);
2181             }
2182             if (tb.ty == Tstruct)
2183             {
2184                 //arg = callCpCtor(sc, arg);
2185             }
2186             // Give error for overloaded function addresses
2187             if (arg.op == TOK.symbolOffset)
2188             {
2189                 SymOffExp se = cast(SymOffExp)arg;
2190                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2191                 {
2192                     arg.error("function `%s` is overloaded", arg.toChars());
2193                     err = true;
2194                 }
2195             }
2196             err |= arg.checkValue();
2197             err |= arg.checkSharedAccess(sc);
2198             arg = arg.optimize(WANTvalue);
2199         }
2200         (*arguments)[i] = arg;
2201     }
2202 
2203     /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2204      */
2205     const isVa_list = tf.parameterList.varargs == VarArg.none;
2206     if (fd && fd.flags & FUNCFLAG.printf)
2207     {
2208         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2209         {
2210             checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2211         }
2212     }
2213     else if (fd && fd.flags & FUNCFLAG.scanf)
2214     {
2215         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2216         {
2217             checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2218         }
2219     }
2220     else
2221     {
2222         // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2223     }
2224 
2225     /* Remaining problems:
2226      * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2227      *    implemented by calling a function) we'll defer this for now.
2228      * 2. value structs (or static arrays of them) that need to be copy constructed
2229      * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2230      *    function gets called (functions normally destroy their parameters)
2231      * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2232      * up properly. Pushing arguments on the stack then cannot fail.
2233      */
2234     {
2235         /* TODO: tackle problem 1)
2236          */
2237         const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2238         if (!leftToRight)
2239             assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2240 
2241         const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2242         const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2243         const ptrdiff_t step = (leftToRight ? 1 : -1);
2244 
2245         /* Compute indices of last throwing argument and first arg needing destruction.
2246          * Used to not set up destructors unless an arg needs destruction on a throw
2247          * in a later argument.
2248          */
2249         ptrdiff_t lastthrow = -1;
2250         ptrdiff_t firstdtor = -1;
2251         for (ptrdiff_t i = start; i != end; i += step)
2252         {
2253             Expression arg = (*arguments)[i];
2254             if (canThrow(arg, sc.func, false))
2255                 lastthrow = i;
2256             if (firstdtor == -1 && arg.type.needsDestruction())
2257             {
2258                 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2259                 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
2260                     firstdtor = i;
2261             }
2262         }
2263 
2264         /* Does problem 3) apply to this call?
2265          */
2266         const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
2267             && (lastthrow - firstdtor) * step > 0);
2268 
2269         /* If so, initialize 'eprefix' by declaring the gate
2270          */
2271         VarDeclaration gate = null;
2272         if (needsPrefix)
2273         {
2274             // eprefix => bool __gate [= false]
2275             Identifier idtmp = Identifier.generateId("__gate");
2276             gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2277             gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2278             gate.dsymbolSemantic(sc);
2279 
2280             auto ae = new DeclarationExp(loc, gate);
2281             eprefix = ae.expressionSemantic(sc);
2282         }
2283 
2284         for (ptrdiff_t i = start; i != end; i += step)
2285         {
2286             Expression arg = (*arguments)[i];
2287 
2288             Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2289             const bool isRef = parameter && parameter.isReference();
2290             const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2291 
2292             /* Skip lazy parameters
2293              */
2294             if (isLazy)
2295                 continue;
2296 
2297             /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
2298              * Declare a temporary variable for this arg and append that declaration to 'eprefix',
2299              * which will implicitly take care of potential problem 2) for this arg.
2300              * 'eprefix' will therefore finally contain all args up to and including the last
2301              * potentially throwing arg, excluding all lazy parameters.
2302              */
2303             if (gate)
2304             {
2305                 const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow);
2306 
2307                 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2308                  */
2309                 auto tmp = copyToTemp(0,
2310                     needsDtor ? "__pfx" : "__pfy",
2311                     !isRef ? arg : arg.addressOf());
2312                 tmp.dsymbolSemantic(sc);
2313 
2314                 /* Modify the destructor so it only runs if gate==false, i.e.,
2315                  * only if there was a throw while constructing the args
2316                  */
2317                 if (!needsDtor)
2318                 {
2319                     if (tmp.edtor)
2320                     {
2321                         assert(i == lastthrow);
2322                         tmp.edtor = null;
2323                     }
2324                 }
2325                 else
2326                 {
2327                     // edtor => (__gate || edtor)
2328                     assert(tmp.edtor);
2329                     Expression e = tmp.edtor;
2330                     e = new LogicalExp(e.loc, TOK.orOr, new VarExp(e.loc, gate), e);
2331                     tmp.edtor = e.expressionSemantic(sc);
2332                     //printf("edtor: %s\n", tmp.edtor.toChars());
2333                 }
2334 
2335                 // eprefix => (eprefix, auto __pfx/y = arg)
2336                 auto ae = new DeclarationExp(loc, tmp);
2337                 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2338 
2339                 // arg => __pfx/y
2340                 arg = new VarExp(loc, tmp);
2341                 arg = arg.expressionSemantic(sc);
2342                 if (isRef)
2343                 {
2344                     arg = new PtrExp(loc, arg);
2345                     arg = arg.expressionSemantic(sc);
2346                 }
2347 
2348                 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
2349                  * i.e., disable the dtors right after constructing the last throwing arg.
2350                  * From now on, the callee will take care of destructing the args because
2351                  * the args are implicitly moved into function parameters.
2352                  *
2353                  * Set gate to null to let the next iterations know they don't need to
2354                  * append to eprefix anymore.
2355                  */
2356                 if (i == lastthrow)
2357                 {
2358                     auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2359                     eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2360                     gate = null;
2361                 }
2362             }
2363             else
2364             {
2365                 /* No gate, no prefix to append to.
2366                  * Handle problem 2) by calling the copy constructor for value structs
2367                  * (or static arrays of them) if appropriate.
2368                  */
2369                 Type tv = arg.type.baseElemOf();
2370                 if (!isRef && tv.ty == Tstruct)
2371                     arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2372             }
2373 
2374             (*arguments)[i] = arg;
2375         }
2376     }
2377     //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2378 
2379     /* Test compliance with DIP1021
2380      */
2381     if (global.params.useDIP1021 &&
2382         tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2383         err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2384 
2385     // If D linkage and variadic, add _arguments[] as first argument
2386     if (tf.isDstyleVariadic())
2387     {
2388         assert(arguments.dim >= nparams);
2389 
2390         auto args = new Parameters(arguments.dim - nparams);
2391         for (size_t i = 0; i < arguments.dim - nparams; i++)
2392         {
2393             auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2394             (*args)[i] = arg;
2395         }
2396         auto tup = new TypeTuple(args);
2397         Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2398         arguments.insert(0, e);
2399     }
2400 
2401     /* Determine function return type: tret
2402      */
2403     Type tret = tf.next;
2404     if (isCtorCall)
2405     {
2406         //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2407         //    wildmatch, tf.isWild(), fd.isReturnIsolated());
2408         if (!tthis)
2409         {
2410             assert(sc.intypeof || global.errors);
2411             tthis = fd.isThis().type.addMod(fd.type.mod);
2412         }
2413         if (tf.isWild() && !fd.isReturnIsolated())
2414         {
2415             if (wildmatch)
2416                 tret = tret.substWildTo(wildmatch);
2417             int offset;
2418             if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2419             {
2420                 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2421                 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2422                 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2423                 err = true;
2424             }
2425         }
2426         tret = tthis;
2427     }
2428     else if (wildmatch && tret)
2429     {
2430         /* Adjust function return type based on wildmatch
2431          */
2432         //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2433         tret = tret.substWildTo(wildmatch);
2434     }
2435 
2436     *prettype = tret;
2437     *peprefix = eprefix;
2438     return (err || olderrors != global.errors);
2439 }
2440 
2441 /**
2442  * Determines whether a symbol represents a module or package
2443  * (Used as a helper for is(type == module) and is(type == package))
2444  *
2445  * Params:
2446  *  sym = the symbol to be checked
2447  *
2448  * Returns:
2449  *  the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2450  */
2451 Package resolveIsPackage(Dsymbol sym)
2452 {
2453     Package pkg;
2454     if (Import imp = sym.isImport())
2455     {
2456         if (imp.pkg is null)
2457         {
2458             .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2459                     imp.toChars());
2460             assert(0);
2461         }
2462         pkg = imp.pkg;
2463     }
2464     else if (auto mod = sym.isModule())
2465         pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2466     else
2467         pkg = sym.isPackage();
2468     if (pkg)
2469         pkg.resolvePKGunknown();
2470     return pkg;
2471 }
2472 
2473 private Module loadStdMath()
2474 {
2475     __gshared Import impStdMath = null;
2476     if (!impStdMath)
2477     {
2478         auto a = new Identifiers();
2479         a.push(Id.std);
2480         auto s = new Import(Loc.initial, a, Id.math, null, false);
2481         // Module.load will call fatal() if there's no std.math available.
2482         // Gag the error here, pushing the error handling to the caller.
2483         uint errors = global.startGagging();
2484         s.load(null);
2485         if (s.mod)
2486         {
2487             s.mod.importAll(null);
2488             s.mod.dsymbolSemantic(null);
2489         }
2490         global.endGagging(errors);
2491         impStdMath = s;
2492     }
2493     return impStdMath.mod;
2494 }
2495 
2496 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2497 {
2498     alias visit = Visitor.visit;
2499 
2500     Scope* sc;
2501     Expression result;
2502 
2503     this(Scope* sc)
2504     {
2505         this.sc = sc;
2506     }
2507 
2508     private void setError()
2509     {
2510         result = ErrorExp.get();
2511     }
2512 
2513     /**************************
2514      * Semantically analyze Expression.
2515      * Determine types, fold constants, etc.
2516      */
2517     override void visit(Expression e)
2518     {
2519         static if (LOGSEMANTIC)
2520         {
2521             printf("Expression::semantic() %s\n", e.toChars());
2522         }
2523         if (e.type)
2524             e.type = e.type.typeSemantic(e.loc, sc);
2525         else
2526             e.type = Type.tvoid;
2527         result = e;
2528     }
2529 
2530     override void visit(IntegerExp e)
2531     {
2532         assert(e.type);
2533         if (e.type.ty == Terror)
2534             return setError();
2535 
2536         assert(e.type.deco);
2537         e.setInteger(e.getInteger());
2538         result = e;
2539     }
2540 
2541     override void visit(RealExp e)
2542     {
2543         if (!e.type)
2544             e.type = Type.tfloat64;
2545         else
2546             e.type = e.type.typeSemantic(e.loc, sc);
2547         result = e;
2548     }
2549 
2550     override void visit(ComplexExp e)
2551     {
2552         if (!e.type)
2553             e.type = Type.tcomplex80;
2554         else
2555             e.type = e.type.typeSemantic(e.loc, sc);
2556         result = e;
2557     }
2558 
2559     override void visit(IdentifierExp exp)
2560     {
2561         static if (LOGSEMANTIC)
2562         {
2563             printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2564         }
2565         if (exp.type) // This is used as the dummy expression
2566         {
2567             result = exp;
2568             return;
2569         }
2570 
2571         Dsymbol scopesym;
2572         Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2573         if (s)
2574         {
2575             if (s.errors)
2576                 return setError();
2577 
2578             Expression e;
2579 
2580             /* See if the symbol was a member of an enclosing 'with'
2581              */
2582             WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2583             if (withsym && withsym.withstate.wthis)
2584             {
2585                 /* Disallow shadowing
2586                  */
2587                 // First find the scope of the with
2588                 Scope* scwith = sc;
2589                 while (scwith.scopesym != scopesym)
2590                 {
2591                     scwith = scwith.enclosing;
2592                     assert(scwith);
2593                 }
2594                 // Look at enclosing scopes for symbols with the same name,
2595                 // in the same function
2596                 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2597                 {
2598                     Dsymbol s2;
2599                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2600                     {
2601                         exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2602                         return setError();
2603                     }
2604                 }
2605                 s = s.toAlias();
2606 
2607                 // Same as wthis.ident
2608                 //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2609                 //  The redudancy should be removed.
2610                 e = new VarExp(exp.loc, withsym.withstate.wthis);
2611                 e = new DotIdExp(exp.loc, e, exp.ident);
2612                 e = e.expressionSemantic(sc);
2613             }
2614             else
2615             {
2616                 if (withsym)
2617                 {
2618                     if (auto t = withsym.withstate.exp.isTypeExp())
2619                     {
2620                         e = new TypeExp(exp.loc, t.type);
2621                         e = new DotIdExp(exp.loc, e, exp.ident);
2622                         result = e.expressionSemantic(sc);
2623                         return;
2624                     }
2625                 }
2626 
2627                 /* If f is really a function template,
2628                  * then replace f with the function template declaration.
2629                  */
2630                 FuncDeclaration f = s.isFuncDeclaration();
2631                 if (f)
2632                 {
2633                     TemplateDeclaration td = getFuncTemplateDecl(f);
2634                     if (td)
2635                     {
2636                         if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2637                             td = td.overroot; // then get the start
2638                         e = new TemplateExp(exp.loc, td, f);
2639                         e = e.expressionSemantic(sc);
2640                         result = e;
2641                         return;
2642                     }
2643                 }
2644 
2645                 if (global.params.fixAliasThis)
2646                 {
2647                     ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2648                     if (expDsym)
2649                     {
2650                         //printf("expDsym = %s\n", expDsym.exp.toChars());
2651                         result = expDsym.exp.expressionSemantic(sc);
2652                         return;
2653                     }
2654                 }
2655                 // Haven't done overload resolution yet, so pass 1
2656                 e = symbolToExp(s, exp.loc, sc, true);
2657             }
2658             result = e;
2659             return;
2660         }
2661 
2662         if (!global.params.fixAliasThis && hasThis(sc))
2663         {
2664             for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2665             {
2666                 if (ad.aliasthis)
2667                 {
2668                     Expression e;
2669                     e = new ThisExp(exp.loc);
2670                     e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2671                     e = new DotIdExp(exp.loc, e, exp.ident);
2672                     e = e.trySemantic(sc);
2673                     if (e)
2674                     {
2675                         result = e;
2676                         return;
2677                     }
2678                 }
2679 
2680                 auto cd = ad.isClassDeclaration();
2681                 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2682                 {
2683                     ad = cd.baseClass;
2684                     continue;
2685                 }
2686                 break;
2687             }
2688         }
2689 
2690         if (exp.ident == Id.ctfe)
2691         {
2692             if (sc.flags & SCOPE.ctfe)
2693             {
2694                 exp.error("variable `__ctfe` cannot be read at compile time");
2695                 return setError();
2696             }
2697 
2698             // Create the magic __ctfe bool variable
2699             auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2700             vd.storage_class |= STC.temp;
2701             vd.semanticRun = PASS.semanticdone;
2702             Expression e = new VarExp(exp.loc, vd);
2703             e = e.expressionSemantic(sc);
2704             result = e;
2705             return;
2706         }
2707 
2708         // If we've reached this point and are inside a with() scope then we may
2709         // try one last attempt by checking whether the 'wthis' object supports
2710         // dynamic dispatching via opDispatch.
2711         // This is done by rewriting this expression as wthis.ident.
2712         // The innermost with() scope of the hierarchy to satisfy the condition
2713         // above wins.
2714         // https://issues.dlang.org/show_bug.cgi?id=6400
2715         for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2716         {
2717             if (!sc2.scopesym)
2718                 continue;
2719 
2720             if (auto ss = sc2.scopesym.isWithScopeSymbol())
2721             {
2722                 if (ss.withstate.wthis)
2723                 {
2724                     Expression e;
2725                     e = new VarExp(exp.loc, ss.withstate.wthis);
2726                     e = new DotIdExp(exp.loc, e, exp.ident);
2727                     e = e.trySemantic(sc);
2728                     if (e)
2729                     {
2730                         result = e;
2731                         return;
2732                     }
2733                 }
2734                 // Try Type.opDispatch (so the static version)
2735                 else if (ss.withstate.exp && ss.withstate.exp.op == TOK.type)
2736                 {
2737                     if (Type t = ss.withstate.exp.isTypeExp().type)
2738                     {
2739                         Expression e;
2740                         e = new TypeExp(exp.loc, t);
2741                         e = new DotIdExp(exp.loc, e, exp.ident);
2742                         e = e.trySemantic(sc);
2743                         if (e)
2744                         {
2745                             result = e;
2746                             return;
2747                         }
2748                     }
2749                 }
2750             }
2751         }
2752 
2753         /* Look for what user might have meant
2754          */
2755         if (const n = importHint(exp.ident.toString()))
2756             exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2757         else if (auto s2 = sc.search_correct(exp.ident))
2758             exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2759         else if (const p = Scope.search_correct_C(exp.ident))
2760             exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2761         else
2762             exp.error("undefined identifier `%s`", exp.ident.toChars());
2763 
2764         result = ErrorExp.get();
2765     }
2766 
2767     override void visit(DsymbolExp e)
2768     {
2769         result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2770     }
2771 
2772     override void visit(ThisExp e)
2773     {
2774         static if (LOGSEMANTIC)
2775         {
2776             printf("ThisExp::semantic()\n");
2777         }
2778         if (e.type)
2779         {
2780             result = e;
2781             return;
2782         }
2783 
2784         FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2785         AggregateDeclaration ad;
2786 
2787         /* Special case for typeof(this) and typeof(super) since both
2788          * should work even if they are not inside a non-static member function
2789          */
2790         if (!fd && sc.intypeof == 1)
2791         {
2792             // Find enclosing struct or class
2793             for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2794             {
2795                 if (!s)
2796                 {
2797                     e.error("`%s` is not in a class or struct scope", e.toChars());
2798                     goto Lerr;
2799                 }
2800                 ClassDeclaration cd = s.isClassDeclaration();
2801                 if (cd)
2802                 {
2803                     e.type = cd.type;
2804                     result = e;
2805                     return;
2806                 }
2807                 StructDeclaration sd = s.isStructDeclaration();
2808                 if (sd)
2809                 {
2810                     e.type = sd.type;
2811                     result = e;
2812                     return;
2813                 }
2814             }
2815         }
2816         if (!fd)
2817             goto Lerr;
2818 
2819         assert(fd.vthis);
2820         e.var = fd.vthis;
2821         assert(e.var.parent);
2822         ad = fd.isMemberLocal();
2823         if (!ad)
2824             ad = fd.isMember2();
2825         assert(ad);
2826         e.type = ad.type.addMod(e.var.type.mod);
2827 
2828         if (e.var.checkNestedReference(sc, e.loc))
2829             return setError();
2830 
2831         result = e;
2832         return;
2833 
2834     Lerr:
2835         e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2836         result = ErrorExp.get();
2837     }
2838 
2839     override void visit(SuperExp e)
2840     {
2841         static if (LOGSEMANTIC)
2842         {
2843             printf("SuperExp::semantic('%s')\n", e.toChars());
2844         }
2845         if (e.type)
2846         {
2847             result = e;
2848             return;
2849         }
2850 
2851         FuncDeclaration fd = hasThis(sc);
2852         ClassDeclaration cd;
2853         Dsymbol s;
2854 
2855         /* Special case for typeof(this) and typeof(super) since both
2856          * should work even if they are not inside a non-static member function
2857          */
2858         if (!fd && sc.intypeof == 1)
2859         {
2860             // Find enclosing class
2861             for (s = sc.getStructClassScope(); 1; s = s.parent)
2862             {
2863                 if (!s)
2864                 {
2865                     e.error("`%s` is not in a class scope", e.toChars());
2866                     goto Lerr;
2867                 }
2868                 cd = s.isClassDeclaration();
2869                 if (cd)
2870                 {
2871                     cd = cd.baseClass;
2872                     if (!cd)
2873                     {
2874                         e.error("class `%s` has no `super`", s.toChars());
2875                         goto Lerr;
2876                     }
2877                     e.type = cd.type;
2878                     result = e;
2879                     return;
2880                 }
2881             }
2882         }
2883         if (!fd)
2884             goto Lerr;
2885 
2886         e.var = fd.vthis;
2887         assert(e.var && e.var.parent);
2888 
2889         s = fd.toParentDecl();
2890         if (s.isTemplateDeclaration()) // allow inside template constraint
2891             s = s.toParent();
2892         assert(s);
2893         cd = s.isClassDeclaration();
2894         //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2895         if (!cd)
2896             goto Lerr;
2897         if (!cd.baseClass)
2898         {
2899             e.error("no base class for `%s`", cd.toChars());
2900             e.type = cd.type.addMod(e.var.type.mod);
2901         }
2902         else
2903         {
2904             e.type = cd.baseClass.type;
2905             e.type = e.type.castMod(e.var.type.mod);
2906         }
2907 
2908         if (e.var.checkNestedReference(sc, e.loc))
2909             return setError();
2910 
2911         result = e;
2912         return;
2913 
2914     Lerr:
2915         e.error("`super` is only allowed in non-static class member functions");
2916         result = ErrorExp.get();
2917     }
2918 
2919     override void visit(NullExp e)
2920     {
2921         static if (LOGSEMANTIC)
2922         {
2923             printf("NullExp::semantic('%s')\n", e.toChars());
2924         }
2925         // NULL is the same as (void *)0
2926         if (e.type)
2927         {
2928             result = e;
2929             return;
2930         }
2931         e.type = Type.tnull;
2932         result = e;
2933     }
2934 
2935     override void visit(StringExp e)
2936     {
2937         static if (LOGSEMANTIC)
2938         {
2939             printf("StringExp::semantic() %s\n", e.toChars());
2940         }
2941         if (e.type)
2942         {
2943             result = e;
2944             return;
2945         }
2946 
2947         OutBuffer buffer;
2948         size_t newlen = 0;
2949         size_t u;
2950         dchar c;
2951 
2952         switch (e.postfix)
2953         {
2954         case 'd':
2955             for (u = 0; u < e.len;)
2956             {
2957                 if (const p = utf_decodeChar(e.peekString(), u, c))
2958                 {
2959                     e.error("%.*s", cast(int)p.length, p.ptr);
2960                     return setError();
2961                 }
2962                 else
2963                 {
2964                     buffer.write4(c);
2965                     newlen++;
2966                 }
2967             }
2968             buffer.write4(0);
2969             e.setData(buffer.extractData(), newlen, 4);
2970             e.type = new TypeDArray(Type.tdchar.immutableOf());
2971             e.committed = 1;
2972             break;
2973 
2974         case 'w':
2975             for (u = 0; u < e.len;)
2976             {
2977                 if (const p = utf_decodeChar(e.peekString(), u, c))
2978                 {
2979                     e.error("%.*s", cast(int)p.length, p.ptr);
2980                     return setError();
2981                 }
2982                 else
2983                 {
2984                     buffer.writeUTF16(c);
2985                     newlen++;
2986                     if (c >= 0x10000)
2987                         newlen++;
2988                 }
2989             }
2990             buffer.writeUTF16(0);
2991             e.setData(buffer.extractData(), newlen, 2);
2992             e.type = new TypeDArray(Type.twchar.immutableOf());
2993             e.committed = 1;
2994             break;
2995 
2996         case 'c':
2997             e.committed = 1;
2998             goto default;
2999 
3000         default:
3001             e.type = new TypeDArray(Type.tchar.immutableOf());
3002             break;
3003         }
3004         e.type = e.type.typeSemantic(e.loc, sc);
3005         //type = type.immutableOf();
3006         //printf("type = %s\n", type.toChars());
3007 
3008         result = e;
3009     }
3010 
3011     override void visit(TupleExp exp)
3012     {
3013         static if (LOGSEMANTIC)
3014         {
3015             printf("+TupleExp::semantic(%s)\n", exp.toChars());
3016         }
3017         if (exp.type)
3018         {
3019             result = exp;
3020             return;
3021         }
3022 
3023         if (exp.e0)
3024             exp.e0 = exp.e0.expressionSemantic(sc);
3025 
3026         // Run semantic() on each argument
3027         bool err = false;
3028         for (size_t i = 0; i < exp.exps.dim; i++)
3029         {
3030             Expression e = (*exp.exps)[i];
3031             e = e.expressionSemantic(sc);
3032             if (!e.type)
3033             {
3034                 exp.error("`%s` has no value", e.toChars());
3035                 err = true;
3036             }
3037             else if (e.op == TOK.error)
3038                 err = true;
3039             else
3040                 (*exp.exps)[i] = e;
3041         }
3042         if (err)
3043             return setError();
3044 
3045         expandTuples(exp.exps);
3046 
3047         exp.type = new TypeTuple(exp.exps);
3048         exp.type = exp.type.typeSemantic(exp.loc, sc);
3049         //printf("-TupleExp::semantic(%s)\n", toChars());
3050         result = exp;
3051     }
3052 
3053     override void visit(ArrayLiteralExp e)
3054     {
3055         static if (LOGSEMANTIC)
3056         {
3057             printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3058         }
3059         if (e.type)
3060         {
3061             result = e;
3062             return;
3063         }
3064 
3065         /* Perhaps an empty array literal [ ] should be rewritten as null?
3066          */
3067 
3068         if (e.basis)
3069             e.basis = e.basis.expressionSemantic(sc);
3070         if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == TOK.error))
3071             return setError();
3072 
3073         expandTuples(e.elements);
3074 
3075         Type t0;
3076         if (e.basis)
3077             e.elements.push(e.basis);
3078         bool err = arrayExpressionToCommonType(sc, e.elements, &t0);
3079         if (e.basis)
3080             e.basis = e.elements.pop();
3081         if (err)
3082             return setError();
3083 
3084         e.type = t0.arrayOf();
3085         e.type = e.type.typeSemantic(e.loc, sc);
3086 
3087         /* Disallow array literals of type void being used.
3088          */
3089         if (e.elements.dim > 0 && t0.ty == Tvoid)
3090         {
3091             e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3092             return setError();
3093         }
3094 
3095         if (global.params.useTypeInfo && Type.dtypeinfo)
3096             semanticTypeInfo(sc, e.type);
3097 
3098         result = e;
3099     }
3100 
3101     override void visit(AssocArrayLiteralExp e)
3102     {
3103         static if (LOGSEMANTIC)
3104         {
3105             printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3106         }
3107         if (e.type)
3108         {
3109             result = e;
3110             return;
3111         }
3112 
3113         // Run semantic() on each element
3114         bool err_keys = arrayExpressionSemantic(e.keys, sc);
3115         bool err_vals = arrayExpressionSemantic(e.values, sc);
3116         if (err_keys || err_vals)
3117             return setError();
3118 
3119         expandTuples(e.keys);
3120         expandTuples(e.values);
3121         if (e.keys.dim != e.values.dim)
3122         {
3123             e.error("number of keys is %llu, must match number of values %llu",
3124                         cast(ulong) e.keys.dim, cast(ulong) e.values.dim);
3125             return setError();
3126         }
3127 
3128         Type tkey = null;
3129         Type tvalue = null;
3130         err_keys = arrayExpressionToCommonType(sc, e.keys, &tkey);
3131         err_vals = arrayExpressionToCommonType(sc, e.values, &tvalue);
3132         if (err_keys || err_vals)
3133             return setError();
3134 
3135         if (tkey == Type.terror || tvalue == Type.terror)
3136             return setError();
3137 
3138         e.type = new TypeAArray(tvalue, tkey);
3139         e.type = e.type.typeSemantic(e.loc, sc);
3140 
3141         semanticTypeInfo(sc, e.type);
3142 
3143         if (global.params.vsafe)
3144         {
3145             if (checkAssocArrayLiteralEscape(sc, e, false))
3146                 return setError();
3147         }
3148 
3149         result = e;
3150     }
3151 
3152     override void visit(StructLiteralExp e)
3153     {
3154         static if (LOGSEMANTIC)
3155         {
3156             printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3157         }
3158         if (e.type)
3159         {
3160             result = e;
3161             return;
3162         }
3163 
3164         e.sd.size(e.loc);
3165         if (e.sd.sizeok != Sizeok.done)
3166             return setError();
3167 
3168         // run semantic() on each element
3169         if (arrayExpressionSemantic(e.elements, sc))
3170             return setError();
3171 
3172         expandTuples(e.elements);
3173 
3174         /* Fit elements[] to the corresponding type of field[].
3175          */
3176         if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3177             return setError();
3178 
3179         /* Fill out remainder of elements[] with default initializers for fields[]
3180          */
3181         if (!e.sd.fill(e.loc, e.elements, false))
3182         {
3183             /* An error in the initializer needs to be recorded as an error
3184              * in the enclosing function or template, since the initializer
3185              * will be part of the stuct declaration.
3186              */
3187             global.increaseErrorCount();
3188             return setError();
3189         }
3190 
3191         if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
3192             return setError();
3193 
3194         e.type = e.stype ? e.stype : e.sd.type;
3195         result = e;
3196     }
3197 
3198     override void visit(TypeExp exp)
3199     {
3200         if (exp.type.ty == Terror)
3201             return setError();
3202 
3203         //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3204         Expression e;
3205         Type t;
3206         Dsymbol s;
3207 
3208         dmd.typesem.resolve(exp.type, exp.loc, sc, &e, &t, &s, true);
3209         if (e)
3210         {
3211             // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3212             // then rewrite as `(this.var)` in case it would be followed by a DotVar
3213             // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3214             VarExp ve = e.isVarExp();
3215             if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3216                 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
3217             {
3218                 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3219                 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3220             }
3221             //printf("e = %s %s\n", Token::toChars(e.op), e.toChars());
3222             e = e.expressionSemantic(sc);
3223         }
3224         else if (t)
3225         {
3226             //printf("t = %d %s\n", t.ty, t.toChars());
3227             exp.type = t.typeSemantic(exp.loc, sc);
3228             e = exp;
3229         }
3230         else if (s)
3231         {
3232             //printf("s = %s %s\n", s.kind(), s.toChars());
3233             e = symbolToExp(s, exp.loc, sc, true);
3234         }
3235         else
3236             assert(0);
3237 
3238         if (global.params.vcomplex)
3239             exp.type.checkComplexTransition(exp.loc, sc);
3240 
3241         result = e;
3242     }
3243 
3244     override void visit(ScopeExp exp)
3245     {
3246         static if (LOGSEMANTIC)
3247         {
3248             printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3249         }
3250         if (exp.type)
3251         {
3252             result = exp;
3253             return;
3254         }
3255 
3256         ScopeDsymbol sds2 = exp.sds;
3257         TemplateInstance ti = sds2.isTemplateInstance();
3258         while (ti)
3259         {
3260             WithScopeSymbol withsym;
3261             if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3262                 return setError();
3263             if (withsym && withsym.withstate.wthis)
3264             {
3265                 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3266                 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3267                 result = e.expressionSemantic(sc);
3268                 return;
3269             }
3270             if (ti.needsTypeInference(sc))
3271             {
3272                 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3273                 {
3274                     Dsymbol p = td.toParentLocal();
3275                     FuncDeclaration fdthis = hasThis(sc);
3276                     AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3277                     if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3278                     {
3279                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3280                         result = e.expressionSemantic(sc);
3281                         return;
3282                     }
3283                 }
3284                 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3285                 {
3286                     FuncDeclaration fdthis = hasThis(sc);
3287                     AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3288                     if (fdthis && ad && fdthis.isMemberLocal() == ad)
3289                     {
3290                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3291                         result = e.expressionSemantic(sc);
3292                         return;
3293                     }
3294                 }
3295                 // ti is an instance which requires IFTI.
3296                 exp.sds = ti;
3297                 exp.type = Type.tvoid;
3298                 result = exp;
3299                 return;
3300             }
3301             ti.dsymbolSemantic(sc);
3302             if (!ti.inst || ti.errors)
3303                 return setError();
3304 
3305             Dsymbol s = ti.toAlias();
3306             if (s == ti)
3307             {
3308                 exp.sds = ti;
3309                 exp.type = Type.tvoid;
3310                 result = exp;
3311                 return;
3312             }
3313             sds2 = s.isScopeDsymbol();
3314             if (sds2)
3315             {
3316                 ti = sds2.isTemplateInstance();
3317                 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3318                 continue;
3319             }
3320 
3321             if (auto v = s.isVarDeclaration())
3322             {
3323                 if (!v.type)
3324                 {
3325                     exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3326                     return setError();
3327                 }
3328                 if ((v.storage_class & STC.manifest) && v._init)
3329                 {
3330                     /* When an instance that will be converted to a constant exists,
3331                      * the instance representation "foo!tiargs" is treated like a
3332                      * variable name, and its recursive appearance check (note that
3333                      * it's equivalent with a recursive instantiation of foo) is done
3334                      * separately from the circular initialization check for the
3335                      * eponymous enum variable declaration.
3336                      *
3337                      *  template foo(T) {
3338                      *    enum bool foo = foo;    // recursive definition check (v.inuse)
3339                      *  }
3340                      *  template bar(T) {
3341                      *    enum bool bar = bar!T;  // recursive instantiation check (ti.inuse)
3342                      *  }
3343                      */
3344                     if (ti.inuse)
3345                     {
3346                         exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3347                         return setError();
3348                     }
3349                     v.checkDeprecated(exp.loc, sc);
3350                     auto e = v.expandInitializer(exp.loc);
3351                     ti.inuse++;
3352                     e = e.expressionSemantic(sc);
3353                     ti.inuse--;
3354                     result = e;
3355                     return;
3356                 }
3357             }
3358 
3359             //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3360             auto e = symbolToExp(s, exp.loc, sc, true);
3361             //printf("-1ScopeExp::semantic()\n");
3362             result = e;
3363             return;
3364         }
3365 
3366         //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3367         //printf("\tparent = '%s'\n", sds2.parent.toChars());
3368         sds2.dsymbolSemantic(sc);
3369 
3370         // (Aggregate|Enum)Declaration
3371         if (auto t = sds2.getType())
3372         {
3373             result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3374             return;
3375         }
3376 
3377         if (auto td = sds2.isTemplateDeclaration())
3378         {
3379             result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3380             return;
3381         }
3382 
3383         exp.sds = sds2;
3384         exp.type = Type.tvoid;
3385         //printf("-2ScopeExp::semantic() %s\n", toChars());
3386         result = exp;
3387     }
3388 
3389     override void visit(NewExp exp)
3390     {
3391         static if (LOGSEMANTIC)
3392         {
3393             printf("NewExp::semantic() %s\n", exp.toChars());
3394             if (exp.thisexp)
3395                 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3396             printf("\tnewtype: %s\n", exp.newtype.toChars());
3397         }
3398         if (exp.type) // if semantic() already run
3399         {
3400             result = exp;
3401             return;
3402         }
3403 
3404         //for error messages if the argument in [] is not convertible to size_t
3405         const originalNewtype = exp.newtype;
3406 
3407         // https://issues.dlang.org/show_bug.cgi?id=11581
3408         // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3409         // T should be analyzed first and edim should go into arguments iff it's
3410         // not a tuple.
3411         Expression edim = null;
3412         if (!exp.arguments && exp.newtype.ty == Tsarray)
3413         {
3414             edim = (cast(TypeSArray)exp.newtype).dim;
3415             exp.newtype = (cast(TypeNext)exp.newtype).next;
3416         }
3417 
3418         ClassDeclaration cdthis = null;
3419         if (exp.thisexp)
3420         {
3421             exp.thisexp = exp.thisexp.expressionSemantic(sc);
3422             if (exp.thisexp.op == TOK.error)
3423                 return setError();
3424 
3425             cdthis = exp.thisexp.type.isClassHandle();
3426             if (!cdthis)
3427             {
3428                 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3429                 return setError();
3430             }
3431 
3432             sc = sc.push(cdthis);
3433             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3434             sc = sc.pop();
3435         }
3436         else
3437         {
3438             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3439         }
3440         if (exp.type.ty == Terror)
3441             return setError();
3442 
3443         if (edim)
3444         {
3445             if (exp.type.toBasetype().ty == Ttuple)
3446             {
3447                 // --> new T[edim]
3448                 exp.type = new TypeSArray(exp.type, edim);
3449                 exp.type = exp.type.typeSemantic(exp.loc, sc);
3450                 if (exp.type.ty == Terror)
3451                     return setError();
3452             }
3453             else
3454             {
3455                 // --> new T[](edim)
3456                 exp.arguments = new Expressions();
3457                 exp.arguments.push(edim);
3458                 exp.type = exp.type.arrayOf();
3459             }
3460         }
3461 
3462         exp.newtype = exp.type; // in case type gets cast to something else
3463         Type tb = exp.type.toBasetype();
3464         //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3465         if (arrayExpressionSemantic(exp.newargs, sc) ||
3466             preFunctionParameters(sc, exp.newargs))
3467         {
3468             return setError();
3469         }
3470         if (arrayExpressionSemantic(exp.arguments, sc))
3471         {
3472             return setError();
3473         }
3474         //https://issues.dlang.org/show_bug.cgi?id=20547
3475         //exp.arguments are the "parameters" to [], not to a real function
3476         //so the errors that come from preFunctionParameters are misleading
3477         if (originalNewtype.ty == Tsarray)
3478         {
3479             if (preFunctionParameters(sc, exp.arguments, false))
3480             {
3481                 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
3482                 return setError();
3483             }
3484         }
3485         else if (preFunctionParameters(sc, exp.arguments))
3486         {
3487             return setError();
3488         }
3489 
3490         if (exp.thisexp && tb.ty != Tclass)
3491         {
3492             exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3493             return setError();
3494         }
3495 
3496         const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
3497         Expression newprefix = null;
3498 
3499         if (tb.ty == Tclass)
3500         {
3501             auto cd = (cast(TypeClass)tb).sym;
3502             cd.size(exp.loc);
3503             if (cd.sizeok != Sizeok.done)
3504                 return setError();
3505             if (!cd.ctor)
3506                 cd.ctor = cd.searchCtor();
3507             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3508             {
3509                 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3510                 return setError();
3511             }
3512 
3513             if (cd.isInterfaceDeclaration())
3514             {
3515                 exp.error("cannot create instance of interface `%s`", cd.toChars());
3516                 return setError();
3517             }
3518 
3519             if (cd.isAbstract())
3520             {
3521                 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3522                 for (size_t i = 0; i < cd.vtbl.dim; i++)
3523                 {
3524                     FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3525                     if (fd && fd.isAbstract())
3526                     {
3527                         errorSupplemental(exp.loc, "function `%s` is not implemented",
3528                             fd.toFullSignature());
3529                     }
3530                 }
3531                 return setError();
3532             }
3533             // checkDeprecated() is already done in newtype.typeSemantic().
3534 
3535             if (cd.isNested())
3536             {
3537                 /* We need a 'this' pointer for the nested class.
3538                  * Ensure we have the right one.
3539                  */
3540                 Dsymbol s = cd.toParentLocal();
3541 
3542                 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3543                 if (auto cdn = s.isClassDeclaration())
3544                 {
3545                     if (!cdthis)
3546                     {
3547                         // Supply an implicit 'this' and try again
3548                         exp.thisexp = new ThisExp(exp.loc);
3549                         for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3550                         {
3551                             if (!sp)
3552                             {
3553                                 exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
3554                                     cdn.toChars(), cd.toChars());
3555                                 return setError();
3556                             }
3557                             ClassDeclaration cdp = sp.isClassDeclaration();
3558                             if (!cdp)
3559                                 continue;
3560                             if (cdp == cdn || cdn.isBaseOf(cdp, null))
3561                                 break;
3562                             // Add a '.outer' and try again
3563                             exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3564                         }
3565 
3566                         exp.thisexp = exp.thisexp.expressionSemantic(sc);
3567                         if (exp.thisexp.op == TOK.error)
3568                             return setError();
3569                         cdthis = exp.thisexp.type.isClassHandle();
3570                     }
3571                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3572                     {
3573                         //printf("cdthis = %s\n", cdthis.toChars());
3574                         exp.error("`this` for nested class must be of type `%s`, not `%s`",
3575                             cdn.toChars(), exp.thisexp.type.toChars());
3576                         return setError();
3577                     }
3578                     if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3579                     {
3580                         exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3581                             exp.newtype.toChars(), exp.thisexp.type.toChars());
3582                         return setError();
3583                     }
3584                 }
3585                 else if (exp.thisexp)
3586                 {
3587                     exp.error("`.new` is only for allocating nested classes");
3588                     return setError();
3589                 }
3590                 else if (auto fdn = s.isFuncDeclaration())
3591                 {
3592                     // make sure the parent context fdn of cd is reachable from sc
3593                     if (!ensureStaticLinkTo(sc.parent, fdn))
3594                     {
3595                         exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3596                             fdn.toPrettyChars(), cd.toPrettyChars());
3597                         return setError();
3598                     }
3599                 }
3600                 else
3601                     assert(0);
3602             }
3603             else if (exp.thisexp)
3604             {
3605                 exp.error("`.new` is only for allocating nested classes");
3606                 return setError();
3607             }
3608 
3609             if (cd.vthis2)
3610             {
3611                 if (AggregateDeclaration ad2 = cd.isMember2())
3612                 {
3613                     Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3614                     if (te.op != TOK.error)
3615                         te = getRightThis(exp.loc, sc, ad2, te, cd);
3616                     if (te.op == TOK.error)
3617                     {
3618                         exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3619                         return setError();
3620                     }
3621                 }
3622             }
3623 
3624             if (cd.aggNew)
3625             {
3626                 // Prepend the size argument to newargs[]
3627                 Expression e = new IntegerExp(exp.loc, cd.size(exp.loc), Type.tsize_t);
3628                 if (!exp.newargs)
3629                     exp.newargs = new Expressions();
3630                 exp.newargs.shift(e);
3631 
3632                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3633                 if (!f || f.errors)
3634                     return setError();
3635 
3636                 checkFunctionAttributes(exp, sc, f);
3637                 checkAccess(cd, exp.loc, sc, f);
3638 
3639                 TypeFunction tf = cast(TypeFunction)f.type;
3640                 Type rettype;
3641                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3642                     return setError();
3643 
3644                 exp.allocator = f.isNewDeclaration();
3645                 assert(exp.allocator);
3646             }
3647             else
3648             {
3649                 if (exp.newargs && exp.newargs.dim)
3650                 {
3651                     exp.error("no allocator for `%s`", cd.toChars());
3652                     return setError();
3653                 }
3654             }
3655 
3656             if (cd.ctor)
3657             {
3658                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3659                 if (!f || f.errors)
3660                     return setError();
3661 
3662                 checkFunctionAttributes(exp, sc, f);
3663                 checkAccess(cd, exp.loc, sc, f);
3664 
3665                 TypeFunction tf = cast(TypeFunction)f.type;
3666                 if (!exp.arguments)
3667                     exp.arguments = new Expressions();
3668                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3669                     return setError();
3670 
3671                 exp.member = f.isCtorDeclaration();
3672                 assert(exp.member);
3673             }
3674             else
3675             {
3676                 if (nargs)
3677                 {
3678                     exp.error("no constructor for `%s`", cd.toChars());
3679                     return setError();
3680                 }
3681 
3682                 // https://issues.dlang.org/show_bug.cgi?id=19941
3683                 // Run semantic on all field initializers to resolve any forward
3684                 // references. This is the same as done for structs in sd.fill().
3685                 for (ClassDeclaration c = cd; c; c = c.baseClass)
3686                 {
3687                     foreach (v; c.fields)
3688                     {
3689                         if (v.inuse || v._scope is null || v._init is null ||
3690                             v._init.isVoidInitializer())
3691                             continue;
3692                         v.inuse++;
3693                         v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3694                         v.inuse--;
3695                     }
3696                 }
3697             }
3698         }
3699         else if (tb.ty == Tstruct)
3700         {
3701             auto sd = (cast(TypeStruct)tb).sym;
3702             sd.size(exp.loc);
3703             if (sd.sizeok != Sizeok.done)
3704                 return setError();
3705             if (!sd.ctor)
3706                 sd.ctor = sd.searchCtor();
3707             if (sd.noDefaultCtor && !nargs)
3708             {
3709                 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3710                 return setError();
3711             }
3712             // checkDeprecated() is already done in newtype.typeSemantic().
3713 
3714             if (sd.aggNew)
3715             {
3716                 // Prepend the uint size argument to newargs[]
3717                 Expression e = new IntegerExp(exp.loc, sd.size(exp.loc), Type.tsize_t);
3718                 if (!exp.newargs)
3719                     exp.newargs = new Expressions();
3720                 exp.newargs.shift(e);
3721 
3722                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.aggNew, null, tb, exp.newargs, FuncResolveFlag.standard);
3723                 if (!f || f.errors)
3724                     return setError();
3725 
3726                 checkFunctionAttributes(exp, sc, f);
3727                 checkAccess(sd, exp.loc, sc, f);
3728 
3729                 TypeFunction tf = cast(TypeFunction)f.type;
3730                 Type rettype;
3731                 if (functionParameters(exp.loc, sc, tf, null, null, exp.newargs, f, &rettype, &newprefix))
3732                     return setError();
3733 
3734                 exp.allocator = f.isNewDeclaration();
3735                 assert(exp.allocator);
3736             }
3737             else
3738             {
3739                 if (exp.newargs && exp.newargs.dim)
3740                 {
3741                     exp.error("no allocator for `%s`", sd.toChars());
3742                     return setError();
3743                 }
3744             }
3745 
3746             if (sd.ctor && nargs)
3747             {
3748                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3749                 if (!f || f.errors)
3750                     return setError();
3751 
3752                 checkFunctionAttributes(exp, sc, f);
3753                 checkAccess(sd, exp.loc, sc, f);
3754 
3755                 TypeFunction tf = cast(TypeFunction)f.type;
3756                 if (!exp.arguments)
3757                     exp.arguments = new Expressions();
3758                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3759                     return setError();
3760 
3761                 exp.member = f.isCtorDeclaration();
3762                 assert(exp.member);
3763 
3764                 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
3765                     return setError();
3766             }
3767             else
3768             {
3769                 if (!exp.arguments)
3770                     exp.arguments = new Expressions();
3771 
3772                 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3773                     return setError();
3774 
3775                 if (!sd.fill(exp.loc, exp.arguments, false))
3776                     return setError();
3777 
3778                 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
3779                     return setError();
3780 
3781                 /* Since a `new` allocation may escape, check each of the arguments for escaping
3782                  */
3783                 if (global.params.vsafe)
3784                 {
3785                     foreach (arg; *exp.arguments)
3786                     {
3787                         if (arg && checkNewEscape(sc, arg, false))
3788                             return setError();
3789                     }
3790                 }
3791             }
3792 
3793             exp.type = exp.type.pointerTo();
3794         }
3795         else if (tb.ty == Tarray)
3796         {
3797             if (!nargs)
3798             {
3799                 // https://issues.dlang.org/show_bug.cgi?id=20422
3800                 // Without this check the compiler would give a misleading error
3801                 exp.error("missing length argument for array");
3802                 return setError();
3803             }
3804 
3805             Type tn = tb.nextOf().baseElemOf();
3806             Dsymbol s = tn.toDsymbol(sc);
3807             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3808             if (ad && ad.noDefaultCtor)
3809             {
3810                 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3811                 return setError();
3812             }
3813             for (size_t i = 0; i < nargs; i++)
3814             {
3815                 if (tb.ty != Tarray)
3816                 {
3817                     exp.error("too many arguments for array");
3818                     return setError();
3819                 }
3820 
3821                 Expression arg = (*exp.arguments)[i];
3822                 arg = resolveProperties(sc, arg);
3823                 arg = arg.implicitCastTo(sc, Type.tsize_t);
3824                 if (arg.op == TOK.error)
3825                     return setError();
3826                 arg = arg.optimize(WANTvalue);
3827                 if (arg.op == TOK.int64 && cast(sinteger_t)arg.toInteger() < 0)
3828                 {
3829                     exp.error("negative array index `%s`", arg.toChars());
3830                     return setError();
3831                 }
3832                 (*exp.arguments)[i] = arg;
3833                 tb = (cast(TypeDArray)tb).next.toBasetype();
3834             }
3835         }
3836         else if (tb.isscalar())
3837         {
3838             if (!nargs)
3839             {
3840             }
3841             else if (nargs == 1)
3842             {
3843                 Expression e = (*exp.arguments)[0];
3844                 e = e.implicitCastTo(sc, tb);
3845                 (*exp.arguments)[0] = e;
3846             }
3847             else
3848             {
3849                 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3850                 return setError();
3851             }
3852 
3853             exp.type = exp.type.pointerTo();
3854         }
3855         else
3856         {
3857             exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3858             return setError();
3859         }
3860 
3861         //printf("NewExp: '%s'\n", toChars());
3862         //printf("NewExp:type '%s'\n", type.toChars());
3863         semanticTypeInfo(sc, exp.type);
3864 
3865         if (newprefix)
3866         {
3867             result = Expression.combine(newprefix, exp);
3868             return;
3869         }
3870         result = exp;
3871     }
3872 
3873     override void visit(NewAnonClassExp e)
3874     {
3875         static if (LOGSEMANTIC)
3876         {
3877             printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3878             //printf("thisexp = %p\n", thisexp);
3879             //printf("type: %s\n", type.toChars());
3880         }
3881 
3882         Expression d = new DeclarationExp(e.loc, e.cd);
3883         sc = sc.push(); // just create new scope
3884         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3885         d = d.expressionSemantic(sc);
3886         sc = sc.pop();
3887 
3888         if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3889         {
3890             ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3891             if (!sds.members)
3892                 sds.members = new Dsymbols();
3893             sds.members.push(e.cd);
3894         }
3895 
3896         Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments);
3897 
3898         Expression c = new CommaExp(e.loc, d, n);
3899         result = c.expressionSemantic(sc);
3900     }
3901 
3902     override void visit(SymOffExp e)
3903     {
3904         static if (LOGSEMANTIC)
3905         {
3906             printf("SymOffExp::semantic('%s')\n", e.toChars());
3907         }
3908         //var.dsymbolSemantic(sc);
3909         if (!e.type)
3910             e.type = e.var.type.pointerTo();
3911 
3912         if (auto v = e.var.isVarDeclaration())
3913         {
3914             if (v.checkNestedReference(sc, e.loc))
3915                 return setError();
3916         }
3917         else if (auto f = e.var.isFuncDeclaration())
3918         {
3919             if (f.checkNestedReference(sc, e.loc))
3920                 return setError();
3921         }
3922 
3923         result = e;
3924     }
3925 
3926     override void visit(VarExp e)
3927     {
3928         static if (LOGSEMANTIC)
3929         {
3930             printf("VarExp::semantic(%s)\n", e.toChars());
3931         }
3932 
3933         auto vd = e.var.isVarDeclaration();
3934         auto fd = e.var.isFuncDeclaration();
3935 
3936         if (fd)
3937         {
3938             //printf("L%d fd = %s\n", __LINE__, f.toChars());
3939             if (!fd.functionSemantic())
3940                 return setError();
3941         }
3942 
3943         if (!e.type)
3944             e.type = e.var.type;
3945         if (e.type && !e.type.deco)
3946         {
3947             auto decl = e.var.isDeclaration();
3948             if (decl)
3949                 decl.inuse++;
3950             e.type = e.type.typeSemantic(e.loc, sc);
3951             if (decl)
3952                 decl.inuse--;
3953         }
3954 
3955         /* Fix for 1161 doesn't work because it causes protection
3956          * problems when instantiating imported templates passing private
3957          * variables as alias template parameters.
3958          */
3959         //checkAccess(loc, sc, NULL, var);
3960 
3961         if (vd)
3962         {
3963             if (vd.checkNestedReference(sc, e.loc))
3964                 return setError();
3965 
3966             // https://issues.dlang.org/show_bug.cgi?id=12025
3967             // If the variable is not actually used in runtime code,
3968             // the purity violation error is redundant.
3969             //checkPurity(sc, vd);
3970         }
3971         else if (fd)
3972         {
3973             // TODO: If fd isn't yet resolved its overload, the checkNestedReference
3974             // call would cause incorrect validation.
3975             // Maybe here should be moved in CallExp, or AddrExp for functions.
3976             if (fd.checkNestedReference(sc, e.loc))
3977                 return setError();
3978         }
3979         else if (auto od = e.var.isOverDeclaration())
3980         {
3981             e.type = Type.tvoid; // ambiguous type?
3982         }
3983 
3984         result = e;
3985     }
3986 
3987     override void visit(FuncExp exp)
3988     {
3989         static if (LOGSEMANTIC)
3990         {
3991             printf("FuncExp::semantic(%s)\n", exp.toChars());
3992             if (exp.fd.treq)
3993                 printf("  treq = %s\n", exp.fd.treq.toChars());
3994         }
3995 
3996         if (exp.type)
3997         {
3998             result = exp;
3999             return;
4000         }
4001 
4002         Expression e = exp;
4003         uint olderrors;
4004 
4005         sc = sc.push(); // just create new scope
4006         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4007         sc.protection = Prot(Prot.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4008 
4009         /* fd.treq might be incomplete type,
4010             * so should not semantic it.
4011             * void foo(T)(T delegate(int) dg){}
4012             * foo(a=>a); // in IFTI, treq == T delegate(int)
4013             */
4014         //if (fd.treq)
4015         //    fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4016 
4017         exp.genIdent(sc);
4018 
4019         // Set target of return type inference
4020         if (exp.fd.treq && !exp.fd.type.nextOf())
4021         {
4022             TypeFunction tfv = null;
4023             if (exp.fd.treq.ty == Tdelegate || (exp.fd.treq.ty == Tpointer && exp.fd.treq.nextOf().ty == Tfunction))
4024                 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4025             if (tfv)
4026             {
4027                 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4028                 tfl.next = tfv.nextOf();
4029             }
4030         }
4031 
4032         //printf("td = %p, treq = %p\n", td, fd.treq);
4033         if (exp.td)
4034         {
4035             assert(exp.td.parameters && exp.td.parameters.dim);
4036             exp.td.dsymbolSemantic(sc);
4037             exp.type = Type.tvoid; // temporary type
4038 
4039             if (exp.fd.treq) // defer type determination
4040             {
4041                 FuncExp fe;
4042                 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4043                     e = fe;
4044                 else
4045                     e = ErrorExp.get();
4046             }
4047             goto Ldone;
4048         }
4049 
4050         olderrors = global.errors;
4051         exp.fd.dsymbolSemantic(sc);
4052         if (olderrors == global.errors)
4053         {
4054             exp.fd.semantic2(sc);
4055             if (olderrors == global.errors)
4056                 exp.fd.semantic3(sc);
4057         }
4058         if (olderrors != global.errors)
4059         {
4060             if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4061                 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4062             e = ErrorExp.get();
4063             goto Ldone;
4064         }
4065 
4066         // Type is a "delegate to" or "pointer to" the function literal
4067         if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4068         {
4069             exp.type = new TypeDelegate(exp.fd.type);
4070             exp.type = exp.type.typeSemantic(exp.loc, sc);
4071 
4072             exp.fd.tok = TOK.delegate_;
4073         }
4074         else
4075         {
4076             exp.type = new TypePointer(exp.fd.type);
4077             exp.type = exp.type.typeSemantic(exp.loc, sc);
4078             //type = fd.type.pointerTo();
4079 
4080             /* A lambda expression deduced to function pointer might become
4081                 * to a delegate literal implicitly.
4082                 *
4083                 *   auto foo(void function() fp) { return 1; }
4084                 *   assert(foo({}) == 1);
4085                 *
4086                 * So, should keep fd.tok == TOKreserve if fd.treq == NULL.
4087                 */
4088             if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4089             {
4090                 // change to non-nested
4091                 exp.fd.tok = TOK.function_;
4092                 exp.fd.vthis = null;
4093             }
4094         }
4095         exp.fd.tookAddressOf++;
4096 
4097     Ldone:
4098         sc = sc.pop();
4099         result = e;
4100     }
4101 
4102     /**
4103      * Perform semantic analysis on function literals
4104      *
4105      * Test the following construct:
4106      * ---
4107      * (x, y, z) { return x + y + z; }(42, 84, 1992);
4108      * ---
4109      */
4110     Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4111     {
4112         if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
4113         {
4114             for (size_t k = 0; k < arguments.dim; k++)
4115             {
4116                 Expression checkarg = (*arguments)[k];
4117                 if (checkarg.op == TOK.error)
4118                     return checkarg;
4119             }
4120 
4121             exp.genIdent(sc);
4122 
4123             assert(exp.td.parameters && exp.td.parameters.dim);
4124             exp.td.dsymbolSemantic(sc);
4125 
4126             TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4127             size_t dim = tfl.parameterList.length;
4128             if (arguments.dim < dim)
4129             {
4130                 // Default arguments are always typed, so they don't need inference.
4131                 Parameter p = tfl.parameterList[arguments.dim];
4132                 if (p.defaultArg)
4133                     dim = arguments.dim;
4134             }
4135 
4136             if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
4137                 arguments.dim < dim)
4138             {
4139                 OutBuffer buf;
4140                 foreach (idx, ref arg; *arguments)
4141                     buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4142                 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4143                           exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4144                           buf.peekChars());
4145                 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
4146                                       arguments.dim < dim ? "few".ptr : "many".ptr,
4147                                       cast(int)dim, cast(int)arguments.dim);
4148                 return ErrorExp.get();
4149             }
4150 
4151             auto tiargs = new Objects();
4152             tiargs.reserve(exp.td.parameters.dim);
4153 
4154             for (size_t i = 0; i < exp.td.parameters.dim; i++)
4155             {
4156                 TemplateParameter tp = (*exp.td.parameters)[i];
4157                 assert(dim <= tfl.parameterList.length);
4158                 foreach (u, p; tfl.parameterList)
4159                 {
4160                     if (u == dim)
4161                         break;
4162 
4163                     if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4164                     {
4165                         Expression e = (*arguments)[u];
4166                         tiargs.push(e.type);
4167                         break;
4168                     }
4169                 }
4170             }
4171 
4172             auto ti = Pool!TemplateInstance.make(exp.loc, exp.td, tiargs);
4173             return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4174         }
4175         return exp.expressionSemantic(sc);
4176     }
4177 
4178     override void visit(CallExp exp)
4179     {
4180         static if (LOGSEMANTIC)
4181         {
4182             printf("CallExp::semantic() %s\n", exp.toChars());
4183         }
4184         if (exp.type)
4185         {
4186             result = exp;
4187             return; // semantic() already run
4188         }
4189 
4190         Objects* tiargs = null; // initial list of template arguments
4191         Expression ethis = null;
4192         Type tthis = null;
4193         Expression e1org = exp.e1;
4194 
4195         if (exp.e1.op == TOK.comma)
4196         {
4197             /* Rewrite (a,b)(args) as (a,(b(args)))
4198              */
4199             auto ce = cast(CommaExp)exp.e1;
4200             exp.e1 = ce.e2;
4201             ce.e2 = exp;
4202             result = ce.expressionSemantic(sc);
4203             return;
4204         }
4205         if (exp.e1.op == TOK.delegate_)
4206         {
4207             DelegateExp de = cast(DelegateExp)exp.e1;
4208             exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4209             visit(exp);
4210             return;
4211         }
4212         if (exp.e1.op == TOK.function_)
4213         {
4214             if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4215                 return setError();
4216 
4217             // Run e1 semantic even if arguments have any errors
4218             FuncExp fe = cast(FuncExp)exp.e1;
4219             exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4220             if (exp.e1.op == TOK.error)
4221             {
4222                 result = exp.e1;
4223                 return;
4224             }
4225         }
4226 
4227         if (Expression ex = resolveUFCS(sc, exp))
4228         {
4229             result = ex;
4230             return;
4231         }
4232 
4233         /* This recognizes:
4234          *  foo!(tiargs)(funcargs)
4235          */
4236         if (exp.e1.op == TOK.scope_)
4237         {
4238             ScopeExp se = cast(ScopeExp)exp.e1;
4239             TemplateInstance ti = se.sds.isTemplateInstance();
4240             if (ti)
4241             {
4242                 /* Attempt to instantiate ti. If that works, go with it.
4243                  * If not, go with partial explicit specialization.
4244                  */
4245                 WithScopeSymbol withsym;
4246                 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4247                     return setError();
4248                 if (withsym && withsym.withstate.wthis)
4249                 {
4250                     exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4251                     exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4252                     goto Ldotti;
4253                 }
4254                 if (ti.needsTypeInference(sc, 1))
4255                 {
4256                     /* Go with partial explicit specialization
4257                      */
4258                     tiargs = ti.tiargs;
4259                     assert(ti.tempdecl);
4260                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4261                         exp.e1 = new TemplateExp(exp.loc, td);
4262                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4263                         exp.e1 = new VarExp(exp.loc, od);
4264                     else
4265                         exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4266                 }
4267                 else
4268                 {
4269                     Expression e1x = exp.e1.expressionSemantic(sc);
4270                     if (e1x.op == TOK.error)
4271                     {
4272                         result = e1x;
4273                         return;
4274                     }
4275                     exp.e1 = e1x;
4276                 }
4277             }
4278         }
4279 
4280         /* This recognizes:
4281          *  expr.foo!(tiargs)(funcargs)
4282          */
4283     Ldotti:
4284         if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4285         {
4286             DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
4287             TemplateInstance ti = se.ti;
4288             {
4289                 /* Attempt to instantiate ti. If that works, go with it.
4290                  * If not, go with partial explicit specialization.
4291                  */
4292                 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4293                     return setError();
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 DotTemplateExp(exp.loc, se.e1, td);
4302                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4303                     {
4304                         exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4305                     }
4306                     else
4307                         exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4308                 }
4309                 else
4310                 {
4311                     Expression e1x = exp.e1.expressionSemantic(sc);
4312                     if (e1x.op == TOK.error)
4313                     {
4314                         result = e1x;
4315                         return;
4316                     }
4317                     exp.e1 = e1x;
4318                 }
4319             }
4320         }
4321 
4322     Lagain:
4323         //printf("Lagain: %s\n", toChars());
4324         exp.f = null;
4325         if (exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_)
4326         {
4327             // semantic() run later for these
4328         }
4329         else
4330         {
4331             if (exp.e1.op == TOK.dotIdentifier)
4332             {
4333                 DotIdExp die = cast(DotIdExp)exp.e1;
4334                 exp.e1 = die.expressionSemantic(sc);
4335                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4336                  * We handle such earlier, so go back.
4337                  * Note that in the rewrite, we carefully did not run semantic() on e1
4338                  */
4339                 if (exp.e1.op == TOK.dotTemplateInstance && !exp.e1.type)
4340                 {
4341                     goto Ldotti;
4342                 }
4343             }
4344             else
4345             {
4346                 __gshared int nest;
4347                 if (++nest > global.recursionLimit)
4348                 {
4349                     exp.error("recursive evaluation of `%s`", exp.toChars());
4350                     --nest;
4351                     return setError();
4352                 }
4353                 Expression ex = unaSemantic(exp, sc);
4354                 --nest;
4355                 if (ex)
4356                 {
4357                     result = ex;
4358                     return;
4359                 }
4360             }
4361 
4362             /* Look for e1 being a lazy parameter
4363              */
4364             if (exp.e1.op == TOK.variable)
4365             {
4366                 VarExp ve = cast(VarExp)exp.e1;
4367                 if (ve.var.storage_class & STC.lazy_)
4368                 {
4369                     // lazy parameters can be called without violating purity and safety
4370                     Type tw = ve.var.type;
4371                     Type tc = ve.var.type.substWildTo(MODFlags.const_);
4372                     auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4373                     (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4374                     auto t = new TypeDelegate(tf);
4375                     ve.type = t.typeSemantic(exp.loc, sc);
4376                 }
4377                 VarDeclaration v = ve.var.isVarDeclaration();
4378                 if (v && ve.checkPurity(sc, v))
4379                     return setError();
4380             }
4381 
4382             if (exp.e1.op == TOK.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4383             {
4384                 SymOffExp se = cast(SymOffExp)exp.e1;
4385                 exp.e1 = new VarExp(se.loc, se.var, true);
4386                 exp.e1 = exp.e1.expressionSemantic(sc);
4387             }
4388             else if (exp.e1.op == TOK.dot)
4389             {
4390                 DotExp de = cast(DotExp)exp.e1;
4391 
4392                 if (de.e2.op == TOK.overloadSet)
4393                 {
4394                     ethis = de.e1;
4395                     tthis = de.e1.type;
4396                     exp.e1 = de.e2;
4397                 }
4398             }
4399             else if (exp.e1.op == TOK.star && exp.e1.type.ty == Tfunction)
4400             {
4401                 // Rewrite (*fp)(arguments) to fp(arguments)
4402                 exp.e1 = (cast(PtrExp)exp.e1).e1;
4403             }
4404         }
4405 
4406         Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4407 
4408         if (exp.e1.op == TOK.error)
4409         {
4410             result = exp.e1;
4411             return;
4412         }
4413         if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4414             return setError();
4415 
4416         // Check for call operator overload
4417         if (t1)
4418         {
4419             if (t1.ty == Tstruct)
4420             {
4421                 auto sd = (cast(TypeStruct)t1).sym;
4422                 sd.size(exp.loc); // Resolve forward references to construct object
4423                 if (sd.sizeok != Sizeok.done)
4424                     return setError();
4425                 if (!sd.ctor)
4426                     sd.ctor = sd.searchCtor();
4427                 /* If `sd.ctor` is a generated copy constructor, this means that it
4428                    is the single constructor that this struct has. In order to not
4429                    disable default construction, the ctor is nullified. The side effect
4430                    of this is that the generated copy constructor cannot be called
4431                    explicitly, but that is ok, because when calling a constructor the
4432                    default constructor should have priority over the generated copy
4433                    constructor.
4434                 */
4435                 if (sd.ctor)
4436                 {
4437                     auto ctor = sd.ctor.isCtorDeclaration();
4438                     if (ctor && ctor.isCpCtor && ctor.generated)
4439                         sd.ctor = null;
4440                 }
4441 
4442                 // First look for constructor
4443                 if (exp.e1.op == TOK.type && sd.ctor)
4444                 {
4445                     if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
4446                         goto Lx;
4447 
4448                     auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4449                     if (!sd.fill(exp.loc, sle.elements, true))
4450                         return setError();
4451                     if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
4452                         return setError();
4453 
4454                     // https://issues.dlang.org/show_bug.cgi?id=14556
4455                     // Set concrete type to avoid further redundant semantic().
4456                     sle.type = exp.e1.type;
4457 
4458                     /* Constructor takes a mutable object, so don't use
4459                      * the immutable initializer symbol.
4460                      */
4461                     sle.useStaticInit = false;
4462 
4463                     Expression e = sle;
4464                     if (auto cf = sd.ctor.isCtorDeclaration())
4465                     {
4466                         e = new DotVarExp(exp.loc, e, cf, true);
4467                     }
4468                     else if (auto td = sd.ctor.isTemplateDeclaration())
4469                     {
4470                         e = new DotIdExp(exp.loc, e, td.ident);
4471                     }
4472                     else if (auto os = sd.ctor.isOverloadSet())
4473                     {
4474                         e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4475                     }
4476                     else
4477                         assert(0);
4478                     e = new CallExp(exp.loc, e, exp.arguments);
4479                     e = e.expressionSemantic(sc);
4480                     result = e;
4481                     return;
4482                 }
4483                 // No constructor, look for overload of opCall
4484                 if (search_function(sd, Id.call))
4485                     goto L1;
4486                 // overload of opCall, therefore it's a call
4487                 if (exp.e1.op != TOK.type)
4488                 {
4489                     if (sd.aliasthis && exp.e1.type != exp.att1)
4490                     {
4491                         if (!exp.att1 && exp.e1.type.checkAliasThisRec())
4492                             exp.att1 = exp.e1.type;
4493                         exp.e1 = resolveAliasThis(sc, exp.e1);
4494                         goto Lagain;
4495                     }
4496                     exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4497                     return setError();
4498                 }
4499 
4500                 /* It's a struct literal
4501                  */
4502             Lx:
4503                 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4504                 e = e.expressionSemantic(sc);
4505                 result = e;
4506                 return;
4507             }
4508             else if (t1.ty == Tclass)
4509             {
4510             L1:
4511                 // Rewrite as e1.call(arguments)
4512                 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4513                 e = new CallExp(exp.loc, e, exp.arguments);
4514                 e = e.expressionSemantic(sc);
4515                 result = e;
4516                 return;
4517             }
4518             else if (exp.e1.op == TOK.type && t1.isscalar())
4519             {
4520                 Expression e;
4521 
4522                 // Make sure to use the the enum type itself rather than its
4523                 // base type
4524                 // https://issues.dlang.org/show_bug.cgi?id=16346
4525                 if (exp.e1.type.ty == Tenum)
4526                 {
4527                     t1 = exp.e1.type;
4528                 }
4529 
4530                 if (!exp.arguments || exp.arguments.dim == 0)
4531                 {
4532                     e = t1.defaultInitLiteral(exp.loc);
4533                 }
4534                 else if (exp.arguments.dim == 1)
4535                 {
4536                     e = (*exp.arguments)[0];
4537                     e = e.implicitCastTo(sc, t1);
4538                     e = new CastExp(exp.loc, e, t1);
4539                 }
4540                 else
4541                 {
4542                     exp.error("more than one argument for construction of `%s`", t1.toChars());
4543                     return setError();
4544                 }
4545                 e = e.expressionSemantic(sc);
4546                 result = e;
4547                 return;
4548             }
4549         }
4550 
4551         static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4552             OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4553         {
4554             FuncDeclaration f = null;
4555             foreach (s; os.a)
4556             {
4557                 if (tiargs && s.isFuncDeclaration())
4558                     continue;
4559                 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4560                 {
4561                     if (f2.errors)
4562                         return null;
4563                     if (f)
4564                     {
4565                         /* Error if match in more than one overload set,
4566                          * even if one is a 'better' match than the other.
4567                          */
4568                         ScopeDsymbol.multiplyDefined(loc, f, f2);
4569                     }
4570                     else
4571                         f = f2;
4572                 }
4573             }
4574             if (!f)
4575                 .error(loc, "no overload matches for `%s`", os.toChars());
4576             else if (f.errors)
4577                 f = null;
4578             return f;
4579         }
4580 
4581         bool isSuper = false;
4582         if (exp.e1.op == TOK.dotVariable && t1.ty == Tfunction || exp.e1.op == TOK.dotTemplateDeclaration)
4583         {
4584             UnaExp ue = cast(UnaExp)exp.e1;
4585 
4586             Expression ue1 = ue.e1;
4587             Expression ue1old = ue1; // need for 'right this' check
4588             VarDeclaration v;
4589             if (ue1.op == TOK.variable && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
4590             {
4591                 ue.e1 = new TypeExp(ue1.loc, ue1.type);
4592                 ue1 = null;
4593             }
4594 
4595             DotVarExp dve;
4596             DotTemplateExp dte;
4597             Dsymbol s;
4598             if (exp.e1.op == TOK.dotVariable)
4599             {
4600                 dve = cast(DotVarExp)exp.e1;
4601                 dte = null;
4602                 s = dve.var;
4603                 tiargs = null;
4604             }
4605             else
4606             {
4607                 dve = null;
4608                 dte = cast(DotTemplateExp)exp.e1;
4609                 s = dte.td;
4610             }
4611 
4612             // Do overload resolution
4613             exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue1 ? ue1.type : null, exp.arguments, FuncResolveFlag.standard);
4614             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4615                 return setError();
4616 
4617             if (exp.f.interfaceVirtual)
4618             {
4619                 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4620                  */
4621                 auto b = exp.f.interfaceVirtual;
4622                 auto ad2 = b.sym;
4623                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4624                 ue.e1 = ue.e1.expressionSemantic(sc);
4625                 ue1 = ue.e1;
4626                 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
4627                 assert(vi >= 0);
4628                 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4629                 assert(exp.f);
4630             }
4631             if (exp.f.needThis())
4632             {
4633                 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
4634                 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4635                 if (ue.e1.op == TOK.error)
4636                 {
4637                     result = ue.e1;
4638                     return;
4639                 }
4640                 ethis = ue.e1;
4641                 tthis = ue.e1.type;
4642                 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4643                 {
4644                     if (global.params.vsafe && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
4645                         return setError();
4646                 }
4647             }
4648 
4649             /* Cannot call public functions from inside invariant
4650              * (because then the invariant would have infinite recursion)
4651              */
4652             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOK.this_ && exp.f.addPostInvariant())
4653             {
4654                 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4655                 return setError();
4656             }
4657 
4658             checkFunctionAttributes(exp, sc, exp.f);
4659             checkAccess(exp.loc, sc, ue.e1, exp.f);
4660             if (!exp.f.needThis())
4661             {
4662                 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4663             }
4664             else
4665             {
4666                 if (ue1old.checkRightThis(sc))
4667                     return setError();
4668                 if (exp.e1.op == TOK.dotVariable)
4669                 {
4670                     dve.var = exp.f;
4671                     exp.e1.type = exp.f.type;
4672                 }
4673                 else
4674                 {
4675                     exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4676                     exp.e1 = exp.e1.expressionSemantic(sc);
4677                     if (exp.e1.op == TOK.error)
4678                         return setError();
4679                     ue = cast(UnaExp)exp.e1;
4680                 }
4681                 version (none)
4682                 {
4683                     printf("ue.e1 = %s\n", ue.e1.toChars());
4684                     printf("f = %s\n", exp.f.toChars());
4685                     printf("t1 = %s\n", t1.toChars());
4686                     printf("e1 = %s\n", exp.e1.toChars());
4687                     printf("e1.type = %s\n", exp.e1.type.toChars());
4688                 }
4689 
4690                 // See if we need to adjust the 'this' pointer
4691                 AggregateDeclaration ad = exp.f.isThis();
4692                 ClassDeclaration cd = ue.e1.type.isClassHandle();
4693                 if (ad && cd && ad.isClassDeclaration())
4694                 {
4695                     if (ue.e1.op == TOK.dotType)
4696                     {
4697                         ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4698                         exp.directcall = true;
4699                     }
4700                     else if (ue.e1.op == TOK.super_)
4701                         exp.directcall = true;
4702                     else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4703                         exp.directcall = true;
4704 
4705                     if (ad != cd)
4706                     {
4707                         ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4708                         ue.e1 = ue.e1.expressionSemantic(sc);
4709                     }
4710                 }
4711             }
4712             // If we've got a pointer to a function then deference it
4713             // https://issues.dlang.org/show_bug.cgi?id=16483
4714             if (exp.e1.type.ty == Tpointer && exp.e1.type.nextOf().ty == Tfunction)
4715             {
4716                 Expression e = new PtrExp(exp.loc, exp.e1);
4717                 e.type = exp.e1.type.nextOf();
4718                 exp.e1 = e;
4719             }
4720             t1 = exp.e1.type;
4721         }
4722         else if (exp.e1.op == TOK.super_ || exp.e1.op == TOK.this_)
4723         {
4724             auto ad = sc.func ? sc.func.isThis() : null;
4725             auto cd = ad ? ad.isClassDeclaration() : null;
4726 
4727             isSuper = exp.e1.op == TOK.super_;
4728             if (isSuper)
4729             {
4730                 // Base class constructor call
4731                 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4732                 {
4733                     exp.error("super class constructor call must be in a constructor");
4734                     return setError();
4735                 }
4736                 if (!cd.baseClass.ctor)
4737                 {
4738                     exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4739                     return setError();
4740                 }
4741             }
4742             else
4743             {
4744                 // `this` call expression must be inside a
4745                 // constructor
4746                 if (!ad || !sc.func.isCtorDeclaration())
4747                 {
4748                     exp.error("constructor call must be in a constructor");
4749                     return setError();
4750                 }
4751 
4752                 // https://issues.dlang.org/show_bug.cgi?id=18719
4753                 // If `exp` is a call expression to another constructor
4754                 // then it means that all struct/class fields will be
4755                 // initialized after this call.
4756                 foreach (ref field; sc.ctorflow.fieldinit)
4757                 {
4758                     field.csx |= CSX.this_ctor;
4759                 }
4760             }
4761 
4762             if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4763             {
4764                 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4765                     exp.error("constructor calls not allowed in loops or after labels");
4766                 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4767                     exp.error("multiple constructor calls");
4768                 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4769                     exp.error("an earlier `return` statement skips constructor");
4770                 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4771             }
4772 
4773             tthis = ad.type.addMod(sc.func.type.mod);
4774             auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4775             if (auto os = ctor.isOverloadSet())
4776                 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4777             else
4778                 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4779 
4780             if (!exp.f || exp.f.errors)
4781                 return setError();
4782 
4783             checkFunctionAttributes(exp, sc, exp.f);
4784             checkAccess(exp.loc, sc, null, exp.f);
4785 
4786             exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4787             exp.e1 = exp.e1.expressionSemantic(sc);
4788             // https://issues.dlang.org/show_bug.cgi?id=21095
4789             if (exp.e1.op == TOK.error)
4790                 return setError();
4791             t1 = exp.e1.type;
4792 
4793             // BUG: this should really be done by checking the static
4794             // call graph
4795             if (exp.f == sc.func)
4796             {
4797                 exp.error("cyclic constructor call");
4798                 return setError();
4799             }
4800         }
4801         else if (exp.e1.op == TOK.overloadSet)
4802         {
4803             auto os = (cast(OverExp)exp.e1).vars;
4804             exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
4805             if (!exp.f)
4806                 return setError();
4807             if (ethis)
4808                 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4809             else
4810                 exp.e1 = new VarExp(exp.loc, exp.f, false);
4811             goto Lagain;
4812         }
4813         else if (!t1)
4814         {
4815             exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4816             return setError();
4817         }
4818         else if (t1.ty == Terror)
4819         {
4820             return setError();
4821         }
4822         else if (t1.ty != Tfunction)
4823         {
4824             TypeFunction tf;
4825             const(char)* p;
4826             Dsymbol s;
4827             exp.f = null;
4828             if (exp.e1.op == TOK.function_)
4829             {
4830                 // function literal that direct called is always inferred.
4831                 assert((cast(FuncExp)exp.e1).fd);
4832                 exp.f = (cast(FuncExp)exp.e1).fd;
4833                 tf = cast(TypeFunction)exp.f.type;
4834                 p = "function literal";
4835             }
4836             else if (t1.ty == Tdelegate)
4837             {
4838                 TypeDelegate td = cast(TypeDelegate)t1;
4839                 assert(td.next.ty == Tfunction);
4840                 tf = cast(TypeFunction)td.next;
4841                 p = "delegate";
4842             }
4843             else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction)
4844             {
4845                 tf = cast(TypeFunction)(cast(TypePointer)t1).next;
4846                 p = "function pointer";
4847             }
4848             else if (exp.e1.op == TOK.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4849             {
4850                 DotVarExp dve = cast(DotVarExp)exp.e1;
4851                 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4852                 if (!exp.f)
4853                     return setError();
4854                 if (exp.f.needThis())
4855                 {
4856                     dve.var = exp.f;
4857                     dve.type = exp.f.type;
4858                     dve.hasOverloads = false;
4859                     goto Lagain;
4860                 }
4861                 exp.e1 = new VarExp(dve.loc, exp.f, false);
4862                 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4863                 result = e.expressionSemantic(sc);
4864                 return;
4865             }
4866             else if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4867             {
4868                 s = (cast(VarExp)exp.e1).var;
4869                 goto L2;
4870             }
4871             else if (exp.e1.op == TOK.template_)
4872             {
4873                 s = (cast(TemplateExp)exp.e1).td;
4874             L2:
4875                 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
4876                 if (!exp.f || exp.f.errors)
4877                     return setError();
4878                 if (exp.f.needThis())
4879                 {
4880                     if (hasThis(sc))
4881                     {
4882                         // Supply an implicit 'this', as in
4883                         //    this.ident
4884                         exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
4885                         goto Lagain;
4886                     }
4887                     else if (isNeedThisScope(sc, exp.f))
4888                     {
4889                         exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4890                         return setError();
4891                     }
4892                 }
4893                 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
4894                 goto Lagain;
4895             }
4896             else
4897             {
4898                 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
4899                 return setError();
4900             }
4901 
4902             const(char)* failMessage;
4903             Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4904             if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4905             {
4906                 OutBuffer buf;
4907                 buf.writeByte('(');
4908                 argExpTypesToCBuffer(&buf, exp.arguments);
4909                 buf.writeByte(')');
4910                 if (tthis)
4911                     tthis.modToBuffer(&buf);
4912 
4913                 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4914                 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4915                     p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4916                 if (failMessage)
4917                     errorSupplemental(exp.loc, "%s", failMessage);
4918                 return setError();
4919             }
4920             // Purity and safety check should run after testing arguments matching
4921             if (exp.f)
4922             {
4923                 exp.checkPurity(sc, exp.f);
4924                 exp.checkSafety(sc, exp.f);
4925                 exp.checkNogc(sc, exp.f);
4926                 if (exp.f.checkNestedReference(sc, exp.loc))
4927                     return setError();
4928             }
4929             else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
4930             {
4931                 bool err = false;
4932                 if (!tf.purity && sc.func.setImpure())
4933                 {
4934                     exp.error("`pure` %s `%s` cannot call impure %s `%s`",
4935                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4936                     err = true;
4937                 }
4938                 if (!tf.isnogc && sc.func.setGC())
4939                 {
4940                     exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
4941                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4942                     err = true;
4943                 }
4944                 if (tf.trust <= TRUST.system && sc.func.setUnsafe())
4945                 {
4946                     exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
4947                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4948                     err = true;
4949                 }
4950                 if (err)
4951                     return setError();
4952             }
4953 
4954             if (t1.ty == Tpointer)
4955             {
4956                 Expression e = new PtrExp(exp.loc, exp.e1);
4957                 e.type = tf;
4958                 exp.e1 = e;
4959             }
4960             t1 = tf;
4961         }
4962         else if (exp.e1.op == TOK.variable)
4963         {
4964             // Do overload resolution
4965             VarExp ve = cast(VarExp)exp.e1;
4966 
4967             exp.f = ve.var.isFuncDeclaration();
4968             assert(exp.f);
4969             tiargs = null;
4970 
4971             if (exp.f.overnext)
4972                 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
4973             else
4974             {
4975                 exp.f = exp.f.toAliasFunc();
4976                 TypeFunction tf = cast(TypeFunction)exp.f.type;
4977                 const(char)* failMessage;
4978                 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4979                 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4980                 {
4981                     OutBuffer buf;
4982                     buf.writeByte('(');
4983                     argExpTypesToCBuffer(&buf, exp.arguments);
4984                     buf.writeByte(')');
4985 
4986                     //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4987                     .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4988                         exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4989                     if (failMessage)
4990                         errorSupplemental(exp.loc, "%s", failMessage);
4991                     exp.f = null;
4992                 }
4993             }
4994             if (!exp.f || exp.f.errors)
4995                 return setError();
4996 
4997             if (exp.f.needThis())
4998             {
4999                 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5000                 if (exp.f.checkNestedReference(sc, exp.loc))
5001                     return setError();
5002 
5003                 if (hasThis(sc))
5004                 {
5005                     // Supply an implicit 'this', as in
5006                     //    this.ident
5007                     exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5008                     // Note: we cannot use f directly, because further overload resolution
5009                     // through the supplied 'this' may cause different result.
5010                     goto Lagain;
5011                 }
5012                 else if (isNeedThisScope(sc, exp.f))
5013                 {
5014                     exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5015                     return setError();
5016                 }
5017             }
5018 
5019             checkFunctionAttributes(exp, sc, exp.f);
5020             checkAccess(exp.loc, sc, null, exp.f);
5021             if (exp.f.checkNestedReference(sc, exp.loc))
5022                 return setError();
5023 
5024             ethis = null;
5025             tthis = null;
5026 
5027             if (ve.hasOverloads)
5028             {
5029                 exp.e1 = new VarExp(ve.loc, exp.f, false);
5030                 exp.e1.type = exp.f.type;
5031             }
5032             t1 = exp.f.type;
5033         }
5034         assert(t1.ty == Tfunction);
5035 
5036         Expression argprefix;
5037         if (!exp.arguments)
5038             exp.arguments = new Expressions();
5039         if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5040             return setError();
5041 
5042         if (!exp.type)
5043         {
5044             exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5045                         // avoid recursive expression printing
5046             exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5047             return setError();
5048         }
5049 
5050         if (exp.f && exp.f.tintro)
5051         {
5052             Type t = exp.type;
5053             int offset = 0;
5054             TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5055             if (tf.next.isBaseOf(t, &offset) && offset)
5056             {
5057                 exp.type = tf.next;
5058                 result = Expression.combine(argprefix, exp.castTo(sc, t));
5059                 return;
5060             }
5061         }
5062 
5063         // Handle the case of a direct lambda call
5064         if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5065         {
5066             exp.f.tookAddressOf = 0;
5067         }
5068 
5069         result = Expression.combine(argprefix, exp);
5070 
5071         if (isSuper)
5072         {
5073             auto ad = sc.func ? sc.func.isThis() : null;
5074             auto cd = ad ? ad.isClassDeclaration() : null;
5075             if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5076             {
5077                 // if super is defined in C++, it sets the vtable pointer to the base class
5078                 // so we have to restore it, but still return 'this' from super() call:
5079                 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5080                 Loc loc = exp.loc;
5081 
5082                 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5083                 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5084                 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5085 
5086                 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5087                 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5088 
5089                 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5090 
5091                 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5092 
5093                 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5094                 result = e.expressionSemantic(sc);
5095             }
5096         }
5097 
5098         // declare dual-context container
5099         if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func)
5100         {
5101             // check access to second `this`
5102             if (AggregateDeclaration ad2 = exp.f.isMember2())
5103             {
5104                 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5105                 if (te.op != TOK.error)
5106                     te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5107                 if (te.op == TOK.error)
5108                 {
5109                     exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5110                     return setError();
5111                 }
5112             }
5113             VarDeclaration vthis2 = makeThis2Argument(exp.loc, sc, exp.f);            exp.vthis2 = vthis2;
5114             Expression de = new DeclarationExp(exp.loc, vthis2);
5115             result = Expression.combine(de, result);
5116             result = result.expressionSemantic(sc);
5117         }
5118     }
5119 
5120     override void visit(DeclarationExp e)
5121     {
5122         if (e.type)
5123         {
5124             result = e;
5125             return;
5126         }
5127         static if (LOGSEMANTIC)
5128         {
5129             printf("DeclarationExp::semantic() %s\n", e.toChars());
5130         }
5131 
5132         uint olderrors = global.errors;
5133 
5134         /* This is here to support extern(linkage) declaration,
5135          * where the extern(linkage) winds up being an AttribDeclaration
5136          * wrapper.
5137          */
5138         Dsymbol s = e.declaration;
5139 
5140         while (1)
5141         {
5142             AttribDeclaration ad = s.isAttribDeclaration();
5143             if (ad)
5144             {
5145                 if (ad.decl && ad.decl.dim == 1)
5146                 {
5147                     s = (*ad.decl)[0];
5148                     continue;
5149                 }
5150             }
5151             break;
5152         }
5153 
5154         VarDeclaration v = s.isVarDeclaration();
5155         if (v)
5156         {
5157             // Do semantic() on initializer first, so:
5158             //      int a = a;
5159             // will be illegal.
5160             e.declaration.dsymbolSemantic(sc);
5161             s.parent = sc.parent;
5162         }
5163 
5164         //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5165         // Insert into both local scope and function scope.
5166         // Must be unique in both.
5167         if (s.ident)
5168         {
5169             if (!sc.insert(s))
5170             {
5171                 auto conflict = sc.search(Loc.initial, s.ident, null);
5172                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5173                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5174                                   conflict.kind(), conflict.toChars());
5175                 return setError();
5176             }
5177             else if (sc.func)
5178             {
5179                 // https://issues.dlang.org/show_bug.cgi?id=11720
5180                 // include Dataseg variables
5181                 if ((s.isFuncDeclaration() ||
5182                      s.isAggregateDeclaration() ||
5183                      s.isEnumDeclaration() ||
5184                      v && v.isDataseg()) && !sc.func.localsymtab.insert(s))
5185                 {
5186                     // https://issues.dlang.org/show_bug.cgi?id=18266
5187                     // set parent so that type semantic does not assert
5188                     s.parent = sc.parent;
5189                     Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5190                     assert(originalSymbol);
5191                     e.error("declaration `%s` is already defined in another scope in `%s` at line `%d`", s.toPrettyChars(), sc.func.toChars(), originalSymbol.loc.linnum);
5192                     return setError();
5193                 }
5194                 else
5195                 {
5196                     /* https://issues.dlang.org/show_bug.cgi?id=21272
5197                      * If we are in a foreach body we need to extract the
5198                      * function containing the foreach
5199                      */
5200                     FuncDeclaration fes_enclosing_func;
5201                     if (sc.func && sc.func.fes)
5202                         fes_enclosing_func = sc.enclosing.enclosing.func;
5203 
5204                     // Disallow shadowing
5205                     for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5206                     {
5207                         Dsymbol s2;
5208                         if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5209                         {
5210                             // allow STC.local symbols to be shadowed
5211                             // TODO: not really an optimal design
5212                             auto decl = s2.isDeclaration();
5213                             if (!decl || !(decl.storage_class & STC.local))
5214                             {
5215                                 if (sc.func.fes)
5216                                 {
5217                                     e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5218                                 }
5219                                 else
5220                                 {
5221                                     e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5222                                     return setError();
5223                                 }
5224                             }
5225                         }
5226                     }
5227                 }
5228             }
5229         }
5230         if (!s.isVarDeclaration())
5231         {
5232             Scope* sc2 = sc;
5233             if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5234                 sc2 = sc.push();
5235             sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5236             e.declaration.dsymbolSemantic(sc2);
5237             if (sc2 != sc)
5238                 sc2.pop();
5239             s.parent = sc.parent;
5240         }
5241         if (global.errors == olderrors)
5242         {
5243             e.declaration.semantic2(sc);
5244             if (global.errors == olderrors)
5245             {
5246                 e.declaration.semantic3(sc);
5247             }
5248         }
5249         // todo: error in declaration should be propagated.
5250 
5251         e.type = Type.tvoid;
5252         result = e;
5253     }
5254 
5255     override void visit(TypeidExp exp)
5256     {
5257         static if (LOGSEMANTIC)
5258         {
5259             printf("TypeidExp::semantic() %s\n", exp.toChars());
5260         }
5261         Type ta = isType(exp.obj);
5262         Expression ea = isExpression(exp.obj);
5263         Dsymbol sa = isDsymbol(exp.obj);
5264         //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5265 
5266         if (ta)
5267         {
5268             dmd.typesem.resolve(ta, exp.loc, sc, &ea, &ta, &sa, true);
5269         }
5270 
5271         if (ea)
5272         {
5273             if (auto sym = getDsymbol(ea))
5274                 ea = symbolToExp(sym, exp.loc, sc, false);
5275             else
5276                 ea = ea.expressionSemantic(sc);
5277             ea = resolveProperties(sc, ea);
5278             ta = ea.type;
5279             if (ea.op == TOK.type)
5280                 ea = null;
5281         }
5282 
5283         if (!ta)
5284         {
5285             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5286             exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5287             return setError();
5288         }
5289 
5290         if (global.params.vcomplex)
5291             ta.checkComplexTransition(exp.loc, sc);
5292 
5293         Expression e;
5294         auto tb = ta.toBasetype();
5295         if (ea && tb.ty == Tclass)
5296         {
5297             if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5298             {
5299                 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
5300                 e = ErrorExp.get();
5301             }
5302             else if (!Type.typeinfoclass)
5303             {
5304                 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5305                 e = ErrorExp.get();
5306             }
5307             else
5308             {
5309                 /* Get the dynamic type, which is .classinfo
5310                 */
5311                 ea = ea.expressionSemantic(sc);
5312                 e = new TypeidExp(ea.loc, ea);
5313                 e.type = Type.typeinfoclass.type;
5314             }
5315         }
5316         else if (ta.ty == Terror)
5317         {
5318             e = ErrorExp.get();
5319         }
5320         else
5321         {
5322             // Handle this in the glue layer
5323             e = new TypeidExp(exp.loc, ta);
5324             e.type = getTypeInfoType(exp.loc, ta, sc);
5325 
5326             semanticTypeInfo(sc, ta);
5327 
5328             if (ea)
5329             {
5330                 e = new CommaExp(exp.loc, ea, e); // execute ea
5331                 e = e.expressionSemantic(sc);
5332             }
5333         }
5334         result = e;
5335     }
5336 
5337     override void visit(TraitsExp e)
5338     {
5339         result = semanticTraits(e, sc);
5340     }
5341 
5342     override void visit(HaltExp e)
5343     {
5344         static if (LOGSEMANTIC)
5345         {
5346             printf("HaltExp::semantic()\n");
5347         }
5348         e.type = Type.tvoid;
5349         result = e;
5350     }
5351 
5352     override void visit(IsExp e)
5353     {
5354         /* is(targ id tok tspec)
5355          * is(targ id :  tok2)
5356          * is(targ id == tok2)
5357          */
5358         Type tded = null;
5359 
5360         void yes()
5361         {
5362             //printf("yes\n");
5363             if (!e.id)
5364             {
5365                 result = IntegerExp.createBool(true);
5366                 return;
5367             }
5368 
5369             Dsymbol s;
5370             Tuple tup = isTuple(tded);
5371             if (tup)
5372                 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5373             else
5374                 s = new AliasDeclaration(e.loc, e.id, tded);
5375             s.dsymbolSemantic(sc);
5376 
5377             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5378              * More investigation is needed.
5379              */
5380             if (!tup && !sc.insert(s))
5381             {
5382                 auto conflict = sc.search(Loc.initial, s.ident, null);
5383                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5384                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5385                                   conflict.kind(), conflict.toChars());
5386             }
5387 
5388             unSpeculative(sc, s);
5389 
5390             result = IntegerExp.createBool(true);
5391         }
5392         void no()
5393         {
5394             result = IntegerExp.createBool(false);
5395             //printf("no\n");
5396         }
5397 
5398         static if (LOGSEMANTIC)
5399         {
5400             printf("IsExp::semantic(%s)\n", e.toChars());
5401         }
5402         if (e.id && !(sc.flags & SCOPE.condition))
5403         {
5404             e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5405             return setError();
5406         }
5407 
5408         if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5409         {
5410             const oldErrors = global.startGagging();
5411             Dsymbol sym = e.targ.toDsymbol(sc);
5412             global.endGagging(oldErrors);
5413 
5414             if (sym is null)
5415                 return no();
5416             Package p = resolveIsPackage(sym);
5417             if (p is null)
5418                 return no();
5419             if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5420                 return no();
5421             else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5422                 return no();
5423             tded = e.targ;
5424             return yes();
5425         }
5426 
5427         {
5428             Scope* sc2 = sc.copy(); // keep sc.flags
5429             sc2.tinst = null;
5430             sc2.minst = null;
5431             sc2.flags |= SCOPE.fullinst;
5432             Type t = e.targ.trySemantic(e.loc, sc2);
5433             sc2.pop();
5434             if (!t) // errors, so condition is false
5435                 return no();
5436             e.targ = t;
5437         }
5438 
5439         if (e.tok2 != TOK.reserved)
5440         {
5441             switch (e.tok2)
5442             {
5443             case TOK.struct_:
5444                 if (e.targ.ty != Tstruct)
5445                     return no();
5446                 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5447                     return no();
5448                 tded = e.targ;
5449                 break;
5450 
5451             case TOK.union_:
5452                 if (e.targ.ty != Tstruct)
5453                     return no();
5454                 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5455                     return no();
5456                 tded = e.targ;
5457                 break;
5458 
5459             case TOK.class_:
5460                 if (e.targ.ty != Tclass)
5461                     return no();
5462                 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5463                     return no();
5464                 tded = e.targ;
5465                 break;
5466 
5467             case TOK.interface_:
5468                 if (e.targ.ty != Tclass)
5469                     return no();
5470                 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5471                     return no();
5472                 tded = e.targ;
5473                 break;
5474 
5475             case TOK.const_:
5476                 if (!e.targ.isConst())
5477                     return no();
5478                 tded = e.targ;
5479                 break;
5480 
5481             case TOK.immutable_:
5482                 if (!e.targ.isImmutable())
5483                     return no();
5484                 tded = e.targ;
5485                 break;
5486 
5487             case TOK.shared_:
5488                 if (!e.targ.isShared())
5489                     return no();
5490                 tded = e.targ;
5491                 break;
5492 
5493             case TOK.inout_:
5494                 if (!e.targ.isWild())
5495                     return no();
5496                 tded = e.targ;
5497                 break;
5498 
5499             case TOK.super_:
5500                 // If class or interface, get the base class and interfaces
5501                 if (e.targ.ty != Tclass)
5502                     return no();
5503                 else
5504                 {
5505                     ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5506                     auto args = new Parameters();
5507                     args.reserve(cd.baseclasses.dim);
5508                     if (cd.semanticRun < PASS.semanticdone)
5509                         cd.dsymbolSemantic(null);
5510                     for (size_t i = 0; i < cd.baseclasses.dim; i++)
5511                     {
5512                         BaseClass* b = (*cd.baseclasses)[i];
5513                         args.push(new Parameter(STC.in_, b.type, null, null, null));
5514                     }
5515                     tded = new TypeTuple(args);
5516                 }
5517                 break;
5518 
5519             case TOK.enum_:
5520                 if (e.targ.ty != Tenum)
5521                     return no();
5522                 if (e.id)
5523                     tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5524                 else
5525                     tded = e.targ;
5526 
5527                 if (tded.ty == Terror)
5528                     return setError();
5529                 break;
5530 
5531             case TOK.delegate_:
5532                 if (e.targ.ty != Tdelegate)
5533                     return no();
5534                 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5535                 break;
5536 
5537             case TOK.function_:
5538             case TOK.parameters:
5539                 {
5540                     if (e.targ.ty != Tfunction)
5541                         return no();
5542                     tded = e.targ;
5543 
5544                     /* Generate tuple from function parameter types.
5545                      */
5546                     assert(tded.ty == Tfunction);
5547                     auto tdedf = tded.isTypeFunction();
5548                     auto args = new Parameters();
5549                     foreach (i, arg; tdedf.parameterList)
5550                     {
5551                         assert(arg && arg.type);
5552                         /* If one of the default arguments was an error,
5553                            don't return an invalid tuple
5554                          */
5555                         if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == TOK.error)
5556                             return setError();
5557                         args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5558                     }
5559                     tded = new TypeTuple(args);
5560                     break;
5561                 }
5562             case TOK.return_:
5563                 /* Get the 'return type' for the function,
5564                  * delegate, or pointer to function.
5565                  */
5566                 if (e.targ.ty == Tfunction)
5567                     tded = (cast(TypeFunction)e.targ).next;
5568                 else if (e.targ.ty == Tdelegate)
5569                 {
5570                     tded = (cast(TypeDelegate)e.targ).next;
5571                     tded = (cast(TypeFunction)tded).next;
5572                 }
5573                 else if (e.targ.ty == Tpointer && (cast(TypePointer)e.targ).next.ty == Tfunction)
5574                 {
5575                     tded = (cast(TypePointer)e.targ).next;
5576                     tded = (cast(TypeFunction)tded).next;
5577                 }
5578                 else
5579                     return no();
5580                 break;
5581 
5582             case TOK.argumentTypes:
5583                 /* Generate a type tuple of the equivalent types used to determine if a
5584                  * function argument of this type can be passed in registers.
5585                  * The results of this are highly platform dependent, and intended
5586                  * primarly for use in implementing va_arg().
5587                  */
5588                 tded = target.toArgTypes(e.targ);
5589                 if (!tded)
5590                     return no();
5591                 // not valid for a parameter
5592                 break;
5593 
5594             case TOK.vector:
5595                 if (e.targ.ty != Tvector)
5596                     return no();
5597                 tded = (cast(TypeVector)e.targ).basetype;
5598                 break;
5599 
5600             default:
5601                 assert(0);
5602             }
5603 
5604             // https://issues.dlang.org/show_bug.cgi?id=18753
5605             if (tded)
5606                 return yes();
5607             return no();
5608         }
5609         else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
5610         {
5611             /* Evaluate to true if targ matches tspec
5612              * is(targ == tspec)
5613              * is(targ : tspec)
5614              */
5615             e.tspec = e.tspec.typeSemantic(e.loc, sc);
5616             //printf("targ  = %s, %s\n", e.targ.toChars(), e.targ.deco);
5617             //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5618 
5619             if (e.tok == TOK.colon)
5620             {
5621                 // current scope is itself deprecated, or deprecations are not errors
5622                 const bool deprecationAllowed = sc.isDeprecated
5623                     || global.params.useDeprecated != DiagnosticReporting.error;
5624                 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5625 
5626                 if (preventAliasThis && e.targ.ty == Tstruct)
5627                 {
5628                     if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5629                         return yes();
5630                     else
5631                         return no();
5632                 }
5633                 else if (preventAliasThis && e.targ.ty == Tclass)
5634                 {
5635                     if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5636                         return yes();
5637                     else
5638                         return no();
5639                 }
5640                 else if (e.targ.implicitConvTo(e.tspec))
5641                     return yes();
5642                 else
5643                     return no();
5644             }
5645             else /* == */
5646             {
5647                 if (e.targ.equals(e.tspec))
5648                     return yes();
5649                 else
5650                     return no();
5651             }
5652         }
5653         else if (e.tspec)
5654         {
5655             /* Evaluate to true if targ matches tspec.
5656              * If true, declare id as an alias for the specialized type.
5657              * is(targ == tspec, tpl)
5658              * is(targ : tspec, tpl)
5659              * is(targ id == tspec)
5660              * is(targ id : tspec)
5661              * is(targ id == tspec, tpl)
5662              * is(targ id : tspec, tpl)
5663              */
5664             Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5665             e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5666 
5667             Objects dedtypes = Objects(e.parameters.dim);
5668             dedtypes.zero();
5669 
5670             MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5671             //printf("targ: %s\n", targ.toChars());
5672             //printf("tspec: %s\n", tspec.toChars());
5673             if (m <= MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5674             {
5675                 return no();
5676             }
5677             else
5678             {
5679                 tded = cast(Type)dedtypes[0];
5680                 if (!tded)
5681                     tded = e.targ;
5682                 Objects tiargs = Objects(1);
5683                 tiargs[0] = e.targ;
5684 
5685                 /* Declare trailing parameters
5686                  */
5687                 for (size_t i = 1; i < e.parameters.dim; i++)
5688                 {
5689                     TemplateParameter tp = (*e.parameters)[i];
5690                     Declaration s = null;
5691 
5692                     m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5693                     if (m <= MATCH.nomatch)
5694                         return no();
5695                     s.dsymbolSemantic(sc);
5696                     if (!sc.insert(s))
5697                     {
5698                         auto conflict = sc.search(Loc.initial, s.ident, null);
5699                         e.error("declaration `%s` is already defined", s.toPrettyChars());
5700                         errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5701                                           conflict.kind(), conflict.toChars());
5702                     }
5703 
5704                     unSpeculative(sc, s);
5705                 }
5706                 return yes();
5707             }
5708         }
5709         else if (e.id)
5710         {
5711             /* Declare id as an alias for type targ. Evaluate to true
5712              * is(targ id)
5713              */
5714             tded = e.targ;
5715         }
5716         return yes();
5717     }
5718 
5719     override void visit(BinAssignExp exp)
5720     {
5721         if (exp.type)
5722         {
5723             result = exp;
5724             return;
5725         }
5726 
5727         Expression e = exp.op_overload(sc);
5728         if (e)
5729         {
5730             result = e;
5731             return;
5732         }
5733 
5734         if (checkIfIsStructLiteralDotExpr(exp.e1))
5735             return setError();
5736         if (exp.e1.op == TOK.arrayLength)
5737         {
5738             // arr.length op= e2;
5739             e = rewriteOpAssign(exp);
5740             e = e.expressionSemantic(sc);
5741             result = e;
5742             return;
5743         }
5744         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5745         {
5746             if (checkNonAssignmentArrayOp(exp.e1))
5747                 return setError();
5748 
5749             if (exp.e1.op == TOK.slice)
5750                 (cast(SliceExp)exp.e1).arrayop = true;
5751 
5752             // T[] op= ...
5753             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5754             {
5755                 // T[] op= T
5756                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5757             }
5758             else if (Expression ex = typeCombine(exp, sc))
5759             {
5760                 result = ex;
5761                 return;
5762             }
5763             exp.type = exp.e1.type;
5764             result = arrayOp(exp, sc);
5765             return;
5766         }
5767 
5768         exp.e1 = exp.e1.expressionSemantic(sc);
5769         exp.e1 = exp.e1.optimize(WANTvalue);
5770         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5771         exp.type = exp.e1.type;
5772 
5773         if (auto ad = isAggregate(exp.e1.type))
5774         {
5775             if (const s = search_function(ad, Id.opOpAssign))
5776             {
5777                 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());
5778                 return setError();
5779             }
5780         }
5781         if (exp.e1.checkScalar() ||
5782             exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5783             exp.e1.checkSharedAccess(sc))
5784             return setError();
5785 
5786         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);
5787         int bitwise = (exp.op == TOK.andAssign || exp.op == TOK.orAssign || exp.op == TOK.xorAssign);
5788         int shift = (exp.op == TOK.leftShiftAssign || exp.op == TOK.rightShiftAssign || exp.op == TOK.unsignedRightShiftAssign);
5789 
5790         if (bitwise && exp.type.toBasetype().ty == Tbool)
5791             exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5792         else if (exp.checkNoBool())
5793             return setError();
5794 
5795         if ((exp.op == TOK.addAssign || exp.op == TOK.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5796         {
5797             result = scaleFactor(exp, sc);
5798             return;
5799         }
5800 
5801         if (Expression ex = typeCombine(exp, sc))
5802         {
5803             result = ex;
5804             return;
5805         }
5806 
5807         if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5808             return setError();
5809         if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5810             return setError();
5811 
5812         if (shift)
5813         {
5814             if (exp.e2.type.toBasetype().ty != Tvector)
5815                 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5816         }
5817 
5818         if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5819         {
5820             result = exp.incompatibleTypes();
5821             return;
5822         }
5823 
5824         if (exp.e1.op == TOK.error || exp.e2.op == TOK.error)
5825             return setError();
5826 
5827         e = exp.checkOpAssignTypes(sc);
5828         if (e.op == TOK.error)
5829         {
5830             result = e;
5831             return;
5832         }
5833 
5834         assert(e.op == TOK.assign || e == exp);
5835         result = (cast(BinExp)e).reorderSettingAAElem(sc);
5836     }
5837 
5838     private Expression compileIt(CompileExp exp)
5839     {
5840         OutBuffer buf;
5841         if (expressionsToString(buf, sc, exp.exps))
5842             return null;
5843 
5844         uint errors = global.errors;
5845         const len = buf.length;
5846         const str = buf.extractChars()[0 .. len];
5847         scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
5848         p.nextToken();
5849         //printf("p.loc.linnum = %d\n", p.loc.linnum);
5850 
5851         Expression e = p.parseExpression();
5852         p.reportDiagnostics();
5853         if (global.errors != errors)
5854             return null;
5855 
5856         if (p.token.value != TOK.endOfFile)
5857         {
5858             exp.error("incomplete mixin expression `%s`", str.ptr);
5859             return null;
5860         }
5861         return e;
5862     }
5863 
5864     override void visit(CompileExp exp)
5865     {
5866         /* https://dlang.org/spec/expression.html#mixin_expressions
5867          */
5868 
5869         static if (LOGSEMANTIC)
5870         {
5871             printf("CompileExp::semantic('%s')\n", exp.toChars());
5872         }
5873 
5874         auto e = compileIt(exp);
5875         if (!e)
5876             return setError();
5877         result = e.expressionSemantic(sc);
5878     }
5879 
5880     override void visit(ImportExp e)
5881     {
5882         static if (LOGSEMANTIC)
5883         {
5884             printf("ImportExp::semantic('%s')\n", e.toChars());
5885         }
5886 
5887         auto se = semanticString(sc, e.e1, "file name argument");
5888         if (!se)
5889             return setError();
5890         se = se.toUTF8(sc);
5891 
5892         auto namez = se.toStringz().ptr;
5893         if (!global.filePath)
5894         {
5895             e.error("need `-J` switch to import text file `%s`", namez);
5896             return setError();
5897         }
5898 
5899         /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5900          * ('Path Traversal') attacks.
5901          * http://cwe.mitre.org/data/definitions/22.html
5902          */
5903 
5904         auto name = FileName.safeSearchPath(global.filePath, namez);
5905         if (!name)
5906         {
5907             e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
5908             e.errorSupplemental("Path(s) searched (as provided by `-J`):");
5909             foreach (idx, path; *global.filePath)
5910             {
5911                 const attr = FileName.exists(path);
5912                 const(char)* err = attr == 2 ? "" :
5913                     (attr == 1 ? " (not a directory)" : " (path not found)");
5914                 e.errorSupplemental("[%zu]: `%s`%s", idx, path, err);
5915             }
5916             return setError();
5917         }
5918 
5919         sc._module.contentImportedFiles.push(name);
5920         if (global.params.verbose)
5921         {
5922             const slice = se.peekString();
5923             message("file      %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
5924         }
5925         if (global.params.moduleDeps !is null)
5926         {
5927             OutBuffer* ob = global.params.moduleDeps;
5928             Module imod = sc.instantiatingModule();
5929 
5930             if (!global.params.moduleDepsFile)
5931                 ob.writestring("depsFile ");
5932             ob.writestring(imod.toPrettyChars());
5933             ob.writestring(" (");
5934             escapePath(ob, imod.srcfile.toChars());
5935             ob.writestring(") : ");
5936             if (global.params.moduleDepsFile)
5937                 ob.writestring("string : ");
5938             ob.write(se.peekString());
5939             ob.writestring(" (");
5940             escapePath(ob, name);
5941             ob.writestring(")");
5942             ob.writenl();
5943         }
5944 
5945         {
5946             auto readResult = File.read(name);
5947             if (!readResult.success)
5948             {
5949                 e.error("cannot read file `%s`", name);
5950                 return setError();
5951             }
5952             else
5953             {
5954                 // take ownership of buffer (probably leaking)
5955                 auto data = readResult.extractSlice();
5956                 se = new StringExp(e.loc, data);
5957             }
5958         }
5959         result = se.expressionSemantic(sc);
5960     }
5961 
5962     override void visit(AssertExp exp)
5963     {
5964         // https://dlang.org/spec/expression.html#assert_expressions
5965         static if (LOGSEMANTIC)
5966         {
5967             printf("AssertExp::semantic('%s')\n", exp.toChars());
5968         }
5969 
5970         const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context;
5971         Expression temporariesPrefix;
5972 
5973         if (generateMsg)
5974         // no message - use assert expression as msg
5975         {
5976             if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
5977                 return setError();
5978 
5979             /*
5980             {
5981               auto a = e1, b = e2;
5982               assert(a == b, _d_assert_fail!"=="(a, b));
5983             }()
5984             */
5985 
5986             /*
5987             Stores the result of an operand expression into a temporary
5988             if necessary, e.g. if it is an impure fuction call containing side
5989             effects as in https://issues.dlang.org/show_bug.cgi?id=20114
5990 
5991             Params:
5992                 op = an expression which may require a temporary (added to
5993                      `temporariesPrefix`: `auto tmp = op`) and will be replaced
5994                      by `tmp` if necessary
5995 
5996             Returns: (possibly replaced) `op`
5997             */
5998             Expression maybePromoteToTmp(ref Expression op)
5999             {
6000                 // https://issues.dlang.org/show_bug.cgi?id=20989
6001                 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6002                 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6003                 {
6004                     auto die = op.isDotIdExp();
6005                     if (die && die.ident == Id.ptr)
6006                         die.noderef = true;
6007                 }
6008 
6009                 op = op.expressionSemantic(sc);
6010                 op = resolveProperties(sc, op);
6011                 if (op.hasSideEffect)
6012                 {
6013                     const stc = op.isLvalue() ? STC.ref_ : 0;
6014                     auto tmp = copyToTemp(stc, "__assertOp", op);
6015                     tmp.dsymbolSemantic(sc);
6016 
6017                     auto decl = new DeclarationExp(op.loc, tmp);
6018                     temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6019 
6020                     op = new VarExp(op.loc, tmp);
6021                     op = op.expressionSemantic(sc);
6022                 }
6023                 return op;
6024             }
6025 
6026             // if the assert condition is a mixin expression, try to compile it
6027             if (auto ce = exp.e1.isCompileExp())
6028             {
6029                 if (auto e1 = compileIt(ce))
6030                     exp.e1 = e1;
6031             }
6032 
6033             Expressions* es;
6034             Objects* tiargs;
6035             Loc loc = exp.e1.loc;
6036 
6037             const tok = exp.e1.op;
6038             bool isEqualsCallExpression;
6039             if (tok == TOK.call)
6040             {
6041                 const callExp = cast(CallExp) exp.e1;
6042 
6043                 // https://issues.dlang.org/show_bug.cgi?id=20331
6044                 // callExp.f may be null if the assert contains a call to
6045                 // a function pointer or literal
6046                 if (const callExpFunc = callExp.f)
6047                 {
6048                     const callExpIdent = callExpFunc.ident;
6049                     isEqualsCallExpression = callExpIdent == Id.__equals ||
6050                                              callExpIdent == Id.eq;
6051                 }
6052             }
6053             if (tok == TOK.equal || tok == TOK.notEqual ||
6054                 tok == TOK.lessThan || tok == TOK.greaterThan ||
6055                 tok == TOK.lessOrEqual || tok == TOK.greaterOrEqual ||
6056                 tok == TOK.identity || tok == TOK.notIdentity ||
6057                 tok == TOK.in_ ||
6058                 isEqualsCallExpression)
6059             {
6060                 es = new Expressions(2);
6061                 tiargs = new Objects(3);
6062 
6063                 if (isEqualsCallExpression)
6064                 {
6065                     auto callExp = cast(CallExp) exp.e1;
6066                     auto args = callExp.arguments;
6067 
6068                     // structs with opEquals get rewritten to a DotVarExp:
6069                     // a.opEquals(b)
6070                     // https://issues.dlang.org/show_bug.cgi?id=20100
6071                     if (args.length == 1)
6072                     {
6073                         auto dv = callExp.e1.isDotVarExp();
6074                         assert(dv);
6075 
6076                         // runtime args
6077                         (*es)[0] = maybePromoteToTmp(dv.e1);
6078                         (*es)[1] = maybePromoteToTmp((*args)[0]);
6079                     }
6080                     else
6081                     {
6082                         // runtime args
6083                         (*es)[0] = maybePromoteToTmp((*args)[0]);
6084                         (*es)[1] = maybePromoteToTmp((*args)[1]);
6085                     }
6086                 }
6087                 else
6088                 {
6089                     auto binExp = cast(EqualExp) exp.e1;
6090 
6091                     // runtime args
6092                     (*es)[0] = maybePromoteToTmp(binExp.e1);
6093                     (*es)[1] = maybePromoteToTmp(binExp.e2);
6094                 }
6095 
6096                 // template args
6097                 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : Token.toString(exp.e1.op));
6098                 comp = comp.expressionSemantic(sc);
6099                 (*tiargs)[0] = comp;
6100                 (*tiargs)[1] = (*es)[0].type;
6101                 (*tiargs)[2] = (*es)[1].type;
6102             }
6103 
6104             // Format exp.e1 before any additional boolean conversion
6105             // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
6106             else if (tok != TOK.andAnd && tok != TOK.orOr)
6107             {
6108                 es = new Expressions(1);
6109                 tiargs = new Objects(2);
6110 
6111                 if (auto ne = exp.e1.isNotExp())
6112                 {
6113                     // Fetch the (potential non-bool) expression and fold
6114                     // (n) negations into (n % 2) negations, e.g. !!a => a
6115                     for (bool neg = true; ; neg = !neg)
6116                     {
6117                         if (auto ne2 = ne.e1.isNotExp())
6118                             ne = ne2;
6119                         else
6120                         {
6121                             (*es)[0] = maybePromoteToTmp(ne.e1);
6122                             (*tiargs)[0] = new StringExp(loc, neg ? "!" : "");
6123                             break;
6124                         }
6125                     }
6126                 }
6127                 else
6128                 {   // Simply format exp.e1
6129                     (*es)[0] = maybePromoteToTmp(exp.e1);
6130                     // No special treatment for other operators to avoid redundant template instantions
6131                     (*tiargs)[0] = new StringExp(loc, "");
6132                 }
6133 
6134                 (*tiargs)[1] = (*es)[0].type;
6135 
6136                 // Passing __ctfe to auto ref infers ref and aborts compilation:
6137                 // "cannot modify compiler-generated variable __ctfe"
6138                 auto ve = (*es)[0].isVarExp();
6139                 if (ve && ve.var.ident == Id.ctfe)
6140                 {
6141                     exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6142                     goto LSkip;
6143                 }
6144             }
6145             else
6146             {
6147                 OutBuffer buf;
6148                 buf.printf("%s failed", exp.toChars());
6149                 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6150                 goto LSkip;
6151             }
6152 
6153             Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6154             auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6155 
6156             auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6157             auto ec = CallExp.create(Loc.initial, dt, es);
6158             exp.msg = ec;
6159         }
6160 
6161         LSkip:
6162         if (Expression ex = unaSemantic(exp, sc))
6163         {
6164             result = ex;
6165             return;
6166         }
6167 
6168         exp.e1 = resolveProperties(sc, exp.e1);
6169         // BUG: see if we can do compile time elimination of the Assert
6170         exp.e1 = exp.e1.optimize(WANTvalue);
6171         exp.e1 = exp.e1.toBoolean(sc);
6172 
6173         if (exp.msg)
6174         {
6175             exp.msg = expressionSemantic(exp.msg, sc);
6176             exp.msg = resolveProperties(sc, exp.msg);
6177             exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6178             exp.msg = exp.msg.optimize(WANTvalue);
6179             checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
6180         }
6181 
6182         if (exp.e1.op == TOK.error)
6183         {
6184             result = exp.e1;
6185             return;
6186         }
6187         if (exp.msg && exp.msg.op == TOK.error)
6188         {
6189             result = exp.msg;
6190             return;
6191         }
6192 
6193         auto f1 = checkNonAssignmentArrayOp(exp.e1);
6194         auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6195         if (f1 || f2)
6196             return setError();
6197 
6198         if (exp.e1.isBool(false))
6199         {
6200             /* This is an `assert(0)` which means halt program execution
6201              */
6202             FuncDeclaration fd = sc.parent.isFuncDeclaration();
6203             if (fd)
6204                 fd.hasReturnExp |= 4;
6205             sc.ctorflow.orCSX(CSX.halt);
6206 
6207             if (global.params.useAssert == CHECKENABLE.off)
6208             {
6209                 Expression e = new HaltExp(exp.loc);
6210                 e = e.expressionSemantic(sc);
6211                 result = e;
6212                 return;
6213             }
6214         }
6215 
6216         exp.type = Type.tvoid;
6217 
6218         result = !temporariesPrefix
6219             ? exp
6220             : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6221     }
6222 
6223     override void visit(DotIdExp exp)
6224     {
6225         static if (LOGSEMANTIC)
6226         {
6227             printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6228             //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
6229         }
6230         Expression e = exp.semanticY(sc, 1);
6231         if (e && isDotOpDispatch(e))
6232         {
6233             uint errors = global.startGagging();
6234             e = resolvePropertiesX(sc, e);
6235             if (global.endGagging(errors))
6236                 e = null; /* fall down to UFCS */
6237             else
6238             {
6239                 result = e;
6240                 return;
6241             }
6242         }
6243         if (!e) // if failed to find the property
6244         {
6245             /* If ident is not a valid property, rewrite:
6246              *   e1.ident
6247              * as:
6248              *   .ident(e1)
6249              */
6250             e = resolveUFCSProperties(sc, exp);
6251         }
6252         result = e;
6253     }
6254 
6255     override void visit(DotTemplateExp e)
6256     {
6257         if (Expression ex = unaSemantic(e, sc))
6258         {
6259             result = ex;
6260             return;
6261         }
6262         result = e;
6263     }
6264 
6265     override void visit(DotVarExp exp)
6266     {
6267         static if (LOGSEMANTIC)
6268         {
6269             printf("DotVarExp::semantic('%s')\n", exp.toChars());
6270         }
6271         if (exp.type)
6272         {
6273             result = exp;
6274             return;
6275         }
6276 
6277         exp.var = exp.var.toAlias().isDeclaration();
6278 
6279         exp.e1 = exp.e1.expressionSemantic(sc);
6280 
6281         if (auto tup = exp.var.isTupleDeclaration())
6282         {
6283             /* Replace:
6284              *  e1.tuple(a, b, c)
6285              * with:
6286              *  tuple(e1.a, e1.b, e1.c)
6287              */
6288             Expression e0;
6289             Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6290 
6291             auto exps = new Expressions();
6292             exps.reserve(tup.objects.dim);
6293             for (size_t i = 0; i < tup.objects.dim; i++)
6294             {
6295                 RootObject o = (*tup.objects)[i];
6296                 Expression e;
6297                 Declaration var;
6298                 if (o.dyncast() == DYNCAST.expression)
6299                 {
6300                     e = cast(Expression)o;
6301                     if (auto se = e.isDsymbolExp())
6302                         var = se.s.isDeclaration();
6303                     else if (auto ve = e.isVarExp())
6304                         if (!ve.var.isFuncDeclaration())
6305                             // Exempt functions for backwards compatibility reasons.
6306                             // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6307                             var = ve.var;
6308                 }
6309                 else if (o.dyncast() == DYNCAST.dsymbol)
6310                 {
6311                     Dsymbol s = cast(Dsymbol) o;
6312                     Declaration d = s.isDeclaration();
6313                     if (!d || d.isFuncDeclaration())
6314                         // Exempt functions for backwards compatibility reasons.
6315                         // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6316                         e = new DsymbolExp(exp.loc, s);
6317                     else
6318                         var = d;
6319                 }
6320                 else if (o.dyncast() == DYNCAST.type)
6321                 {
6322                     e = new TypeExp(exp.loc, cast(Type)o);
6323                 }
6324                 else
6325                 {
6326                     exp.error("`%s` is not an expression", o.toChars());
6327                     return setError();
6328                 }
6329                 if (var)
6330                     e = new DotVarExp(exp.loc, ev, var);
6331                 exps.push(e);
6332             }
6333 
6334             Expression e = new TupleExp(exp.loc, e0, exps);
6335             e = e.expressionSemantic(sc);
6336             result = e;
6337             return;
6338         }
6339 
6340         exp.e1 = exp.e1.addDtorHook(sc);
6341 
6342         Type t1 = exp.e1.type;
6343 
6344         if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6345         {
6346             // for functions, do checks after overload resolution
6347             if (!fd.functionSemantic())
6348                 return setError();
6349 
6350             /* https://issues.dlang.org/show_bug.cgi?id=13843
6351              * If fd obviously has no overloads, we should
6352              * normalize AST, and it will give a chance to wrap fd with FuncExp.
6353              */
6354             if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6355             {
6356                 // (e1, fd)
6357                 auto e = symbolToExp(fd, exp.loc, sc, false);
6358                 result = Expression.combine(exp.e1, e);
6359                 return;
6360             }
6361 
6362             exp.type = fd.type;
6363             assert(exp.type);
6364         }
6365         else if (OverDeclaration od = exp.var.isOverDeclaration())
6366         {
6367             exp.type = Type.tvoid; // ambiguous type?
6368         }
6369         else
6370         {
6371             exp.type = exp.var.type;
6372             if (!exp.type && global.errors) // var is goofed up, just return error.
6373                 return setError();
6374             assert(exp.type);
6375 
6376             if (t1.ty == Tpointer)
6377                 t1 = t1.nextOf();
6378 
6379             exp.type = exp.type.addMod(t1.mod);
6380 
6381             Dsymbol vparent = exp.var.toParent();
6382             AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6383             if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6384                 exp.e1 = e1x;
6385             else
6386             {
6387                 /* Later checkRightThis will report correct error for invalid field variable access.
6388                  */
6389                 Expression e = new VarExp(exp.loc, exp.var);
6390                 e = e.expressionSemantic(sc);
6391                 result = e;
6392                 return;
6393             }
6394             checkAccess(exp.loc, sc, exp.e1, exp.var);
6395 
6396             VarDeclaration v = exp.var.isVarDeclaration();
6397             if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6398             {
6399                 Expression e = expandVar(WANTvalue, v);
6400                 if (e)
6401                 {
6402                     result = e;
6403                     return;
6404                 }
6405             }
6406 
6407             if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6408                       (!v.needThis() && v.semanticRun > PASS.init)))  // fix https://issues.dlang.org/show_bug.cgi?id=17258
6409             {
6410                 // (e1, v)
6411                 checkAccess(exp.loc, sc, exp.e1, v);
6412                 Expression e = new VarExp(exp.loc, v);
6413                 e = new CommaExp(exp.loc, exp.e1, e);
6414                 e = e.expressionSemantic(sc);
6415                 result = e;
6416                 return;
6417             }
6418         }
6419         //printf("-DotVarExp::semantic('%s')\n", toChars());
6420         result = exp;
6421     }
6422 
6423     override void visit(DotTemplateInstanceExp exp)
6424     {
6425         static if (LOGSEMANTIC)
6426         {
6427             printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6428         }
6429         // Indicate we need to resolve by UFCS.
6430         Expression e = exp.semanticY(sc, 1);
6431         if (!e)
6432             e = resolveUFCSProperties(sc, exp);
6433         result = e;
6434     }
6435 
6436     override void visit(DelegateExp e)
6437     {
6438         static if (LOGSEMANTIC)
6439         {
6440             printf("DelegateExp::semantic('%s')\n", e.toChars());
6441         }
6442         if (e.type)
6443         {
6444             result = e;
6445             return;
6446         }
6447 
6448         e.e1 = e.e1.expressionSemantic(sc);
6449 
6450         e.type = new TypeDelegate(e.func.type);
6451         e.type = e.type.typeSemantic(e.loc, sc);
6452 
6453         FuncDeclaration f = e.func.toAliasFunc();
6454         AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
6455         if (f.needThis())
6456             e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6457         if (e.e1.op == TOK.error)
6458             return setError();
6459 
6460         /* A delegate takes the address of e.e1 in order to set the .ptr field
6461          * https://issues.dlang.org/show_bug.cgi?id=18575
6462          */
6463         if (global.params.vsafe && e.e1.type.toBasetype().ty == Tstruct)
6464         {
6465             if (auto v = expToVariable(e.e1))
6466             {
6467                 if (!checkAddressVar(sc, e.e1, v))
6468                     return setError();
6469             }
6470         }
6471 
6472         if (f.type.ty == Tfunction)
6473         {
6474             TypeFunction tf = cast(TypeFunction)f.type;
6475             if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6476             {
6477                 OutBuffer thisBuf, funcBuf;
6478                 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6479                 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6480                 e.error("%smethod `%s` is not callable using a %s`%s`",
6481                     funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6482                 return setError();
6483             }
6484         }
6485         if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6486         {
6487             // A downcast is required for interfaces
6488             // https://issues.dlang.org/show_bug.cgi?id=3706
6489             e.e1 = new CastExp(e.loc, e.e1, ad.type);
6490             e.e1 = e.e1.expressionSemantic(sc);
6491         }
6492         result = e;
6493         // declare dual-context container
6494         if (f.isThis2 && !sc.intypeof && sc.func)
6495         {
6496             // check access to second `this`
6497             if (AggregateDeclaration ad2 = f.isMember2())
6498             {
6499                 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6500                 if (te.op != TOK.error)
6501                     te = getRightThis(e.loc, sc, ad2, te, f);
6502                 if (te.op == TOK.error)
6503                 {
6504                     e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6505                     return setError();
6506                 }
6507             }
6508             VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6509             e.vthis2 = vthis2;
6510             Expression de = new DeclarationExp(e.loc, vthis2);
6511             result = Expression.combine(de, result);
6512             result = result.expressionSemantic(sc);
6513         }
6514     }
6515 
6516     override void visit(DotTypeExp exp)
6517     {
6518         static if (LOGSEMANTIC)
6519         {
6520             printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6521         }
6522         if (exp.type)
6523         {
6524             result = exp;
6525             return;
6526         }
6527 
6528         if (auto e = unaSemantic(exp, sc))
6529         {
6530             result = e;
6531             return;
6532         }
6533 
6534         exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6535         result = exp;
6536     }
6537 
6538     override void visit(AddrExp exp)
6539     {
6540         static if (LOGSEMANTIC)
6541         {
6542             printf("AddrExp::semantic('%s')\n", exp.toChars());
6543         }
6544         if (exp.type)
6545         {
6546             result = exp;
6547             return;
6548         }
6549 
6550         if (Expression ex = unaSemantic(exp, sc))
6551         {
6552             result = ex;
6553             return;
6554         }
6555 
6556         int wasCond = exp.e1.op == TOK.question;
6557 
6558         if (exp.e1.op == TOK.dotTemplateInstance)
6559         {
6560             DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6561             TemplateInstance ti = dti.ti;
6562             {
6563                 //assert(ti.needsTypeInference(sc));
6564                 ti.dsymbolSemantic(sc);
6565                 if (!ti.inst || ti.errors) // if template failed to expand
6566                     return setError();
6567 
6568                 Dsymbol s = ti.toAlias();
6569                 FuncDeclaration f = s.isFuncDeclaration();
6570                 if (f)
6571                 {
6572                     exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6573                     exp.e1 = exp.e1.expressionSemantic(sc);
6574                 }
6575             }
6576         }
6577         else if (exp.e1.op == TOK.scope_)
6578         {
6579             TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6580             if (ti)
6581             {
6582                 //assert(ti.needsTypeInference(sc));
6583                 ti.dsymbolSemantic(sc);
6584                 if (!ti.inst || ti.errors) // if template failed to expand
6585                     return setError();
6586 
6587                 Dsymbol s = ti.toAlias();
6588                 FuncDeclaration f = s.isFuncDeclaration();
6589                 if (f)
6590                 {
6591                     exp.e1 = new VarExp(exp.e1.loc, f);
6592                     exp.e1 = exp.e1.expressionSemantic(sc);
6593                 }
6594             }
6595         }
6596         /* https://issues.dlang.org/show_bug.cgi?id=809
6597          *
6598          * If the address of a lazy variable is taken,
6599          * the expression is rewritten so that the type
6600          * of it is the delegate type. This means that
6601          * the symbol is not going to represent a call
6602          * to the delegate anymore, but rather, the
6603          * actual symbol.
6604          */
6605         if (auto ve = exp.e1.isVarExp())
6606         {
6607             if (ve.var.storage_class & STC.lazy_)
6608             {
6609                 exp.e1 = exp.e1.expressionSemantic(sc);
6610                 exp.e1 = resolveProperties(sc, exp.e1);
6611                 if (auto callExp = exp.e1.isCallExp())
6612                 {
6613                     if (callExp.e1.type.toBasetype().ty == Tdelegate)
6614                     {
6615                         /* https://issues.dlang.org/show_bug.cgi?id=20551
6616                          *
6617                          * Cannot take address of lazy parameter in @safe code
6618                          * because it might end up being a pointer to undefined
6619                          * memory.
6620                          */
6621                         if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6622                         {
6623                             exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
6624                                      ve.toChars(), sc.func.toChars());
6625                             setError();
6626                         }
6627                         else
6628                         {
6629                             VarExp ve2 = callExp.e1.isVarExp();
6630                             ve2.delegateWasExtracted = true;
6631                             ve2.var.storage_class |= STC.scope_;
6632                             result = ve2;
6633                         }
6634                         return;
6635                     }
6636                 }
6637             }
6638         }
6639 
6640         exp.e1 = exp.e1.toLvalue(sc, null);
6641         if (exp.e1.op == TOK.error)
6642         {
6643             result = exp.e1;
6644             return;
6645         }
6646         if (checkNonAssignmentArrayOp(exp.e1))
6647             return setError();
6648 
6649         if (!exp.e1.type)
6650         {
6651             exp.error("cannot take address of `%s`", exp.e1.toChars());
6652             return setError();
6653         }
6654 
6655         bool hasOverloads;
6656         if (auto f = isFuncAddress(exp, &hasOverloads))
6657         {
6658             if (!hasOverloads && f.checkForwardRef(exp.loc))
6659                 return setError();
6660         }
6661         else if (!exp.e1.type.deco)
6662         {
6663             if (exp.e1.op == TOK.variable)
6664             {
6665                 VarExp ve = cast(VarExp)exp.e1;
6666                 Declaration d = ve.var;
6667                 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
6668             }
6669             else
6670                 exp.error("forward reference to `%s`", exp.e1.toChars());
6671             return setError();
6672         }
6673 
6674         exp.type = exp.e1.type.pointerTo();
6675 
6676         // See if this should really be a delegate
6677         if (exp.e1.op == TOK.dotVariable)
6678         {
6679             DotVarExp dve = cast(DotVarExp)exp.e1;
6680             FuncDeclaration f = dve.var.isFuncDeclaration();
6681             if (f)
6682             {
6683                 f = f.toAliasFunc(); // FIXME, should see overloads
6684                                      // https://issues.dlang.org/show_bug.cgi?id=1983
6685                 if (!dve.hasOverloads)
6686                     f.tookAddressOf++;
6687 
6688                 Expression e;
6689                 if (f.needThis())
6690                     e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
6691                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
6692                     e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
6693                 e = e.expressionSemantic(sc);
6694                 result = e;
6695                 return;
6696             }
6697 
6698             // Look for misaligned pointer in @safe mode
6699             if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
6700                 return setError();
6701 
6702             if (global.params.vsafe)
6703             {
6704                 if (VarDeclaration v = expToVariable(dve.e1))
6705                 {
6706                     if (!checkAddressVar(sc, exp.e1, v))
6707                         return setError();
6708                 }
6709             }
6710         }
6711         else if (exp.e1.op == TOK.variable)
6712         {
6713             VarExp ve = cast(VarExp)exp.e1;
6714             VarDeclaration v = ve.var.isVarDeclaration();
6715             if (v)
6716             {
6717                 if (!checkAddressVar(sc, exp.e1, v))
6718                     return setError();
6719 
6720                 ve.checkPurity(sc, v);
6721             }
6722             FuncDeclaration f = ve.var.isFuncDeclaration();
6723             if (f)
6724             {
6725                 /* Because nested functions cannot be overloaded,
6726                  * mark here that we took its address because castTo()
6727                  * may not be called with an exact match.
6728                  */
6729                 if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
6730                     f.tookAddressOf++;
6731                 if (f.isNested() && !f.needThis())
6732                 {
6733                     if (f.isFuncLiteralDeclaration())
6734                     {
6735                         if (!f.FuncDeclaration.isNested())
6736                         {
6737                             /* Supply a 'null' for a this pointer if no this is available
6738                              */
6739                             Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
6740                             e = e.expressionSemantic(sc);
6741                             result = e;
6742                             return;
6743                         }
6744                     }
6745                     Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
6746                     e = e.expressionSemantic(sc);
6747                     result = e;
6748                     return;
6749                 }
6750                 if (f.needThis())
6751                 {
6752                     if (hasThis(sc))
6753                     {
6754                         /* Should probably supply 'this' after overload resolution,
6755                          * not before.
6756                          */
6757                         Expression ethis = new ThisExp(exp.loc);
6758                         Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
6759                         e = e.expressionSemantic(sc);
6760                         result = e;
6761                         return;
6762                     }
6763                     if (sc.func && !sc.intypeof)
6764                     {
6765                         if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6766                         {
6767                             exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
6768                         }
6769                     }
6770                 }
6771             }
6772         }
6773         else if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && global.params.vsafe)
6774         {
6775             if (VarDeclaration v = expToVariable(exp.e1))
6776             {
6777                 if (!checkAddressVar(sc, exp.e1, v))
6778                     return setError();
6779             }
6780         }
6781         else if (exp.e1.op == TOK.call)
6782         {
6783             CallExp ce = cast(CallExp)exp.e1;
6784             if (ce.e1.type.ty == Tfunction)
6785             {
6786                 TypeFunction tf = cast(TypeFunction)ce.e1.type;
6787                 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6788                 {
6789                     exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
6790                         ce.e1.toChars(), sc.func.toChars());
6791                 }
6792             }
6793         }
6794         else if (exp.e1.op == TOK.index)
6795         {
6796             /* For:
6797              *   int[3] a;
6798              *   &a[i]
6799              * check 'a' the same as for a regular variable
6800              */
6801             if (VarDeclaration v = expToVariable(exp.e1))
6802             {
6803                 if (global.params.vsafe && !checkAddressVar(sc, exp.e1, v))
6804                     return setError();
6805 
6806                 exp.e1.checkPurity(sc, v);
6807             }
6808         }
6809         else if (wasCond)
6810         {
6811             /* a ? b : c was transformed to *(a ? &b : &c), but we still
6812              * need to do safety checks
6813              */
6814             assert(exp.e1.op == TOK.star);
6815             PtrExp pe = cast(PtrExp)exp.e1;
6816             assert(pe.e1.op == TOK.question);
6817             CondExp ce = cast(CondExp)pe.e1;
6818             assert(ce.e1.op == TOK.address);
6819             assert(ce.e2.op == TOK.address);
6820 
6821             // Re-run semantic on the address expressions only
6822             ce.e1.type = null;
6823             ce.e1 = ce.e1.expressionSemantic(sc);
6824             ce.e2.type = null;
6825             ce.e2 = ce.e2.expressionSemantic(sc);
6826         }
6827         result = exp.optimize(WANTvalue);
6828     }
6829 
6830     override void visit(PtrExp exp)
6831     {
6832         static if (LOGSEMANTIC)
6833         {
6834             printf("PtrExp::semantic('%s')\n", exp.toChars());
6835         }
6836         if (exp.type)
6837         {
6838             result = exp;
6839             return;
6840         }
6841 
6842         Expression e = exp.op_overload(sc);
6843         if (e)
6844         {
6845             result = e;
6846             return;
6847         }
6848 
6849         Type tb = exp.e1.type.toBasetype();
6850         switch (tb.ty)
6851         {
6852         case Tpointer:
6853             exp.type = (cast(TypePointer)tb).next;
6854             break;
6855 
6856         case Tsarray:
6857         case Tarray:
6858             if (isNonAssignmentArrayOp(exp.e1))
6859                 goto default;
6860             exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
6861             exp.type = (cast(TypeArray)tb).next;
6862             exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
6863             break;
6864 
6865         case Terror:
6866             return setError();
6867 
6868         default:
6869             exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
6870             goto case Terror;
6871         }
6872 
6873         if (exp.checkValue())
6874             return setError();
6875 
6876         result = exp;
6877     }
6878 
6879     override void visit(NegExp exp)
6880     {
6881         static if (LOGSEMANTIC)
6882         {
6883             printf("NegExp::semantic('%s')\n", exp.toChars());
6884         }
6885         if (exp.type)
6886         {
6887             result = exp;
6888             return;
6889         }
6890 
6891         Expression e = exp.op_overload(sc);
6892         if (e)
6893         {
6894             result = e;
6895             return;
6896         }
6897 
6898         fix16997(sc, exp);
6899         exp.type = exp.e1.type;
6900         Type tb = exp.type.toBasetype();
6901         if (tb.ty == Tarray || tb.ty == Tsarray)
6902         {
6903             if (!isArrayOpValid(exp.e1))
6904             {
6905                 result = arrayOpInvalidError(exp);
6906                 return;
6907             }
6908             result = exp;
6909             return;
6910         }
6911         if (!target.isVectorOpSupported(tb, exp.op))
6912         {
6913             result = exp.incompatibleTypes();
6914             return;
6915         }
6916         if (exp.e1.checkNoBool())
6917             return setError();
6918         if (exp.e1.checkArithmetic() ||
6919             exp.e1.checkSharedAccess(sc))
6920             return setError();
6921 
6922         result = exp;
6923     }
6924 
6925     override void visit(UAddExp exp)
6926     {
6927         static if (LOGSEMANTIC)
6928         {
6929             printf("UAddExp::semantic('%s')\n", exp.toChars());
6930         }
6931         assert(!exp.type);
6932 
6933         Expression e = exp.op_overload(sc);
6934         if (e)
6935         {
6936             result = e;
6937             return;
6938         }
6939 
6940         fix16997(sc, exp);
6941         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
6942         {
6943             result = exp.incompatibleTypes();
6944             return;
6945         }
6946         if (exp.e1.checkNoBool())
6947             return setError();
6948         if (exp.e1.checkArithmetic())
6949             return setError();
6950         if (exp.e1.checkSharedAccess(sc))
6951             return setError();
6952 
6953         result = exp.e1;
6954     }
6955 
6956     override void visit(ComExp exp)
6957     {
6958         if (exp.type)
6959         {
6960             result = exp;
6961             return;
6962         }
6963 
6964         Expression e = exp.op_overload(sc);
6965         if (e)
6966         {
6967             result = e;
6968             return;
6969         }
6970 
6971         fix16997(sc, exp);
6972         exp.type = exp.e1.type;
6973         Type tb = exp.type.toBasetype();
6974         if (tb.ty == Tarray || tb.ty == Tsarray)
6975         {
6976             if (!isArrayOpValid(exp.e1))
6977             {
6978                 result = arrayOpInvalidError(exp);
6979                 return;
6980             }
6981             result = exp;
6982             return;
6983         }
6984         if (!target.isVectorOpSupported(tb, exp.op))
6985         {
6986             result = exp.incompatibleTypes();
6987             return;
6988         }
6989         if (exp.e1.checkNoBool())
6990             return setError();
6991         if (exp.e1.checkIntegral() ||
6992             exp.e1.checkSharedAccess(sc))
6993             return setError();
6994 
6995         result = exp;
6996     }
6997 
6998     override void visit(NotExp e)
6999     {
7000         if (e.type)
7001         {
7002             result = e;
7003             return;
7004         }
7005 
7006         e.setNoderefOperand();
7007 
7008         // Note there is no operator overload
7009         if (Expression ex = unaSemantic(e, sc))
7010         {
7011             result = ex;
7012             return;
7013         }
7014 
7015         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7016         if (e.e1.op == TOK.type)
7017             e.e1 = resolveAliasThis(sc, e.e1);
7018 
7019         e.e1 = resolveProperties(sc, e.e1);
7020         e.e1 = e.e1.toBoolean(sc);
7021         if (e.e1.type == Type.terror)
7022         {
7023             result = e.e1;
7024             return;
7025         }
7026 
7027         if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7028         {
7029             result = e.incompatibleTypes();
7030         }
7031         // https://issues.dlang.org/show_bug.cgi?id=13910
7032         // Today NotExp can take an array as its operand.
7033         if (checkNonAssignmentArrayOp(e.e1))
7034             return setError();
7035 
7036         e.type = Type.tbool;
7037         result = e;
7038     }
7039 
7040     override void visit(DeleteExp exp)
7041     {
7042         if (!sc.isDeprecated)
7043         {
7044             // @@@DEPRECATED_2019-02@@@
7045             // 1. Deprecation for 1 year
7046             // 2. Error for 1 year
7047             // 3. Removal of keyword, "delete" can be used for other identities
7048             if (!exp.isRAII)
7049                 deprecation(exp.loc, "The `delete` keyword has been deprecated.  Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
7050         }
7051 
7052         if (Expression ex = unaSemantic(exp, sc))
7053         {
7054             result = ex;
7055             return;
7056         }
7057         exp.e1 = resolveProperties(sc, exp.e1);
7058         exp.e1 = exp.e1.modifiableLvalue(sc, null);
7059         if (exp.e1.op == TOK.error)
7060         {
7061             result = exp.e1;
7062             return;
7063         }
7064         exp.type = Type.tvoid;
7065 
7066         AggregateDeclaration ad = null;
7067         Type tb = exp.e1.type.toBasetype();
7068         switch (tb.ty)
7069         {
7070         case Tclass:
7071             {
7072                 auto cd = (cast(TypeClass)tb).sym;
7073                 if (cd.isCOMinterface())
7074                 {
7075                     /* Because COM classes are deleted by IUnknown.Release()
7076                      */
7077                     exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7078                     return setError();
7079                 }
7080                 ad = cd;
7081                 break;
7082             }
7083         case Tpointer:
7084             tb = (cast(TypePointer)tb).next.toBasetype();
7085             if (tb.ty == Tstruct)
7086             {
7087                 ad = (cast(TypeStruct)tb).sym;
7088                 semanticTypeInfo(sc, tb);
7089             }
7090             break;
7091 
7092         case Tarray:
7093             {
7094                 Type tv = tb.nextOf().baseElemOf();
7095                 if (tv.ty == Tstruct)
7096                 {
7097                     ad = (cast(TypeStruct)tv).sym;
7098                     if (ad.dtor)
7099                         semanticTypeInfo(sc, ad.type);
7100                 }
7101                 break;
7102             }
7103         default:
7104             exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7105             return setError();
7106         }
7107 
7108         bool err = false;
7109         if (ad)
7110         {
7111             if (ad.dtor)
7112             {
7113                 err |= exp.checkPurity(sc, ad.dtor);
7114                 err |= exp.checkSafety(sc, ad.dtor);
7115                 err |= exp.checkNogc(sc, ad.dtor);
7116             }
7117             if (err)
7118                 return setError();
7119         }
7120 
7121         if (!sc.intypeof && sc.func &&
7122             !exp.isRAII &&
7123             !(sc.flags & SCOPE.debug_) &&
7124             sc.func.setUnsafe())
7125         {
7126             exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars());
7127             err = true;
7128         }
7129         if (err)
7130             return setError();
7131 
7132         result = exp;
7133     }
7134 
7135     override void visit(CastExp exp)
7136     {
7137         static if (LOGSEMANTIC)
7138         {
7139             printf("CastExp::semantic('%s')\n", exp.toChars());
7140         }
7141         //static int x; assert(++x < 10);
7142         if (exp.type)
7143         {
7144             result = exp;
7145             return;
7146         }
7147 
7148         if (exp.to)
7149         {
7150             exp.to = exp.to.typeSemantic(exp.loc, sc);
7151             if (exp.to == Type.terror)
7152                 return setError();
7153 
7154             if (!exp.to.hasPointers())
7155                 exp.setNoderefOperand();
7156 
7157             // When e1 is a template lambda, this cast may instantiate it with
7158             // the type 'to'.
7159             exp.e1 = inferType(exp.e1, exp.to);
7160         }
7161 
7162         if (auto e = unaSemantic(exp, sc))
7163         {
7164             result = e;
7165             return;
7166         }
7167 
7168         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7169         if (exp.e1.op == TOK.type)
7170             exp.e1 = resolveAliasThis(sc, exp.e1);
7171 
7172         auto e1x = resolveProperties(sc, exp.e1);
7173         if (e1x.op == TOK.error)
7174         {
7175             result = e1x;
7176             return;
7177         }
7178         if (e1x.checkType())
7179             return setError();
7180         exp.e1 = e1x;
7181 
7182         if (!exp.e1.type)
7183         {
7184             exp.error("cannot cast `%s`", exp.e1.toChars());
7185             return setError();
7186         }
7187 
7188         // https://issues.dlang.org/show_bug.cgi?id=19954
7189         if (exp.e1.type.ty == Ttuple)
7190         {
7191             TupleExp te = exp.e1.isTupleExp();
7192             if (te.exps.dim == 1)
7193                 exp.e1 = (*te.exps)[0];
7194         }
7195 
7196         // only allow S(x) rewrite if cast specified S explicitly.
7197         // See https://issues.dlang.org/show_bug.cgi?id=18545
7198         const bool allowImplicitConstruction = exp.to !is null;
7199 
7200         if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7201         {
7202             exp.to = exp.e1.type.castMod(exp.mod);
7203             exp.to = exp.to.typeSemantic(exp.loc, sc);
7204 
7205             if (exp.to == Type.terror)
7206                 return setError();
7207         }
7208 
7209         if (exp.to.ty == Ttuple)
7210         {
7211             exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
7212             return setError();
7213         }
7214 
7215         // cast(void) is used to mark e1 as unused, so it is safe
7216         if (exp.to.ty == Tvoid)
7217         {
7218             exp.type = exp.to;
7219             result = exp;
7220             return;
7221         }
7222 
7223         if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7224         {
7225             if (Expression e = exp.op_overload(sc))
7226             {
7227                 result = e.implicitCastTo(sc, exp.to);
7228                 return;
7229             }
7230         }
7231 
7232         Type t1b = exp.e1.type.toBasetype();
7233         Type tob = exp.to.toBasetype();
7234 
7235         if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7236         {
7237             /* Look to replace:
7238              *  cast(S)t
7239              * with:
7240              *  S(t)
7241              */
7242 
7243             // Rewrite as to.call(e1)
7244             Expression e = new TypeExp(exp.loc, exp.to);
7245             e = new CallExp(exp.loc, e, exp.e1);
7246             e = e.trySemantic(sc);
7247             if (e)
7248             {
7249                 result = e;
7250                 return;
7251             }
7252         }
7253 
7254         if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7255         {
7256             if (checkNonAssignmentArrayOp(exp.e1))
7257                 return setError();
7258         }
7259 
7260         // Look for casting to a vector type
7261         if (tob.ty == Tvector && t1b.ty != Tvector)
7262         {
7263             result = new VectorExp(exp.loc, exp.e1, exp.to);
7264             result = result.expressionSemantic(sc);
7265             return;
7266         }
7267 
7268         Expression ex = exp.e1.castTo(sc, exp.to);
7269         if (ex.op == TOK.error)
7270         {
7271             result = ex;
7272             return;
7273         }
7274 
7275         // Check for unsafe casts
7276         if (!sc.intypeof &&
7277             !(sc.flags & SCOPE.debug_) &&
7278             !isSafeCast(ex, t1b, tob) &&
7279             (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe()))
7280         {
7281             exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
7282             return setError();
7283         }
7284 
7285         // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7286         // to handle certain casts.  Those casts which `object.__ArrayCast` does not support are filtered out.
7287         // See `e2ir.toElemCast` for other types of casts.  If `object.__ArrayCast` is improved to support more
7288         // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7289         if (tob.ty == Tarray)
7290         {
7291             // https://issues.dlang.org/show_bug.cgi?id=19840
7292             if (auto ad = isAggregate(t1b))
7293             {
7294                 if (ad.aliasthis)
7295                 {
7296                     Expression e = resolveAliasThis(sc, exp.e1);
7297                     e = new CastExp(exp.loc, e, exp.to);
7298                     result = e.expressionSemantic(sc);
7299                     return;
7300                 }
7301             }
7302 
7303             if(t1b.ty == Tarray && exp.e1.op != TOK.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7304             {
7305                 auto tFrom = t1b.nextOf();
7306                 auto tTo = tob.nextOf();
7307 
7308                 // https://issues.dlang.org/show_bug.cgi?id=20130
7309                 if (exp.e1.op != TOK.string_ || !ex.isStringExp)
7310                 {
7311                     const uint fromSize = cast(uint)tFrom.size();
7312                     const uint toSize = cast(uint)tTo.size();
7313 
7314                     // If array element sizes do not match, we must adjust the dimensions
7315                     if (fromSize != toSize)
7316                     {
7317                         if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7318                             return setError();
7319 
7320                         // A runtime check is needed in case arrays don't line up.  That check should
7321                         // be done in the implementation of `object.__ArrayCast`
7322                         if (toSize == 0 || (fromSize % toSize) != 0)
7323                         {
7324                             // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7325 
7326                             // fully qualify as `object.__ArrayCast`
7327                             Expression id = new IdentifierExp(exp.loc, Id.empty);
7328                             auto dotid = new DotIdExp(exp.loc, id, Id.object);
7329 
7330                             auto tiargs = new Objects();
7331                             tiargs.push(tFrom);
7332                             tiargs.push(tTo);
7333                             auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7334 
7335                             auto arguments = new Expressions();
7336                             arguments.push(exp.e1);
7337                             Expression ce = new CallExp(exp.loc, dt, arguments);
7338 
7339                             result = expressionSemantic(ce, sc);
7340                             return;
7341                         }
7342                     }
7343                 }
7344             }
7345         }
7346 
7347         result = ex;
7348     }
7349 
7350     override void visit(VectorExp exp)
7351     {
7352         static if (LOGSEMANTIC)
7353         {
7354             printf("VectorExp::semantic('%s')\n", exp.toChars());
7355         }
7356         if (exp.type)
7357         {
7358             result = exp;
7359             return;
7360         }
7361 
7362         exp.e1 = exp.e1.expressionSemantic(sc);
7363         exp.type = exp.to.typeSemantic(exp.loc, sc);
7364         if (exp.e1.op == TOK.error || exp.type.ty == Terror)
7365         {
7366             result = exp.e1;
7367             return;
7368         }
7369 
7370         Type tb = exp.type.toBasetype();
7371         assert(tb.ty == Tvector);
7372         TypeVector tv = cast(TypeVector)tb;
7373         Type te = tv.elementType();
7374         exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7375 
7376         bool checkElem(Expression elem)
7377         {
7378             if (elem.isConst() == 1)
7379                 return false;
7380 
7381              exp.error("constant expression expected, not `%s`", elem.toChars());
7382              return true;
7383         }
7384 
7385         exp.e1 = exp.e1.optimize(WANTvalue);
7386         bool res;
7387         if (exp.e1.op == TOK.arrayLiteral)
7388         {
7389             foreach (i; 0 .. exp.dim)
7390             {
7391                 // Do not stop on first error - check all AST nodes even if error found
7392                 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7393             }
7394         }
7395         else if (exp.e1.type.ty == Tvoid)
7396             checkElem(exp.e1);
7397 
7398         result = res ? ErrorExp.get() : exp;
7399     }
7400 
7401     override void visit(VectorArrayExp e)
7402     {
7403         static if (LOGSEMANTIC)
7404         {
7405             printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7406         }
7407         if (!e.type)
7408         {
7409             unaSemantic(e, sc);
7410             e.e1 = resolveProperties(sc, e.e1);
7411 
7412             if (e.e1.op == TOK.error)
7413             {
7414                 result = e.e1;
7415                 return;
7416             }
7417             assert(e.e1.type.ty == Tvector);
7418             e.type = e.e1.type.isTypeVector().basetype;
7419         }
7420         result = e;
7421     }
7422 
7423     override void visit(SliceExp exp)
7424     {
7425         static if (LOGSEMANTIC)
7426         {
7427             printf("SliceExp::semantic('%s')\n", exp.toChars());
7428         }
7429         if (exp.type)
7430         {
7431             result = exp;
7432             return;
7433         }
7434 
7435         // operator overloading should be handled in ArrayExp already.
7436         if (Expression ex = unaSemantic(exp, sc))
7437         {
7438             result = ex;
7439             return;
7440         }
7441         exp.e1 = resolveProperties(sc, exp.e1);
7442         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7443         {
7444             if (exp.lwr || exp.upr)
7445             {
7446                 exp.error("cannot slice type `%s`", exp.e1.toChars());
7447                 return setError();
7448             }
7449             Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7450             result = e.expressionSemantic(sc);
7451             return;
7452         }
7453         if (!exp.lwr && !exp.upr)
7454         {
7455             if (exp.e1.op == TOK.arrayLiteral)
7456             {
7457                 // Convert [a,b,c][] to [a,b,c]
7458                 Type t1b = exp.e1.type.toBasetype();
7459                 Expression e = exp.e1;
7460                 if (t1b.ty == Tsarray)
7461                 {
7462                     e = e.copy();
7463                     e.type = t1b.nextOf().arrayOf();
7464                 }
7465                 result = e;
7466                 return;
7467             }
7468             if (exp.e1.op == TOK.slice)
7469             {
7470                 // Convert e[][] to e[]
7471                 SliceExp se = cast(SliceExp)exp.e1;
7472                 if (!se.lwr && !se.upr)
7473                 {
7474                     result = se;
7475                     return;
7476                 }
7477             }
7478             if (isArrayOpOperand(exp.e1))
7479             {
7480                 // Convert (a[]+b[])[] to a[]+b[]
7481                 result = exp.e1;
7482                 return;
7483             }
7484         }
7485         if (exp.e1.op == TOK.error)
7486         {
7487             result = exp.e1;
7488             return;
7489         }
7490         if (exp.e1.type.ty == Terror)
7491             return setError();
7492 
7493         Type t1b = exp.e1.type.toBasetype();
7494         if (t1b.ty == Tpointer)
7495         {
7496             if ((cast(TypePointer)t1b).next.ty == Tfunction)
7497             {
7498                 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7499                 return setError();
7500             }
7501             if (!exp.lwr || !exp.upr)
7502             {
7503                 exp.error("need upper and lower bound to slice pointer");
7504                 return setError();
7505             }
7506             if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7507             {
7508                 exp.error("pointer slicing not allowed in safe functions");
7509                 return setError();
7510             }
7511         }
7512         else if (t1b.ty == Tarray)
7513         {
7514         }
7515         else if (t1b.ty == Tsarray)
7516         {
7517             if (!exp.arrayop && global.params.vsafe)
7518             {
7519                 /* Slicing a static array is like taking the address of it.
7520                  * Perform checks as if e[] was &e
7521                  */
7522                 if (VarDeclaration v = expToVariable(exp.e1))
7523                 {
7524                     if (exp.e1.op == TOK.dotVariable)
7525                     {
7526                         DotVarExp dve = cast(DotVarExp)exp.e1;
7527                         if ((dve.e1.op == TOK.this_ || dve.e1.op == TOK.super_) &&
7528                             !(v.storage_class & STC.ref_))
7529                         {
7530                             // because it's a class
7531                             v = null;
7532                         }
7533                     }
7534 
7535                     if (v && !checkAddressVar(sc, exp.e1, v))
7536                         return setError();
7537                 }
7538             }
7539         }
7540         else if (t1b.ty == Ttuple)
7541         {
7542             if (!exp.lwr && !exp.upr)
7543             {
7544                 result = exp.e1;
7545                 return;
7546             }
7547             if (!exp.lwr || !exp.upr)
7548             {
7549                 exp.error("need upper and lower bound to slice tuple");
7550                 return setError();
7551             }
7552         }
7553         else if (t1b.ty == Tvector)
7554         {
7555             // Convert e1 to corresponding static array
7556             TypeVector tv1 = cast(TypeVector)t1b;
7557             t1b = tv1.basetype;
7558             t1b = t1b.castMod(tv1.mod);
7559             exp.e1.type = t1b;
7560         }
7561         else
7562         {
7563             exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7564             return setError();
7565         }
7566 
7567         /* Run semantic on lwr and upr.
7568          */
7569         Scope* scx = sc;
7570         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7571         {
7572             // Create scope for 'length' variable
7573             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7574             sym.parent = sc.scopesym;
7575             sc = sc.push(sym);
7576         }
7577         if (exp.lwr)
7578         {
7579             if (t1b.ty == Ttuple)
7580                 sc = sc.startCTFE();
7581             exp.lwr = exp.lwr.expressionSemantic(sc);
7582             exp.lwr = resolveProperties(sc, exp.lwr);
7583             if (t1b.ty == Ttuple)
7584                 sc = sc.endCTFE();
7585             exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7586         }
7587         if (exp.upr)
7588         {
7589             if (t1b.ty == Ttuple)
7590                 sc = sc.startCTFE();
7591             exp.upr = exp.upr.expressionSemantic(sc);
7592             exp.upr = resolveProperties(sc, exp.upr);
7593             if (t1b.ty == Ttuple)
7594                 sc = sc.endCTFE();
7595             exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7596         }
7597         if (sc != scx)
7598             sc = sc.pop();
7599         if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7600             return setError();
7601 
7602         if (t1b.ty == Ttuple)
7603         {
7604             exp.lwr = exp.lwr.ctfeInterpret();
7605             exp.upr = exp.upr.ctfeInterpret();
7606             uinteger_t i1 = exp.lwr.toUInteger();
7607             uinteger_t i2 = exp.upr.toUInteger();
7608 
7609             TupleExp te;
7610             TypeTuple tup;
7611             size_t length;
7612             if (exp.e1.op == TOK.tuple) // slicing an expression tuple
7613             {
7614                 te = cast(TupleExp)exp.e1;
7615                 tup = null;
7616                 length = te.exps.dim;
7617             }
7618             else if (exp.e1.op == TOK.type) // slicing a type tuple
7619             {
7620                 te = null;
7621                 tup = cast(TypeTuple)t1b;
7622                 length = Parameter.dim(tup.arguments);
7623             }
7624             else
7625                 assert(0);
7626 
7627             if (i2 < i1 || length < i2)
7628             {
7629                 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7630                 return setError();
7631             }
7632 
7633             size_t j1 = cast(size_t)i1;
7634             size_t j2 = cast(size_t)i2;
7635             Expression e;
7636             if (exp.e1.op == TOK.tuple)
7637             {
7638                 auto exps = new Expressions(j2 - j1);
7639                 for (size_t i = 0; i < j2 - j1; i++)
7640                 {
7641                     (*exps)[i] = (*te.exps)[j1 + i];
7642                 }
7643                 e = new TupleExp(exp.loc, te.e0, exps);
7644             }
7645             else
7646             {
7647                 auto args = new Parameters();
7648                 args.reserve(j2 - j1);
7649                 for (size_t i = j1; i < j2; i++)
7650                 {
7651                     Parameter arg = Parameter.getNth(tup.arguments, i);
7652                     args.push(arg);
7653                 }
7654                 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
7655             }
7656             e = e.expressionSemantic(sc);
7657             result = e;
7658             return;
7659         }
7660 
7661         exp.type = t1b.nextOf().arrayOf();
7662         // Allow typedef[] -> typedef[]
7663         if (exp.type.equals(t1b))
7664             exp.type = exp.e1.type;
7665 
7666         // We might know $ now
7667         setLengthVarIfKnown(exp.lengthVar, t1b);
7668 
7669         if (exp.lwr && exp.upr)
7670         {
7671             exp.lwr = exp.lwr.optimize(WANTvalue);
7672             exp.upr = exp.upr.optimize(WANTvalue);
7673 
7674             IntRange lwrRange = getIntRange(exp.lwr);
7675             IntRange uprRange = getIntRange(exp.upr);
7676 
7677             if (t1b.ty == Tsarray || t1b.ty == Tarray)
7678             {
7679                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
7680                 el = el.expressionSemantic(sc);
7681                 el = el.optimize(WANTvalue);
7682                 if (el.op == TOK.int64)
7683                 {
7684                     // Array length is known at compile-time. Upper is in bounds if it fits length.
7685                     dinteger_t length = el.toInteger();
7686                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
7687                     exp.upperIsInBounds = bounds.contains(uprRange);
7688                 }
7689                 else if (exp.upr.op == TOK.int64 && exp.upr.toInteger() == 0)
7690                 {
7691                     // Upper slice expression is '0'. Value is always in bounds.
7692                     exp.upperIsInBounds = true;
7693                 }
7694                 else if (exp.upr.op == TOK.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
7695                 {
7696                     // Upper slice expression is '$'. Value is always in bounds.
7697                     exp.upperIsInBounds = true;
7698                 }
7699             }
7700             else if (t1b.ty == Tpointer)
7701             {
7702                 exp.upperIsInBounds = true;
7703             }
7704             else
7705                 assert(0);
7706 
7707             exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
7708 
7709             //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
7710         }
7711 
7712         result = exp;
7713     }
7714 
7715     override void visit(ArrayLengthExp e)
7716     {
7717         static if (LOGSEMANTIC)
7718         {
7719             printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
7720         }
7721         if (e.type)
7722         {
7723             result = e;
7724             return;
7725         }
7726 
7727         if (Expression ex = unaSemantic(e, sc))
7728         {
7729             result = ex;
7730             return;
7731         }
7732         e.e1 = resolveProperties(sc, e.e1);
7733 
7734         e.type = Type.tsize_t;
7735         result = e;
7736     }
7737 
7738     override void visit(ArrayExp exp)
7739     {
7740         static if (LOGSEMANTIC)
7741         {
7742             printf("ArrayExp::semantic('%s')\n", exp.toChars());
7743         }
7744         assert(!exp.type);
7745         Expression e = exp.op_overload(sc);
7746         if (e)
7747         {
7748             result = e;
7749             return;
7750         }
7751 
7752         if (isAggregate(exp.e1.type))
7753             exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
7754         else if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7755             exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
7756         else if (isIndexableNonAggregate(exp.e1.type))
7757             exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
7758         else
7759             exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
7760 
7761         result = ErrorExp.get();
7762     }
7763 
7764     override void visit(DotExp exp)
7765     {
7766         static if (LOGSEMANTIC)
7767         {
7768             printf("DotExp::semantic('%s')\n", exp.toChars());
7769             if (exp.type)
7770                 printf("\ttype = %s\n", exp.type.toChars());
7771         }
7772         exp.e1 = exp.e1.expressionSemantic(sc);
7773         exp.e2 = exp.e2.expressionSemantic(sc);
7774 
7775         if (exp.e1.op == TOK.type)
7776         {
7777             result = exp.e2;
7778             return;
7779         }
7780         if (exp.e2.op == TOK.type)
7781         {
7782             result = exp.e2;
7783             return;
7784         }
7785         if (exp.e2.op == TOK.template_)
7786         {
7787             auto td = (cast(TemplateExp)exp.e2).td;
7788             Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
7789             result = e.expressionSemantic(sc);
7790             return;
7791         }
7792         if (!exp.type || exp.e1.op == TOK.this_)
7793             exp.type = exp.e2.type;
7794         result = exp;
7795     }
7796 
7797     override void visit(CommaExp e)
7798     {
7799         if (e.type)
7800         {
7801             result = e;
7802             return;
7803         }
7804 
7805         // Allow `((a,b),(x,y))`
7806         if (e.allowCommaExp)
7807         {
7808             CommaExp.allow(e.e1);
7809             CommaExp.allow(e.e2);
7810         }
7811 
7812         if (Expression ex = binSemanticProp(e, sc))
7813         {
7814             result = ex;
7815             return;
7816         }
7817         e.e1 = e.e1.addDtorHook(sc);
7818 
7819         if (checkNonAssignmentArrayOp(e.e1))
7820             return setError();
7821 
7822         e.type = e.e2.type;
7823         if (e.type is Type.tvoid)
7824             discardValue(e.e1);
7825         else if (!e.allowCommaExp && !e.isGenerated)
7826             e.error("Using the result of a comma expression is not allowed");
7827         result = e;
7828     }
7829 
7830     override void visit(IntervalExp e)
7831     {
7832         static if (LOGSEMANTIC)
7833         {
7834             printf("IntervalExp::semantic('%s')\n", e.toChars());
7835         }
7836         if (e.type)
7837         {
7838             result = e;
7839             return;
7840         }
7841 
7842         Expression le = e.lwr;
7843         le = le.expressionSemantic(sc);
7844         le = resolveProperties(sc, le);
7845 
7846         Expression ue = e.upr;
7847         ue = ue.expressionSemantic(sc);
7848         ue = resolveProperties(sc, ue);
7849 
7850         if (le.op == TOK.error)
7851         {
7852             result = le;
7853             return;
7854         }
7855         if (ue.op == TOK.error)
7856         {
7857             result = ue;
7858             return;
7859         }
7860 
7861         e.lwr = le;
7862         e.upr = ue;
7863 
7864         e.type = Type.tvoid;
7865         result = e;
7866     }
7867 
7868     override void visit(DelegatePtrExp e)
7869     {
7870         static if (LOGSEMANTIC)
7871         {
7872             printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
7873         }
7874         if (!e.type)
7875         {
7876             unaSemantic(e, sc);
7877             e.e1 = resolveProperties(sc, e.e1);
7878 
7879             if (e.e1.op == TOK.error)
7880             {
7881                 result = e.e1;
7882                 return;
7883             }
7884             e.type = Type.tvoidptr;
7885         }
7886         result = e;
7887     }
7888 
7889     override void visit(DelegateFuncptrExp e)
7890     {
7891         static if (LOGSEMANTIC)
7892         {
7893             printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
7894         }
7895         if (!e.type)
7896         {
7897             unaSemantic(e, sc);
7898             e.e1 = resolveProperties(sc, e.e1);
7899             if (e.e1.op == TOK.error)
7900             {
7901                 result = e.e1;
7902                 return;
7903             }
7904             e.type = e.e1.type.nextOf().pointerTo();
7905         }
7906         result = e;
7907     }
7908 
7909     override void visit(IndexExp exp)
7910     {
7911         static if (LOGSEMANTIC)
7912         {
7913             printf("IndexExp::semantic('%s')\n", exp.toChars());
7914         }
7915         if (exp.type)
7916         {
7917             result = exp;
7918             return;
7919         }
7920 
7921         // operator overloading should be handled in ArrayExp already.
7922         if (!exp.e1.type)
7923             exp.e1 = exp.e1.expressionSemantic(sc);
7924         assert(exp.e1.type); // semantic() should already be run on it
7925         if (exp.e1.op == TOK.type && exp.e1.type.ty != Ttuple)
7926         {
7927             exp.e2 = exp.e2.expressionSemantic(sc);
7928             exp.e2 = resolveProperties(sc, exp.e2);
7929             Type nt;
7930             if (exp.e2.op == TOK.type)
7931                 nt = new TypeAArray(exp.e1.type, exp.e2.type);
7932             else
7933                 nt = new TypeSArray(exp.e1.type, exp.e2);
7934             Expression e = new TypeExp(exp.loc, nt);
7935             result = e.expressionSemantic(sc);
7936             return;
7937         }
7938         if (exp.e1.op == TOK.error)
7939         {
7940             result = exp.e1;
7941             return;
7942         }
7943         if (exp.e1.type.ty == Terror)
7944             return setError();
7945 
7946         // Note that unlike C we do not implement the int[ptr]
7947 
7948         Type t1b = exp.e1.type.toBasetype();
7949 
7950         if (t1b.ty == Tvector)
7951         {
7952             // Convert e1 to corresponding static array
7953             TypeVector tv1 = cast(TypeVector)t1b;
7954             t1b = tv1.basetype;
7955             t1b = t1b.castMod(tv1.mod);
7956             exp.e1.type = t1b;
7957         }
7958 
7959         /* Run semantic on e2
7960          */
7961         Scope* scx = sc;
7962         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7963         {
7964             // Create scope for 'length' variable
7965             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7966             sym.parent = sc.scopesym;
7967             sc = sc.push(sym);
7968         }
7969         if (t1b.ty == Ttuple)
7970             sc = sc.startCTFE();
7971         exp.e2 = exp.e2.expressionSemantic(sc);
7972         exp.e2 = resolveProperties(sc, exp.e2);
7973         if (t1b.ty == Ttuple)
7974             sc = sc.endCTFE();
7975         if (exp.e2.op == TOK.tuple)
7976         {
7977             TupleExp te = cast(TupleExp)exp.e2;
7978             if (te.exps && te.exps.dim == 1)
7979                 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
7980         }
7981         if (sc != scx)
7982             sc = sc.pop();
7983         if (exp.e2.type == Type.terror)
7984             return setError();
7985 
7986         if (checkNonAssignmentArrayOp(exp.e1))
7987             return setError();
7988 
7989         switch (t1b.ty)
7990         {
7991         case Tpointer:
7992             if ((cast(TypePointer)t1b).next.ty == Tfunction)
7993             {
7994                 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
7995                 return setError();
7996             }
7997             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
7998             if (exp.e2.type == Type.terror)
7999                 return setError();
8000             exp.e2 = exp.e2.optimize(WANTvalue);
8001             if (exp.e2.op == TOK.int64 && exp.e2.toInteger() == 0)
8002             {
8003             }
8004             else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
8005             {
8006                 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
8007                 return setError();
8008             }
8009             exp.type = (cast(TypeNext)t1b).next;
8010             break;
8011 
8012         case Tarray:
8013             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8014             if (exp.e2.type == Type.terror)
8015                 return setError();
8016             exp.type = (cast(TypeNext)t1b).next;
8017             break;
8018 
8019         case Tsarray:
8020             {
8021                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8022                 if (exp.e2.type == Type.terror)
8023                     return setError();
8024                 exp.type = t1b.nextOf();
8025                 break;
8026             }
8027         case Taarray:
8028             {
8029                 TypeAArray taa = cast(TypeAArray)t1b;
8030                 /* We can skip the implicit conversion if they differ only by
8031                  * constness
8032                  * https://issues.dlang.org/show_bug.cgi?id=2684
8033                  * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8034                  */
8035                 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8036                 {
8037                     exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8038                     if (exp.e2.type == Type.terror)
8039                         return setError();
8040                 }
8041 
8042                 semanticTypeInfo(sc, taa);
8043 
8044                 exp.type = taa.next;
8045                 break;
8046             }
8047         case Ttuple:
8048             {
8049                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8050                 if (exp.e2.type == Type.terror)
8051                     return setError();
8052 
8053                 exp.e2 = exp.e2.ctfeInterpret();
8054                 uinteger_t index = exp.e2.toUInteger();
8055 
8056                 TupleExp te;
8057                 TypeTuple tup;
8058                 size_t length;
8059                 if (exp.e1.op == TOK.tuple)
8060                 {
8061                     te = cast(TupleExp)exp.e1;
8062                     tup = null;
8063                     length = te.exps.dim;
8064                 }
8065                 else if (exp.e1.op == TOK.type)
8066                 {
8067                     te = null;
8068                     tup = cast(TypeTuple)t1b;
8069                     length = Parameter.dim(tup.arguments);
8070                 }
8071                 else
8072                     assert(0);
8073 
8074                 if (length <= index)
8075                 {
8076                     exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8077                     return setError();
8078                 }
8079                 Expression e;
8080                 if (exp.e1.op == TOK.tuple)
8081                 {
8082                     e = (*te.exps)[cast(size_t)index];
8083                     e = Expression.combine(te.e0, e);
8084                 }
8085                 else
8086                     e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8087                 result = e;
8088                 return;
8089             }
8090         default:
8091             exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8092             return setError();
8093         }
8094 
8095         // We might know $ now
8096         setLengthVarIfKnown(exp.lengthVar, t1b);
8097 
8098         if (t1b.ty == Tsarray || t1b.ty == Tarray)
8099         {
8100             Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8101             el = el.expressionSemantic(sc);
8102             el = el.optimize(WANTvalue);
8103             if (el.op == TOK.int64)
8104             {
8105                 exp.e2 = exp.e2.optimize(WANTvalue);
8106                 dinteger_t length = el.toInteger();
8107                 if (length)
8108                 {
8109                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8110                     exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2));
8111                 }
8112             }
8113         }
8114 
8115         result = exp;
8116     }
8117 
8118     override void visit(PostExp exp)
8119     {
8120         static if (LOGSEMANTIC)
8121         {
8122             printf("PostExp::semantic('%s')\n", exp.toChars());
8123         }
8124         if (exp.type)
8125         {
8126             result = exp;
8127             return;
8128         }
8129 
8130         if (Expression ex = binSemantic(exp, sc))
8131         {
8132             result = ex;
8133             return;
8134         }
8135         Expression e1x = resolveProperties(sc, exp.e1);
8136         if (e1x.op == TOK.error)
8137         {
8138             result = e1x;
8139             return;
8140         }
8141         exp.e1 = e1x;
8142 
8143         Expression e = exp.op_overload(sc);
8144         if (e)
8145         {
8146             result = e;
8147             return;
8148         }
8149 
8150         if (exp.e1.checkReadModifyWrite(exp.op))
8151             return setError();
8152 
8153         if (exp.e1.op == TOK.slice)
8154         {
8155             const(char)* s = exp.op == TOK.plusPlus ? "increment" : "decrement";
8156             exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8157             return setError();
8158         }
8159 
8160         exp.e1 = exp.e1.optimize(WANTvalue);
8161 
8162         Type t1 = exp.e1.type.toBasetype();
8163         if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == TOK.arrayLength)
8164         {
8165             /* Check for operator overloading,
8166              * but rewrite in terms of ++e instead of e++
8167              */
8168 
8169             /* If e1 is not trivial, take a reference to it
8170              */
8171             Expression de = null;
8172             if (exp.e1.op != TOK.variable && exp.e1.op != TOK.arrayLength)
8173             {
8174                 // ref v = e1;
8175                 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8176                 de = new DeclarationExp(exp.loc, v);
8177                 exp.e1 = new VarExp(exp.e1.loc, v);
8178             }
8179 
8180             /* Rewrite as:
8181              * auto tmp = e1; ++e1; tmp
8182              */
8183             auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8184             Expression ea = new DeclarationExp(exp.loc, tmp);
8185 
8186             Expression eb = exp.e1.syntaxCopy();
8187             eb = new PreExp(exp.op == TOK.plusPlus ? TOK.prePlusPlus : TOK.preMinusMinus, exp.loc, eb);
8188 
8189             Expression ec = new VarExp(exp.loc, tmp);
8190 
8191             // Combine de,ea,eb,ec
8192             if (de)
8193                 ea = new CommaExp(exp.loc, de, ea);
8194             e = new CommaExp(exp.loc, ea, eb);
8195             e = new CommaExp(exp.loc, e, ec);
8196             e = e.expressionSemantic(sc);
8197             result = e;
8198             return;
8199         }
8200 
8201         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8202 
8203         e = exp;
8204         if (exp.e1.checkScalar() ||
8205             exp.e1.checkSharedAccess(sc))
8206             return setError();
8207         if (exp.e1.checkNoBool())
8208             return setError();
8209 
8210         if (exp.e1.type.ty == Tpointer)
8211             e = scaleFactor(exp, sc);
8212         else
8213             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8214         e.type = exp.e1.type;
8215         result = e;
8216     }
8217 
8218     override void visit(PreExp exp)
8219     {
8220         Expression e = exp.op_overload(sc);
8221         // printf("PreExp::semantic('%s')\n", toChars());
8222         if (e)
8223         {
8224             result = e;
8225             return;
8226         }
8227 
8228         // Rewrite as e1+=1 or e1-=1
8229         if (exp.op == TOK.prePlusPlus)
8230             e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8231         else
8232             e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8233         result = e.expressionSemantic(sc);
8234     }
8235 
8236     /*
8237      * Get the expression initializer for a specific struct
8238      *
8239      * Params:
8240      *  sd = the struct for which the expression initializer is needed
8241      *  loc = the location of the initializer
8242      *  sc = the scope where the expression is located
8243      *  t = the type of the expression
8244      *
8245      * Returns:
8246      *  The expression initializer or error expression if any errors occured
8247      */
8248     private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8249     {
8250         if (sd.zeroInit && !sd.isNested())
8251         {
8252             // https://issues.dlang.org/show_bug.cgi?id=14606
8253             // Always use BlitExp for the special expression: (struct = 0)
8254             return IntegerExp.literal!0;
8255         }
8256 
8257         if (sd.isNested())
8258         {
8259             auto sle = new StructLiteralExp(loc, sd, null, t);
8260             if (!sd.fill(loc, sle.elements, true))
8261                 return ErrorExp.get();
8262             if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
8263                 return ErrorExp.get();
8264 
8265             sle.type = t;
8266             return sle;
8267         }
8268 
8269         return t.defaultInit(loc);
8270     }
8271 
8272     override void visit(AssignExp exp)
8273     {
8274         static if (LOGSEMANTIC)
8275         {
8276             printf("AssignExp::semantic('%s')\n", exp.toChars());
8277         }
8278         //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, Token.toChars(exp.e1.op));
8279         //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, Token.toChars(exp.e2.op));
8280 
8281         void setResult(Expression e, int line = __LINE__)
8282         {
8283             //printf("line %d\n", line);
8284             result = e;
8285         }
8286 
8287         if (exp.type)
8288         {
8289             return setResult(exp);
8290         }
8291 
8292         Expression e1old = exp.e1;
8293 
8294         if (auto e2comma = exp.e2.isCommaExp())
8295         {
8296             if (!e2comma.isGenerated)
8297                 exp.error("Using the result of a comma expression is not allowed");
8298 
8299             /* Rewrite to get rid of the comma from rvalue
8300              *   e1=(e0,e2) => e0,(e1=e2)
8301              */
8302             Expression e0;
8303             exp.e2 = Expression.extractLast(e2comma, e0);
8304             Expression e = Expression.combine(e0, exp);
8305             return setResult(e.expressionSemantic(sc));
8306         }
8307 
8308         /* Look for operator overloading of a[arguments] = e2.
8309          * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8310          * converted to unary operator overloading already.
8311          */
8312         if (auto ae = exp.e1.isArrayExp())
8313         {
8314             Expression res;
8315 
8316             ae.e1 = ae.e1.expressionSemantic(sc);
8317             ae.e1 = resolveProperties(sc, ae.e1);
8318             Expression ae1old = ae.e1;
8319 
8320             const(bool) maybeSlice =
8321                 (ae.arguments.dim == 0 ||
8322                  ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOK.interval);
8323 
8324             IntervalExp ie = null;
8325             if (maybeSlice && ae.arguments.dim)
8326             {
8327                 assert((*ae.arguments)[0].op == TOK.interval);
8328                 ie = cast(IntervalExp)(*ae.arguments)[0];
8329             }
8330             while (true)
8331             {
8332                 if (ae.e1.op == TOK.error)
8333                     return setResult(ae.e1);
8334 
8335                 Expression e0 = null;
8336                 Expression ae1save = ae.e1;
8337                 ae.lengthVar = null;
8338 
8339                 Type t1b = ae.e1.type.toBasetype();
8340                 AggregateDeclaration ad = isAggregate(t1b);
8341                 if (!ad)
8342                     break;
8343                 if (search_function(ad, Id.indexass))
8344                 {
8345                     // Deal with $
8346                     res = resolveOpDollar(sc, ae, &e0);
8347                     if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8348                         goto Lfallback;
8349                     if (res.op == TOK.error)
8350                         return setResult(res);
8351 
8352                     res = exp.e2.expressionSemantic(sc);
8353                     if (res.op == TOK.error)
8354                         return setResult(res);
8355                     exp.e2 = res;
8356 
8357                     /* Rewrite (a[arguments] = e2) as:
8358                      *      a.opIndexAssign(e2, arguments)
8359                      */
8360                     Expressions* a = ae.arguments.copy();
8361                     a.insert(0, exp.e2);
8362                     res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8363                     res = new CallExp(exp.loc, res, a);
8364                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8365                         res = res.trySemantic(sc);
8366                     else
8367                         res = res.expressionSemantic(sc);
8368                     if (res)
8369                         return setResult(Expression.combine(e0, res));
8370                 }
8371 
8372             Lfallback:
8373                 if (maybeSlice && search_function(ad, Id.sliceass))
8374                 {
8375                     // Deal with $
8376                     res = resolveOpDollar(sc, ae, ie, &e0);
8377                     if (res.op == TOK.error)
8378                         return setResult(res);
8379 
8380                     res = exp.e2.expressionSemantic(sc);
8381                     if (res.op == TOK.error)
8382                         return setResult(res);
8383 
8384                     exp.e2 = res;
8385 
8386                     /* Rewrite (a[i..j] = e2) as:
8387                      *      a.opSliceAssign(e2, i, j)
8388                      */
8389                     auto a = new Expressions();
8390                     a.push(exp.e2);
8391                     if (ie)
8392                     {
8393                         a.push(ie.lwr);
8394                         a.push(ie.upr);
8395                     }
8396                     res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8397                     res = new CallExp(exp.loc, res, a);
8398                     res = res.expressionSemantic(sc);
8399                     return setResult(Expression.combine(e0, res));
8400                 }
8401 
8402                 // No operator overloading member function found yet, but
8403                 // there might be an alias this to try.
8404                 if (ad.aliasthis && t1b != ae.att1)
8405                 {
8406                     if (!ae.att1 && t1b.checkAliasThisRec())
8407                         ae.att1 = t1b;
8408 
8409                     /* Rewrite (a[arguments] op e2) as:
8410                      *      a.aliasthis[arguments] op e2
8411                      */
8412                     ae.e1 = resolveAliasThis(sc, ae1save, true);
8413                     if (ae.e1)
8414                         continue;
8415                 }
8416                 break;
8417             }
8418             ae.e1 = ae1old; // recovery
8419             ae.lengthVar = null;
8420         }
8421 
8422         /* Run this.e1 semantic.
8423          */
8424         {
8425             Expression e1x = exp.e1;
8426 
8427             /* With UFCS, e.f = value
8428              * Could mean:
8429              *      .f(e, value)
8430              * or:
8431              *      .f(e) = value
8432              */
8433             if (auto dti = e1x.isDotTemplateInstanceExp())
8434             {
8435                 Expression e = dti.semanticY(sc, 1);
8436                 if (!e)
8437                 {
8438                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8439                 }
8440 
8441                 e1x = e;
8442             }
8443             else if (auto die = e1x.isDotIdExp())
8444             {
8445                 Expression e = die.semanticY(sc, 1);
8446                 if (e && isDotOpDispatch(e))
8447                 {
8448                     /* https://issues.dlang.org/show_bug.cgi?id=19687
8449                      *
8450                      * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8451                      * but that call is done with gagged errors. That is the only time when
8452                      * semantic gets ran on e2, that is why the error never gets to be printed.
8453                      * In order to make sure that UFCS is tried with correct parameters, e2
8454                      * needs to have semantic ran on it.
8455                      */
8456                     exp.e2 = exp.e2.expressionSemantic(sc);
8457                     uint errors = global.startGagging();
8458                     e = resolvePropertiesX(sc, e, exp.e2);
8459                     if (global.endGagging(errors))
8460                         e = null; /* fall down to UFCS */
8461                     else
8462                         return setResult(e);
8463                 }
8464                 if (!e)
8465                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8466                 e1x = e;
8467             }
8468             else
8469             {
8470                 if (auto se = e1x.isSliceExp())
8471                     se.arrayop = true;
8472 
8473                 e1x = e1x.expressionSemantic(sc);
8474             }
8475 
8476             /* We have f = value.
8477              * Could mean:
8478              *      f(value)
8479              * or:
8480              *      f() = value
8481              */
8482             if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8483                 return setResult(e);
8484 
8485             if (e1x.checkRightThis(sc))
8486             {
8487                 return setError();
8488             }
8489             exp.e1 = e1x;
8490             assert(exp.e1.type);
8491         }
8492         Type t1 = exp.e1.type.toBasetype();
8493 
8494         /* Run this.e2 semantic.
8495          * Different from other binary expressions, the analysis of e2
8496          * depends on the result of e1 in assignments.
8497          */
8498         {
8499             Expression e2x = inferType(exp.e2, t1.baseElemOf());
8500             e2x = e2x.expressionSemantic(sc);
8501             e2x = resolveProperties(sc, e2x);
8502             if (e2x.op == TOK.type)
8503                 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8504             if (e2x.op == TOK.error)
8505                 return setResult(e2x);
8506             if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8507                 return setError();
8508             exp.e2 = e2x;
8509         }
8510 
8511         /* Rewrite tuple assignment as a tuple of assignments.
8512          */
8513         {
8514             Expression e2x = exp.e2;
8515 
8516         Ltupleassign:
8517             if (exp.e1.op == TOK.tuple && e2x.op == TOK.tuple)
8518             {
8519                 TupleExp tup1 = cast(TupleExp)exp.e1;
8520                 TupleExp tup2 = cast(TupleExp)e2x;
8521                 size_t dim = tup1.exps.dim;
8522                 Expression e = null;
8523                 if (dim != tup2.exps.dim)
8524                 {
8525                     exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
8526                     return setError();
8527                 }
8528                 if (dim == 0)
8529                 {
8530                     e = IntegerExp.literal!0;
8531                     e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8532                     e = Expression.combine(tup1.e0, tup2.e0, e);
8533                 }
8534                 else
8535                 {
8536                     auto exps = new Expressions(dim);
8537                     for (size_t i = 0; i < dim; i++)
8538                     {
8539                         Expression ex1 = (*tup1.exps)[i];
8540                         Expression ex2 = (*tup2.exps)[i];
8541                         (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8542                     }
8543                     e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8544                 }
8545                 return setResult(e.expressionSemantic(sc));
8546             }
8547 
8548             /* Look for form: e1 = e2.aliasthis.
8549              */
8550             if (exp.e1.op == TOK.tuple)
8551             {
8552                 TupleDeclaration td = isAliasThisTuple(e2x);
8553                 if (!td)
8554                     goto Lnomatch;
8555 
8556                 assert(exp.e1.type.ty == Ttuple);
8557                 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8558 
8559                 Expression e0;
8560                 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8561 
8562                 auto iexps = new Expressions();
8563                 iexps.push(ev);
8564                 for (size_t u = 0; u < iexps.dim; u++)
8565                 {
8566                 Lexpand:
8567                     Expression e = (*iexps)[u];
8568 
8569                     Parameter arg = Parameter.getNth(tt.arguments, u);
8570                     //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
8571                     //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars());
8572                     //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
8573 
8574                     if (!arg || !e.type.implicitConvTo(arg.type))
8575                     {
8576                         // expand initializer to tuple
8577                         if (expandAliasThisTuples(iexps, u) != -1)
8578                         {
8579                             if (iexps.dim <= u)
8580                                 break;
8581                             goto Lexpand;
8582                         }
8583                         goto Lnomatch;
8584                     }
8585                 }
8586                 e2x = new TupleExp(e2x.loc, e0, iexps);
8587                 e2x = e2x.expressionSemantic(sc);
8588                 if (e2x.op == TOK.error)
8589                 {
8590                     result = e2x;
8591                     return;
8592                 }
8593                 // Do not need to overwrite this.e2
8594                 goto Ltupleassign;
8595             }
8596         Lnomatch:
8597         }
8598 
8599         if (exp.op == TOK.assign)  // skip TOK.blit and TOK.construct, which are initializations
8600             exp.e1.checkSharedAccess(sc);
8601 
8602         /* Inside constructor, if this is the first assignment of object field,
8603          * rewrite this to initializing the field.
8604          */
8605         if (exp.op == TOK.assign
8606             && exp.e1.checkModifiable(sc) == Modifiable.initialization)
8607         {
8608             //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
8609             auto t = exp.type;
8610             exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
8611             exp.type = t;
8612 
8613             // @@@DEPRECATED_2020-06@@@
8614             // When removing, alter `checkModifiable` to return the correct value.
8615             if (sc.func.isStaticCtorDeclaration() && !sc.func.isSharedStaticCtorDeclaration() &&
8616                 exp.e1.type.isImmutable())
8617             {
8618                 deprecation(exp.loc, "initialization of `immutable` variable from `static this` is deprecated.");
8619                 deprecationSupplemental(exp.loc, "Use `shared static this` instead.");
8620             }
8621 
8622             // https://issues.dlang.org/show_bug.cgi?id=13515
8623             // set Index::modifiable flag for complex AA element initialization
8624             if (auto ie1 = exp.e1.isIndexExp())
8625             {
8626                 Expression e1x = ie1.markSettingAAElem();
8627                 if (e1x.op == TOK.error)
8628                 {
8629                     result = e1x;
8630                     return;
8631                 }
8632             }
8633         }
8634         else if (exp.op == TOK.construct && exp.e1.op == TOK.variable &&
8635                  (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
8636         {
8637             exp.memset = MemorySet.referenceInit;
8638         }
8639 
8640         /* If it is an assignment from a 'foreign' type,
8641          * check for operator overloading.
8642          */
8643         if (exp.memset == MemorySet.referenceInit)
8644         {
8645             // If this is an initialization of a reference,
8646             // do nothing
8647         }
8648         else if (t1.ty == Tstruct)
8649         {
8650             auto e1x = exp.e1;
8651             auto e2x = exp.e2;
8652             auto sd = (cast(TypeStruct)t1).sym;
8653 
8654             if (exp.op == TOK.construct)
8655             {
8656                 Type t2 = e2x.type.toBasetype();
8657                 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
8658                 {
8659                     sd.size(exp.loc);
8660                     if (sd.sizeok != Sizeok.done)
8661                         return setError();
8662                     if (!sd.ctor)
8663                         sd.ctor = sd.searchCtor();
8664 
8665                     // https://issues.dlang.org/show_bug.cgi?id=15661
8666                     // Look for the form from last of comma chain.
8667                     auto e2y = lastComma(e2x);
8668 
8669                     CallExp ce = (e2y.op == TOK.call) ? cast(CallExp)e2y : null;
8670                     DotVarExp dve = (ce && ce.e1.op == TOK.dotVariable)
8671                         ? cast(DotVarExp)ce.e1 : null;
8672                     if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
8673                         // https://issues.dlang.org/show_bug.cgi?id=19389
8674                         dve.e1.op != TOK.dotVariable &&
8675                         e2y.type.implicitConvTo(t1))
8676                     {
8677                         /* Look for form of constructor call which is:
8678                          *    __ctmp.ctor(arguments...)
8679                          */
8680 
8681                         /* Before calling the constructor, initialize
8682                          * variable with a bit copy of the default
8683                          * initializer
8684                          */
8685                         Expression einit = getInitExp(sd, exp.loc, sc, t1);
8686                         if (einit.op == TOK.error)
8687                         {
8688                             result = einit;
8689                             return;
8690                         }
8691 
8692                         auto ae = new BlitExp(exp.loc, exp.e1, einit);
8693                         ae.type = e1x.type;
8694 
8695                         /* Replace __ctmp being constructed with e1.
8696                          * We need to copy constructor call expression,
8697                          * because it may be used in other place.
8698                          */
8699                         auto dvx = cast(DotVarExp)dve.copy();
8700                         dvx.e1 = e1x;
8701                         auto cx = cast(CallExp)ce.copy();
8702                         cx.e1 = dvx;
8703                         if (checkConstructorEscape(sc, cx, false))
8704                             return setError();
8705 
8706                         Expression e0;
8707                         Expression.extractLast(e2x, e0);
8708 
8709                         auto e = Expression.combine(e0, ae, cx);
8710                         e = e.expressionSemantic(sc);
8711                         result = e;
8712                         return;
8713                     }
8714                     if (sd.postblit || sd.hasCopyCtor)
8715                     {
8716                         /* We have a copy constructor for this
8717                          */
8718                         if (e2x.op == TOK.question)
8719                         {
8720                             /* Rewrite as:
8721                              *  a ? e1 = b : e1 = c;
8722                              */
8723                             CondExp econd = cast(CondExp)e2x;
8724                             Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
8725                             Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2);
8726                             Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
8727                             result = e.expressionSemantic(sc);
8728                             return;
8729                         }
8730 
8731                         if (e2x.isLvalue())
8732                         {
8733                             if (sd.hasCopyCtor)
8734                             {
8735                                 /* Rewrite as:
8736                                  * e1 = init, e1.copyCtor(e2);
8737                                  */
8738                                 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
8739                                 einit.type = e1x.type;
8740 
8741                                 Expression e;
8742                                 e = new DotIdExp(exp.loc, e1x, Id.ctor);
8743                                 e = new CallExp(exp.loc, e, e2x);
8744                                 e = new CommaExp(exp.loc, einit, e);
8745 
8746                                 //printf("e: %s\n", e.toChars());
8747 
8748                                 result = e.expressionSemantic(sc);
8749                                 return;
8750                             }
8751                             else
8752                             {
8753                                 if (!e2x.type.implicitConvTo(e1x.type))
8754                                 {
8755                                     exp.error("conversion error from `%s` to `%s`",
8756                                         e2x.type.toChars(), e1x.type.toChars());
8757                                     return setError();
8758                                 }
8759 
8760                                 /* Rewrite as:
8761                                  *  (e1 = e2).postblit();
8762                                  *
8763                                  * Blit assignment e1 = e2 returns a reference to the original e1,
8764                                  * then call the postblit on it.
8765                                  */
8766                                 Expression e = e1x.copy();
8767                                 e.type = e.type.mutableOf();
8768                                 if (e.type.isShared && !sd.type.isShared)
8769                                     e.type = e.type.unSharedOf();
8770                                 e = new BlitExp(exp.loc, e, e2x);
8771                                 e = new DotVarExp(exp.loc, e, sd.postblit, false);
8772                                 e = new CallExp(exp.loc, e);
8773                                 result = e.expressionSemantic(sc);
8774                                 return;
8775                             }
8776                         }
8777                         else
8778                         {
8779                             /* The struct value returned from the function is transferred
8780                              * so should not call the destructor on it.
8781                              */
8782                             e2x = valueNoDtor(e2x);
8783                         }
8784                     }
8785 
8786                     // https://issues.dlang.org/show_bug.cgi?id=19251
8787                     // if e2 cannot be converted to e1.type, maybe there is an alias this
8788                     if (!e2x.implicitConvTo(t1))
8789                     {
8790                         AggregateDeclaration ad2 = isAggregate(e2x.type);
8791                         if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2))
8792                         {
8793                             if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8794                             exp.att2 = exp.e2.type;
8795                             /* Rewrite (e1 op e2) as:
8796                              *      (e1 op e2.aliasthis)
8797                              */
8798                             exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8799                             result = exp.expressionSemantic(sc);
8800                             return;
8801                         }
8802                     }
8803                 }
8804                 else if (!e2x.implicitConvTo(t1))
8805                 {
8806                     sd.size(exp.loc);
8807                     if (sd.sizeok != Sizeok.done)
8808                         return setError();
8809                     if (!sd.ctor)
8810                         sd.ctor = sd.searchCtor();
8811 
8812                     if (sd.ctor)
8813                     {
8814                         /* Look for implicit constructor call
8815                          * Rewrite as:
8816                          *  e1 = init, e1.ctor(e2)
8817                          */
8818 
8819                         /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
8820                          * Using `new` to initialize a struct object is a common mistake, but
8821                          * the error message from the compiler is not very helpful in that
8822                          * case. If exp.e2 is a NewExp and the type of new is the same as
8823                          * the type as exp.e1 (struct in this case), then we know for sure
8824                          * that the user wants to instantiate a struct. This is done to avoid
8825                          * issuing an error when the user actually wants to call a constructor
8826                          * which receives a class object.
8827                          *
8828                          * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
8829                          * which receives an instance of a Foo2 class
8830                          */
8831                         if (exp.e2.op == TOK.new_)
8832                         {
8833                             auto newExp = cast(NewExp)(exp.e2);
8834                             if (newExp.newtype && newExp.newtype == t1)
8835                             {
8836                                 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
8837                                       newExp.toChars(), newExp.type.toChars(), t1.toChars());
8838                                 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
8839                                 return setError();
8840                             }
8841                         }
8842 
8843                         Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
8844                         einit.type = e1x.type;
8845 
8846                         Expression e;
8847                         e = new DotIdExp(exp.loc, e1x, Id.ctor);
8848                         e = new CallExp(exp.loc, e, e2x);
8849                         e = new CommaExp(exp.loc, einit, e);
8850                         e = e.expressionSemantic(sc);
8851                         result = e;
8852                         return;
8853                     }
8854                     if (search_function(sd, Id.call))
8855                     {
8856                         /* Look for static opCall
8857                          * https://issues.dlang.org/show_bug.cgi?id=2702
8858                          * Rewrite as:
8859                          *  e1 = typeof(e1).opCall(arguments)
8860                          */
8861                         e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
8862                         e2x = new CallExp(exp.loc, e2x, exp.e2);
8863 
8864                         e2x = e2x.expressionSemantic(sc);
8865                         e2x = resolveProperties(sc, e2x);
8866                         if (e2x.op == TOK.error)
8867                         {
8868                             result = e2x;
8869                             return;
8870                         }
8871                         if (e2x.checkValue() || e2x.checkSharedAccess(sc))
8872                             return setError();
8873                     }
8874                 }
8875                 else // https://issues.dlang.org/show_bug.cgi?id=11355
8876                 {
8877                     AggregateDeclaration ad2 = isAggregate(e2x.type);
8878                     if (ad2 && ad2.aliasthis && !(exp.att2 && e2x.type == exp.att2))
8879                     {
8880                         if (!exp.att2 && exp.e2.type.checkAliasThisRec())
8881                             exp.att2 = exp.e2.type;
8882                         /* Rewrite (e1 op e2) as:
8883                          *      (e1 op e2.aliasthis)
8884                          */
8885                         exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
8886                         result = exp.expressionSemantic(sc);
8887                         return;
8888                     }
8889                 }
8890             }
8891             else if (exp.op == TOK.assign)
8892             {
8893                 if (e1x.op == TOK.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
8894                 {
8895                     /*
8896                      * Rewrite:
8897                      *      aa[key] = e2;
8898                      * as:
8899                      *      ref __aatmp = aa;
8900                      *      ref __aakey = key;
8901                      *      ref __aaval = e2;
8902                      *      (__aakey in __aatmp
8903                      *          ? __aatmp[__aakey].opAssign(__aaval)
8904                      *          : ConstructExp(__aatmp[__aakey], __aaval));
8905                      */
8906                     // ensure we keep the expr modifiable
8907                     Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
8908                     if (esetting.op == TOK.error)
8909                     {
8910                         result = esetting;
8911                         return;
8912                     }
8913                     assert(esetting.op == TOK.index);
8914                     IndexExp ie = cast(IndexExp) esetting;
8915                     Type t2 = e2x.type.toBasetype();
8916 
8917                     Expression e0 = null;
8918                     Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
8919                     Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
8920                     Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
8921 
8922                     AssignExp ae = cast(AssignExp)exp.copy();
8923                     ae.e1 = new IndexExp(exp.loc, ea, ek);
8924                     ae.e1 = ae.e1.expressionSemantic(sc);
8925                     ae.e1 = ae.e1.optimize(WANTvalue);
8926                     ae.e2 = ev;
8927                     Expression e = ae.op_overload(sc);
8928                     if (e)
8929                     {
8930                         Expression ey = null;
8931                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
8932                         {
8933                             ey = ev;
8934                         }
8935                         else if (!ev.implicitConvTo(ie.type) && sd.ctor)
8936                         {
8937                             // Look for implicit constructor call
8938                             // Rewrite as S().ctor(e2)
8939                             ey = new StructLiteralExp(exp.loc, sd, null);
8940                             ey = new DotIdExp(exp.loc, ey, Id.ctor);
8941                             ey = new CallExp(exp.loc, ey, ev);
8942                             ey = ey.trySemantic(sc);
8943                         }
8944                         if (ey)
8945                         {
8946                             Expression ex;
8947                             ex = new IndexExp(exp.loc, ea, ek);
8948                             ex = ex.expressionSemantic(sc);
8949                             ex = ex.optimize(WANTvalue);
8950                             ex = ex.modifiableLvalue(sc, ex); // allocate new slot
8951 
8952                             ey = new ConstructExp(exp.loc, ex, ey);
8953                             ey = ey.expressionSemantic(sc);
8954                             if (ey.op == TOK.error)
8955                             {
8956                                 result = ey;
8957                                 return;
8958                             }
8959                             ex = e;
8960 
8961                             // https://issues.dlang.org/show_bug.cgi?id=14144
8962                             // The whole expression should have the common type
8963                             // of opAssign() return and assigned AA entry.
8964                             // Even if there's no common type, expression should be typed as void.
8965                             Type t = null;
8966                             if (!typeMerge(sc, TOK.question, &t, &ex, &ey))
8967                             {
8968                                 ex = new CastExp(ex.loc, ex, Type.tvoid);
8969                                 ey = new CastExp(ey.loc, ey, Type.tvoid);
8970                             }
8971                             e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
8972                         }
8973                         e = Expression.combine(e0, e);
8974                         e = e.expressionSemantic(sc);
8975                         result = e;
8976                         return;
8977                     }
8978                 }
8979                 else
8980                 {
8981                     Expression e = exp.op_overload(sc);
8982                     if (e)
8983                     {
8984                         result = e;
8985                         return;
8986                     }
8987                 }
8988             }
8989             else
8990                 assert(exp.op == TOK.blit);
8991 
8992             exp.e1 = e1x;
8993             exp.e2 = e2x;
8994         }
8995         else if (t1.ty == Tclass)
8996         {
8997             // Disallow assignment operator overloads for same type
8998             if (exp.op == TOK.assign && !exp.e2.implicitConvTo(exp.e1.type))
8999             {
9000                 Expression e = exp.op_overload(sc);
9001                 if (e)
9002                 {
9003                     result = e;
9004                     return;
9005                 }
9006             }
9007         }
9008         else if (t1.ty == Tsarray)
9009         {
9010             // SliceExp cannot have static array type without context inference.
9011             assert(exp.e1.op != TOK.slice);
9012             Expression e1x = exp.e1;
9013             Expression e2x = exp.e2;
9014 
9015             if (e2x.implicitConvTo(e1x.type))
9016             {
9017                 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()))
9018                 {
9019                     if (e1x.checkPostblit(sc, t1))
9020                         return setError();
9021                 }
9022 
9023                 // e2 matches to t1 because of the implicit length match, so
9024                 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9025                 {
9026                     // convert e1 to e1[]
9027                     // e.g. e1[] = a[] + b[];
9028                     auto sle = new SliceExp(e1x.loc, e1x, null, null);
9029                     sle.arrayop = true;
9030                     e1x = sle.expressionSemantic(sc);
9031                 }
9032                 else
9033                 {
9034                     // convert e2 to t1 later
9035                     // e.g. e1 = [1, 2, 3];
9036                 }
9037             }
9038             else
9039             {
9040                 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9041                 {
9042                     uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9043                     uinteger_t dim2 = dim1;
9044                     if (auto ale = e2x.isArrayLiteralExp())
9045                     {
9046                         dim2 = ale.elements ? ale.elements.dim : 0;
9047                     }
9048                     else if (auto se = e2x.isSliceExp())
9049                     {
9050                         Type tx = toStaticArrayType(se);
9051                         if (tx)
9052                             dim2 = (cast(TypeSArray)tx).dim.toInteger();
9053                     }
9054                     if (dim1 != dim2)
9055                     {
9056                         exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9057                         return setError();
9058                     }
9059                 }
9060 
9061                 // May be block or element-wise assignment, so
9062                 // convert e1 to e1[]
9063                 if (exp.op != TOK.assign)
9064                 {
9065                     // If multidimensional static array, treat as one large array
9066                     //
9067                     // Find the appropriate array type depending on the assignment, e.g.
9068                     // int[3] = int => int[3]
9069                     // int[3][2] = int => int[6]
9070                     // int[3][2] = int[] => int[3][2]
9071                     // int[3][2][4] + int => int[24]
9072                     // int[3][2][4] + int[] => int[3][8]
9073                     ulong dim = t1.isTypeSArray().dim.toUInteger();
9074                     auto type = t1.nextOf();
9075 
9076                     for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9077                     {
9078                         import core.checkedint : mulu;
9079 
9080                         // Accumulate skipped dimensions
9081                         bool overflow = false;
9082                         dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9083                         if (overflow || dim >= uint.max)
9084                         {
9085                             // dym exceeds maximum array size
9086                             exp.error("static array `%s` size overflowed to %llu",
9087                                         e1x.type.toChars(), cast(ulong) dim);
9088                             return setError();
9089                         }
9090 
9091                         // Move to the element type
9092                         type = tsa.nextOf().toBasetype();
9093 
9094                         // Rewrite ex1 as a static array if a matching type was found
9095                         if (e2x.implicitConvTo(type) > MATCH.nomatch)
9096                         {
9097                             e1x.type = type.sarrayOf(dim);
9098                             break;
9099                         }
9100                     }
9101                 }
9102                 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9103                 sle.arrayop = true;
9104                 e1x = sle.expressionSemantic(sc);
9105             }
9106             if (e1x.op == TOK.error)
9107                 return setResult(e1x);
9108             if (e2x.op == TOK.error)
9109                 return setResult(e2x);
9110 
9111             exp.e1 = e1x;
9112             exp.e2 = e2x;
9113             t1 = e1x.type.toBasetype();
9114         }
9115         /* Check the mutability of e1.
9116          */
9117         if (auto ale = exp.e1.isArrayLengthExp())
9118         {
9119             // e1 is not an lvalue, but we let code generator handle it
9120 
9121             auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9122             if (ale1x.op == TOK.error)
9123                 return setResult(ale1x);
9124             ale.e1 = ale1x;
9125 
9126             Type tn = ale.e1.type.toBasetype().nextOf();
9127             checkDefCtor(ale.loc, tn);
9128 
9129             Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9130             if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9131                 return setError();
9132 
9133             // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9134             Expression id = new IdentifierExp(ale.loc, Id.empty);
9135             id = new DotIdExp(ale.loc, id, Id.object);
9136             auto tiargs = new Objects();
9137             tiargs.push(ale.e1.type);
9138             id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9139             id = new DotIdExp(ale.loc, id, hook);
9140             id = id.expressionSemantic(sc);
9141 
9142             auto arguments = new Expressions();
9143             arguments.reserve(5);
9144             if (global.params.tracegc)
9145             {
9146                 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9147                 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9148                 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9149                 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9150             }
9151             arguments.push(ale.e1);
9152             arguments.push(exp.e2);
9153 
9154             Expression ce = new CallExp(ale.loc, id, arguments);
9155             auto res = ce.expressionSemantic(sc);
9156             // if (global.params.verbose)
9157             //     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
9158             return setResult(res);
9159         }
9160         else if (auto se = exp.e1.isSliceExp())
9161         {
9162             Type tn = se.type.nextOf();
9163             const fun = sc.func;
9164             if (exp.op == TOK.assign && !tn.isMutable() &&
9165                 // allow modifiation in module ctor, see
9166                 // https://issues.dlang.org/show_bug.cgi?id=9884
9167                 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9168             {
9169                 exp.error("slice `%s` is not mutable", se.toChars());
9170                 return setError();
9171             }
9172 
9173             if (exp.op == TOK.assign && !tn.baseElemOf().isAssignable())
9174             {
9175                 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9176                     exp.e1.toChars(), tn.baseElemOf().toChars());
9177                 result = ErrorExp.get();
9178                 return;
9179             }
9180 
9181             // For conditional operator, both branches need conversion.
9182             while (se.e1.op == TOK.slice)
9183                 se = cast(SliceExp)se.e1;
9184             if (se.e1.op == TOK.question && se.e1.type.toBasetype().ty == Tsarray)
9185             {
9186                 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9187                 if (se.e1.op == TOK.error)
9188                     return setResult(se.e1);
9189             }
9190         }
9191         else
9192         {
9193             if (t1.ty == Tsarray && exp.op == TOK.assign)
9194             {
9195                 Type tn = exp.e1.type.nextOf();
9196                 if (tn && !tn.baseElemOf().isAssignable())
9197                 {
9198                     exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9199                         exp.e1.toChars(), tn.baseElemOf().toChars());
9200                     result = ErrorExp.get();
9201                     return;
9202                 }
9203             }
9204 
9205             Expression e1x = exp.e1;
9206 
9207             // Try to do a decent error message with the expression
9208             // before it got constant folded
9209 
9210             if (e1x.op != TOK.variable)
9211                 e1x = e1x.optimize(WANTvalue);
9212 
9213             if (exp.op == TOK.assign)
9214                 e1x = e1x.modifiableLvalue(sc, e1old);
9215 
9216             if (checkIfIsStructLiteralDotExpr(e1x))
9217                 return setError();
9218 
9219             if (e1x.op == TOK.error)
9220             {
9221                 result = e1x;
9222                 return;
9223             }
9224             exp.e1 = e1x;
9225         }
9226 
9227         /* Tweak e2 based on the type of e1.
9228          */
9229         Expression e2x = exp.e2;
9230         Type t2 = e2x.type.toBasetype();
9231 
9232         // If it is a array, get the element type. Note that it may be
9233         // multi-dimensional.
9234         Type telem = t1;
9235         while (telem.ty == Tarray)
9236             telem = telem.nextOf();
9237 
9238         if (exp.e1.op == TOK.slice && t1.nextOf() &&
9239             (telem.ty != Tvoid || e2x.op == TOK.null_) &&
9240             e2x.implicitConvTo(t1.nextOf()))
9241         {
9242             // Check for block assignment. If it is of type void[], void[][], etc,
9243             // '= null' is the only allowable block assignment (Bug 7493)
9244             exp.memset = MemorySet.blockAssign;    // make it easy for back end to tell what this is
9245             e2x = e2x.implicitCastTo(sc, t1.nextOf());
9246             if (exp.op != TOK.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9247                 return setError();
9248         }
9249         else if (exp.e1.op == TOK.slice &&
9250                  (t2.ty == Tarray || t2.ty == Tsarray) &&
9251                  t2.nextOf().implicitConvTo(t1.nextOf()))
9252         {
9253             // Check element-wise assignment.
9254 
9255             /* If assigned elements number is known at compile time,
9256              * check the mismatch.
9257              */
9258             SliceExp se1 = cast(SliceExp)exp.e1;
9259             TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9260             TypeSArray tsa2 = null;
9261             if (auto ale = e2x.isArrayLiteralExp())
9262                 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
9263             else if (auto se = e2x.isSliceExp())
9264                 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9265             else
9266                 tsa2 = t2.isTypeSArray();
9267             if (tsa1 && tsa2)
9268             {
9269                 uinteger_t dim1 = tsa1.dim.toInteger();
9270                 uinteger_t dim2 = tsa2.dim.toInteger();
9271                 if (dim1 != dim2)
9272                 {
9273                     exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9274                     return setError();
9275                 }
9276             }
9277 
9278             if (exp.op != TOK.blit &&
9279                 (e2x.op == TOK.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9280                  e2x.op == TOK.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9281                  e2x.op != TOK.slice && e2x.isLvalue()))
9282             {
9283                 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9284                     return setError();
9285             }
9286 
9287             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9288                 e2x.op != TOK.slice && e2x.op != TOK.assign &&
9289                 e2x.op != TOK.arrayLiteral && e2x.op != TOK.string_ &&
9290                 !(e2x.op == TOK.add || e2x.op == TOK.min ||
9291                   e2x.op == TOK.mul || e2x.op == TOK.div ||
9292                   e2x.op == TOK.mod || e2x.op == TOK.xor ||
9293                   e2x.op == TOK.and || e2x.op == TOK.or ||
9294                   e2x.op == TOK.pow ||
9295                   e2x.op == TOK.tilde || e2x.op == TOK.negate))
9296             {
9297                 const(char)* e1str = exp.e1.toChars();
9298                 const(char)* e2str = e2x.toChars();
9299                 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9300             }
9301 
9302             Type t2n = t2.nextOf();
9303             Type t1n = t1.nextOf();
9304             int offset;
9305             if (t2n.equivalent(t1n) ||
9306                 t1n.isBaseOf(t2n, &offset) && offset == 0)
9307             {
9308                 /* Allow copy of distinct qualifier elements.
9309                  * eg.
9310                  *  char[] dst;  const(char)[] src;
9311                  *  dst[] = src;
9312                  *
9313                  *  class C {}   class D : C {}
9314                  *  C[2] ca;  D[] da;
9315                  *  ca[] = da;
9316                  */
9317                 if (isArrayOpValid(e2x))
9318                 {
9319                     // Don't add CastExp to keep AST for array operations
9320                     e2x = e2x.copy();
9321                     e2x.type = exp.e1.type.constOf();
9322                 }
9323                 else
9324                     e2x = e2x.castTo(sc, exp.e1.type.constOf());
9325             }
9326             else
9327             {
9328                 /* https://issues.dlang.org/show_bug.cgi?id=15778
9329                  * A string literal has an array type of immutable
9330                  * elements by default, and normally it cannot be convertible to
9331                  * array type of mutable elements. But for element-wise assignment,
9332                  * elements need to be const at best. So we should give a chance
9333                  * to change code unit size for polysemous string literal.
9334                  */
9335                 if (e2x.op == TOK.string_)
9336                     e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9337                 else
9338                     e2x = e2x.implicitCastTo(sc, exp.e1.type);
9339             }
9340             if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9341             {
9342                 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
9343                 {
9344                     exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
9345                     return setError();
9346                 }
9347             }
9348         }
9349         else
9350         {
9351             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == TOK.assign &&
9352                 t1.ty == Tarray && t2.ty == Tsarray &&
9353                 e2x.op != TOK.slice &&
9354                 t2.implicitConvTo(t1))
9355             {
9356                 // Disallow ar[] = sa (Converted to ar[] = sa[])
9357                 // Disallow da   = sa (Converted to da   = sa[])
9358                 const(char)* e1str = exp.e1.toChars();
9359                 const(char)* e2str = e2x.toChars();
9360                 const(char)* atypestr = exp.e1.op == TOK.slice ? "element-wise" : "slice";
9361                 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9362             }
9363             if (exp.op == TOK.blit)
9364                 e2x = e2x.castTo(sc, exp.e1.type);
9365             else
9366             {
9367                 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9368 
9369                 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9370 
9371                 // If the implicit cast has failed and the assign expression is
9372                 // the initialization of a struct member field
9373                 if (e2x.op == TOK.error && exp.op == TOK.construct && t1.ty == Tstruct)
9374                 {
9375                     scope sd = (cast(TypeStruct)t1).sym;
9376                     Dsymbol opAssign = search_function(sd, Id.assign);
9377 
9378                     // and the struct defines an opAssign
9379                     if (opAssign)
9380                     {
9381                         // offer more information about the cause of the problem
9382                         errorSupplemental(exp.loc,
9383                                           "`%s` is the first assignment of `%s` therefore it represents its initialization",
9384                                           exp.toChars(), exp.e1.toChars());
9385                         errorSupplemental(exp.loc,
9386                                           "`opAssign` methods are not used for initialization, but for subsequent assignments");
9387                     }
9388                 }
9389             }
9390         }
9391         if (e2x.op == TOK.error)
9392         {
9393             result = e2x;
9394             return;
9395         }
9396         exp.e2 = e2x;
9397         t2 = exp.e2.type.toBasetype();
9398 
9399         /* Look for array operations
9400          */
9401         if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9402         {
9403             // Look for valid array operations
9404             if (exp.memset != MemorySet.blockAssign &&
9405                 exp.e1.op == TOK.slice &&
9406                 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9407             {
9408                 exp.type = exp.e1.type;
9409                 if (exp.op == TOK.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9410                                         // tweak mutability of e1 element
9411                     exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9412                 result = arrayOp(exp, sc);
9413                 return;
9414             }
9415 
9416             // Drop invalid array operations in e2
9417             //  d = a[] + b[], d = (a[] + b[])[0..2], etc
9418             if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == TOK.assign))
9419                 return setError();
9420 
9421             // Remains valid array assignments
9422             //  d = d[], d = [1,2,3], etc
9423         }
9424 
9425         /* Don't allow assignment to classes that were allocated on the stack with:
9426          *      scope Class c = new Class();
9427          */
9428         if (exp.e1.op == TOK.variable && exp.op == TOK.assign)
9429         {
9430             VarExp ve = cast(VarExp)exp.e1;
9431             VarDeclaration vd = ve.var.isVarDeclaration();
9432             if (vd && (vd.onstack || vd.mynew))
9433             {
9434                 assert(t1.ty == Tclass);
9435                 exp.error("cannot rebind scope variables");
9436             }
9437         }
9438 
9439         if (exp.e1.op == TOK.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9440         {
9441             exp.error("cannot modify compiler-generated variable `__ctfe`");
9442         }
9443 
9444         exp.type = exp.e1.type;
9445         assert(exp.type);
9446         auto res = exp.op == TOK.assign ? exp.reorderSettingAAElem(sc) : exp;
9447         checkAssignEscape(sc, res, false);
9448         return setResult(res);
9449     }
9450 
9451     override void visit(PowAssignExp exp)
9452     {
9453         if (exp.type)
9454         {
9455             result = exp;
9456             return;
9457         }
9458 
9459         Expression e = exp.op_overload(sc);
9460         if (e)
9461         {
9462             result = e;
9463             return;
9464         }
9465 
9466         if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
9467             return setError();
9468 
9469         assert(exp.e1.type && exp.e2.type);
9470         if (exp.e1.op == TOK.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
9471         {
9472             if (checkNonAssignmentArrayOp(exp.e1))
9473                 return setError();
9474 
9475             // T[] ^^= ...
9476             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
9477             {
9478                 // T[] ^^= T
9479                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
9480             }
9481             else if (Expression ex = typeCombine(exp, sc))
9482             {
9483                 result = ex;
9484                 return;
9485             }
9486 
9487             // Check element types are arithmetic
9488             Type tb1 = exp.e1.type.nextOf().toBasetype();
9489             Type tb2 = exp.e2.type.toBasetype();
9490             if (tb2.ty == Tarray || tb2.ty == Tsarray)
9491                 tb2 = tb2.nextOf().toBasetype();
9492             if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
9493             {
9494                 exp.type = exp.e1.type;
9495                 result = arrayOp(exp, sc);
9496                 return;
9497             }
9498         }
9499         else
9500         {
9501             exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9502         }
9503 
9504         if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
9505         {
9506             Expression e0 = null;
9507             e = exp.reorderSettingAAElem(sc);
9508             e = Expression.extractLast(e, e0);
9509             assert(e == exp);
9510 
9511             if (exp.e1.op == TOK.variable)
9512             {
9513                 // Rewrite: e1 = e1 ^^ e2
9514                 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
9515                 e = new AssignExp(exp.loc, exp.e1, e);
9516             }
9517             else
9518             {
9519                 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
9520                 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
9521                 auto de = new DeclarationExp(exp.e1.loc, v);
9522                 auto ve = new VarExp(exp.e1.loc, v);
9523                 e = new PowExp(exp.loc, ve, exp.e2);
9524                 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
9525                 e = new CommaExp(exp.loc, de, e);
9526             }
9527             e = Expression.combine(e0, e);
9528             e = e.expressionSemantic(sc);
9529             result = e;
9530             return;
9531         }
9532         result = exp.incompatibleTypes();
9533     }
9534 
9535     override void visit(CatAssignExp exp)
9536     {
9537         if (exp.type)
9538         {
9539             result = exp;
9540             return;
9541         }
9542 
9543         //printf("CatAssignExp::semantic() %s\n", exp.toChars());
9544         Expression e = exp.op_overload(sc);
9545         if (e)
9546         {
9547             result = e;
9548             return;
9549         }
9550 
9551         if (exp.e1.op == TOK.slice)
9552         {
9553             SliceExp se = cast(SliceExp)exp.e1;
9554             if (se.e1.type.toBasetype().ty == Tsarray)
9555             {
9556                 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
9557                 return setError();
9558             }
9559         }
9560 
9561         if (checkIfIsStructLiteralDotExpr(exp.e1))
9562             return setError();
9563 
9564         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9565         if (exp.e1.op == TOK.error)
9566         {
9567             result = exp.e1;
9568             return;
9569         }
9570         if (exp.e2.op == TOK.error)
9571         {
9572             result = exp.e2;
9573             return;
9574         }
9575 
9576         if (checkNonAssignmentArrayOp(exp.e2))
9577             return setError();
9578 
9579         Type tb1 = exp.e1.type.toBasetype();
9580         Type tb1next = tb1.nextOf();
9581         Type tb2 = exp.e2.type.toBasetype();
9582 
9583         /* Possibilities:
9584          * TOK.concatenateAssign: appending T[] to T[]
9585          * TOK.concatenateElemAssign: appending T to T[]
9586          * TOK.concatenateDcharAssign: appending dchar to T[]
9587          */
9588         if ((tb1.ty == Tarray) &&
9589             (tb2.ty == Tarray || tb2.ty == Tsarray) &&
9590             (exp.e2.implicitConvTo(exp.e1.type) ||
9591              (tb2.nextOf().implicitConvTo(tb1next) &&
9592               (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
9593         {
9594             // TOK.concatenateAssign
9595             assert(exp.op == TOK.concatenateAssign);
9596             if (exp.e1.checkPostblit(sc, tb1next))
9597                 return setError();
9598 
9599             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
9600         }
9601         else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
9602         {
9603             /* https://issues.dlang.org/show_bug.cgi?id=19782
9604              *
9605              * If e2 is implicitly convertible to tb1next, the conversion
9606              * might be done through alias this, in which case, e2 needs to
9607              * be modified accordingly (e2 => e2.aliasthis).
9608              */
9609             if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
9610                 goto Laliasthis;
9611             if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
9612                 goto Laliasthis;
9613             // Append element
9614             if (exp.e2.checkPostblit(sc, tb2))
9615                 return setError();
9616 
9617             if (checkNewEscape(sc, exp.e2, false))
9618                 return setError();
9619 
9620             exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
9621             exp.e2 = doCopyOrMove(sc, exp.e2);
9622         }
9623         else if (tb1.ty == Tarray &&
9624                  (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
9625                  exp.e2.type.ty != tb1next.ty &&
9626                  exp.e2.implicitConvTo(Type.tdchar))
9627         {
9628             // Append dchar to char[] or wchar[]
9629             exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
9630 
9631             /* Do not allow appending wchar to char[] because if wchar happens
9632              * to be a surrogate pair, nothing good can result.
9633              */
9634         }
9635         else
9636         {
9637             // Try alias this on first operand
9638             static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
9639             {
9640                 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
9641                 if (!ad1 || !ad1.aliasthis)
9642                     return null;
9643 
9644                 /* Rewrite (e1 op e2) as:
9645                  *      (e1.aliasthis op e2)
9646                  */
9647                 if (exp.att1 && exp.e1.type == exp.att1)
9648                     return null;
9649                 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
9650                 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
9651                 BinExp be = cast(BinExp)exp.copy();
9652                 if (!be.att1 && exp.e1.type.checkAliasThisRec())
9653                     be.att1 = exp.e1.type;
9654                 be.e1 = e1;
9655                 return be.trySemantic(sc);
9656             }
9657 
9658             // Try alias this on second operand
9659             static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
9660             {
9661                 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
9662                 if (!ad2 || !ad2.aliasthis)
9663                     return null;
9664                 /* Rewrite (e1 op e2) as:
9665                  *      (e1 op e2.aliasthis)
9666                  */
9667                 if (exp.att2 && exp.e2.type == exp.att2)
9668                     return null;
9669                 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
9670                 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
9671                 BinExp be = cast(BinExp)exp.copy();
9672                 if (!be.att2 && exp.e2.type.checkAliasThisRec())
9673                     be.att2 = exp.e2.type;
9674                 be.e2 = e2;
9675                 return be.trySemantic(sc);
9676             }
9677 
9678     Laliasthis:
9679             result = tryAliasThisForLhs(exp, sc);
9680             if (result)
9681                 return;
9682 
9683             result = tryAliasThisForRhs(exp, sc);
9684             if (result)
9685                 return;
9686 
9687             exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
9688             return setError();
9689         }
9690 
9691         if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
9692             return setError();
9693 
9694         exp.type = exp.e1.type;
9695         auto res = exp.reorderSettingAAElem(sc);
9696         if ((exp.op == TOK.concatenateElemAssign || exp.op == TOK.concatenateDcharAssign) && global.params.vsafe)
9697             checkAssignEscape(sc, res, false);
9698         result = res;
9699     }
9700 
9701     override void visit(AddExp exp)
9702     {
9703         static if (LOGSEMANTIC)
9704         {
9705             printf("AddExp::semantic('%s')\n", exp.toChars());
9706         }
9707         if (exp.type)
9708         {
9709             result = exp;
9710             return;
9711         }
9712 
9713         if (Expression ex = binSemanticProp(exp, sc))
9714         {
9715             result = ex;
9716             return;
9717         }
9718         Expression e = exp.op_overload(sc);
9719         if (e)
9720         {
9721             result = e;
9722             return;
9723         }
9724 
9725         Type tb1 = exp.e1.type.toBasetype();
9726         Type tb2 = exp.e2.type.toBasetype();
9727 
9728         bool err = false;
9729         if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction)
9730         {
9731             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9732         }
9733         if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction)
9734         {
9735             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9736         }
9737         if (err)
9738             return setError();
9739 
9740         if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
9741         {
9742             result = scaleFactor(exp, sc);
9743             return;
9744         }
9745 
9746         if (tb1.ty == Tpointer && tb2.ty == Tpointer)
9747         {
9748             result = exp.incompatibleTypes();
9749             return;
9750         }
9751 
9752         if (Expression ex = typeCombine(exp, sc))
9753         {
9754             result = ex;
9755             return;
9756         }
9757 
9758         Type tb = exp.type.toBasetype();
9759         if (tb.ty == Tarray || tb.ty == Tsarray)
9760         {
9761             if (!isArrayOpValid(exp))
9762             {
9763                 result = arrayOpInvalidError(exp);
9764                 return;
9765             }
9766             result = exp;
9767             return;
9768         }
9769 
9770         tb1 = exp.e1.type.toBasetype();
9771         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
9772         {
9773             result = exp.incompatibleTypes();
9774             return;
9775         }
9776         if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
9777         {
9778             switch (exp.type.toBasetype().ty)
9779             {
9780             case Tfloat32:
9781             case Timaginary32:
9782                 exp.type = Type.tcomplex32;
9783                 break;
9784 
9785             case Tfloat64:
9786             case Timaginary64:
9787                 exp.type = Type.tcomplex64;
9788                 break;
9789 
9790             case Tfloat80:
9791             case Timaginary80:
9792                 exp.type = Type.tcomplex80;
9793                 break;
9794 
9795             default:
9796                 assert(0);
9797             }
9798         }
9799         result = exp;
9800     }
9801 
9802     override void visit(MinExp exp)
9803     {
9804         static if (LOGSEMANTIC)
9805         {
9806             printf("MinExp::semantic('%s')\n", exp.toChars());
9807         }
9808         if (exp.type)
9809         {
9810             result = exp;
9811             return;
9812         }
9813 
9814         if (Expression ex = binSemanticProp(exp, sc))
9815         {
9816             result = ex;
9817             return;
9818         }
9819         Expression e = exp.op_overload(sc);
9820         if (e)
9821         {
9822             result = e;
9823             return;
9824         }
9825 
9826         Type t1 = exp.e1.type.toBasetype();
9827         Type t2 = exp.e2.type.toBasetype();
9828 
9829         bool err = false;
9830         if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction)
9831         {
9832             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
9833         }
9834         if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction)
9835         {
9836             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
9837         }
9838         if (err)
9839             return setError();
9840 
9841         if (t1.ty == Tpointer)
9842         {
9843             if (t2.ty == Tpointer)
9844             {
9845                 // https://dlang.org/spec/expression.html#add_expressions
9846                 // "If both operands are pointers, and the operator is -, the pointers are
9847                 // subtracted and the result is divided by the size of the type pointed to
9848                 // by the operands. It is an error if the pointers point to different types."
9849                 Type p1 = t1.nextOf();
9850                 Type p2 = t2.nextOf();
9851 
9852                 if (!p1.equivalent(p2))
9853                 {
9854                     // Deprecation to remain for at least a year, after which this should be
9855                     // changed to an error
9856                     // See https://github.com/dlang/dmd/pull/7332
9857                     deprecation(exp.loc,
9858                         "cannot subtract pointers to different types: `%s` and `%s`.",
9859                         t1.toChars(), t2.toChars());
9860                 }
9861 
9862                 // Need to divide the result by the stride
9863                 // Replace (ptr - ptr) with (ptr - ptr) / stride
9864                 d_int64 stride;
9865 
9866                 // make sure pointer types are compatible
9867                 if (Expression ex = typeCombine(exp, sc))
9868                 {
9869                     result = ex;
9870                     return;
9871                 }
9872 
9873                 exp.type = Type.tptrdiff_t;
9874                 stride = t2.nextOf().size();
9875                 if (stride == 0)
9876                 {
9877                     e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
9878                 }
9879                 else
9880                 {
9881                     e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
9882                     e.type = Type.tptrdiff_t;
9883                 }
9884             }
9885             else if (t2.isintegral())
9886                 e = scaleFactor(exp, sc);
9887             else
9888             {
9889                 exp.error("can't subtract `%s` from pointer", t2.toChars());
9890                 e = ErrorExp.get();
9891             }
9892             result = e;
9893             return;
9894         }
9895         if (t2.ty == Tpointer)
9896         {
9897             exp.type = exp.e2.type;
9898             exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
9899             return setError();
9900         }
9901 
9902         if (Expression ex = typeCombine(exp, sc))
9903         {
9904             result = ex;
9905             return;
9906         }
9907 
9908         Type tb = exp.type.toBasetype();
9909         if (tb.ty == Tarray || tb.ty == Tsarray)
9910         {
9911             if (!isArrayOpValid(exp))
9912             {
9913                 result = arrayOpInvalidError(exp);
9914                 return;
9915             }
9916             result = exp;
9917             return;
9918         }
9919 
9920         t1 = exp.e1.type.toBasetype();
9921         t2 = exp.e2.type.toBasetype();
9922         if (!target.isVectorOpSupported(t1, exp.op, t2))
9923         {
9924             result = exp.incompatibleTypes();
9925             return;
9926         }
9927         if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
9928         {
9929             switch (exp.type.ty)
9930             {
9931             case Tfloat32:
9932             case Timaginary32:
9933                 exp.type = Type.tcomplex32;
9934                 break;
9935 
9936             case Tfloat64:
9937             case Timaginary64:
9938                 exp.type = Type.tcomplex64;
9939                 break;
9940 
9941             case Tfloat80:
9942             case Timaginary80:
9943                 exp.type = Type.tcomplex80;
9944                 break;
9945 
9946             default:
9947                 assert(0);
9948             }
9949         }
9950         result = exp;
9951         return;
9952     }
9953 
9954     override void visit(CatExp exp)
9955     {
9956         // https://dlang.org/spec/expression.html#cat_expressions
9957         //printf("CatExp.semantic() %s\n", toChars());
9958         if (exp.type)
9959         {
9960             result = exp;
9961             return;
9962         }
9963 
9964         if (Expression ex = binSemanticProp(exp, sc))
9965         {
9966             result = ex;
9967             return;
9968         }
9969         Expression e = exp.op_overload(sc);
9970         if (e)
9971         {
9972             result = e;
9973             return;
9974         }
9975 
9976         Type tb1 = exp.e1.type.toBasetype();
9977         Type tb2 = exp.e2.type.toBasetype();
9978 
9979         auto f1 = checkNonAssignmentArrayOp(exp.e1);
9980         auto f2 = checkNonAssignmentArrayOp(exp.e2);
9981         if (f1 || f2)
9982             return setError();
9983 
9984         /* BUG: Should handle things like:
9985          *      char c;
9986          *      c ~ ' '
9987          *      ' ' ~ c;
9988          */
9989 
9990         Type tb1next = tb1.nextOf();
9991         Type tb2next = tb2.nextOf();
9992 
9993         // Check for: array ~ array
9994         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)))
9995         {
9996             /* https://issues.dlang.org/show_bug.cgi?id=9248
9997              * Here to avoid the case of:
9998              *    void*[] a = [cast(void*)1];
9999              *    void*[] b = [cast(void*)2];
10000              *    a ~ b;
10001              * becoming:
10002              *    a ~ [cast(void*)b];
10003              */
10004 
10005             /* https://issues.dlang.org/show_bug.cgi?id=14682
10006              * Also to avoid the case of:
10007              *    int[][] a;
10008              *    a ~ [];
10009              * becoming:
10010              *    a ~ cast(int[])[];
10011              */
10012             goto Lpeer;
10013         }
10014 
10015         // Check for: array ~ element
10016         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10017         {
10018             if (exp.e1.op == TOK.arrayLiteral)
10019             {
10020                 exp.e2 = doCopyOrMove(sc, exp.e2);
10021                 // https://issues.dlang.org/show_bug.cgi?id=14686
10022                 // Postblit call appears in AST, and this is
10023                 // finally translated  to an ArrayLiteralExp in below optimize().
10024             }
10025             else if (exp.e1.op == TOK.string_)
10026             {
10027                 // No postblit call exists on character (integer) value.
10028             }
10029             else
10030             {
10031                 if (exp.e2.checkPostblit(sc, tb2))
10032                     return setError();
10033                 // Postblit call will be done in runtime helper function
10034             }
10035 
10036             if (exp.e1.op == TOK.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
10037             {
10038                 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10039                 exp.type = tb2.arrayOf();
10040                 goto L2elem;
10041             }
10042             if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10043             {
10044                 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10045                 exp.type = tb1next.arrayOf();
10046             L2elem:
10047                 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10048                 {
10049                     // Make e2 into [e2]
10050                     exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10051                 }
10052                 else if (checkNewEscape(sc, exp.e2, false))
10053                     return setError();
10054                 result = exp.optimize(WANTvalue);
10055                 return;
10056             }
10057         }
10058         // Check for: element ~ array
10059         if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10060         {
10061             if (exp.e2.op == TOK.arrayLiteral)
10062             {
10063                 exp.e1 = doCopyOrMove(sc, exp.e1);
10064             }
10065             else if (exp.e2.op == TOK.string_)
10066             {
10067             }
10068             else
10069             {
10070                 if (exp.e1.checkPostblit(sc, tb1))
10071                     return setError();
10072             }
10073 
10074             if (exp.e2.op == TOK.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
10075             {
10076                 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10077                 exp.type = tb1.arrayOf();
10078                 goto L1elem;
10079             }
10080             if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10081             {
10082                 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10083                 exp.type = tb2next.arrayOf();
10084             L1elem:
10085                 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10086                 {
10087                     // Make e1 into [e1]
10088                     exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10089                 }
10090                 else if (checkNewEscape(sc, exp.e1, false))
10091                     return setError();
10092                 result = exp.optimize(WANTvalue);
10093                 return;
10094             }
10095         }
10096 
10097     Lpeer:
10098         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10099         {
10100             Type t1 = tb1next.mutableOf().constOf().arrayOf();
10101             Type t2 = tb2next.mutableOf().constOf().arrayOf();
10102             if (exp.e1.op == TOK.string_ && !(cast(StringExp)exp.e1).committed)
10103                 exp.e1.type = t1;
10104             else
10105                 exp.e1 = exp.e1.castTo(sc, t1);
10106             if (exp.e2.op == TOK.string_ && !(cast(StringExp)exp.e2).committed)
10107                 exp.e2.type = t2;
10108             else
10109                 exp.e2 = exp.e2.castTo(sc, t2);
10110         }
10111 
10112         if (Expression ex = typeCombine(exp, sc))
10113         {
10114             result = ex;
10115             return;
10116         }
10117         exp.type = exp.type.toHeadMutable();
10118 
10119         Type tb = exp.type.toBasetype();
10120         if (tb.ty == Tsarray)
10121             exp.type = tb.nextOf().arrayOf();
10122         if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10123         {
10124             exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10125         }
10126         if (Type tbn = tb.nextOf())
10127         {
10128             if (exp.checkPostblit(sc, tbn))
10129                 return setError();
10130         }
10131         Type t1 = exp.e1.type.toBasetype();
10132         Type t2 = exp.e2.type.toBasetype();
10133         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10134             (t2.ty == Tarray || t2.ty == Tsarray))
10135         {
10136             // Normalize to ArrayLiteralExp or StringExp as far as possible
10137             e = exp.optimize(WANTvalue);
10138         }
10139         else
10140         {
10141             //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10142             result = exp.incompatibleTypes();
10143             return;
10144         }
10145 
10146         result = e;
10147     }
10148 
10149     override void visit(MulExp exp)
10150     {
10151         version (none)
10152         {
10153             printf("MulExp::semantic() %s\n", exp.toChars());
10154         }
10155         if (exp.type)
10156         {
10157             result = exp;
10158             return;
10159         }
10160 
10161         if (Expression ex = binSemanticProp(exp, sc))
10162         {
10163             result = ex;
10164             return;
10165         }
10166         Expression e = exp.op_overload(sc);
10167         if (e)
10168         {
10169             result = e;
10170             return;
10171         }
10172 
10173         if (Expression ex = typeCombine(exp, sc))
10174         {
10175             result = ex;
10176             return;
10177         }
10178 
10179         Type tb = exp.type.toBasetype();
10180         if (tb.ty == Tarray || tb.ty == Tsarray)
10181         {
10182             if (!isArrayOpValid(exp))
10183             {
10184                 result = arrayOpInvalidError(exp);
10185                 return;
10186             }
10187             result = exp;
10188             return;
10189         }
10190 
10191         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10192             return setError();
10193 
10194         if (exp.type.isfloating())
10195         {
10196             Type t1 = exp.e1.type;
10197             Type t2 = exp.e2.type;
10198 
10199             if (t1.isreal())
10200             {
10201                 exp.type = t2;
10202             }
10203             else if (t2.isreal())
10204             {
10205                 exp.type = t1;
10206             }
10207             else if (t1.isimaginary())
10208             {
10209                 if (t2.isimaginary())
10210                 {
10211                     switch (t1.toBasetype().ty)
10212                     {
10213                     case Timaginary32:
10214                         exp.type = Type.tfloat32;
10215                         break;
10216 
10217                     case Timaginary64:
10218                         exp.type = Type.tfloat64;
10219                         break;
10220 
10221                     case Timaginary80:
10222                         exp.type = Type.tfloat80;
10223                         break;
10224 
10225                     default:
10226                         assert(0);
10227                     }
10228 
10229                     // iy * iv = -yv
10230                     exp.e1.type = exp.type;
10231                     exp.e2.type = exp.type;
10232                     e = new NegExp(exp.loc, exp);
10233                     e = e.expressionSemantic(sc);
10234                     result = e;
10235                     return;
10236                 }
10237                 else
10238                     exp.type = t2; // t2 is complex
10239             }
10240             else if (t2.isimaginary())
10241             {
10242                 exp.type = t1; // t1 is complex
10243             }
10244         }
10245         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10246         {
10247             result = exp.incompatibleTypes();
10248             return;
10249         }
10250         result = exp;
10251     }
10252 
10253     override void visit(DivExp exp)
10254     {
10255         if (exp.type)
10256         {
10257             result = exp;
10258             return;
10259         }
10260 
10261         if (Expression ex = binSemanticProp(exp, sc))
10262         {
10263             result = ex;
10264             return;
10265         }
10266         Expression e = exp.op_overload(sc);
10267         if (e)
10268         {
10269             result = e;
10270             return;
10271         }
10272 
10273         if (Expression ex = typeCombine(exp, sc))
10274         {
10275             result = ex;
10276             return;
10277         }
10278 
10279         Type tb = exp.type.toBasetype();
10280         if (tb.ty == Tarray || tb.ty == Tsarray)
10281         {
10282             if (!isArrayOpValid(exp))
10283             {
10284                 result = arrayOpInvalidError(exp);
10285                 return;
10286             }
10287             result = exp;
10288             return;
10289         }
10290 
10291         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10292             return setError();
10293 
10294         if (exp.type.isfloating())
10295         {
10296             Type t1 = exp.e1.type;
10297             Type t2 = exp.e2.type;
10298 
10299             if (t1.isreal())
10300             {
10301                 exp.type = t2;
10302                 if (t2.isimaginary())
10303                 {
10304                     // x/iv = i(-x/v)
10305                     exp.e2.type = t1;
10306                     e = new NegExp(exp.loc, exp);
10307                     e = e.expressionSemantic(sc);
10308                     result = e;
10309                     return;
10310                 }
10311             }
10312             else if (t2.isreal())
10313             {
10314                 exp.type = t1;
10315             }
10316             else if (t1.isimaginary())
10317             {
10318                 if (t2.isimaginary())
10319                 {
10320                     switch (t1.toBasetype().ty)
10321                     {
10322                     case Timaginary32:
10323                         exp.type = Type.tfloat32;
10324                         break;
10325 
10326                     case Timaginary64:
10327                         exp.type = Type.tfloat64;
10328                         break;
10329 
10330                     case Timaginary80:
10331                         exp.type = Type.tfloat80;
10332                         break;
10333 
10334                     default:
10335                         assert(0);
10336                     }
10337                 }
10338                 else
10339                     exp.type = t2; // t2 is complex
10340             }
10341             else if (t2.isimaginary())
10342             {
10343                 exp.type = t1; // t1 is complex
10344             }
10345         }
10346         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10347         {
10348             result = exp.incompatibleTypes();
10349             return;
10350         }
10351         result = exp;
10352     }
10353 
10354     override void visit(ModExp exp)
10355     {
10356         if (exp.type)
10357         {
10358             result = exp;
10359             return;
10360         }
10361 
10362         if (Expression ex = binSemanticProp(exp, sc))
10363         {
10364             result = ex;
10365             return;
10366         }
10367         Expression e = exp.op_overload(sc);
10368         if (e)
10369         {
10370             result = e;
10371             return;
10372         }
10373 
10374         if (Expression ex = typeCombine(exp, sc))
10375         {
10376             result = ex;
10377             return;
10378         }
10379 
10380         Type tb = exp.type.toBasetype();
10381         if (tb.ty == Tarray || tb.ty == Tsarray)
10382         {
10383             if (!isArrayOpValid(exp))
10384             {
10385                 result = arrayOpInvalidError(exp);
10386                 return;
10387             }
10388             result = exp;
10389             return;
10390         }
10391         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10392         {
10393             result = exp.incompatibleTypes();
10394             return;
10395         }
10396 
10397         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10398             return setError();
10399 
10400         if (exp.type.isfloating())
10401         {
10402             exp.type = exp.e1.type;
10403             if (exp.e2.type.iscomplex())
10404             {
10405                 exp.error("cannot perform modulo complex arithmetic");
10406                 return setError();
10407             }
10408         }
10409         result = exp;
10410     }
10411 
10412     override void visit(PowExp exp)
10413     {
10414         if (exp.type)
10415         {
10416             result = exp;
10417             return;
10418         }
10419 
10420         //printf("PowExp::semantic() %s\n", toChars());
10421         if (Expression ex = binSemanticProp(exp, sc))
10422         {
10423             result = ex;
10424             return;
10425         }
10426         Expression e = exp.op_overload(sc);
10427         if (e)
10428         {
10429             result = e;
10430             return;
10431         }
10432 
10433         if (Expression ex = typeCombine(exp, sc))
10434         {
10435             result = ex;
10436             return;
10437         }
10438 
10439         Type tb = exp.type.toBasetype();
10440         if (tb.ty == Tarray || tb.ty == Tsarray)
10441         {
10442             if (!isArrayOpValid(exp))
10443             {
10444                 result = arrayOpInvalidError(exp);
10445                 return;
10446             }
10447             result = exp;
10448             return;
10449         }
10450 
10451         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10452             return setError();
10453 
10454         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10455         {
10456             result = exp.incompatibleTypes();
10457             return;
10458         }
10459 
10460         // First, attempt to fold the expression.
10461         e = exp.optimize(WANTvalue);
10462         if (e.op != TOK.pow)
10463         {
10464             e = e.expressionSemantic(sc);
10465             result = e;
10466             return;
10467         }
10468 
10469         Module mmath = loadStdMath();
10470         if (!mmath)
10471         {
10472             e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
10473             return setError();
10474         }
10475         e = new ScopeExp(exp.loc, mmath);
10476 
10477         if (exp.e2.op == TOK.float64 && exp.e2.toReal() == CTFloat.half)
10478         {
10479             // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
10480             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
10481         }
10482         else
10483         {
10484             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
10485             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
10486         }
10487         e = e.expressionSemantic(sc);
10488         result = e;
10489         return;
10490     }
10491 
10492     override void visit(ShlExp exp)
10493     {
10494         //printf("ShlExp::semantic(), type = %p\n", type);
10495         if (exp.type)
10496         {
10497             result = exp;
10498             return;
10499         }
10500 
10501         if (Expression ex = binSemanticProp(exp, sc))
10502         {
10503             result = ex;
10504             return;
10505         }
10506         Expression e = exp.op_overload(sc);
10507         if (e)
10508         {
10509             result = e;
10510             return;
10511         }
10512 
10513         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10514             return setError();
10515 
10516         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10517         {
10518             result = exp.incompatibleTypes();
10519             return;
10520         }
10521         exp.e1 = integralPromotions(exp.e1, sc);
10522         if (exp.e2.type.toBasetype().ty != Tvector)
10523             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10524 
10525         exp.type = exp.e1.type;
10526         result = exp;
10527     }
10528 
10529     override void visit(ShrExp exp)
10530     {
10531         if (exp.type)
10532         {
10533             result = exp;
10534             return;
10535         }
10536 
10537         if (Expression ex = binSemanticProp(exp, sc))
10538         {
10539             result = ex;
10540             return;
10541         }
10542         Expression e = exp.op_overload(sc);
10543         if (e)
10544         {
10545             result = e;
10546             return;
10547         }
10548 
10549         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10550             return setError();
10551 
10552         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10553         {
10554             result = exp.incompatibleTypes();
10555             return;
10556         }
10557         exp.e1 = integralPromotions(exp.e1, sc);
10558         if (exp.e2.type.toBasetype().ty != Tvector)
10559             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10560 
10561         exp.type = exp.e1.type;
10562         result = exp;
10563     }
10564 
10565     override void visit(UshrExp exp)
10566     {
10567         if (exp.type)
10568         {
10569             result = exp;
10570             return;
10571         }
10572 
10573         if (Expression ex = binSemanticProp(exp, sc))
10574         {
10575             result = ex;
10576             return;
10577         }
10578         Expression e = exp.op_overload(sc);
10579         if (e)
10580         {
10581             result = e;
10582             return;
10583         }
10584 
10585         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10586             return setError();
10587 
10588         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10589         {
10590             result = exp.incompatibleTypes();
10591             return;
10592         }
10593         exp.e1 = integralPromotions(exp.e1, sc);
10594         if (exp.e2.type.toBasetype().ty != Tvector)
10595             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10596 
10597         exp.type = exp.e1.type;
10598         result = exp;
10599     }
10600 
10601     override void visit(AndExp exp)
10602     {
10603         if (exp.type)
10604         {
10605             result = exp;
10606             return;
10607         }
10608 
10609         if (Expression ex = binSemanticProp(exp, sc))
10610         {
10611             result = ex;
10612             return;
10613         }
10614         Expression e = exp.op_overload(sc);
10615         if (e)
10616         {
10617             result = e;
10618             return;
10619         }
10620 
10621         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10622         {
10623             exp.type = exp.e1.type;
10624             result = exp;
10625             return;
10626         }
10627 
10628         if (Expression ex = typeCombine(exp, sc))
10629         {
10630             result = ex;
10631             return;
10632         }
10633 
10634         Type tb = exp.type.toBasetype();
10635         if (tb.ty == Tarray || tb.ty == Tsarray)
10636         {
10637             if (!isArrayOpValid(exp))
10638             {
10639                 result = arrayOpInvalidError(exp);
10640                 return;
10641             }
10642             result = exp;
10643             return;
10644         }
10645         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10646         {
10647             result = exp.incompatibleTypes();
10648             return;
10649         }
10650         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10651             return setError();
10652 
10653         result = exp;
10654     }
10655 
10656     override void visit(OrExp exp)
10657     {
10658         if (exp.type)
10659         {
10660             result = exp;
10661             return;
10662         }
10663 
10664         if (Expression ex = binSemanticProp(exp, sc))
10665         {
10666             result = ex;
10667             return;
10668         }
10669         Expression e = exp.op_overload(sc);
10670         if (e)
10671         {
10672             result = e;
10673             return;
10674         }
10675 
10676         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10677         {
10678             exp.type = exp.e1.type;
10679             result = exp;
10680             return;
10681         }
10682 
10683         if (Expression ex = typeCombine(exp, sc))
10684         {
10685             result = ex;
10686             return;
10687         }
10688 
10689         Type tb = exp.type.toBasetype();
10690         if (tb.ty == Tarray || tb.ty == Tsarray)
10691         {
10692             if (!isArrayOpValid(exp))
10693             {
10694                 result = arrayOpInvalidError(exp);
10695                 return;
10696             }
10697             result = exp;
10698             return;
10699         }
10700         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10701         {
10702             result = exp.incompatibleTypes();
10703             return;
10704         }
10705         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10706             return setError();
10707 
10708         result = exp;
10709     }
10710 
10711     override void visit(XorExp exp)
10712     {
10713         if (exp.type)
10714         {
10715             result = exp;
10716             return;
10717         }
10718 
10719         if (Expression ex = binSemanticProp(exp, sc))
10720         {
10721             result = ex;
10722             return;
10723         }
10724         Expression e = exp.op_overload(sc);
10725         if (e)
10726         {
10727             result = e;
10728             return;
10729         }
10730 
10731         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
10732         {
10733             exp.type = exp.e1.type;
10734             result = exp;
10735             return;
10736         }
10737 
10738         if (Expression ex = typeCombine(exp, sc))
10739         {
10740             result = ex;
10741             return;
10742         }
10743 
10744         Type tb = exp.type.toBasetype();
10745         if (tb.ty == Tarray || tb.ty == Tsarray)
10746         {
10747             if (!isArrayOpValid(exp))
10748             {
10749                 result = arrayOpInvalidError(exp);
10750                 return;
10751             }
10752             result = exp;
10753             return;
10754         }
10755         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10756         {
10757             result = exp.incompatibleTypes();
10758             return;
10759         }
10760         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10761             return setError();
10762 
10763         result = exp;
10764     }
10765 
10766     override void visit(LogicalExp exp)
10767     {
10768         static if (LOGSEMANTIC)
10769         {
10770             printf("LogicalExp::semantic() %s\n", exp.toChars());
10771         }
10772 
10773         if (exp.type)
10774         {
10775             result = exp;
10776             return;
10777         }
10778 
10779         exp.setNoderefOperands();
10780 
10781         Expression e1x = exp.e1.expressionSemantic(sc);
10782 
10783         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10784         if (e1x.op == TOK.type)
10785             e1x = resolveAliasThis(sc, e1x);
10786 
10787         e1x = resolveProperties(sc, e1x);
10788         e1x = e1x.toBoolean(sc);
10789 
10790         if (sc.flags & SCOPE.condition)
10791         {
10792             /* If in static if, don't evaluate e2 if we don't have to.
10793              */
10794             e1x = e1x.optimize(WANTvalue);
10795             if (e1x.isBool(exp.op == TOK.orOr))
10796             {
10797                 result = IntegerExp.createBool(exp.op == TOK.orOr);
10798                 return;
10799             }
10800         }
10801 
10802         CtorFlow ctorflow = sc.ctorflow.clone();
10803         Expression e2x = exp.e2.expressionSemantic(sc);
10804         sc.merge(exp.loc, ctorflow);
10805         ctorflow.freeFieldinit();
10806 
10807         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
10808         if (e2x.op == TOK.type)
10809             e2x = resolveAliasThis(sc, e2x);
10810 
10811         e2x = resolveProperties(sc, e2x);
10812 
10813         auto f1 = checkNonAssignmentArrayOp(e1x);
10814         auto f2 = checkNonAssignmentArrayOp(e2x);
10815         if (f1 || f2)
10816             return setError();
10817 
10818         // Unless the right operand is 'void', the expression is converted to 'bool'.
10819         if (e2x.type.ty != Tvoid)
10820             e2x = e2x.toBoolean(sc);
10821 
10822         if (e2x.op == TOK.type || e2x.op == TOK.scope_)
10823         {
10824             exp.error("`%s` is not an expression", exp.e2.toChars());
10825             return setError();
10826         }
10827         if (e1x.op == TOK.error)
10828         {
10829             result = e1x;
10830             return;
10831         }
10832         if (e2x.op == TOK.error)
10833         {
10834             result = e2x;
10835             return;
10836         }
10837 
10838         // The result type is 'bool', unless the right operand has type 'void'.
10839         if (e2x.type.ty == Tvoid)
10840             exp.type = Type.tvoid;
10841         else
10842             exp.type = Type.tbool;
10843 
10844         exp.e1 = e1x;
10845         exp.e2 = e2x;
10846         result = exp;
10847     }
10848 
10849 
10850     override void visit(CmpExp exp)
10851     {
10852         static if (LOGSEMANTIC)
10853         {
10854             printf("CmpExp::semantic('%s')\n", exp.toChars());
10855         }
10856         if (exp.type)
10857         {
10858             result = exp;
10859             return;
10860         }
10861 
10862         exp.setNoderefOperands();
10863 
10864         if (Expression ex = binSemanticProp(exp, sc))
10865         {
10866             result = ex;
10867             return;
10868         }
10869         Type t1 = exp.e1.type.toBasetype();
10870         Type t2 = exp.e2.type.toBasetype();
10871         if (t1.ty == Tclass && exp.e2.op == TOK.null_ || t2.ty == Tclass && exp.e1.op == TOK.null_)
10872         {
10873             exp.error("do not use `null` when comparing class types");
10874             return setError();
10875         }
10876 
10877         TOK cmpop;
10878         if (auto e = exp.op_overload(sc, &cmpop))
10879         {
10880             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
10881             {
10882                 exp.error("recursive `opCmp` expansion");
10883                 return setError();
10884             }
10885             if (e.op == TOK.call)
10886             {
10887                 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
10888                 e = e.expressionSemantic(sc);
10889             }
10890             result = e;
10891             return;
10892         }
10893 
10894         if (Expression ex = typeCombine(exp, sc))
10895         {
10896             result = ex;
10897             return;
10898         }
10899 
10900         auto f1 = checkNonAssignmentArrayOp(exp.e1);
10901         auto f2 = checkNonAssignmentArrayOp(exp.e2);
10902         if (f1 || f2)
10903             return setError();
10904 
10905         exp.type = Type.tbool;
10906 
10907         // Special handling for array comparisons
10908         Expression arrayLowering = null;
10909         t1 = exp.e1.type.toBasetype();
10910         t2 = exp.e2.type.toBasetype();
10911         if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
10912         {
10913             Type t1next = t1.nextOf();
10914             Type t2next = t2.nextOf();
10915             if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
10916             {
10917                 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
10918                 return setError();
10919             }
10920             if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
10921             {
10922                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
10923                     return setError();
10924 
10925                 // Lower to object.__cmp(e1, e2)
10926                 Expression al = new IdentifierExp(exp.loc, Id.empty);
10927                 al = new DotIdExp(exp.loc, al, Id.object);
10928                 al = new DotIdExp(exp.loc, al, Id.__cmp);
10929                 al = al.expressionSemantic(sc);
10930 
10931                 auto arguments = new Expressions(2);
10932                 (*arguments)[0] = exp.e1;
10933                 (*arguments)[1] = exp.e2;
10934 
10935                 al = new CallExp(exp.loc, al, arguments);
10936                 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
10937 
10938                 arrayLowering = al;
10939             }
10940         }
10941         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
10942         {
10943             if (t2.ty == Tstruct)
10944                 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
10945             else
10946                 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
10947             return setError();
10948         }
10949         else if (t1.iscomplex() || t2.iscomplex())
10950         {
10951             exp.error("compare not defined for complex operands");
10952             return setError();
10953         }
10954         else if (t1.ty == Taarray || t2.ty == Taarray)
10955         {
10956             exp.error("`%s` is not defined for associative arrays", Token.toChars(exp.op));
10957             return setError();
10958         }
10959         else if (!target.isVectorOpSupported(t1, exp.op, t2))
10960         {
10961             result = exp.incompatibleTypes();
10962             return;
10963         }
10964         else
10965         {
10966             bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
10967             bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
10968             if (r1 || r2)
10969                 return setError();
10970         }
10971 
10972         //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
10973         if (arrayLowering)
10974         {
10975             arrayLowering = arrayLowering.expressionSemantic(sc);
10976             result = arrayLowering;
10977             return;
10978         }
10979         result = exp;
10980         return;
10981     }
10982 
10983     override void visit(InExp exp)
10984     {
10985         if (exp.type)
10986         {
10987             result = exp;
10988             return;
10989         }
10990 
10991         if (Expression ex = binSemanticProp(exp, sc))
10992         {
10993             result = ex;
10994             return;
10995         }
10996         Expression e = exp.op_overload(sc);
10997         if (e)
10998         {
10999             result = e;
11000             return;
11001         }
11002 
11003         Type t2b = exp.e2.type.toBasetype();
11004         switch (t2b.ty)
11005         {
11006         case Taarray:
11007             {
11008                 TypeAArray ta = cast(TypeAArray)t2b;
11009 
11010                 // Special handling for array keys
11011                 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11012                 {
11013                     // Convert key to type of key
11014                     exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11015                 }
11016 
11017                 semanticTypeInfo(sc, ta.index);
11018 
11019                 // Return type is pointer to value
11020                 exp.type = ta.nextOf().pointerTo();
11021                 break;
11022             }
11023 
11024         case Terror:
11025             return setError();
11026 
11027         default:
11028             result = exp.incompatibleTypes();
11029             return;
11030         }
11031         result = exp;
11032     }
11033 
11034     override void visit(RemoveExp e)
11035     {
11036         if (Expression ex = binSemantic(e, sc))
11037         {
11038             result = ex;
11039             return;
11040         }
11041         result = e;
11042     }
11043 
11044     override void visit(EqualExp exp)
11045     {
11046         //printf("EqualExp::semantic('%s')\n", exp.toChars());
11047         if (exp.type)
11048         {
11049             result = exp;
11050             return;
11051         }
11052 
11053         exp.setNoderefOperands();
11054 
11055         if (auto e = binSemanticProp(exp, sc))
11056         {
11057             result = e;
11058             return;
11059         }
11060         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
11061         {
11062             /* https://issues.dlang.org/show_bug.cgi?id=12520
11063              * empty tuples are represented as types so special cases are added
11064              * so that they can be compared for equality with tuples of values.
11065              */
11066             static auto extractTypeTupAndExpTup(Expression e)
11067             {
11068                 static struct Result { bool ttEmpty; bool te; }
11069                 auto tt = e.op == TOK.type ? e.isTypeExp().type.isTypeTuple() : null;
11070                 return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
11071             }
11072             auto tups1 = extractTypeTupAndExpTup(exp.e1);
11073             auto tups2 = extractTypeTupAndExpTup(exp.e2);
11074             // AliasSeq!() == AliasSeq!(<at least a value>)
11075             if (tups1.ttEmpty && tups2.te)
11076             {
11077                 result = IntegerExp.createBool(exp.op != TOK.equal);
11078                 return;
11079             }
11080             // AliasSeq!(<at least a value>) == AliasSeq!()
11081             else if (tups1.te && tups2.ttEmpty)
11082             {
11083                 result = IntegerExp.createBool(exp.op != TOK.equal);
11084                 return;
11085             }
11086             // AliasSeq!() == AliasSeq!()
11087             else if (tups1.ttEmpty && tups2.ttEmpty)
11088             {
11089                 result = IntegerExp.createBool(exp.op == TOK.equal);
11090                 return;
11091             }
11092             // otherwise, two types are really not comparable
11093             result = exp.incompatibleTypes();
11094             return;
11095         }
11096 
11097         {
11098             auto t1 = exp.e1.type;
11099             auto t2 = exp.e2.type;
11100             if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11101                 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11102                     t1.toChars(), t2.toChars());
11103         }
11104 
11105         /* Before checking for operator overloading, check to see if we're
11106          * comparing the addresses of two statics. If so, we can just see
11107          * if they are the same symbol.
11108          */
11109         if (exp.e1.op == TOK.address && exp.e2.op == TOK.address)
11110         {
11111             AddrExp ae1 = cast(AddrExp)exp.e1;
11112             AddrExp ae2 = cast(AddrExp)exp.e2;
11113             if (ae1.e1.op == TOK.variable && ae2.e1.op == TOK.variable)
11114             {
11115                 VarExp ve1 = cast(VarExp)ae1.e1;
11116                 VarExp ve2 = cast(VarExp)ae2.e1;
11117                 if (ve1.var == ve2.var)
11118                 {
11119                     // They are the same, result is 'true' for ==, 'false' for !=
11120                     result = IntegerExp.createBool(exp.op == TOK.equal);
11121                     return;
11122                 }
11123             }
11124         }
11125 
11126         Type t1 = exp.e1.type.toBasetype();
11127         Type t2 = exp.e2.type.toBasetype();
11128 
11129         // Indicates whether the comparison of the 2 specified array types
11130         // requires an object.__equals() lowering.
11131         static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11132         {
11133             Type t1n = t1.nextOf().toBasetype();
11134             Type t2n = t2.nextOf().toBasetype();
11135             if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11136                 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11137             {
11138                 return false;
11139             }
11140             if (t1n.constOf() != t2n.constOf())
11141                 return true;
11142 
11143             Type t = t1n;
11144             while (t.toBasetype().nextOf())
11145                 t = t.nextOf().toBasetype();
11146             if (auto ts = t.isTypeStruct())
11147             {
11148                 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11149                 if (global.params.useTypeInfo && Type.dtypeinfo)
11150                     semanticTypeInfo(sc, ts);
11151 
11152                 return ts.sym.hasIdentityEquals; // has custom opEquals
11153             }
11154 
11155             return false;
11156         }
11157 
11158         if (auto e = exp.op_overload(sc))
11159         {
11160             result = e;
11161             return;
11162         }
11163 
11164 
11165         const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11166                                   (t2.ty == Tarray || t2.ty == Tsarray);
11167         const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11168 
11169         if (!needsArrayLowering)
11170         {
11171             if (auto e = typeCombine(exp, sc))
11172             {
11173                 result = e;
11174                 return;
11175             }
11176         }
11177 
11178         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11179         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11180         if (f1 || f2)
11181             return setError();
11182 
11183         exp.type = Type.tbool;
11184 
11185         if (!isArrayComparison)
11186         {
11187             if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11188             {
11189                 // Cast both to complex
11190                 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11191                 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11192             }
11193         }
11194 
11195         // lower some array comparisons to object.__equals(e1, e2)
11196         if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
11197         {
11198             //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
11199 
11200             if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
11201                 return setError();
11202 
11203             Expression __equals = new IdentifierExp(exp.loc, Id.empty);
11204             Identifier id = Identifier.idPool("__equals");
11205             __equals = new DotIdExp(exp.loc, __equals, Id.object);
11206             __equals = new DotIdExp(exp.loc, __equals, id);
11207 
11208             auto arguments = new Expressions(2);
11209             (*arguments)[0] = exp.e1;
11210             (*arguments)[1] = exp.e2;
11211 
11212             __equals = new CallExp(exp.loc, __equals, arguments);
11213             if (exp.op == TOK.notEqual)
11214             {
11215                 __equals = new NotExp(exp.loc, __equals);
11216             }
11217             __equals = __equals.trySemantic(sc); // for better error message
11218             if (!__equals)
11219             {
11220                 exp.error("incompatible types for array comparison: `%s` and `%s`",
11221                           exp.e1.type.toChars(), exp.e2.type.toChars());
11222                 __equals = ErrorExp.get();
11223             }
11224 
11225             result = __equals;
11226             return;
11227         }
11228 
11229         if (exp.e1.type.toBasetype().ty == Taarray)
11230             semanticTypeInfo(sc, exp.e1.type.toBasetype());
11231 
11232 
11233         if (!target.isVectorOpSupported(t1, exp.op, t2))
11234         {
11235             result = exp.incompatibleTypes();
11236             return;
11237         }
11238 
11239         result = exp;
11240     }
11241 
11242     override void visit(IdentityExp exp)
11243     {
11244         if (exp.type)
11245         {
11246             result = exp;
11247             return;
11248         }
11249 
11250         exp.setNoderefOperands();
11251 
11252         if (auto e = binSemanticProp(exp, sc))
11253         {
11254             result = e;
11255             return;
11256         }
11257 
11258         if (auto e = typeCombine(exp, sc))
11259         {
11260             result = e;
11261             return;
11262         }
11263 
11264         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11265         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11266         if (f1 || f2)
11267             return setError();
11268 
11269         if (exp.e1.op == TOK.type || exp.e2.op == TOK.type)
11270         {
11271             result = exp.incompatibleTypes();
11272             return;
11273         }
11274 
11275         exp.type = Type.tbool;
11276 
11277         if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11278         {
11279             // Cast both to complex
11280             exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11281             exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11282         }
11283 
11284         auto tb1 = exp.e1.type.toBasetype();
11285         auto tb2 = exp.e2.type.toBasetype();
11286         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
11287         {
11288             result = exp.incompatibleTypes();
11289             return;
11290         }
11291 
11292         if (exp.e1.op == TOK.call)
11293             exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
11294         if (exp.e2.op == TOK.call)
11295             exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
11296 
11297         if (exp.e1.type.toBasetype().ty == Tsarray ||
11298             exp.e2.type.toBasetype().ty == Tsarray)
11299             exp.deprecation("identity comparison of static arrays "
11300                 ~ "implicitly coerces them to slices, "
11301                 ~ "which are compared by reference");
11302 
11303         result = exp;
11304     }
11305 
11306     override void visit(CondExp exp)
11307     {
11308         static if (LOGSEMANTIC)
11309         {
11310             printf("CondExp::semantic('%s')\n", exp.toChars());
11311         }
11312         if (exp.type)
11313         {
11314             result = exp;
11315             return;
11316         }
11317 
11318         if (exp.econd.op == TOK.dotIdentifier)
11319             (cast(DotIdExp)exp.econd).noderef = true;
11320 
11321         Expression ec = exp.econd.expressionSemantic(sc);
11322         ec = resolveProperties(sc, ec);
11323         ec = ec.toBoolean(sc);
11324 
11325         CtorFlow ctorflow_root = sc.ctorflow.clone();
11326         Expression e1x = exp.e1.expressionSemantic(sc);
11327         e1x = resolveProperties(sc, e1x);
11328 
11329         CtorFlow ctorflow1 = sc.ctorflow;
11330         sc.ctorflow = ctorflow_root;
11331         Expression e2x = exp.e2.expressionSemantic(sc);
11332         e2x = resolveProperties(sc, e2x);
11333 
11334         sc.merge(exp.loc, ctorflow1);
11335         ctorflow1.freeFieldinit();
11336 
11337         if (ec.op == TOK.error)
11338         {
11339             result = ec;
11340             return;
11341         }
11342         if (ec.type == Type.terror)
11343             return setError();
11344         exp.econd = ec;
11345 
11346         if (e1x.op == TOK.error)
11347         {
11348             result = e1x;
11349             return;
11350         }
11351         if (e1x.type == Type.terror)
11352             return setError();
11353         exp.e1 = e1x;
11354 
11355         if (e2x.op == TOK.error)
11356         {
11357             result = e2x;
11358             return;
11359         }
11360         if (e2x.type == Type.terror)
11361             return setError();
11362         exp.e2 = e2x;
11363 
11364         auto f0 = checkNonAssignmentArrayOp(exp.econd);
11365         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11366         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11367         if (f0 || f1 || f2)
11368             return setError();
11369 
11370         Type t1 = exp.e1.type;
11371         Type t2 = exp.e2.type;
11372         // If either operand is void the result is void, we have to cast both
11373         // the expression to void so that we explicitly discard the expression
11374         // value if any
11375         // https://issues.dlang.org/show_bug.cgi?id=16598
11376         if (t1.ty == Tvoid || t2.ty == Tvoid)
11377         {
11378             exp.type = Type.tvoid;
11379             exp.e1 = exp.e1.castTo(sc, exp.type);
11380             exp.e2 = exp.e2.castTo(sc, exp.type);
11381         }
11382         else if (t1 == t2)
11383             exp.type = t1;
11384         else
11385         {
11386             if (Expression ex = typeCombine(exp, sc))
11387             {
11388                 result = ex;
11389                 return;
11390             }
11391 
11392             switch (exp.e1.type.toBasetype().ty)
11393             {
11394             case Tcomplex32:
11395             case Tcomplex64:
11396             case Tcomplex80:
11397                 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
11398                 break;
11399             default:
11400                 break;
11401             }
11402             switch (exp.e2.type.toBasetype().ty)
11403             {
11404             case Tcomplex32:
11405             case Tcomplex64:
11406             case Tcomplex80:
11407                 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
11408                 break;
11409             default:
11410                 break;
11411             }
11412             if (exp.type.toBasetype().ty == Tarray)
11413             {
11414                 exp.e1 = exp.e1.castTo(sc, exp.type);
11415                 exp.e2 = exp.e2.castTo(sc, exp.type);
11416             }
11417         }
11418         exp.type = exp.type.merge2();
11419         version (none)
11420         {
11421             printf("res: %s\n", exp.type.toChars());
11422             printf("e1 : %s\n", exp.e1.type.toChars());
11423             printf("e2 : %s\n", exp.e2.type.toChars());
11424         }
11425 
11426         /* https://issues.dlang.org/show_bug.cgi?id=14696
11427          * If either e1 or e2 contain temporaries which need dtor,
11428          * make them conditional.
11429          * Rewrite:
11430          *      cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
11431          * to:
11432          *      (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
11433          * and replace edtors of __tmp1 and __tmp2 with:
11434          *      __tmp1.edtor --> __cond && __tmp1.dtor()
11435          *      __tmp2.edtor --> __cond || __tmp2.dtor()
11436          */
11437         exp.hookDtors(sc);
11438 
11439         result = exp;
11440     }
11441 
11442     override void visit(FileInitExp e)
11443     {
11444         //printf("FileInitExp::semantic()\n");
11445         e.type = Type.tstring;
11446         result = e;
11447     }
11448 
11449     override void visit(LineInitExp e)
11450     {
11451         e.type = Type.tint32;
11452         result = e;
11453     }
11454 
11455     override void visit(ModuleInitExp e)
11456     {
11457         //printf("ModuleInitExp::semantic()\n");
11458         e.type = Type.tstring;
11459         result = e;
11460     }
11461 
11462     override void visit(FuncInitExp e)
11463     {
11464         //printf("FuncInitExp::semantic()\n");
11465         e.type = Type.tstring;
11466         if (sc.func)
11467         {
11468             result = e.resolveLoc(Loc.initial, sc);
11469             return;
11470         }
11471         result = e;
11472     }
11473 
11474     override void visit(PrettyFuncInitExp e)
11475     {
11476         //printf("PrettyFuncInitExp::semantic()\n");
11477         e.type = Type.tstring;
11478         if (sc.func)
11479         {
11480             result = e.resolveLoc(Loc.initial, sc);
11481             return;
11482         }
11483 
11484         result = e;
11485     }
11486 }
11487 
11488 /**********************************
11489  * Try to run semantic routines.
11490  * If they fail, return NULL.
11491  */
11492 Expression trySemantic(Expression exp, Scope* sc)
11493 {
11494     //printf("+trySemantic(%s)\n", exp.toChars());
11495     uint errors = global.startGagging();
11496     Expression e = expressionSemantic(exp, sc);
11497     if (global.endGagging(errors))
11498     {
11499         e = null;
11500     }
11501     //printf("-trySemantic(%s)\n", exp.toChars());
11502     return e;
11503 }
11504 
11505 /**************************
11506  * Helper function for easy error propagation.
11507  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11508  */
11509 Expression unaSemantic(UnaExp e, Scope* sc)
11510 {
11511     static if (LOGSEMANTIC)
11512     {
11513         printf("UnaExp::semantic('%s')\n", e.toChars());
11514     }
11515     Expression e1x = e.e1.expressionSemantic(sc);
11516     if (e1x.op == TOK.error)
11517         return e1x;
11518     e.e1 = e1x;
11519     return null;
11520 }
11521 
11522 /**************************
11523  * Helper function for easy error propagation.
11524  * If error occurs, returns ErrorExp. Otherwise returns NULL.
11525  */
11526 Expression binSemantic(BinExp e, Scope* sc)
11527 {
11528     static if (LOGSEMANTIC)
11529     {
11530         printf("BinExp::semantic('%s')\n", e.toChars());
11531     }
11532     Expression e1x = e.e1.expressionSemantic(sc);
11533     Expression e2x = e.e2.expressionSemantic(sc);
11534 
11535     // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11536     if (e1x.op == TOK.type)
11537         e1x = resolveAliasThis(sc, e1x);
11538     if (e2x.op == TOK.type)
11539         e2x = resolveAliasThis(sc, e2x);
11540 
11541     if (e1x.op == TOK.error)
11542         return e1x;
11543     if (e2x.op == TOK.error)
11544         return e2x;
11545     e.e1 = e1x;
11546     e.e2 = e2x;
11547     return null;
11548 }
11549 
11550 Expression binSemanticProp(BinExp e, Scope* sc)
11551 {
11552     if (Expression ex = binSemantic(e, sc))
11553         return ex;
11554     Expression e1x = resolveProperties(sc, e.e1);
11555     Expression e2x = resolveProperties(sc, e.e2);
11556     if (e1x.op == TOK.error)
11557         return e1x;
11558     if (e2x.op == TOK.error)
11559         return e2x;
11560     e.e1 = e1x;
11561     e.e2 = e2x;
11562     return null;
11563 }
11564 
11565 // entrypoint for semantic ExpressionSemanticVisitor
11566 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
11567 {
11568     scope v = new ExpressionSemanticVisitor(sc);
11569     e.accept(v);
11570     return v.result;
11571 }
11572 
11573 Expression semanticX(DotIdExp exp, Scope* sc)
11574 {
11575     //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
11576     if (Expression ex = unaSemantic(exp, sc))
11577         return ex;
11578 
11579     if (exp.ident == Id._mangleof)
11580     {
11581         // symbol.mangleof
11582         Dsymbol ds;
11583         switch (exp.e1.op)
11584         {
11585         case TOK.scope_:
11586             ds = (cast(ScopeExp)exp.e1).sds;
11587             goto L1;
11588         case TOK.variable:
11589             ds = (cast(VarExp)exp.e1).var;
11590             goto L1;
11591         case TOK.dotVariable:
11592             ds = (cast(DotVarExp)exp.e1).var;
11593             goto L1;
11594         case TOK.overloadSet:
11595             ds = (cast(OverExp)exp.e1).vars;
11596             goto L1;
11597         case TOK.template_:
11598             {
11599                 TemplateExp te = cast(TemplateExp)exp.e1;
11600                 ds = te.fd ? cast(Dsymbol)te.fd : te.td;
11601             }
11602         L1:
11603             {
11604                 assert(ds);
11605                 if (auto f = ds.isFuncDeclaration())
11606                 {
11607                     if (f.checkForwardRef(exp.loc))
11608                     {
11609                         return ErrorExp.get();
11610                     }
11611                     if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
11612                                    FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
11613                     {
11614                         f.error(exp.loc, "cannot retrieve its `.mangleof` while inferring attributes");
11615                         return ErrorExp.get();
11616                     }
11617                 }
11618                 OutBuffer buf;
11619                 mangleToBuffer(ds, &buf);
11620                 Expression e = new StringExp(exp.loc, buf.extractSlice());
11621                 e = e.expressionSemantic(sc);
11622                 return e;
11623             }
11624         default:
11625             break;
11626         }
11627     }
11628 
11629     if (exp.e1.op == TOK.variable && exp.e1.type.toBasetype().ty == Tsarray && exp.ident == Id.length)
11630     {
11631         // bypass checkPurity
11632         return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
11633     }
11634 
11635     if (exp.e1.op == TOK.dot)
11636     {
11637     }
11638     else
11639     {
11640         exp.e1 = resolvePropertiesX(sc, exp.e1);
11641     }
11642     if (exp.e1.op == TOK.tuple && exp.ident == Id.offsetof)
11643     {
11644         /* 'distribute' the .offsetof to each of the tuple elements.
11645          */
11646         TupleExp te = cast(TupleExp)exp.e1;
11647         auto exps = new Expressions(te.exps.dim);
11648         for (size_t i = 0; i < exps.dim; i++)
11649         {
11650             Expression e = (*te.exps)[i];
11651             e = e.expressionSemantic(sc);
11652             e = new DotIdExp(e.loc, e, Id.offsetof);
11653             (*exps)[i] = e;
11654         }
11655         // Don't evaluate te.e0 in runtime
11656         Expression e = new TupleExp(exp.loc, null, exps);
11657         e = e.expressionSemantic(sc);
11658         return e;
11659     }
11660     if (exp.e1.op == TOK.tuple && exp.ident == Id.length)
11661     {
11662         TupleExp te = cast(TupleExp)exp.e1;
11663         // Don't evaluate te.e0 in runtime
11664         Expression e = new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
11665         return e;
11666     }
11667 
11668     // https://issues.dlang.org/show_bug.cgi?id=14416
11669     // Template has no built-in properties except for 'stringof'.
11670     if ((exp.e1.op == TOK.dotTemplateDeclaration || exp.e1.op == TOK.template_) && exp.ident != Id.stringof)
11671     {
11672         exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11673         return ErrorExp.get();
11674     }
11675     if (!exp.e1.type)
11676     {
11677         exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
11678         return ErrorExp.get();
11679     }
11680 
11681     return exp;
11682 }
11683 
11684 // Resolve e1.ident without seeing UFCS.
11685 // If flag == 1, stop "not a property" error and return NULL.
11686 Expression semanticY(DotIdExp exp, Scope* sc, int flag)
11687 {
11688     //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
11689 
11690     //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
11691 
11692     /* Special case: rewrite this.id and super.id
11693      * to be classtype.id and baseclasstype.id
11694      * if we have no this pointer.
11695      */
11696     if ((exp.e1.op == TOK.this_ || exp.e1.op == TOK.super_) && !hasThis(sc))
11697     {
11698         if (AggregateDeclaration ad = sc.getStructClassScope())
11699         {
11700             if (exp.e1.op == TOK.this_)
11701             {
11702                 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
11703             }
11704             else
11705             {
11706                 ClassDeclaration cd = ad.isClassDeclaration();
11707                 if (cd && cd.baseClass)
11708                     exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
11709             }
11710         }
11711     }
11712 
11713     Expression e = semanticX(exp, sc);
11714     if (e != exp)
11715         return e;
11716 
11717     Expression eleft;
11718     Expression eright;
11719     if (exp.e1.op == TOK.dot)
11720     {
11721         DotExp de = cast(DotExp)exp.e1;
11722         eleft = de.e1;
11723         eright = de.e2;
11724     }
11725     else
11726     {
11727         eleft = null;
11728         eright = exp.e1;
11729     }
11730 
11731     Type t1b = exp.e1.type.toBasetype();
11732 
11733     if (eright.op == TOK.scope_) // also used for template alias's
11734     {
11735         ScopeExp ie = cast(ScopeExp)eright;
11736 
11737         int flags = SearchLocalsOnly;
11738         /* Disable access to another module's private imports.
11739          * The check for 'is sds our current module' is because
11740          * the current module should have access to its own imports.
11741          */
11742         if (ie.sds.isModule() && ie.sds != sc._module)
11743             flags |= IgnorePrivateImports;
11744         if (sc.flags & SCOPE.ignoresymbolvisibility)
11745             flags |= IgnoreSymbolVisibility;
11746         Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
11747         /* Check for visibility before resolving aliases because public
11748          * aliases to private symbols are public.
11749          */
11750         if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
11751         {
11752             s = null;
11753         }
11754         if (s)
11755         {
11756             auto p = s.isPackage();
11757             if (p && checkAccess(sc, p))
11758             {
11759                 s = null;
11760             }
11761         }
11762         if (s)
11763         {
11764             // if 's' is a tuple variable, the tuple is returned.
11765             s = s.toAlias();
11766 
11767             exp.checkDeprecated(sc, s);
11768             exp.checkDisabled(sc, s);
11769 
11770             EnumMember em = s.isEnumMember();
11771             if (em)
11772             {
11773                 return em.getVarExp(exp.loc, sc);
11774             }
11775             VarDeclaration v = s.isVarDeclaration();
11776             if (v)
11777             {
11778                 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
11779                 if (!v.type ||
11780                     !v.type.deco && v.inuse)
11781                 {
11782                     if (v.inuse)
11783                         exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
11784                     else
11785                         exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
11786                     return ErrorExp.get();
11787                 }
11788                 if (v.type.ty == Terror)
11789                     return ErrorExp.get();
11790 
11791                 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
11792                 {
11793                     /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
11794                      * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
11795                      * be reverted. `wantsym` is the hack to work around the problem.
11796                      */
11797                     if (v.inuse)
11798                     {
11799                         error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
11800                         return ErrorExp.get();
11801                     }
11802                     e = v.expandInitializer(exp.loc);
11803                     v.inuse++;
11804                     e = e.expressionSemantic(sc);
11805                     v.inuse--;
11806                     return e;
11807                 }
11808 
11809                 if (v.needThis())
11810                 {
11811                     if (!eleft)
11812                         eleft = new ThisExp(exp.loc);
11813                     e = new DotVarExp(exp.loc, eleft, v);
11814                     e = e.expressionSemantic(sc);
11815                 }
11816                 else
11817                 {
11818                     e = new VarExp(exp.loc, v);
11819                     if (eleft)
11820                     {
11821                         e = new CommaExp(exp.loc, eleft, e);
11822                         e.type = v.type;
11823                     }
11824                 }
11825                 e = e.deref();
11826                 return e.expressionSemantic(sc);
11827             }
11828 
11829             FuncDeclaration f = s.isFuncDeclaration();
11830             if (f)
11831             {
11832                 //printf("it's a function\n");
11833                 if (!f.functionSemantic())
11834                     return ErrorExp.get();
11835                 if (f.needThis())
11836                 {
11837                     if (!eleft)
11838                         eleft = new ThisExp(exp.loc);
11839                     e = new DotVarExp(exp.loc, eleft, f, true);
11840                     e = e.expressionSemantic(sc);
11841                 }
11842                 else
11843                 {
11844                     e = new VarExp(exp.loc, f, true);
11845                     if (eleft)
11846                     {
11847                         e = new CommaExp(exp.loc, eleft, e);
11848                         e.type = f.type;
11849                     }
11850                 }
11851                 return e;
11852             }
11853             if (auto td = s.isTemplateDeclaration())
11854             {
11855                 if (eleft)
11856                     e = new DotTemplateExp(exp.loc, eleft, td);
11857                 else
11858                     e = new TemplateExp(exp.loc, td);
11859                 e = e.expressionSemantic(sc);
11860                 return e;
11861             }
11862             if (OverDeclaration od = s.isOverDeclaration())
11863             {
11864                 e = new VarExp(exp.loc, od, true);
11865                 if (eleft)
11866                 {
11867                     e = new CommaExp(exp.loc, eleft, e);
11868                     e.type = Type.tvoid; // ambiguous type?
11869                 }
11870                 return e;
11871             }
11872             OverloadSet o = s.isOverloadSet();
11873             if (o)
11874             {
11875                 //printf("'%s' is an overload set\n", o.toChars());
11876                 return new OverExp(exp.loc, o);
11877             }
11878 
11879             if (auto t = s.getType())
11880             {
11881                 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
11882             }
11883 
11884             TupleDeclaration tup = s.isTupleDeclaration();
11885             if (tup)
11886             {
11887                 if (eleft)
11888                 {
11889                     e = new DotVarExp(exp.loc, eleft, tup);
11890                     e = e.expressionSemantic(sc);
11891                     return e;
11892                 }
11893                 e = new TupleExp(exp.loc, tup);
11894                 e = e.expressionSemantic(sc);
11895                 return e;
11896             }
11897 
11898             ScopeDsymbol sds = s.isScopeDsymbol();
11899             if (sds)
11900             {
11901                 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
11902                 e = new ScopeExp(exp.loc, sds);
11903                 e = e.expressionSemantic(sc);
11904                 if (eleft)
11905                     e = new DotExp(exp.loc, eleft, e);
11906                 return e;
11907             }
11908 
11909             Import imp = s.isImport();
11910             if (imp)
11911             {
11912                 ie = new ScopeExp(exp.loc, imp.pkg);
11913                 return ie.expressionSemantic(sc);
11914             }
11915             // BUG: handle other cases like in IdentifierExp::semantic()
11916             debug
11917             {
11918                 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
11919             }
11920             assert(0);
11921         }
11922         else if (exp.ident == Id.stringof)
11923         {
11924             e = new StringExp(exp.loc, ie.toString());
11925             e = e.expressionSemantic(sc);
11926             return e;
11927         }
11928         if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
11929         {
11930             flag = 0;
11931         }
11932         if (flag)
11933             return null;
11934         s = ie.sds.search_correct(exp.ident);
11935         if (s && symbolIsVisible(sc, s))
11936         {
11937             if (s.isPackage())
11938                 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
11939             else
11940                 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());
11941         }
11942         else
11943             exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
11944         return ErrorExp.get();
11945     }
11946     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)
11947     {
11948         Type t1bn = t1b.nextOf();
11949         if (flag)
11950         {
11951             AggregateDeclaration ad = isAggregate(t1bn);
11952             if (ad && !ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
11953                 return null;
11954         }
11955 
11956         /* Rewrite:
11957          *   p.ident
11958          * as:
11959          *   (*p).ident
11960          */
11961         if (flag && t1bn.ty == Tvoid)
11962             return null;
11963         e = new PtrExp(exp.loc, exp.e1);
11964         e = e.expressionSemantic(sc);
11965         return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
11966     }
11967     else
11968     {
11969         if (exp.e1.op == TOK.type || exp.e1.op == TOK.template_)
11970             flag = 0;
11971         e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
11972         if (e)
11973             e = e.expressionSemantic(sc);
11974         return e;
11975     }
11976 }
11977 
11978 // Resolve e1.ident!tiargs without seeing UFCS.
11979 // If flag == 1, stop "not a property" error and return NULL.
11980 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
11981 {
11982     static if (LOGSEMANTIC)
11983     {
11984         printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
11985     }
11986 
11987     static Expression errorExp()
11988     {
11989         return ErrorExp.get();
11990     }
11991 
11992     Expression e1 = exp.e1;
11993 
11994     if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
11995     {
11996         // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
11997         // and do the symbol search in that context (Issue: 19476)
11998         auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
11999         e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12000     }
12001 
12002     auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12003 
12004     Expression e = die.semanticX(sc);
12005     if (e == die)
12006     {
12007         exp.e1 = die.e1; // take back
12008         Type t1b = exp.e1.type.toBasetype();
12009         if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12010         {
12011             /* No built-in type has templatized properties, so do shortcut.
12012              * It is necessary in: 1024.max!"a < b"
12013              */
12014             if (flag)
12015                 return null;
12016         }
12017         e = die.semanticY(sc, flag);
12018         if (flag)
12019         {
12020             if (!e ||
12021                 isDotOpDispatch(e))
12022             {
12023                 /* opDispatch!tiargs would be a function template that needs IFTI,
12024                  * so it's not a template
12025                  */
12026                 return null;
12027             }
12028         }
12029     }
12030     assert(e);
12031 
12032     if (e.op == TOK.error)
12033         return e;
12034     if (e.op == TOK.dotVariable)
12035     {
12036         DotVarExp dve = cast(DotVarExp)e;
12037         if (FuncDeclaration fd = dve.var.isFuncDeclaration())
12038         {
12039             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12040             {
12041                 e = new DotTemplateExp(dve.loc, dve.e1, td);
12042                 e = e.expressionSemantic(sc);
12043             }
12044         }
12045         else if (OverDeclaration od = dve.var.isOverDeclaration())
12046         {
12047             exp.e1 = dve.e1; // pull semantic() result
12048 
12049             if (!exp.findTempDecl(sc))
12050                 goto Lerr;
12051             if (exp.ti.needsTypeInference(sc))
12052                 return exp;
12053             exp.ti.dsymbolSemantic(sc);
12054             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12055                 return errorExp();
12056 
12057             if (Declaration v = exp.ti.toAlias().isDeclaration())
12058             {
12059                 if (v.type && !v.type.deco)
12060                     v.type = v.type.typeSemantic(v.loc, sc);
12061                 return new DotVarExp(exp.loc, exp.e1, v)
12062                        .expressionSemantic(sc);
12063             }
12064             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12065                    .expressionSemantic(sc);
12066         }
12067     }
12068     else if (e.op == TOK.variable)
12069     {
12070         VarExp ve = cast(VarExp)e;
12071         if (FuncDeclaration fd = ve.var.isFuncDeclaration())
12072         {
12073             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12074             {
12075                 e = new TemplateExp(ve.loc, td)
12076                     .expressionSemantic(sc);
12077             }
12078         }
12079         else if (OverDeclaration od = ve.var.isOverDeclaration())
12080         {
12081             exp.ti.tempdecl = od;
12082             return new ScopeExp(exp.loc, exp.ti)
12083                    .expressionSemantic(sc);
12084         }
12085     }
12086 
12087     if (e.op == TOK.dotTemplateDeclaration)
12088     {
12089         DotTemplateExp dte = cast(DotTemplateExp)e;
12090         exp.e1 = dte.e1; // pull semantic() result
12091 
12092         exp.ti.tempdecl = dte.td;
12093         if (!exp.ti.semanticTiargs(sc))
12094             return errorExp();
12095         if (exp.ti.needsTypeInference(sc))
12096             return exp;
12097         exp.ti.dsymbolSemantic(sc);
12098         if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12099             return errorExp();
12100 
12101         if (Declaration v = exp.ti.toAlias().isDeclaration())
12102         {
12103             if (v.isFuncDeclaration() || v.isVarDeclaration())
12104             {
12105                 return new DotVarExp(exp.loc, exp.e1, v)
12106                        .expressionSemantic(sc);
12107             }
12108         }
12109         return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12110                .expressionSemantic(sc);
12111     }
12112     else if (e.op == TOK.template_)
12113     {
12114         exp.ti.tempdecl = (cast(TemplateExp)e).td;
12115         return new ScopeExp(exp.loc, exp.ti)
12116                .expressionSemantic(sc);
12117     }
12118     else if (e.op == TOK.dot)
12119     {
12120         DotExp de = cast(DotExp)e;
12121 
12122         if (de.e2.op == TOK.overloadSet)
12123         {
12124             if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
12125             {
12126                 return errorExp();
12127             }
12128             if (exp.ti.needsTypeInference(sc))
12129                 return exp;
12130             exp.ti.dsymbolSemantic(sc);
12131             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12132                 return errorExp();
12133 
12134             if (Declaration v = exp.ti.toAlias().isDeclaration())
12135             {
12136                 if (v.type && !v.type.deco)
12137                     v.type = v.type.typeSemantic(v.loc, sc);
12138                 return new DotVarExp(exp.loc, exp.e1, v)
12139                        .expressionSemantic(sc);
12140             }
12141             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12142                    .expressionSemantic(sc);
12143         }
12144     }
12145     else if (e.op == TOK.overloadSet)
12146     {
12147         OverExp oe = cast(OverExp)e;
12148         exp.ti.tempdecl = oe.vars;
12149         return new ScopeExp(exp.loc, exp.ti)
12150                .expressionSemantic(sc);
12151     }
12152 
12153 Lerr:
12154     exp.error("`%s` isn't a template", e.toChars());
12155     return errorExp();
12156 }
12157 
12158 /***************************************
12159  * If expression is shared, check that we can access it.
12160  * Give error message if not.
12161  *
12162  * Params:
12163  *      e = expression to check
12164  *      sc = context
12165  *      returnRef = Whether this expression is for a `return` statement
12166  *                  off a `ref` function, in which case a single level
12167  *                  of dereference is allowed (e.g. `shared(int)*`).
12168  * Returns:
12169  *      true on error
12170  */
12171 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
12172 {
12173     if (!global.params.noSharedAccess ||
12174         sc.intypeof ||
12175         sc.flags & SCOPE.ctfe)
12176     {
12177         return false;
12178     }
12179 
12180     //printf("checkSharedAccess() %s\n", e.toChars());
12181 
12182     static extern(C++) final class SharedCheckVisitor : SemanticTimeTransitiveVisitor
12183     {
12184         /// In case we don't know which expression triggered it,
12185         /// e.g. for `visit(Type)` overload
12186         Expression original;
12187         /// Where the result is stored (`true` == error)
12188         bool result;
12189         /// Whether we should allow one level of dereferencing
12190         bool allowRef;
12191 
12192         /// Ctor
12193         this(Expression oe, bool allowRef_)
12194         {
12195             this.original = oe;
12196             this.allowRef = allowRef_;
12197         }
12198 
12199         void sharedError(Expression e)
12200         {
12201             // https://dlang.org/phobos/core_atomic.html
12202             e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
12203             this.result = true;
12204         }
12205 
12206         /// Introduce base class overrides
12207         alias visit = SemanticTimeTransitiveVisitor.visit;
12208 
12209         // Error by default
12210         override void visit(Expression e)
12211         {
12212             if (e.type.isShared())
12213                 this.sharedError(e);
12214         }
12215 
12216         /// Ditto
12217         override void visit(Type t)
12218         {
12219             // Note: This handles things like `new shared(Throwable).msg`,
12220             // where accessing `msg` would violate `shared`.
12221             if (t.isShared())
12222                 this.sharedError(this.original);
12223         }
12224 
12225         // Those have no indirections / can be ignored
12226         override void visit(ErrorExp e) {}
12227         override void visit(ComplexExp e) {}
12228         override void visit(IntegerExp e) {}
12229         override void visit(NullExp e) {}
12230 
12231         override void visit(VarExp e)
12232         {
12233             if (!this.allowRef && e.var.type.isShared())
12234                 this.sharedError(e);
12235         }
12236 
12237         override void visit(AddrExp e)
12238         {
12239             this.allowRef = true;
12240             e.e1.accept(this);
12241         }
12242 
12243         override void visit(PtrExp e)
12244         {
12245             if (!this.allowRef && e.type.isShared())
12246                 return this.sharedError(e);
12247 
12248             if (e.e1.type.isShared())
12249                 return this.sharedError(e);
12250 
12251             this.allowRef = false;
12252             e.e1.accept(this);
12253         }
12254 
12255         override void visit(DotVarExp e)
12256         {
12257             if (!this.allowRef && e.type.isShared())
12258                 return this.sharedError(e);
12259 
12260             // Allow to use `DotVarExp` within value types
12261             if (e.e1.type.ty == Tsarray || e.e1.type.ty == Tstruct)
12262                 return e.e1.accept(this);
12263 
12264             // If we end up with a single `VarExp`, it might be a `ref` param
12265             // `shared ref T` param == `shared(T)*`.
12266             if (auto ve = e.e1.isVarExp())
12267             {
12268                 this.allowRef = this.allowRef && (ve.var.storage_class & STC.ref_);
12269                 return e.e1.accept(this);
12270             }
12271 
12272             this.allowRef = false;
12273             return e.e1.accept(this);
12274         }
12275 
12276         override void visit(IndexExp e)
12277         {
12278             if (!this.allowRef && e.type.isShared())
12279                 return this.sharedError(e);
12280 
12281             if (e.e1.type.isShared())
12282                 return this.sharedError(e);
12283 
12284             this.allowRef = false;
12285             e.e1.accept(this);
12286         }
12287 
12288         override void visit(CommaExp e)
12289         {
12290             // Cannot be `return ref` since we can't use the return,
12291             // but it's better to show that error than an unrelated `shared` one
12292             this.allowRef = true;
12293             e.e2.accept(this);
12294         }
12295     }
12296 
12297     scope visitor = new SharedCheckVisitor(e, returnRef);
12298     e.accept(visitor);
12299     return visitor.result;
12300 }
12301 
12302 
12303 
12304 /****************************************************
12305  * Determine if `exp`, which gets its address taken, can do so safely.
12306  * Params:
12307  *      sc = context
12308  *      exp = expression having its address taken
12309  *      v = the variable getting its address taken
12310  * Returns:
12311  *      `true` if ok, `false` for error
12312  */
12313 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
12314 {
12315     //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
12316     if (v)
12317     {
12318         if (!v.canTakeAddressOf())
12319         {
12320             exp.error("cannot take address of `%s`", exp.toChars());
12321             return false;
12322         }
12323         if (sc.func && !sc.intypeof && !v.isDataseg())
12324         {
12325             const(char)* p = v.isParameter() ? "parameter" : "local";
12326             if (global.params.vsafe)
12327             {
12328                 // Taking the address of v means it cannot be set to 'scope' later
12329                 v.storage_class &= ~STC.maybescope;
12330                 v.doNotInferScope = true;
12331                 if (exp.type.hasPointers() && v.storage_class & STC.scope_ &&
12332                     !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
12333                 {
12334                     exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12335                     return false;
12336                 }
12337             }
12338             else if (!(sc.flags & SCOPE.debug_) &&
12339                      sc.func.setUnsafe())
12340             {
12341                 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12342                 return false;
12343             }
12344         }
12345     }
12346     return true;
12347 }
12348 
12349 /*******************************
12350  * Checks the attributes of a function.
12351  * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
12352  * and usage of `deprecated` and `@disabled`-ed symbols are checked.
12353  *
12354  * Params:
12355  *  exp = expression to check attributes for
12356  *  sc  = scope of the function
12357  *  f   = function to be checked
12358  * Returns: `true` if error occur.
12359  */
12360 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
12361 {
12362     with(exp)
12363     {
12364         bool error = checkDisabled(sc, f);
12365         error |= checkDeprecated(sc, f);
12366         error |= checkPurity(sc, f);
12367         error |= checkSafety(sc, f);
12368         error |= checkNogc(sc, f);
12369         return error;
12370     }
12371 }
12372 
12373 /*******************************
12374  * Helper function for `getRightThis()`.
12375  * Gets `this` of the next outer aggregate.
12376  * Params:
12377  *      loc = location to use for error messages
12378  *      sc = context
12379  *      s = the parent symbol of the existing `this`
12380  *      ad = struct or class we need the correct `this` for
12381  *      e1 = existing `this`
12382  *      t = type of the existing `this`
12383  *      var = the specific member of ad we're accessing
12384  *      flag = if true, return `null` instead of throwing an error
12385  * Returns:
12386  *      Expression representing the `this` for the var
12387  */
12388 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
12389 {
12390     int n = 0;
12391     while (s && s.isFuncDeclaration())
12392     {
12393         FuncDeclaration f = s.isFuncDeclaration();
12394         if (f.vthis)
12395         {
12396             n++;
12397             e1 = new VarExp(loc, f.vthis);
12398             if (f.isThis2)
12399             {
12400                 // (*__this)[i]
12401                 if (n > 1)
12402                     e1 = e1.expressionSemantic(sc);
12403                 e1 = new PtrExp(loc, e1);
12404                 uint i = f.followInstantiationContext(ad);
12405                 e1 = new IndexExp(loc, e1, new IntegerExp(i));
12406                 s = f.toParentP(ad);
12407                 continue;
12408             }
12409         }
12410         else
12411         {
12412             if (flag)
12413                 return null;
12414             e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
12415             e1 = ErrorExp.get();
12416             return e1;
12417         }
12418         s = s.toParent2();
12419     }
12420     if (n > 1 || e1.op == TOK.index)
12421         e1 = e1.expressionSemantic(sc);
12422     if (s && e1.type.equivalent(Type.tvoidptr))
12423     {
12424         if (auto sad = s.isAggregateDeclaration())
12425         {
12426             Type ta = sad.handleType();
12427             if (ta.ty == Tstruct)
12428                 ta = ta.pointerTo();
12429             e1.type = ta;
12430         }
12431     }
12432     e1.type = e1.type.addMod(t.mod);
12433     return e1;
12434 }
12435 
12436 /*******************************
12437  * Make a dual-context container for use as a `this` argument.
12438  * Params:
12439  *      loc = location to use for error messages
12440  *      sc = current scope
12441  *      fd = target function that will take the `this` argument
12442  * Returns:
12443  *      Temporary closure variable.
12444  * Note:
12445  *      The function `fd` is added to the nested references of the
12446  *      newly created variable such that a closure is made for the variable when
12447  *      the address of `fd` is taken.
12448  */
12449 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
12450 {
12451     Type tthis2 = Type.tvoidptr.sarrayOf(2);
12452     VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
12453     vthis2.storage_class |= STC.temp;
12454     vthis2.dsymbolSemantic(sc);
12455     vthis2.parent = sc.parent;
12456     // make it a closure var
12457     assert(sc.func);
12458     sc.func.closureVars.push(vthis2);
12459     // add `fd` to the nested refs
12460     vthis2.nestedrefs.push(fd);
12461     return vthis2;
12462 }
12463 
12464 /*******************************
12465  * Make sure that the runtime hook `id` exists.
12466  * Params:
12467  *      loc = location to use for error messages
12468  *      sc = current scope
12469  *      id = the hook identifier
12470  *      description = what the hook does
12471  *      module_ = what module the hook is located in
12472  * Returns:
12473  *      a `bool` indicating if the hook is present.
12474  */
12475 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
12476 {
12477     auto rootSymbol = sc.search(loc, Id.empty, null);
12478     if (auto moduleSymbol = rootSymbol.search(loc, module_))
12479         if (moduleSymbol.search(loc, id))
12480           return true;
12481     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);
12482     return false;
12483 }
12484 
12485 /**
12486  * Check if an expression is an access to a struct member with the struct
12487  * defined from a literal.
12488  *
12489  * This happens with manifest constants since the initializer is reused as is,
12490  * each time the declaration is part of an expression, which means that the
12491  * literal used as initializer can become a Lvalue. This Lvalue must not be modifiable.
12492  *
12493  * Params:
12494  *      exp = An expression that's attempted to be written.
12495  *            Must be the LHS of an `AssignExp`, `BinAssignExp`, `CatAssignExp`,
12496  *            or the expression passed to a modifiable function parameter.
12497  * Returns:
12498  *      `true` if `expr` is a dot var or a dot identifier touching to a struct literal,
12499  *      in which case an error message is issued, and `false` otherwise.
12500  */
12501 private bool checkIfIsStructLiteralDotExpr(Expression exp)
12502 {
12503     // e1.var = ...
12504     // e1.ident = ...
12505     Expression e1;
12506     if (exp.op == TOK.dotVariable)
12507         e1 = exp.isDotVarExp().e1;
12508     else if (exp.op == TOK.dotIdentifier)
12509         e1 = exp.isDotIdExp().e1;
12510     else
12511         return false;
12512 
12513     // enum SomeStruct ss = { ... }
12514     // also true for access from a .init: SomeStruct.init.member = ...
12515     if (e1.op != TOK.structLiteral)
12516         return false;
12517 
12518     error(exp.loc, "cannot modify constant expression `%s`", exp.toChars());
12519     return true;
12520 }