xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/expressionsem.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /**
2  * Semantic analysis of expressions.
3  *
4  * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5  *
6  * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
7  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
8  * License:     $(LINK2 https://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.astenums;
26 import dmd.canthrow;
27 import dmd.chkformat;
28 import dmd.ctorflow;
29 import dmd.dscope;
30 import dmd.dsymbol;
31 import dmd.declaration;
32 import dmd.dclass;
33 import dmd.dcast;
34 import dmd.delegatize;
35 import dmd.denum;
36 import dmd.dimport;
37 import dmd.dinterpret;
38 import dmd.dmangle;
39 import dmd.dmodule;
40 import dmd.dstruct;
41 import dmd.dsymbolsem;
42 import dmd.dtemplate;
43 import dmd.errors;
44 import dmd.escape;
45 import dmd.expression;
46 import dmd.file_manager;
47 import dmd.func;
48 import dmd.globals;
49 import dmd.hdrgen;
50 import dmd.id;
51 import dmd.identifier;
52 import dmd.imphint;
53 import dmd.importc;
54 import dmd.init;
55 import dmd.initsem;
56 import dmd.inline;
57 import dmd.intrange;
58 import dmd.mtype;
59 import dmd.mustuse;
60 import dmd.nspace;
61 import dmd.opover;
62 import dmd.optimize;
63 import dmd.parse;
64 import dmd.printast;
65 import dmd.root.ctfloat;
66 import dmd.root.file;
67 import dmd.root.filename;
68 import dmd.common.outbuffer;
69 import dmd.root.rootobject;
70 import dmd.root.string;
71 import dmd.root.utf;
72 import dmd.semantic2;
73 import dmd.semantic3;
74 import dmd.sideeffect;
75 import dmd.safe;
76 import dmd.target;
77 import dmd.tokens;
78 import dmd.traits;
79 import dmd.typesem;
80 import dmd.typinf;
81 import dmd.utils;
82 import dmd.visitor;
83 
84 enum LOGSEMANTIC = false;
85 
86 /********************************************************
87  * Perform semantic analysis and CTFE on expressions to produce
88  * a string.
89  * Params:
90  *      buf = append generated string to buffer
91  *      sc = context
92  *      exps = array of Expressions
93  * Returns:
94  *      true on error
95  */
expressionsToString(ref OutBuffer buf,Scope * sc,Expressions * exps)96 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
97 {
98     if (!exps)
99         return false;
100 
101     foreach (ex; *exps)
102     {
103         if (!ex)
104             continue;
105         auto sc2 = sc.startCTFE();
106         auto e2 = ex.expressionSemantic(sc2);
107         auto e3 = resolveProperties(sc2, e2);
108         sc2.endCTFE();
109 
110         // allowed to contain types as well as expressions
111         auto e4 = ctfeInterpretForPragmaMsg(e3);
112         if (!e4 || e4.op == EXP.error)
113             return true;
114 
115         // expand tuple
116         if (auto te = e4.isTupleExp())
117         {
118             if (expressionsToString(buf, sc, te.exps))
119                 return true;
120             continue;
121         }
122         // char literals exp `.toStringExp` return `null` but we cant override it
123         // because in most contexts we don't want the conversion to succeed.
124         IntegerExp ie = e4.isIntegerExp();
125         const ty = (ie && ie.type) ? ie.type.ty : Terror;
126         if (ty.isSomeChar)
127         {
128             auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
129             e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
130         }
131 
132         if (StringExp se = e4.toStringExp())
133             buf.writestring(se.toUTF8(sc).peekString());
134         else
135             buf.writestring(e4.toString());
136     }
137     return false;
138 }
139 
140 
141 /***********************************************************
142  * Resolve `exp` as a compile-time known string.
143  * Params:
144  *  sc  = scope
145  *  exp = Expression which expected as a string
146  *  s   = What the string is expected for, will be used in error diagnostic.
147  * Returns:
148  *  String literal, or `null` if error happens.
149  */
semanticString(Scope * sc,Expression exp,const char * s)150 StringExp semanticString(Scope *sc, Expression exp, const char* s)
151 {
152     sc = sc.startCTFE();
153     exp = exp.expressionSemantic(sc);
154     exp = resolveProperties(sc, exp);
155     sc = sc.endCTFE();
156 
157     if (exp.op == EXP.error)
158         return null;
159 
160     auto e = exp;
161     if (exp.type.isString())
162     {
163         e = e.ctfeInterpret();
164         if (e.op == EXP.error)
165             return null;
166     }
167 
168     auto se = e.toStringExp();
169     if (!se)
170     {
171         exp.error("`string` expected for %s, not `(%s)` of type `%s`",
172             s, exp.toChars(), exp.type.toChars());
173         return null;
174     }
175     return se;
176 }
177 
extractOpDollarSideEffect(Scope * sc,UnaExp ue)178 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
179 {
180     Expression e0;
181     Expression e1 = Expression.extractLast(ue.e1, e0);
182     // https://issues.dlang.org/show_bug.cgi?id=12585
183     // Extract the side effect part if ue.e1 is comma.
184 
185     if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
186     {
187         /* Even if opDollar is needed, 'e1' should be evaluate only once. So
188          * Rewrite:
189          *      e1.opIndex( ... use of $ ... )
190          *      e1.opSlice( ... use of $ ... )
191          * as:
192          *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
193          *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
194          */
195         e1 = extractSideEffect(sc, "__dop", e0, e1, false);
196         assert(e1.isVarExp());
197         e1.isVarExp().var.storage_class |= STC.exptemp;     // lifetime limited to expression
198     }
199     ue.e1 = e1;
200     return e0;
201 }
202 
203 /**************************************
204  * Runs semantic on ae.arguments. Declares temporary variables
205  * if '$' was used.
206  */
resolveOpDollar(Scope * sc,ArrayExp ae,Expression * pe0)207 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
208 {
209     assert(!ae.lengthVar);
210     *pe0 = null;
211     AggregateDeclaration ad = isAggregate(ae.e1.type);
212     Dsymbol slice = search_function(ad, Id.slice);
213     //printf("slice = %s %s\n", slice.kind(), slice.toChars());
214     foreach (i, e; *ae.arguments)
215     {
216         if (i == 0)
217             *pe0 = extractOpDollarSideEffect(sc, ae);
218 
219         if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
220         {
221         Lfallback:
222             if (ae.arguments.dim == 1)
223                 return null;
224             ae.error("multi-dimensional slicing requires template `opSlice`");
225             return ErrorExp.get();
226         }
227         //printf("[%d] e = %s\n", i, e.toChars());
228 
229         // Create scope for '$' variable for this dimension
230         auto sym = new ArrayScopeSymbol(sc, ae);
231         sym.parent = sc.scopesym;
232         sc = sc.push(sym);
233         ae.lengthVar = null; // Create it only if required
234         ae.currentDimension = i; // Dimension for $, if required
235 
236         e = e.expressionSemantic(sc);
237         e = resolveProperties(sc, e);
238 
239         if (ae.lengthVar && sc.func)
240         {
241             // If $ was used, declare it now
242             Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
243             de = de.expressionSemantic(sc);
244             *pe0 = Expression.combine(*pe0, de);
245         }
246         sc = sc.pop();
247 
248         if (auto ie = e.isIntervalExp())
249         {
250             auto tiargs = new Objects();
251             Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
252             edim = edim.expressionSemantic(sc);
253             tiargs.push(edim);
254 
255             auto fargs = new Expressions(2);
256             (*fargs)[0] = ie.lwr;
257             (*fargs)[1] = ie.upr;
258 
259             uint xerrors = global.startGagging();
260             sc = sc.push();
261             FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
262             sc = sc.pop();
263             global.endGagging(xerrors);
264             if (!fslice)
265                 goto Lfallback;
266 
267             e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
268             e = new CallExp(ae.loc, e, fargs);
269             e = e.expressionSemantic(sc);
270         }
271 
272         if (!e.type)
273         {
274             ae.error("`%s` has no value", e.toChars());
275             e = ErrorExp.get();
276         }
277         if (e.op == EXP.error)
278             return e;
279 
280         (*ae.arguments)[i] = e;
281     }
282     return ae;
283 }
284 
285 /**************************************
286  * Runs semantic on se.lwr and se.upr. Declares a temporary variable
287  * if '$' was used.
288  * Returns:
289  *      ae, or ErrorExp if errors occurred
290  */
resolveOpDollar(Scope * sc,ArrayExp ae,IntervalExp ie,Expression * pe0)291 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
292 {
293     //assert(!ae.lengthVar);
294     if (!ie)
295         return ae;
296 
297     VarDeclaration lengthVar = ae.lengthVar;
298     bool errors = false;
299 
300     // create scope for '$'
301     auto sym = new ArrayScopeSymbol(sc, ae);
302     sym.parent = sc.scopesym;
303     sc = sc.push(sym);
304 
305     Expression sem(Expression e)
306     {
307         e = e.expressionSemantic(sc);
308         e = resolveProperties(sc, e);
309         if (!e.type)
310         {
311             ae.error("`%s` has no value", e.toChars());
312             errors = true;
313         }
314         return e;
315     }
316 
317     ie.lwr = sem(ie.lwr);
318     ie.upr = sem(ie.upr);
319 
320     if (ie.lwr.isErrorExp() || ie.upr.isErrorExp())
321         errors = true;
322 
323     if (lengthVar != ae.lengthVar && sc.func)
324     {
325         // If $ was used, declare it now
326         Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
327         de = de.expressionSemantic(sc);
328         *pe0 = Expression.combine(*pe0, de);
329     }
330 
331     sc = sc.pop();
332 
333     return errors ? ErrorExp.get() : ae;
334 }
335 
336 /******************************
337  * Perform semantic() on an array of Expressions.
338  */
339 bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
340 {
341     bool err = false;
342     if (exps)
343     {
foreach(ref e;* exps)344         foreach (ref e; *exps)
345         {
346             if (e)
347             {
348                 auto e2 = e.expressionSemantic(sc);
349                 if (e2.op == EXP.error)
350                     err = true;
351                 if (preserveErrors || e2.op != EXP.error)
352                     e = e2;
353             }
354         }
355     }
356     return err;
357 }
358 
359 /******************************
360  * Check the tail CallExp is really property function call.
361  * Bugs:
362  * This doesn't appear to do anything.
363  */
checkPropertyCall(Expression e)364 private bool checkPropertyCall(Expression e)
365 {
366     e = lastComma(e);
367 
368     if (auto ce = e.isCallExp())
369     {
370         if (ce.f)
371         {
372             auto tf = ce.f.type.isTypeFunction();
373             /* If a forward reference to ce.f, try to resolve it
374              */
375             if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
376             {
377                 ce.f.dsymbolSemantic(null);
378                 tf = ce.f.type.isTypeFunction();
379             }
380         }
381         else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
382             assert(0);
383     }
384     return false;
385 }
386 
387 /******************************
388  * Find symbol in accordance with the UFCS name look up rule
389  */
searchUFCS(Scope * sc,UnaExp ue,Identifier ident)390 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
391 {
392     //printf("searchUFCS(ident = %s)\n", ident.toChars());
393     Loc loc = ue.loc;
394 
395     // TODO: merge with Scope.search.searchScopes()
396     Dsymbol searchScopes(int flags)
397     {
398         Dsymbol s = null;
399         for (Scope* scx = sc; scx; scx = scx.enclosing)
400         {
401             if (!scx.scopesym)
402                 continue;
403             if (scx.scopesym.isModule())
404                 flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
405             s = scx.scopesym.search(loc, ident, flags);
406             if (s)
407             {
408                 // overload set contains only module scope symbols.
409                 if (s.isOverloadSet())
410                     break;
411                 // selective/renamed imports also be picked up
412                 if (AliasDeclaration ad = s.isAliasDeclaration())
413                 {
414                     if (ad._import)
415                         break;
416                 }
417                 // See only module scope symbols for UFCS target.
418                 Dsymbol p = s.toParent2();
419                 if (p && p.isModule())
420                     break;
421             }
422             s = null;
423 
424             // Stop when we hit a module, but keep going if that is not just under the global scope
425             if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
426                 break;
427         }
428         return s;
429     }
430 
431     int flags = 0;
432     Dsymbol s;
433 
434     if (sc.flags & SCOPE.ignoresymbolvisibility)
435         flags |= IgnoreSymbolVisibility;
436 
437     // First look in local scopes
438     s = searchScopes(flags | SearchLocalsOnly);
439     if (!s)
440     {
441         // Second look in imported modules
442         s = searchScopes(flags | SearchImportsOnly);
443     }
444 
445     if (!s)
446         return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
447 
448     FuncDeclaration f = s.isFuncDeclaration();
449     if (f)
450     {
451         TemplateDeclaration td = getFuncTemplateDecl(f);
452         if (td)
453         {
454             if (td.overroot)
455                 td = td.overroot;
456             s = td;
457         }
458     }
459 
460     if (auto dti = ue.isDotTemplateInstanceExp())
461     {
462         auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
463         if (!ti.updateTempDecl(sc, s))
464             return ErrorExp.get();
465         return new ScopeExp(loc, ti);
466     }
467     else
468     {
469         //printf("-searchUFCS() %s\n", s.toChars());
470         return new DsymbolExp(loc, s);
471     }
472 }
473 
474 /******************************
475  * Pull out callable entity with UFCS.
476  */
resolveUFCS(Scope * sc,CallExp ce)477 private Expression resolveUFCS(Scope* sc, CallExp ce)
478 {
479     Loc loc = ce.loc;
480     Expression eleft;
481     Expression e;
482 
483     if (auto die = ce.e1.isDotIdExp())
484     {
485         Identifier ident = die.ident;
486 
487         Expression ex = die.semanticX(sc);
488         if (ex != die)
489         {
490             ce.e1 = ex;
491             return null;
492         }
493         eleft = die.e1;
494 
495         Type t = eleft.type.toBasetype();
496         if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
497         {
498             /* Built-in types and arrays have no callable properties, so do shortcut.
499              * It is necessary in: e.init()
500              */
501         }
502         else if (t.ty == Taarray)
503         {
504             if (ident == Id.remove)
505             {
506                 /* Transform:
507                  *  aa.remove(arg) into delete aa[arg]
508                  */
509                 if (!ce.arguments || ce.arguments.dim != 1)
510                 {
511                     ce.error("expected key as argument to `aa.remove()`");
512                     return ErrorExp.get();
513                 }
514                 if (!eleft.type.isMutable())
515                 {
516                     ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
517                     return ErrorExp.get();
518                 }
519                 Expression key = (*ce.arguments)[0];
520                 key = key.expressionSemantic(sc);
521                 key = resolveProperties(sc, key);
522 
523                 TypeAArray taa = t.isTypeAArray();
524                 key = key.implicitCastTo(sc, taa.index);
525 
526                 if (key.checkValue() || key.checkSharedAccess(sc))
527                     return ErrorExp.get();
528 
529                 semanticTypeInfo(sc, taa.index);
530 
531                 return new RemoveExp(loc, eleft, key);
532             }
533         }
534         else
535         {
536             if (Expression ey = die.semanticY(sc, 1))
537             {
538                 if (ey.op == EXP.error)
539                     return ey;
540                 ce.e1 = ey;
541                 if (isDotOpDispatch(ey))
542                 {
543                     // even opDispatch and UFCS must have valid arguments,
544                     // so now that we've seen indication of a problem,
545                     // check them for issues.
546                     Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
547 
548                     uint errors = global.startGagging();
549                     e = ce.expressionSemantic(sc);
550                     if (!global.endGagging(errors))
551                         return e;
552 
553                     if (arrayExpressionSemantic(originalArguments, sc))
554                         return ErrorExp.get();
555 
556                     /* fall down to UFCS */
557                 }
558                 else
559                     return null;
560             }
561         }
562 
563         /* https://issues.dlang.org/show_bug.cgi?id=13953
564          *
565          * If a struct has an alias this to an associative array
566          * and remove is used on a struct instance, we have to
567          * check first if there is a remove function that can be called
568          * on the struct. If not we must check the alias this.
569          *
570          * struct A
571          * {
572          *      string[string] a;
573          *      alias a this;
574          * }
575          *
576          * void fun()
577          * {
578          *      A s;
579          *      s.remove("foo");
580          * }
581          */
582         const errors = global.startGagging();
583         e = searchUFCS(sc, die, ident);
584         // if there were any errors and the identifier was remove
585         if (global.endGagging(errors))
586         {
587             if (ident == Id.remove)
588             {
589                 // check alias this
590                 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
591                 if (alias_e && alias_e != die.e1)
592                 {
593                     die.e1 = alias_e;
594                     CallExp ce2 = ce.syntaxCopy();
595                     ce2.e1 = die;
596                     e = ce2.isCallExp().trySemantic(sc);
597                     if (e)
598                         return e;
599                 }
600             }
601             // if alias this did not work out, print the initial errors
602             searchUFCS(sc, die, ident);
603         }
604     }
605     else if (auto dti = ce.e1.isDotTemplateInstanceExp())
606     {
607         if (Expression ey = dti.semanticY(sc, 1))
608         {
609             ce.e1 = ey;
610             return null;
611         }
612         eleft = dti.e1;
613         e = searchUFCS(sc, dti, dti.ti.name);
614     }
615     else
616         return null;
617 
618     // Rewrite
619     ce.e1 = e;
620     if (!ce.arguments)
621         ce.arguments = new Expressions();
622     ce.arguments.shift(eleft);
623 
624     return null;
625 }
626 
627 /******************************
628  * Pull out property with UFCS.
629  */
630 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
631 {
632     Loc loc = e1.loc;
633     Expression eleft;
634     Expression e;
635 
636     if (auto die = e1.isDotIdExp())
637     {
638         eleft = die.e1;
639         e = searchUFCS(sc, die, die.ident);
640     }
641     else if (auto dti = e1.isDotTemplateInstanceExp())
642     {
643         eleft = dti.e1;
644         e = searchUFCS(sc, dti, dti.ti.name);
645     }
646     else
647         return null;
648 
649     if (e is null)
650         return null;
651 
652     // Rewrite
653     if (e2)
654     {
655         // run semantic without gagging
656         e2 = e2.expressionSemantic(sc);
657 
658         /* f(e1) = e2
659          */
660         Expression ex = e.copy();
661         auto a1 = new Expressions(1);
662         (*a1)[0] = eleft;
663         ex = new CallExp(loc, ex, a1);
664         auto e1PassSemantic = ex.trySemantic(sc);
665 
666         /* f(e1, e2)
667          */
668         auto a2 = new Expressions(2);
669         (*a2)[0] = eleft;
670         (*a2)[1] = e2;
671         e = new CallExp(loc, e, a2);
672         e = e.trySemantic(sc);
673         if (!e1PassSemantic && !e)
674         {
675             /* https://issues.dlang.org/show_bug.cgi?id=20448
676              *
677              * If both versions have failed to pass semantic,
678              * f(e1) = e2 gets priority in error printing
679              * because f might be a templated function that
680              * failed to instantiate and we have to print
681              * the instantiation errors.
682              */
683             return e1.expressionSemantic(sc);
684         }
685         else if (ex && !e)
686         {
687             checkPropertyCall(ex);
688             ex = new AssignExp(loc, ex, e2);
689             return ex.expressionSemantic(sc);
690         }
691         else
692         {
693             // strict setter prints errors if fails
694             e = e.expressionSemantic(sc);
695         }
696         checkPropertyCall(e);
697         return e;
698     }
699     else
700     {
701         /* f(e1)
702          */
703         auto arguments = new Expressions(1);
704         (*arguments)[0] = eleft;
705         e = new CallExp(loc, e, arguments);
706         e = e.expressionSemantic(sc);
707         checkPropertyCall(e);
708         return e.expressionSemantic(sc);
709     }
710 }
711 
712 /******************************
713  * If e1 is a property function (template), resolve it.
714  */
resolvePropertiesOnly(Scope * sc,Expression e1)715 Expression resolvePropertiesOnly(Scope* sc, Expression e1)
716 {
717     //printf("e1 = %s %s\n", Token.toChars(e1.op), e1.toChars());
718 
719     Expression handleOverloadSet(OverloadSet os)
720     {
721         assert(os);
722         foreach (s; os.a)
723         {
724             auto fd = s.isFuncDeclaration();
725             auto td = s.isTemplateDeclaration();
726             if (fd)
727             {
728                 if (fd.type.isTypeFunction().isproperty)
729                     return resolveProperties(sc, e1);
730             }
731             else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
732             {
733                 if (fd.type.isTypeFunction().isproperty ||
734                     (fd.storage_class2 & STC.property) ||
735                     (td._scope.stc & STC.property))
736                     return resolveProperties(sc, e1);
737             }
738         }
739         return e1;
740     }
741 
742     Expression handleTemplateDecl(TemplateDeclaration td)
743     {
744         assert(td);
745         if (td.onemember)
746         {
747             if (auto fd = td.onemember.isFuncDeclaration())
748             {
749                 if (fd.type.isTypeFunction().isproperty ||
750                     (fd.storage_class2 & STC.property) ||
751                     (td._scope.stc & STC.property))
752                     return resolveProperties(sc, e1);
753             }
754         }
755         return e1;
756     }
757 
758     Expression handleFuncDecl(FuncDeclaration fd)
759     {
760         assert(fd);
761         if (fd.type.isTypeFunction().isproperty)
762             return resolveProperties(sc, e1);
763         return e1;
764     }
765 
766     if (auto de = e1.isDotExp())
767     {
768         if (auto os = de.e2.isOverExp())
769             return handleOverloadSet(os.vars);
770     }
771     else if (auto oe = e1.isOverExp())
772         return handleOverloadSet(oe.vars);
773     else if (auto dti = e1.isDotTemplateInstanceExp())
774     {
775         if (dti.ti.tempdecl)
776             if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
777                 return handleTemplateDecl(td);
778     }
779     else if (auto dte = e1.isDotTemplateExp())
780         return handleTemplateDecl(dte.td);
781     else if (auto se = e1.isScopeExp())
782     {
783         Dsymbol s = se.sds;
784         TemplateInstance ti = s.isTemplateInstance();
785         if (ti && !ti.semanticRun && ti.tempdecl)
786             if (auto td = ti.tempdecl.isTemplateDeclaration())
787                 return handleTemplateDecl(td);
788     }
789     else if (auto et = e1.isTemplateExp())
790         return handleTemplateDecl(et.td);
791     else if (e1.isDotVarExp() && e1.type.isTypeFunction())
792     {
793         DotVarExp dve = e1.isDotVarExp();
794         return handleFuncDecl(dve.var.isFuncDeclaration());
795     }
796     else if (e1.isVarExp() && e1.type && e1.type.isTypeFunction() && (sc.intypeof || !e1.isVarExp().var.needThis()))
797         return handleFuncDecl(e1.isVarExp().var.isFuncDeclaration());
798     return e1;
799 }
800 
801 /****************************************
802  * Turn symbol `s` into the expression it represents.
803  *
804  * Params:
805  *      s = symbol to resolve
806  *      loc = location of use of `s`
807  *      sc = context
808  *      hasOverloads = applies if `s` represents a function.
809  *          true means it's overloaded and will be resolved later,
810  *          false means it's the exact function symbol.
811  * Returns:
812  *      `s` turned into an expression, `ErrorExp` if an error occurred
813  */
symbolToExp(Dsymbol s,const ref Loc loc,Scope * sc,bool hasOverloads)814 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
815 {
816     static if (LOGSEMANTIC)
817     {
818         printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
819     }
820 
821 Lagain:
822     Expression e;
823 
824     //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
825     //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
826     Dsymbol olds = s;
827     Declaration d = s.isDeclaration();
828     if (d && (d.storage_class & STC.templateparameter))
829     {
830         s = s.toAlias();
831     }
832     else
833     {
834         // functions are checked after overloading
835         // templates are checked after matching constraints
836         if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
837         {
838             s.checkDeprecated(loc, sc);
839             if (d)
840                 d.checkDisabled(loc, sc);
841         }
842 
843         // https://issues.dlang.org/show_bug.cgi?id=12023
844         // if 's' is a tuple variable, the tuple is returned.
845         s = s.toAlias();
846 
847         //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
848         if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration())
849         {
850             s.checkDeprecated(loc, sc);
851             if (d)
852                 d.checkDisabled(loc, sc);
853         }
854     }
855 
856     if (auto em = s.isEnumMember())
857     {
858         return em.getVarExp(loc, sc);
859     }
860     if (auto v = s.isVarDeclaration())
861     {
862         //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
863         if (sc.intypeof == 1 && !v.inuse)
864             v.dsymbolSemantic(sc);
865         if (!v.type ||                  // during variable type inference
866             !v.type.deco && v.inuse)    // during variable type semantic
867         {
868             if (v.inuse)    // variable type depends on the variable itself
869                 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
870             else            // variable type cannot be determined
871                 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
872             return ErrorExp.get();
873         }
874         if (v.type.ty == Terror)
875             return ErrorExp.get();
876 
877         if ((v.storage_class & STC.manifest) && v._init)
878         {
879             if (v.inuse)
880             {
881                 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
882                 return ErrorExp.get();
883             }
884             e = v.expandInitializer(loc);
885             v.inuse++;
886             e = e.expressionSemantic(sc);
887             v.inuse--;
888             return e;
889         }
890 
891         // We need to run semantics to correctly set 'STC.field' if it is a member variable
892         // that could be forward referenced. This is needed for 'v.needThis()' to work
893         if (v.isThis())
894             v.dsymbolSemantic(sc);
895 
896         // Change the ancestor lambdas to delegate before hasThis(sc) call.
897         if (v.checkNestedReference(sc, loc))
898             return ErrorExp.get();
899 
900         if (v.needThis() && hasThis(sc))
901             e = new DotVarExp(loc, new ThisExp(loc), v);
902         else
903             e = new VarExp(loc, v);
904         e = e.expressionSemantic(sc);
905         return e;
906     }
907     if (auto fld = s.isFuncLiteralDeclaration())
908     {
909         //printf("'%s' is a function literal\n", fld.toChars());
910         e = new FuncExp(loc, fld);
911         return e.expressionSemantic(sc);
912     }
913     if (auto f = s.isFuncDeclaration())
914     {
915         f = f.toAliasFunc();
916         if (!f.functionSemantic())
917             return ErrorExp.get();
918 
919         if (!hasOverloads && f.checkForwardRef(loc))
920             return ErrorExp.get();
921 
922         auto fd = s.isFuncDeclaration();
923         fd.type = f.type;
924         return new VarExp(loc, fd, hasOverloads);
925     }
926     if (OverDeclaration od = s.isOverDeclaration())
927     {
928         e = new VarExp(loc, od, true);
929         e.type = Type.tvoid;
930         return e;
931     }
932     if (OverloadSet o = s.isOverloadSet())
933     {
934         //printf("'%s' is an overload set\n", o.toChars());
935         return new OverExp(loc, o);
936     }
937 
938     if (Import imp = s.isImport())
939     {
940         if (!imp.pkg)
941         {
942             .error(loc, "forward reference of import `%s`", imp.toChars());
943             return ErrorExp.get();
944         }
945         auto ie = new ScopeExp(loc, imp.pkg);
946         return ie.expressionSemantic(sc);
947     }
948     if (Package pkg = s.isPackage())
949     {
950         auto ie = new ScopeExp(loc, pkg);
951         return ie.expressionSemantic(sc);
952     }
953     if (Module mod = s.isModule())
954     {
955         auto ie = new ScopeExp(loc, mod);
956         return ie.expressionSemantic(sc);
957     }
958     if (Nspace ns = s.isNspace())
959     {
960         auto ie = new ScopeExp(loc, ns);
961         return ie.expressionSemantic(sc);
962     }
963 
964     if (Type t = s.getType())
965     {
966         return (new TypeExp(loc, t)).expressionSemantic(sc);
967     }
968 
969     if (TupleDeclaration tup = s.isTupleDeclaration())
970     {
971         if (tup.needThis() && hasThis(sc))
972             e = new DotVarExp(loc, new ThisExp(loc), tup);
973         else
974             e = new TupleExp(loc, tup);
975         e = e.expressionSemantic(sc);
976         return e;
977     }
978 
979     if (TemplateInstance ti = s.isTemplateInstance())
980     {
981         ti.dsymbolSemantic(sc);
982         if (!ti.inst || ti.errors)
983             return ErrorExp.get();
984         s = ti.toAlias();
985         if (!s.isTemplateInstance())
986             goto Lagain;
987         e = new ScopeExp(loc, ti);
988         e = e.expressionSemantic(sc);
989         return e;
990     }
991     if (TemplateDeclaration td = s.isTemplateDeclaration())
992     {
993         Dsymbol p = td.toParentLocal();
994         FuncDeclaration fdthis = hasThis(sc);
995         AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
996         if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
997         {
998             e = new DotTemplateExp(loc, new ThisExp(loc), td);
999         }
1000         else
1001             e = new TemplateExp(loc, td);
1002         e = e.expressionSemantic(sc);
1003         return e;
1004     }
1005 
1006     .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1007     return ErrorExp.get();
1008 }
1009 
1010 /*************************************************************
1011  * Given var, get the
1012  * right `this` pointer if var is in an outer class, but our
1013  * existing `this` pointer is in an inner class.
1014  * Params:
1015  *      loc = location to use for error messages
1016  *      sc = context
1017  *      ad = struct or class we need the correct `this` for
1018  *      e1 = existing `this`
1019  *      var = the specific member of ad we're accessing
1020  *      flag = if true, return `null` instead of throwing an error
1021  * Returns:
1022  *      Expression representing the `this` for the var
1023  */
1024 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1025 {
1026     //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1027 L1:
1028     Type t = e1.type.toBasetype();
1029     //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1030 
1031     if (e1.op == EXP.objcClassReference)
1032     {
1033         // We already have an Objective-C class reference, just use that as 'this'.
1034         return e1;
1035     }
1036     else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1037              var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1038              var.isFuncDeclaration.objc.selector)
1039     {
1040         return new ObjcClassReferenceExp(e1.loc, ad.isClassDeclaration());
1041     }
1042 
1043     /* Access of a member which is a template parameter in dual-scope scenario
1044      * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1045      * class B {int m; inc() { new A().inc!m(); } }
1046      */
1047     if (e1.op == EXP.this_)
1048     {
1049         FuncDeclaration f = hasThis(sc);
1050         if (f && f.hasDualContext())
1051         {
1052             if (f.followInstantiationContext(ad))
1053             {
1054                 e1 = new VarExp(loc, f.vthis);
1055                 e1 = new PtrExp(loc, e1);
1056                 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1057                 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1058                 if (e1.op == EXP.error)
1059                     return e1;
1060                 goto L1;
1061             }
1062         }
1063     }
1064 
1065     /* If e1 is not the 'this' pointer for ad
1066      */
1067     if (ad &&
1068         !(t.isTypePointer() && t.nextOf().isTypeStruct() && t.nextOf().isTypeStruct().sym == ad) &&
1069         !(t.isTypeStruct() && t.isTypeStruct().sym == ad))
1070     {
1071         ClassDeclaration cd = ad.isClassDeclaration();
1072         ClassDeclaration tcd = t.isClassHandle();
1073 
1074         /* e1 is the right this if ad is a base class of e1
1075          */
1076         if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1077         {
1078             /* Only classes can be inner classes with an 'outer'
1079              * member pointing to the enclosing class instance
1080              */
1081             if (tcd && tcd.isNested())
1082             {
1083                 /* e1 is the 'this' pointer for an inner class: tcd.
1084                  * Rewrite it as the 'this' pointer for the outer class.
1085                  */
1086                 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1087                 e1 = new DotVarExp(loc, e1, vthis);
1088                 e1.type = vthis.type;
1089                 e1.type = e1.type.addMod(t.mod);
1090                 // Do not call ensureStaticLinkTo()
1091                 //e1 = e1.semantic(sc);
1092 
1093                 // Skip up over nested functions, and get the enclosing
1094                 // class type.
1095                 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1096                 if (e1.op == EXP.error)
1097                     return e1;
1098                 goto L1;
1099             }
1100 
1101             /* Can't find a path from e1 to ad
1102              */
1103             if (flag)
1104                 return null;
1105             e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1106             return ErrorExp.get();
1107         }
1108     }
1109     return e1;
1110 }
1111 
1112 /***************************************
1113  * Pull out any properties.
1114  */
1115 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1116 {
1117     //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
1118     Loc loc = e1.loc;
1119 
1120     OverloadSet os;
1121     Dsymbol s;
1122     Objects* tiargs;
1123     Type tthis;
1124     if (auto de = e1.isDotExp())
1125     {
1126         if (auto oe = de.e2.isOverExp())
1127         {
1128             tiargs = null;
1129             tthis = de.e1.type;
1130             os = oe.vars;
1131             goto Los;
1132         }
1133     }
1134     else if (e1.isOverExp())
1135     {
1136         tiargs = null;
1137         tthis = null;
1138         os = e1.isOverExp().vars;
1139     Los:
1140         assert(os);
1141         FuncDeclaration fd = null;
1142         if (e2)
1143         {
1144             e2 = e2.expressionSemantic(sc);
1145             if (e2.op == EXP.error)
1146                 return ErrorExp.get();
1147             e2 = resolveProperties(sc, e2);
1148 
1149             Expressions a;
1150             a.push(e2);
1151 
1152             for (size_t i = 0; i < os.a.dim; i++)
1153             {
1154                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1155                 {
1156                     if (f.errors)
1157                         return ErrorExp.get();
1158                     fd = f;
1159                     assert(fd.type.ty == Tfunction);
1160                 }
1161             }
1162             if (fd)
1163             {
1164                 Expression e = new CallExp(loc, e1, e2);
1165                 return e.expressionSemantic(sc);
1166             }
1167         }
1168         {
1169             for (size_t i = 0; i < os.a.dim; i++)
1170             {
1171                 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1172                 {
1173                     if (f.errors)
1174                         return ErrorExp.get();
1175                     fd = f;
1176                     assert(fd.type.ty == Tfunction);
1177                     auto tf = fd.type.isTypeFunction();
1178                     if (!tf.isref && e2)
1179                     {
1180                         error(loc, "%s is not an lvalue", e1.toChars());
1181                         return ErrorExp.get();
1182                     }
1183                 }
1184             }
1185             if (fd)
1186             {
1187                 Expression e = new CallExp(loc, e1);
1188                 if (e2)
1189                     e = new AssignExp(loc, e, e2);
1190                 return e.expressionSemantic(sc);
1191             }
1192         }
1193         if (e2)
1194             goto Leprop;
1195     }
1196     else if (auto dti = e1.isDotTemplateInstanceExp())
1197     {
1198         if (!dti.findTempDecl(sc))
1199             goto Leprop;
1200         if (!dti.ti.semanticTiargs(sc))
1201             goto Leprop;
1202         tiargs = dti.ti.tiargs;
1203         tthis = dti.e1.type;
1204         if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1205             goto Los;
1206         if ((s = dti.ti.tempdecl) !is null)
1207             goto Lfd;
1208     }
1209     else if (auto dte = e1.isDotTemplateExp())
1210     {
1211         s = dte.td;
1212         tiargs = null;
1213         tthis = dte.e1.type;
1214         goto Lfd;
1215     }
1216     else if (auto se = e1.isScopeExp())
1217     {
1218         s = se.sds;
1219         TemplateInstance ti = s.isTemplateInstance();
1220         if (ti && !ti.semanticRun && ti.tempdecl)
1221         {
1222             //assert(ti.needsTypeInference(sc));
1223             if (!ti.semanticTiargs(sc))
1224                 goto Leprop;
1225             tiargs = ti.tiargs;
1226             tthis = null;
1227             if ((os = ti.tempdecl.isOverloadSet()) !is null)
1228                 goto Los;
1229             if ((s = ti.tempdecl) !is null)
1230                 goto Lfd;
1231         }
1232     }
1233     else if (auto te = e1.isTemplateExp())
1234     {
1235         s = te.td;
1236         tiargs = null;
1237         tthis = null;
1238         goto Lfd;
1239     }
1240     else if (e1.isDotVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isDotVarExp().var.isOverDeclaration()))
1241     {
1242         DotVarExp dve = e1.isDotVarExp();
1243         s = dve.var;
1244         tiargs = null;
1245         tthis = dve.e1.type;
1246         goto Lfd;
1247     }
1248     else if (sc && sc.flags & SCOPE.Cfile && e1.isVarExp() && !e2)
1249     {
1250         // ImportC: do not implicitly call function if no ( ) are present
1251     }
1252     else if (e1.isVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isVarExp().var.isOverDeclaration()))
1253     {
1254         s = e1.isVarExp().var;
1255         tiargs = null;
1256         tthis = null;
1257     Lfd:
1258         assert(s);
1259         if (e2)
1260         {
1261             e2 = e2.expressionSemantic(sc);
1262             if (e2.op == EXP.error)
1263                 return ErrorExp.get();
1264             e2 = resolveProperties(sc, e2);
1265 
1266             Expressions a;
1267             a.push(e2);
1268 
1269             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1270             if (fd && fd.type)
1271             {
1272                 if (fd.errors)
1273                     return ErrorExp.get();
1274                 if (!checkSymbolAccess(sc, fd))
1275                 {
1276                     // @@@DEPRECATED_2.105@@@
1277                     // When turning into error, uncomment the return statement
1278                     TypeFunction tf = fd.type.isTypeFunction();
1279                     deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1280                                 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1281                     //return ErrorExp.get();
1282                 }
1283                 assert(fd.type.ty == Tfunction);
1284                 Expression e = new CallExp(loc, e1, e2);
1285                 return e.expressionSemantic(sc);
1286             }
1287         }
1288         {
1289             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1290             if (fd && fd.type)
1291             {
1292                 if (fd.errors)
1293                     return ErrorExp.get();
1294                 TypeFunction tf = fd.type.isTypeFunction();
1295                 if (!e2 || tf.isref)
1296                 {
1297                     if (!checkSymbolAccess(sc, fd))
1298                     {
1299                         // @@@DEPRECATED_2.105@@@
1300                         // When turning into error, uncomment the return statement
1301                         deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1302                                     fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1303                         //return ErrorExp.get();
1304                     }
1305                     Expression e = new CallExp(loc, e1);
1306                     if (e2)
1307                         e = new AssignExp(loc, e, e2);
1308                     return e.expressionSemantic(sc);
1309                 }
1310             }
1311         }
1312         if (FuncDeclaration fd = s.isFuncDeclaration())
1313         {
1314             // Keep better diagnostic message for invalid property usage of functions
1315             assert(fd.type.ty == Tfunction);
1316             Expression e = new CallExp(loc, e1, e2);
1317             return e.expressionSemantic(sc);
1318         }
1319         if (e2)
1320             goto Leprop;
1321     }
1322     if (auto ve = e1.isVarExp())
1323     {
1324         if (auto v = ve.var.isVarDeclaration())
1325         {
1326             if (ve.checkPurity(sc, v))
1327                 return ErrorExp.get();
1328         }
1329     }
1330     if (e2)
1331         return null;
1332 
1333     if (e1.type && !e1.isTypeExp()) // function type is not a property
1334     {
1335         /* Look for e1 being a lazy parameter; rewrite as delegate call
1336          * only if the symbol wasn't already treated as a delegate
1337          */
1338         auto ve = e1.isVarExp();
1339         if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1340         {
1341                 Expression e = new CallExp(loc, e1);
1342                 return e.expressionSemantic(sc);
1343         }
1344         else if (e1.isDotVarExp())
1345         {
1346             // Check for reading overlapped pointer field in @safe code.
1347             if (checkUnsafeAccess(sc, e1, true, true))
1348                 return ErrorExp.get();
1349         }
1350         else if (auto ce = e1.isCallExp())
1351         {
1352             // Check for reading overlapped pointer field in @safe code.
1353             if (checkUnsafeAccess(sc, ce.e1, true, true))
1354                 return ErrorExp.get();
1355         }
1356     }
1357 
1358     if (!e1.type)
1359     {
1360         error(loc, "cannot resolve type for %s", e1.toChars());
1361         e1 = ErrorExp.get();
1362     }
1363     return e1;
1364 
1365 Leprop:
1366     error(loc, "not a property %s", e1.toChars());
1367     return ErrorExp.get();
1368 }
1369 
resolveProperties(Scope * sc,Expression e)1370 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1371 {
1372     //printf("resolveProperties(%s)\n", e.toChars());
1373     e = resolvePropertiesX(sc, e);
1374     if (e.checkRightThis(sc))
1375         return ErrorExp.get();
1376     return e;
1377 }
1378 
1379 /****************************************
1380  * The common type is determined by applying ?: to each pair.
1381  * Output:
1382  *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1383  * Returns:
1384  *      The common type, or `null` if an error has occured
1385  */
arrayExpressionToCommonType(Scope * sc,ref Expressions exps)1386 private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
1387 {
1388     /* Still have a problem with:
1389      *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1390      * which works if the array literal is initialized top down with the ubyte[][]
1391      * type, but fails with this function doing bottom up typing.
1392      */
1393 
1394     //printf("arrayExpressionToCommonType()\n");
1395     scope IntegerExp integerexp = IntegerExp.literal!0;
1396     scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1397 
1398     Type t0 = null;
1399     Expression e0 = null;
1400     bool foundType;
1401 
1402     for (size_t i = 0; i < exps.dim; i++)
1403     {
1404         Expression e = exps[i];
1405         if (!e)
1406             continue;
1407 
1408         e = resolveProperties(sc, e);
1409         if (!e.type)
1410         {
1411             e.error("`%s` has no value", e.toChars());
1412             t0 = Type.terror;
1413             continue;
1414         }
1415         if (e.op == EXP.type)
1416         {
1417             foundType = true; // do not break immediately, there might be more errors
1418             e.checkValue(); // report an error "type T has no value"
1419             t0 = Type.terror;
1420             continue;
1421         }
1422         if (e.type.ty == Tvoid)
1423         {
1424             // void expressions do not concur to the determination of the common
1425             // type.
1426             continue;
1427         }
1428         if (checkNonAssignmentArrayOp(e))
1429         {
1430             t0 = Type.terror;
1431             continue;
1432         }
1433 
1434         e = doCopyOrMove(sc, e);
1435 
1436         if (!foundType && t0 && !t0.equals(e.type))
1437         {
1438             /* This applies ?: to merge the types. It's backwards;
1439              * ?: should call this function to merge types.
1440              */
1441             condexp.type = null;
1442             condexp.e1 = e0;
1443             condexp.e2 = e;
1444             condexp.loc = e.loc;
1445             Expression ex = condexp.expressionSemantic(sc);
1446             if (ex.op == EXP.error)
1447                 e = ex;
1448             else
1449             {
1450                 // Convert to common type
1451                 exps[i] = condexp.e1.castTo(sc, condexp.type);
1452                 e = condexp.e2.castTo(sc, condexp.type);
1453             }
1454         }
1455         e0 = e;
1456         t0 = e.type;
1457         if (e.op != EXP.error)
1458             exps[i] = e;
1459     }
1460 
1461     // [] is typed as void[]
1462     if (!t0)
1463         return Type.tvoid;
1464 
1465     // It's an error, don't do the cast
1466     if (t0.ty == Terror)
1467         return null;
1468 
1469     for (size_t i = 0; i < exps.dim; i++)
1470     {
1471         Expression e = exps[i];
1472         if (!e)
1473             continue;
1474 
1475         e = e.implicitCastTo(sc, t0);
1476         if (e.op == EXP.error)
1477         {
1478             /* https://issues.dlang.org/show_bug.cgi?id=13024
1479              * a workaround for the bug in typeMerge -
1480              * it should paint e1 and e2 by deduced common type,
1481              * but doesn't in this particular case.
1482              */
1483             return null;
1484         }
1485         exps[i] = e;
1486     }
1487     return t0;
1488 }
1489 
opAssignToOp(const ref Loc loc,EXP op,Expression e1,Expression e2)1490 private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expression e2)
1491 {
1492     Expression e;
1493     switch (op)
1494     {
1495     case EXP.addAssign:
1496         e = new AddExp(loc, e1, e2);
1497         break;
1498 
1499     case EXP.minAssign:
1500         e = new MinExp(loc, e1, e2);
1501         break;
1502 
1503     case EXP.mulAssign:
1504         e = new MulExp(loc, e1, e2);
1505         break;
1506 
1507     case EXP.divAssign:
1508         e = new DivExp(loc, e1, e2);
1509         break;
1510 
1511     case EXP.modAssign:
1512         e = new ModExp(loc, e1, e2);
1513         break;
1514 
1515     case EXP.andAssign:
1516         e = new AndExp(loc, e1, e2);
1517         break;
1518 
1519     case EXP.orAssign:
1520         e = new OrExp(loc, e1, e2);
1521         break;
1522 
1523     case EXP.xorAssign:
1524         e = new XorExp(loc, e1, e2);
1525         break;
1526 
1527     case EXP.leftShiftAssign:
1528         e = new ShlExp(loc, e1, e2);
1529         break;
1530 
1531     case EXP.rightShiftAssign:
1532         e = new ShrExp(loc, e1, e2);
1533         break;
1534 
1535     case EXP.unsignedRightShiftAssign:
1536         e = new UshrExp(loc, e1, e2);
1537         break;
1538 
1539     default:
1540         assert(0);
1541     }
1542     return e;
1543 }
1544 
1545 /*********************
1546  * Rewrite:
1547  *    array.length op= e2
1548  * as:
1549  *    array.length = array.length op e2
1550  * or:
1551  *    auto tmp = &array;
1552  *    (*tmp).length = (*tmp).length op e2
1553  */
rewriteOpAssign(BinExp exp)1554 private Expression rewriteOpAssign(BinExp exp)
1555 {
1556     ArrayLengthExp ale = exp.e1.isArrayLengthExp();
1557     if (ale.e1.isVarExp())
1558     {
1559         Expression e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1560         e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1561         return e;
1562     }
1563     else
1564     {
1565         /*    auto tmp = &array;
1566          *    (*tmp).length = (*tmp).length op e2
1567          */
1568         auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1569 
1570         Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1571         Expression elvalue = e1.syntaxCopy();
1572         Expression e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1573         e = new AssignExp(exp.loc, elvalue, e);
1574         e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1575         return e;
1576     }
1577 }
1578 
1579 /****************************************
1580  * Preprocess arguments to function.
1581  * Input:
1582  *      reportErrors    whether or not to report errors here.  Some callers are not
1583  *                      checking actual function params, so they'll do their own error reporting
1584  * Output:
1585  *      exps[]  tuples expanded, properties resolved, rewritten in place
1586  * Returns:
1587  *      true    a semantic error occurred
1588  */
1589 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1590 {
1591     bool err = false;
1592     if (exps)
1593     {
1594         expandTuples(exps);
1595 
1596         for (size_t i = 0; i < exps.dim; i++)
1597         {
1598             Expression arg = (*exps)[i];
1599             arg = resolveProperties(sc, arg);
1600             arg = arg.arrayFuncConv(sc);
1601             if (arg.op == EXP.type)
1602             {
1603                 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1604                 arg = resolveAliasThis(sc, arg);
1605 
1606                 if (arg.op == EXP.type)
1607                 {
1608                     if (reportErrors)
1609                     {
1610                         arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1611                         arg = ErrorExp.get();
1612                     }
1613                     err = true;
1614                 }
1615             }
1616             else if (arg.type.toBasetype().ty == Tfunction)
1617             {
1618                 if (reportErrors)
1619                 {
1620                     arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1621                     arg = ErrorExp.get();
1622                 }
1623                 err = true;
1624             }
1625             else if (checkNonAssignmentArrayOp(arg))
1626             {
1627                 arg = ErrorExp.get();
1628                 err = true;
1629             }
1630             (*exps)[i] = arg;
1631         }
1632     }
1633     return err;
1634 }
1635 
1636 /********************************************
1637  * Issue an error if default construction is disabled for type t.
1638  * Default construction is required for arrays and 'out' parameters.
1639  * Returns:
1640  *      true    an error was issued
1641  */
checkDefCtor(Loc loc,Type t)1642 private bool checkDefCtor(Loc loc, Type t)
1643 {
1644     if (auto ts = t.baseElemOf().isTypeStruct())
1645     {
1646         StructDeclaration sd = ts.sym;
1647         if (sd.noDefaultCtor)
1648         {
1649             sd.error(loc, "default construction is disabled");
1650             return true;
1651         }
1652     }
1653     return false;
1654 }
1655 
1656 /****************************************
1657  * Now that we know the exact type of the function we're calling,
1658  * the arguments[] need to be adjusted:
1659  *      1. implicitly convert argument to the corresponding parameter type
1660  *      2. add default arguments for any missing arguments
1661  *      3. do default promotions on arguments corresponding to ...
1662  *      4. add hidden _arguments[] argument
1663  *      5. call copy constructor for struct value arguments
1664  * Params:
1665  *      loc       = location of function call
1666  *      sc        = context
1667  *      tf        = type of the function
1668  *      ethis     = `this` argument, `null` if none or not known
1669  *      tthis     = type of `this` argument, `null` if no `this` argument
1670  *      arguments = array of actual arguments to function call
1671  *      fd        = the function being called, `null` if called indirectly
1672  *      prettype  = set to return type of function
1673  *      peprefix  = set to expression to execute before `arguments[]` are evaluated, `null` if none
1674  * Returns:
1675  *      true    errors happened
1676  */
functionParameters(const ref Loc loc,Scope * sc,TypeFunction tf,Expression ethis,Type tthis,Expressions * arguments,FuncDeclaration fd,Type * prettype,Expression * peprefix)1677 private bool functionParameters(const ref Loc loc, Scope* sc,
1678     TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1679     Type* prettype, Expression* peprefix)
1680 {
1681     //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1682     assert(arguments);
1683     assert(fd || tf.next);
1684     size_t nargs = arguments ? arguments.dim : 0;
1685     const size_t nparams = tf.parameterList.length;
1686     const olderrors = global.errors;
1687     bool err = false;
1688     *prettype = Type.terror;
1689     Expression eprefix = null;
1690     *peprefix = null;
1691 
1692     if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1693     {
1694         error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1695         return true;
1696     }
1697 
1698     // If inferring return type, and semantic3() needs to be run if not already run
1699     if (!tf.next && fd.inferRetType)
1700     {
1701         fd.functionSemantic();
1702     }
1703     else if (fd && fd.parent)
1704     {
1705         TemplateInstance ti = fd.parent.isTemplateInstance();
1706         if (ti && ti.tempdecl)
1707         {
1708             fd.functionSemantic3();
1709         }
1710     }
1711 
1712     /* If calling a pragma(inline, true) function,
1713      * set flag to later scan for inlines.
1714      */
1715     if (fd && fd.inlining == PINLINE.always)
1716     {
1717         if (sc._module)
1718             sc._module.hasAlwaysInlines = true;
1719         if (sc.func)
1720             sc.func.flags |= FUNCFLAG.hasAlwaysInline;
1721     }
1722 
1723     const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1724 
1725     const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1726 
1727     /* If the function return type has wildcards in it, we'll need to figure out the actual type
1728      * based on the actual argument types.
1729      * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1730      * of the arguments.
1731      */
1732     MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1733 
1734     bool done = false;
1735     foreach (const i; 0 .. n)
1736     {
1737         Expression arg = (i < nargs) ? (*arguments)[i] : null;
1738 
1739         if (i < nparams)
1740         {
1741             bool errorArgs()
1742             {
1743                 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1744                 return true;
1745             }
1746 
1747             Parameter p = tf.parameterList[i];
1748 
1749             if (!arg)
1750             {
1751                 if (!p.defaultArg)
1752                 {
1753                     if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1754                         goto L2;
1755                     return errorArgs();
1756                 }
1757                 arg = p.defaultArg;
1758                 arg = inlineCopy(arg, sc);
1759                 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1760                 arg = arg.resolveLoc(loc, sc);
1761                 arguments.push(arg);
1762                 nargs++;
1763             }
1764             else
1765             {
1766                 if (isDefaultInitOp(arg.op))
1767                 {
1768                     arg = arg.resolveLoc(loc, sc);
1769                     (*arguments)[i] = arg;
1770                 }
1771             }
1772 
1773 
1774             if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1775             {
1776                 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1777                 {
1778                     MATCH m;
1779                     if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1780                     {
1781                         if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1782                             goto L2;
1783                         else if (nargs != nparams)
1784                             return errorArgs();
1785                         goto L1;
1786                     }
1787                 }
1788             L2:
1789                 Type tb = p.type.toBasetype();
1790                 switch (tb.ty)
1791                 {
1792                 case Tsarray:
1793                 case Tarray:
1794                     {
1795                         /* Create a static array variable v of type arg.type:
1796                          *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1797                          *
1798                          * The array literal in the initializer of the hidden variable
1799                          * is now optimized.
1800                          * https://issues.dlang.org/show_bug.cgi?id=2356
1801                          */
1802                         Type tbn = (cast(TypeArray)tb).next;    // array element type
1803                         Type tret = p.isLazyArray();
1804 
1805                         auto elements = new Expressions(nargs - i);
1806                         foreach (u; 0 .. elements.dim)
1807                         {
1808                             Expression a = (*arguments)[i + u];
1809                             if (tret && a.implicitConvTo(tret))
1810                             {
1811                                 // p is a lazy array of delegates, tret is return type of the delegates
1812                                 a = a.implicitCastTo(sc, tret)
1813                                      .optimize(WANTvalue)
1814                                      .toDelegate(tret, sc);
1815                             }
1816                             else
1817                                 a = a.implicitCastTo(sc, tbn);
1818                             a = a.addDtorHook(sc);
1819                             (*elements)[u] = a;
1820                         }
1821                         // https://issues.dlang.org/show_bug.cgi?id=14395
1822                         // Convert to a static array literal, or its slice.
1823                         arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1824                         if (tb.ty == Tarray)
1825                         {
1826                             arg = new SliceExp(loc, arg, null, null);
1827                             arg.type = p.type;
1828                         }
1829                         break;
1830                     }
1831                 case Tclass:
1832                     {
1833                         /* Set arg to be:
1834                          *      new Tclass(arg0, arg1, ..., argn)
1835                          */
1836                         auto args = new Expressions(nargs - i);
1837                         foreach (u; i .. nargs)
1838                             (*args)[u - i] = (*arguments)[u];
1839                         arg = new NewExp(loc, null, p.type, args);
1840                         break;
1841                     }
1842                 default:
1843                     if (!arg)
1844                     {
1845                         error(loc, "not enough arguments");
1846                         return true;
1847                     }
1848                     break;
1849                 }
1850                 arg = arg.expressionSemantic(sc);
1851                 //printf("\targ = '%s'\n", arg.toChars());
1852                 arguments.setDim(i + 1);
1853                 (*arguments)[i] = arg;
1854                 nargs = i + 1;
1855                 done = true;
1856             }
1857 
1858         L1:
1859             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1860             {
1861                 if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
1862                 {
1863                     wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1864                     //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1865                 }
1866             }
1867         }
1868         if (done)
1869             break;
1870     }
1871     if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1872         tf.next && tf.next.hasWild() &&
1873         (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1874     {
1875         bool errorInout(MOD wildmatch)
1876         {
1877             const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1878             error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1879             return true;
1880         }
1881 
1882         if (fd)
1883         {
1884             /* If the called function may return the reference to
1885              * outer inout data, it should be rejected.
1886              *
1887              * void foo(ref inout(int) x) {
1888              *   ref inout(int) bar(inout(int)) { return x; }
1889              *   struct S {
1890              *      ref inout(int) bar() inout { return x; }
1891              *      ref inout(int) baz(alias a)() inout { return x; }
1892              *   }
1893              *   bar(int.init) = 1;  // bad!
1894              *   S().bar() = 1;      // bad!
1895              * }
1896              * void test() {
1897              *   int a;
1898              *   auto s = foo(a);
1899              *   s.baz!a() = 1;      // bad!
1900              * }
1901              *
1902              */
1903             bool checkEnclosingWild(Dsymbol s)
1904             {
1905                 bool checkWild(Dsymbol s)
1906                 {
1907                     if (!s)
1908                         return false;
1909                     if (auto ad = s.isAggregateDeclaration())
1910                     {
1911                         if (ad.isNested())
1912                             return checkEnclosingWild(s);
1913                     }
1914                     else if (auto ff = s.isFuncDeclaration())
1915                     {
1916                         if (ff.type.isTypeFunction().iswild)
1917                             return errorInout(wildmatch);
1918 
1919                         if (ff.isNested() || ff.isThis())
1920                             return checkEnclosingWild(s);
1921                     }
1922                     return false;
1923                 }
1924 
1925                 Dsymbol ctx0 = s.toParent2();
1926                 Dsymbol ctx1 = s.toParentLocal();
1927                 if (checkWild(ctx0))
1928                     return true;
1929                 if (ctx0 != ctx1)
1930                     return checkWild(ctx1);
1931                 return false;
1932             }
1933             if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1934                 return true;
1935         }
1936         else if (tf.isWild())
1937             return errorInout(wildmatch);
1938     }
1939 
1940     Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1941                            tthis &&
1942                            tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1943                            tthis.hasPointers())
1944                           ? ethis : null;
1945 
1946     assert(nargs >= nparams);
1947     foreach (const i, arg; (*arguments)[0 .. nargs])
1948     {
1949         assert(arg);
1950         if (i < nparams)
1951         {
1952             Parameter p = tf.parameterList[i];
1953             Type targ = arg.type;               // keep original type for isCopyable() because alias this
1954                                                 // resolution may hide an uncopyable type
1955 
1956             if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1957             {
1958                 Type tprm = p.type.hasWild()
1959                     ? p.type.substWildTo(wildmatch)
1960                     : p.type;
1961 
1962                 const hasCopyCtor = arg.type.isTypeStruct() && arg.type.isTypeStruct().sym.hasCopyCtor;
1963                 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1964                 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1965                 {
1966                     //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1967                     arg = arg.implicitCastTo(sc, tprm);
1968                     arg = arg.optimize(WANTvalue, p.isReference());
1969                 }
1970             }
1971 
1972             // Support passing rvalue to `in` parameters
1973             if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
1974             {
1975                 if (!arg.isLvalue())
1976                 {
1977                     auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
1978                     Expression ev = new DeclarationExp(arg.loc, v);
1979                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1980                     arg = ev.expressionSemantic(sc);
1981                 }
1982                 arg = arg.toLvalue(sc, arg);
1983 
1984                 // Look for mutable misaligned pointer, etc., in @safe mode
1985                 err |= checkUnsafeAccess(sc, arg, false, true);
1986             }
1987             else if (p.storageClass & STC.ref_)
1988             {
1989                 if (global.params.rvalueRefParam == FeatureState.enabled &&
1990                     !arg.isLvalue() &&
1991                     targ.isCopyable())
1992                 {   /* allow rvalues to be passed to ref parameters by copying
1993                      * them to a temp, then pass the temp as the argument
1994                      */
1995                     auto v = copyToTemp(0, "__rvalue", arg);
1996                     Expression ev = new DeclarationExp(arg.loc, v);
1997                     ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1998                     arg = ev.expressionSemantic(sc);
1999                 }
2000                 arg = arg.toLvalue(sc, arg);
2001 
2002                 // Look for mutable misaligned pointer, etc., in @safe mode
2003                 err |= checkUnsafeAccess(sc, arg, false, true);
2004             }
2005             else if (p.storageClass & STC.out_)
2006             {
2007                 Type t = arg.type;
2008                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2009                 {
2010                     arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2011                     err = true;
2012                 }
2013                 else
2014                 {
2015                     // Look for misaligned pointer, etc., in @safe mode
2016                     err |= checkUnsafeAccess(sc, arg, false, true);
2017                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
2018                 }
2019                 arg = arg.toLvalue(sc, arg);
2020             }
2021             else if (p.storageClass & STC.lazy_)
2022             {
2023                 // Convert lazy argument to a delegate
2024                 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2025                 arg = toDelegate(arg, t, sc);
2026             }
2027             //printf("arg: %s\n", arg.toChars());
2028             //printf("type: %s\n", arg.type.toChars());
2029             //printf("param: %s\n", p.toChars());
2030 
2031             const pStc = tf.parameterStorageClass(tthis, p);
2032 
2033             if (firstArg && (pStc & STC.return_))
2034             {
2035                 /* Argument value can be assigned to firstArg.
2036                  * Check arg to see if it matters.
2037                  */
2038                 if (global.params.useDIP1000 == FeatureState.enabled)
2039                     err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
2040             }
2041             // Allow 'lazy' to imply 'scope' - lazy parameters can be passed along
2042             // as lazy parameters to the next function, but that isn't escaping.
2043             else if (!(pStc & (STC.scope_ | STC.lazy_)))
2044             {
2045                 /* Argument value can escape from the called function.
2046                  * Check arg to see if it matters.
2047                  */
2048                 if (global.params.useDIP1000 == FeatureState.enabled)
2049                     err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2050             }
2051             else if (!(pStc & STC.return_) &&
2052                 ((global.params.useDIP1000 == FeatureState.enabled) || !(p.storageClass & STC.scopeinferred)))
2053             {
2054                 /* Argument value cannot escape from the called function.
2055                  */
2056                 Expression a = arg;
2057                 if (auto ce = a.isCastExp())
2058                     a = ce.e1;
2059 
2060                 ArrayLiteralExp ale;
2061                 if (p.type.toBasetype().ty == Tarray &&
2062                     (ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0)
2063                 {
2064                     // allocate the array literal as temporary static array on the stack
2065                     ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
2066                     auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2067                     auto declareTmp = new DeclarationExp(ale.loc, tmp);
2068                     auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
2069                         p.type.substWildTo(MODFlags.mutable));
2070                     arg = CommaExp.combine(declareTmp, castToSlice);
2071                     arg = arg.expressionSemantic(sc);
2072                 }
2073                 else if (auto fe = a.isFuncExp())
2074                 {
2075                     /* Function literals can only appear once, so if this
2076                      * appearance was scoped, there cannot be any others.
2077                      */
2078                     fe.fd.tookAddressOf = 0;
2079                 }
2080                 else if (auto de = a.isDelegateExp())
2081                 {
2082                     /* For passing a delegate to a scoped parameter,
2083                      * this doesn't count as taking the address of it.
2084                      * We only worry about 'escaping' references to the function.
2085                      */
2086                     if (auto ve = de.e1.isVarExp())
2087                     {
2088                         if (auto f = ve.var.isFuncDeclaration())
2089                         {
2090                             if (f.tookAddressOf)
2091                                 --f.tookAddressOf;
2092                             //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2093                         }
2094                     }
2095                 }
2096             }
2097             if (!p.isReference())
2098                 err |= arg.checkSharedAccess(sc);
2099 
2100             arg = arg.optimize(WANTvalue, p.isReference());
2101 
2102             /* Determine if this parameter is the "first reference" parameter through which
2103              * later "return" arguments can be stored.
2104              */
2105             if (i == 0 && !tthis && p.isReference() && p.type &&
2106                 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2107             {
2108                 Type tb = p.type.baseElemOf();
2109                 if (tb.isMutable() && tb.hasPointers())
2110                 {
2111                     firstArg = arg;
2112                 }
2113             }
2114         }
2115         else
2116         {
2117             // These will be the trailing ... arguments
2118             // If not D linkage, do promotions
2119             if (tf.linkage != LINK.d)
2120             {
2121                 // Promote bytes, words, etc., to ints
2122                 arg = integralPromotions(arg, sc);
2123 
2124                 // Promote floats to doubles
2125                 switch (arg.type.ty)
2126                 {
2127                 case Tfloat32:
2128                     arg = arg.castTo(sc, Type.tfloat64);
2129                     break;
2130 
2131                 case Timaginary32:
2132                     arg = arg.castTo(sc, Type.timaginary64);
2133                     break;
2134 
2135                 default:
2136                     break;
2137                 }
2138                 if (tf.parameterList.varargs == VarArg.variadic)
2139                 {
2140                     const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2141                     if (arg.type.ty == Tarray)
2142                     {
2143                         arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2144                         err = true;
2145                     }
2146                     if (arg.type.ty == Tsarray)
2147                     {
2148                         arg.error("cannot pass static arrays to `%s` vararg functions", p);
2149                         err = true;
2150                     }
2151                 }
2152             }
2153 
2154             // Do not allow types that need destructors or copy constructors.
2155             if (arg.type.needsDestruction())
2156             {
2157                 arg.error("cannot pass types that need destruction as variadic arguments");
2158                 err = true;
2159             }
2160             if (arg.type.needsCopyOrPostblit())
2161             {
2162                 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2163                 err = true;
2164             }
2165 
2166             // Convert static arrays to dynamic arrays
2167             // BUG: I don't think this is right for D2
2168             Type tb = arg.type.toBasetype();
2169             if (auto ts = tb.isTypeSArray())
2170             {
2171                 Type ta = ts.next.arrayOf();
2172                 if (ts.size(arg.loc) == 0)
2173                     arg = new NullExp(arg.loc, ta);
2174                 else
2175                     arg = arg.castTo(sc, ta);
2176             }
2177             if (tb.ty == Tstruct)
2178             {
2179                 //arg = callCpCtor(sc, arg);
2180             }
2181             // Give error for overloaded function addresses
2182             if (auto se = arg.isSymOffExp())
2183             {
2184                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2185                 {
2186                     arg.error("function `%s` is overloaded", arg.toChars());
2187                     err = true;
2188                 }
2189             }
2190             err |= arg.checkValue();
2191             err |= arg.checkSharedAccess(sc);
2192             arg = arg.optimize(WANTvalue);
2193         }
2194         (*arguments)[i] = arg;
2195     }
2196 
2197     /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2198      */
2199     const isVa_list = tf.parameterList.varargs == VarArg.none;
2200     if (fd && fd.flags & FUNCFLAG.printf)
2201     {
2202         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2203         {
2204             checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2205         }
2206     }
2207     else if (fd && fd.flags & FUNCFLAG.scanf)
2208     {
2209         if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2210         {
2211             checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2212         }
2213     }
2214     else
2215     {
2216         // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2217     }
2218 
2219     /* Remaining problems:
2220      * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2221      *    implemented by calling a function) we'll defer this for now.
2222      * 2. value structs (or static arrays of them) that need to be copy constructed
2223      * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2224      *    function gets called.
2225      * 4. value structs need to be destructed after the function call for platforms where the caller destroys the arguments.
2226      * 2, 3 and 4 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2227      * up properly. Pushing arguments on the stack then cannot fail.
2228      */
2229      {
2230         /* TODO: tackle problem 1)
2231          */
2232         const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2233         if (!leftToRight)
2234             assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2235 
2236         /* Does Problem (4) apply?
2237          */
2238         const bool callerDestroysArgs = !target.isCalleeDestroyingArgs(tf);
2239 
2240         const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2241         const ptrdiff_t end   = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2242         const ptrdiff_t step  = (leftToRight ? 1 : -1);
2243 
2244         /* Compute indices of last throwing argument and first arg needing destruction.
2245          * Used to not set up destructors unless an arg needs destruction on a throw
2246          * in a later argument.
2247          */
2248         ptrdiff_t lastthrow = -1;   // last argument that may throw
2249         ptrdiff_t firstdtor = -1;   // first argument that needs destruction
2250         ptrdiff_t lastdtor  = -1;   // last argument that needs destruction
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 (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                 {
2261                     if (firstdtor == -1)
2262                         firstdtor = i;
2263                     lastdtor = i;
2264                 }
2265             }
2266         }
2267 
2268         /* Do we need 'eprefix' for problems 3 or 4?
2269          */
2270         const bool needsPrefix = callerDestroysArgs
2271             ? firstdtor >= 0 // true if any argument needs destruction
2272             : firstdtor >= 0 && lastthrow >= 0 &&
2273               (lastthrow - firstdtor) * step > 0; // last throw after first destruction
2274         const ptrdiff_t lastPrefix = callerDestroysArgs
2275             ? lastdtor   // up to last argument requiring destruction
2276             : lastthrow; // up to last potentially throwing argument
2277 
2278         /* Problem 3: initialize 'eprefix' by declaring the gate
2279          */
2280         VarDeclaration gate;
2281         if (needsPrefix && !callerDestroysArgs)
2282         {
2283             // eprefix => bool __gate [= false]
2284             Identifier idtmp = Identifier.generateId("__gate");
2285             gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2286             gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2287             gate.dsymbolSemantic(sc);
2288 
2289             auto ae = new DeclarationExp(loc, gate);
2290             eprefix = ae.expressionSemantic(sc);
2291         }
2292 
2293         for (ptrdiff_t i = start; i != end; i += step)
2294         {
2295             Expression arg = (*arguments)[i];
2296             //printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
2297 
2298             Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2299             const bool isRef = parameter && parameter.isReference();
2300             const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2301 
2302             /* Skip lazy parameters
2303              */
2304             if (isLazy)
2305                 continue;
2306 
2307             /* Do we have 'eprefix' and aren't past 'lastPrefix' yet?
2308              * Then declare a temporary variable for this arg and append that declaration
2309              * to 'eprefix', which will implicitly take care of potential problem 2) for
2310              * this arg.
2311              * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
2312              * excluding all lazy parameters.
2313              */
2314             if (needsPrefix && (lastPrefix - i) * step >= 0)
2315             {
2316                 const bool needsDtor = !isRef && arg.type.needsDestruction() &&
2317                                        // Problem 3: last throwing arg doesn't require dtor patching
2318                                        (callerDestroysArgs || i != lastPrefix);
2319 
2320                 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2321                  */
2322                 auto tmp = copyToTemp(
2323                     (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_),
2324                     needsDtor ? "__pfx" : "__pfy",
2325                     !isRef ? arg : arg.addressOf());
2326                 tmp.dsymbolSemantic(sc);
2327 
2328                 if (callerDestroysArgs)
2329                 {
2330                     /* Problem 4: Normal temporary, destructed after the call
2331                      */
2332                     if (needsDtor)
2333                         tmp.isArgDtorVar = true;   // mark it so that the backend passes it by ref to the function being called
2334                 }
2335                 else
2336                 {
2337                     /* Problem 3: Modify the destructor so it only runs if gate==false,
2338                      * i.e., only if there was a throw while constructing the args
2339                      */
2340                     if (!needsDtor)
2341                     {
2342                         if (tmp.edtor)
2343                         {
2344                             assert(i == lastPrefix);
2345                             tmp.edtor = null;
2346                         }
2347                     }
2348                     else
2349                     {
2350                         // edtor => (__gate || edtor)
2351                         assert(tmp.edtor);
2352                         Expression e = tmp.edtor;
2353                         e = new LogicalExp(e.loc, EXP.orOr, new VarExp(e.loc, gate), e);
2354                         tmp.edtor = e.expressionSemantic(sc);
2355                         //printf("edtor: %s\n", tmp.edtor.toChars());
2356                     }
2357                 }
2358 
2359                 // eprefix => (eprefix, auto __pfx/y = arg)
2360                 auto ae = new DeclarationExp(loc, tmp);
2361                 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2362 
2363                 // arg => __pfx/y
2364                 arg = new VarExp(loc, tmp);
2365                 arg = arg.expressionSemantic(sc);
2366                 if (isRef)
2367                 {
2368                     arg = new PtrExp(loc, arg);
2369                     arg = arg.expressionSemantic(sc);
2370                 }
2371 
2372                 /* Problem 3: Last throwing arg?
2373                  * Then finalize eprefix => (eprefix, gate = true), i.e., disable the
2374                  * dtors right after constructing the last throwing arg.
2375                  * From now on, the callee will take care of destructing the args because
2376                  * the args are implicitly moved into function parameters.
2377                  */
2378                 if (!callerDestroysArgs && i == lastPrefix)
2379                 {
2380                     auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2381                     eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2382                 }
2383             }
2384             else // not part of 'eprefix'
2385             {
2386                 /* Handle problem 2) by calling the copy constructor for value structs
2387                  * (or static arrays of them) if appropriate.
2388                  */
2389                 Type tv = arg.type.baseElemOf();
2390                 if (!isRef && tv.ty == Tstruct)
2391                     arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2392             }
2393 
2394             (*arguments)[i] = arg;
2395         }
2396     }
2397     //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2398 
2399     /* Test compliance with DIP1021
2400      */
2401     if (global.params.useDIP1021 &&
2402         tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2403         err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2404 
2405     // If D linkage and variadic, add _arguments[] as first argument
2406     if (tf.isDstyleVariadic())
2407     {
2408         assert(arguments.dim >= nparams);
2409 
2410         auto args = new Parameters(arguments.dim - nparams);
2411         for (size_t i = 0; i < arguments.dim - nparams; i++)
2412         {
2413             auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2414             (*args)[i] = arg;
2415         }
2416         auto tup = new TypeTuple(args);
2417         Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2418         arguments.insert(0, e);
2419     }
2420 
2421     /* Determine function return type: tret
2422      */
2423     Type tret = tf.next;
2424     if (isCtorCall)
2425     {
2426         //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2427         //    wildmatch, tf.isWild(), fd.isReturnIsolated());
2428         if (!tthis)
2429         {
2430             assert(sc.intypeof || global.errors);
2431             tthis = fd.isThis().type.addMod(fd.type.mod);
2432         }
2433         if (tf.isWild() && !fd.isReturnIsolated())
2434         {
2435             if (wildmatch)
2436                 tret = tret.substWildTo(wildmatch);
2437             int offset;
2438             if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2439             {
2440                 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2441                 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2442                 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2443                 err = true;
2444             }
2445         }
2446         tret = tthis;
2447     }
2448     else if (wildmatch && tret)
2449     {
2450         /* Adjust function return type based on wildmatch
2451          */
2452         //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2453         tret = tret.substWildTo(wildmatch);
2454     }
2455 
2456     *prettype = tret;
2457     *peprefix = eprefix;
2458     return (err || olderrors != global.errors);
2459 }
2460 
2461 /**
2462  * Determines whether a symbol represents a module or package
2463  * (Used as a helper for is(type == module) and is(type == package))
2464  *
2465  * Params:
2466  *  sym = the symbol to be checked
2467  *
2468  * Returns:
2469  *  the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2470  */
resolveIsPackage(Dsymbol sym)2471 Package resolveIsPackage(Dsymbol sym)
2472 {
2473     Package pkg;
2474     if (Import imp = sym.isImport())
2475     {
2476         if (imp.pkg is null)
2477         {
2478             .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2479                     imp.toChars());
2480             assert(0);
2481         }
2482         pkg = imp.pkg;
2483     }
2484     else if (auto mod = sym.isModule())
2485         pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2486     else
2487         pkg = sym.isPackage();
2488     if (pkg)
2489         pkg.resolvePKGunknown();
2490     return pkg;
2491 }
2492 
loadStdMath()2493 private Module loadStdMath()
2494 {
2495     __gshared Import impStdMath = null;
2496     __gshared Identifier[1] stdID;
2497     if (!impStdMath)
2498     {
2499         stdID[0] = Id.std;
2500         auto s = new Import(Loc.initial, stdID[], Id.math, null, false);
2501         // Module.load will call fatal() if there's no std.math available.
2502         // Gag the error here, pushing the error handling to the caller.
2503         uint errors = global.startGagging();
2504         s.load(null);
2505         if (s.mod)
2506         {
2507             s.mod.importAll(null);
2508             s.mod.dsymbolSemantic(null);
2509         }
2510         global.endGagging(errors);
2511         impStdMath = s;
2512     }
2513     return impStdMath.mod;
2514 }
2515 
2516 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2517 {
2518     alias visit = Visitor.visit;
2519 
2520     Scope* sc;
2521     Expression result;
2522 
this(Scope * sc)2523     this(Scope* sc)
2524     {
2525         this.sc = sc;
2526     }
2527 
setError()2528     private void setError()
2529     {
2530         result = ErrorExp.get();
2531     }
2532 
2533     /**************************
2534      * Semantically analyze Expression.
2535      * Determine types, fold constants, etc.
2536      */
visit(Expression e)2537     override void visit(Expression e)
2538     {
2539         static if (LOGSEMANTIC)
2540         {
2541             printf("Expression::semantic() %s\n", e.toChars());
2542         }
2543         if (e.type)
2544             e.type = e.type.typeSemantic(e.loc, sc);
2545         else
2546             e.type = Type.tvoid;
2547         result = e;
2548     }
2549 
visit(IntegerExp e)2550     override void visit(IntegerExp e)
2551     {
2552         assert(e.type);
2553         if (e.type.ty == Terror)
2554             return setError();
2555 
2556         assert(e.type.deco);
2557         e.setInteger(e.getInteger());
2558         result = e;
2559     }
2560 
visit(RealExp e)2561     override void visit(RealExp e)
2562     {
2563         if (!e.type)
2564             e.type = Type.tfloat64;
2565         else
2566             e.type = e.type.typeSemantic(e.loc, sc);
2567         result = e;
2568     }
2569 
visit(ComplexExp e)2570     override void visit(ComplexExp e)
2571     {
2572         if (!e.type)
2573             e.type = Type.tcomplex80;
2574         else
2575             e.type = e.type.typeSemantic(e.loc, sc);
2576         result = e;
2577     }
2578 
visit(IdentifierExp exp)2579     override void visit(IdentifierExp exp)
2580     {
2581         static if (LOGSEMANTIC)
2582         {
2583             printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2584         }
2585         if (exp.type) // This is used as the dummy expression
2586         {
2587             result = exp;
2588             return;
2589         }
2590 
2591         Dsymbol scopesym;
2592         Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2593         if (s)
2594         {
2595             if (s.errors)
2596                 return setError();
2597 
2598             Expression e;
2599 
2600             /* See if the symbol was a member of an enclosing 'with'
2601              */
2602             WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2603             if (withsym && withsym.withstate.wthis && symbolIsVisible(sc, s))
2604             {
2605                 /* Disallow shadowing
2606                  */
2607                 // First find the scope of the with
2608                 Scope* scwith = sc;
2609                 while (scwith.scopesym != scopesym)
2610                 {
2611                     scwith = scwith.enclosing;
2612                     assert(scwith);
2613                 }
2614                 // Look at enclosing scopes for symbols with the same name,
2615                 // in the same function
2616                 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2617                 {
2618                     Dsymbol s2;
2619                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2620                     {
2621                         exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2622                         return setError();
2623                     }
2624                 }
2625                 s = s.toAlias();
2626 
2627                 // Same as wthis.ident
2628                 //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2629                 //  The redudancy should be removed.
2630                 e = new VarExp(exp.loc, withsym.withstate.wthis);
2631                 e = new DotIdExp(exp.loc, e, exp.ident);
2632                 e = e.expressionSemantic(sc);
2633             }
2634             else
2635             {
2636                 if (withsym)
2637                 {
2638                     if (withsym.withstate.exp.type.ty != Tvoid)
2639                     {
2640                         // 'with (exp)' is a type expression
2641                         // or 's' is not visible there (for error message)
2642                         e = new TypeExp(exp.loc, withsym.withstate.exp.type);
2643                     }
2644                     else
2645                     {
2646                         // 'with (exp)' is a Package/Module
2647                         e = withsym.withstate.exp;
2648                     }
2649                     e = new DotIdExp(exp.loc, e, exp.ident);
2650                     result = e.expressionSemantic(sc);
2651                     return;
2652                 }
2653 
2654                 /* If f is really a function template,
2655                  * then replace f with the function template declaration.
2656                  */
2657                 FuncDeclaration f = s.isFuncDeclaration();
2658                 if (f)
2659                 {
2660                     TemplateDeclaration td = getFuncTemplateDecl(f);
2661                     if (td)
2662                     {
2663                         if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2664                             td = td.overroot; // then get the start
2665                         e = new TemplateExp(exp.loc, td, f);
2666                         e = e.expressionSemantic(sc);
2667                         result = e;
2668                         return;
2669                     }
2670                 }
2671 
2672                 if (global.params.fixAliasThis)
2673                 {
2674                     ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2675                     if (expDsym)
2676                     {
2677                         //printf("expDsym = %s\n", expDsym.exp.toChars());
2678                         result = expDsym.exp.expressionSemantic(sc);
2679                         return;
2680                     }
2681                 }
2682                 // Haven't done overload resolution yet, so pass 1
2683                 e = symbolToExp(s, exp.loc, sc, true);
2684             }
2685             result = e;
2686             return;
2687         }
2688 
2689         if (!global.params.fixAliasThis && hasThis(sc))
2690         {
2691             for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2692             {
2693                 if (ad.aliasthis)
2694                 {
2695                     Expression e;
2696                     e = new ThisExp(exp.loc);
2697                     e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2698                     e = new DotIdExp(exp.loc, e, exp.ident);
2699                     e = e.trySemantic(sc);
2700                     if (e)
2701                     {
2702                         result = e;
2703                         return;
2704                     }
2705                 }
2706 
2707                 auto cd = ad.isClassDeclaration();
2708                 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2709                 {
2710                     ad = cd.baseClass;
2711                     continue;
2712                 }
2713                 break;
2714             }
2715         }
2716 
2717         if (exp.ident == Id.ctfe)
2718         {
2719             if (sc.flags & SCOPE.ctfe)
2720             {
2721                 exp.error("variable `__ctfe` cannot be read at compile time");
2722                 return setError();
2723             }
2724 
2725             // Create the magic __ctfe bool variable
2726             auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2727             vd.storage_class |= STC.temp;
2728             vd.semanticRun = PASS.semanticdone;
2729             Expression e = new VarExp(exp.loc, vd);
2730             e = e.expressionSemantic(sc);
2731             result = e;
2732             return;
2733         }
2734 
2735         // If we've reached this point and are inside a with() scope then we may
2736         // try one last attempt by checking whether the 'wthis' object supports
2737         // dynamic dispatching via opDispatch.
2738         // This is done by rewriting this expression as wthis.ident.
2739         // The innermost with() scope of the hierarchy to satisfy the condition
2740         // above wins.
2741         // https://issues.dlang.org/show_bug.cgi?id=6400
2742         for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2743         {
2744             if (!sc2.scopesym)
2745                 continue;
2746 
2747             if (auto ss = sc2.scopesym.isWithScopeSymbol())
2748             {
2749                 if (ss.withstate.wthis)
2750                 {
2751                     Expression e;
2752                     e = new VarExp(exp.loc, ss.withstate.wthis);
2753                     e = new DotIdExp(exp.loc, e, exp.ident);
2754                     e = e.trySemantic(sc);
2755                     if (e)
2756                     {
2757                         result = e;
2758                         return;
2759                     }
2760                 }
2761                 // Try Type.opDispatch (so the static version)
2762                 else if (ss.withstate.exp && ss.withstate.exp.op == EXP.type)
2763                 {
2764                     if (Type t = ss.withstate.exp.isTypeExp().type)
2765                     {
2766                         Expression e;
2767                         e = new TypeExp(exp.loc, t);
2768                         e = new DotIdExp(exp.loc, e, exp.ident);
2769                         e = e.trySemantic(sc);
2770                         if (e)
2771                         {
2772                             result = e;
2773                             return;
2774                         }
2775                     }
2776                 }
2777             }
2778         }
2779 
2780         /* Look for what user might have meant
2781          */
2782         if (const n = importHint(exp.ident.toString()))
2783             exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2784         else if (auto s2 = sc.search_correct(exp.ident))
2785             exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2786         else if (const p = Scope.search_correct_C(exp.ident))
2787             exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2788         else if (exp.ident == Id.dollar)
2789             exp.error("undefined identifier `$`");
2790         else
2791             exp.error("undefined identifier `%s`", exp.ident.toChars());
2792 
2793         result = ErrorExp.get();
2794     }
2795 
visit(DsymbolExp e)2796     override void visit(DsymbolExp e)
2797     {
2798         result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2799     }
2800 
visit(ThisExp e)2801     override void visit(ThisExp e)
2802     {
2803         static if (LOGSEMANTIC)
2804         {
2805             printf("ThisExp::semantic()\n");
2806         }
2807         if (e.type)
2808         {
2809             result = e;
2810             return;
2811         }
2812 
2813         FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2814         AggregateDeclaration ad;
2815 
2816         /* Special case for typeof(this) and typeof(super) since both
2817          * should work even if they are not inside a non-static member function
2818          */
2819         if (!fd && sc.intypeof == 1)
2820         {
2821             // Find enclosing struct or class
2822             for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2823             {
2824                 if (!s)
2825                 {
2826                     e.error("`%s` is not in a class or struct scope", e.toChars());
2827                     goto Lerr;
2828                 }
2829                 ClassDeclaration cd = s.isClassDeclaration();
2830                 if (cd)
2831                 {
2832                     e.type = cd.type;
2833                     result = e;
2834                     return;
2835                 }
2836                 StructDeclaration sd = s.isStructDeclaration();
2837                 if (sd)
2838                 {
2839                     e.type = sd.type;
2840                     result = e;
2841                     return;
2842                 }
2843             }
2844         }
2845         if (!fd)
2846             goto Lerr;
2847 
2848         assert(fd.vthis);
2849         e.var = fd.vthis;
2850         assert(e.var.parent);
2851         ad = fd.isMemberLocal();
2852         if (!ad)
2853             ad = fd.isMember2();
2854         assert(ad);
2855         e.type = ad.type.addMod(e.var.type.mod);
2856 
2857         if (e.var.checkNestedReference(sc, e.loc))
2858             return setError();
2859 
2860         result = e;
2861         return;
2862 
2863     Lerr:
2864         e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2865         result = ErrorExp.get();
2866     }
2867 
visit(SuperExp e)2868     override void visit(SuperExp e)
2869     {
2870         static if (LOGSEMANTIC)
2871         {
2872             printf("SuperExp::semantic('%s')\n", e.toChars());
2873         }
2874         if (e.type)
2875         {
2876             result = e;
2877             return;
2878         }
2879 
2880         FuncDeclaration fd = hasThis(sc);
2881         ClassDeclaration cd;
2882         Dsymbol s;
2883 
2884         /* Special case for typeof(this) and typeof(super) since both
2885          * should work even if they are not inside a non-static member function
2886          */
2887         if (!fd && sc.intypeof == 1)
2888         {
2889             // Find enclosing class
2890             for (s = sc.getStructClassScope(); 1; s = s.parent)
2891             {
2892                 if (!s)
2893                 {
2894                     e.error("`%s` is not in a class scope", e.toChars());
2895                     goto Lerr;
2896                 }
2897                 cd = s.isClassDeclaration();
2898                 if (cd)
2899                 {
2900                     cd = cd.baseClass;
2901                     if (!cd)
2902                     {
2903                         e.error("class `%s` has no `super`", s.toChars());
2904                         goto Lerr;
2905                     }
2906                     e.type = cd.type;
2907                     result = e;
2908                     return;
2909                 }
2910             }
2911         }
2912         if (!fd)
2913             goto Lerr;
2914 
2915         e.var = fd.vthis;
2916         assert(e.var && e.var.parent);
2917 
2918         s = fd.toParentDecl();
2919         if (s.isTemplateDeclaration()) // allow inside template constraint
2920             s = s.toParent();
2921         assert(s);
2922         cd = s.isClassDeclaration();
2923         //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2924         if (!cd)
2925             goto Lerr;
2926         if (!cd.baseClass)
2927         {
2928             e.error("no base class for `%s`", cd.toChars());
2929             e.type = cd.type.addMod(e.var.type.mod);
2930         }
2931         else
2932         {
2933             e.type = cd.baseClass.type;
2934             e.type = e.type.castMod(e.var.type.mod);
2935         }
2936 
2937         if (e.var.checkNestedReference(sc, e.loc))
2938             return setError();
2939 
2940         result = e;
2941         return;
2942 
2943     Lerr:
2944         e.error("`super` is only allowed in non-static class member functions");
2945         result = ErrorExp.get();
2946     }
2947 
visit(NullExp e)2948     override void visit(NullExp e)
2949     {
2950         static if (LOGSEMANTIC)
2951         {
2952             printf("NullExp::semantic('%s')\n", e.toChars());
2953         }
2954         // NULL is the same as (void *)0
2955         if (e.type)
2956         {
2957             result = e;
2958             return;
2959         }
2960         e.type = Type.tnull;
2961         result = e;
2962     }
2963 
visit(StringExp e)2964     override void visit(StringExp e)
2965     {
2966         static if (LOGSEMANTIC)
2967         {
2968             printf("StringExp::semantic() %s\n", e.toChars());
2969         }
2970         if (e.type)
2971         {
2972             result = e;
2973             return;
2974         }
2975 
2976         OutBuffer buffer;
2977         size_t newlen = 0;
2978         size_t u;
2979         dchar c;
2980 
2981         switch (e.postfix)
2982         {
2983         case 'd':
2984             for (u = 0; u < e.len;)
2985             {
2986                 if (const p = utf_decodeChar(e.peekString(), u, c))
2987                 {
2988                     e.error("%.*s", cast(int)p.length, p.ptr);
2989                     return setError();
2990                 }
2991                 else
2992                 {
2993                     buffer.write4(c);
2994                     newlen++;
2995                 }
2996             }
2997             buffer.write4(0);
2998             e.setData(buffer.extractData(), newlen, 4);
2999             if (sc && sc.flags & SCOPE.Cfile)
3000                 e.type = Type.tuns32.pointerTo();
3001             else
3002                 e.type = Type.tdchar.immutableOf().arrayOf();
3003             e.committed = 1;
3004             break;
3005 
3006         case 'w':
3007             for (u = 0; u < e.len;)
3008             {
3009                 if (const p = utf_decodeChar(e.peekString(), u, c))
3010                 {
3011                     e.error("%.*s", cast(int)p.length, p.ptr);
3012                     return setError();
3013                 }
3014                 else
3015                 {
3016                     buffer.writeUTF16(c);
3017                     newlen++;
3018                     if (c >= 0x10000)
3019                         newlen++;
3020                 }
3021             }
3022             buffer.writeUTF16(0);
3023             e.setData(buffer.extractData(), newlen, 2);
3024             if (sc && sc.flags & SCOPE.Cfile)
3025                 e.type = Type.tuns16.pointerTo();
3026             else
3027                 e.type = Type.twchar.immutableOf().arrayOf();
3028             e.committed = 1;
3029             break;
3030 
3031         case 'c':
3032             e.committed = 1;
3033             goto default;
3034 
3035         default:
3036             if (sc && sc.flags & SCOPE.Cfile)
3037                 e.type = Type.tchar.pointerTo();
3038             else
3039                 e.type = Type.tchar.immutableOf().arrayOf();
3040             break;
3041         }
3042         e.type = e.type.typeSemantic(e.loc, sc);
3043         //type = type.immutableOf();
3044         //printf("type = %s\n", type.toChars());
3045 
3046         result = e;
3047     }
3048 
visit(TupleExp exp)3049     override void visit(TupleExp exp)
3050     {
3051         static if (LOGSEMANTIC)
3052         {
3053             printf("+TupleExp::semantic(%s)\n", exp.toChars());
3054         }
3055         if (exp.type)
3056         {
3057             result = exp;
3058             return;
3059         }
3060 
3061         if (exp.e0)
3062             exp.e0 = exp.e0.expressionSemantic(sc);
3063 
3064         // Run semantic() on each argument
3065         bool err = false;
3066         for (size_t i = 0; i < exp.exps.dim; i++)
3067         {
3068             Expression e = (*exp.exps)[i];
3069             e = e.expressionSemantic(sc);
3070             if (!e.type)
3071             {
3072                 exp.error("`%s` has no value", e.toChars());
3073                 err = true;
3074             }
3075             else if (e.op == EXP.error)
3076                 err = true;
3077             else
3078                 (*exp.exps)[i] = e;
3079         }
3080         if (err)
3081             return setError();
3082 
3083         expandTuples(exp.exps);
3084 
3085         exp.type = new TypeTuple(exp.exps);
3086         exp.type = exp.type.typeSemantic(exp.loc, sc);
3087         //printf("-TupleExp::semantic(%s)\n", toChars());
3088         result = exp;
3089     }
3090 
visit(ArrayLiteralExp e)3091     override void visit(ArrayLiteralExp e)
3092     {
3093         static if (LOGSEMANTIC)
3094         {
3095             printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3096         }
3097         if (e.type)
3098         {
3099             result = e;
3100             return;
3101         }
3102 
3103         /* Perhaps an empty array literal [ ] should be rewritten as null?
3104          */
3105 
3106         if (e.basis)
3107             e.basis = e.basis.expressionSemantic(sc);
3108         if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == EXP.error))
3109             return setError();
3110 
3111         expandTuples(e.elements);
3112 
3113         if (e.basis)
3114             e.elements.push(e.basis);
3115         Type t0 = arrayExpressionToCommonType(sc, *e.elements);
3116         if (e.basis)
3117             e.basis = e.elements.pop();
3118         if (t0 is null)
3119             return setError();
3120 
3121         e.type = t0.arrayOf();
3122         e.type = e.type.typeSemantic(e.loc, sc);
3123 
3124         /* Disallow array literals of type void being used.
3125          */
3126         if (e.elements.dim > 0 && t0.ty == Tvoid)
3127         {
3128             e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3129             return setError();
3130         }
3131 
3132         if (global.params.useTypeInfo && Type.dtypeinfo)
3133             semanticTypeInfo(sc, e.type);
3134 
3135         result = e;
3136     }
3137 
visit(AssocArrayLiteralExp e)3138     override void visit(AssocArrayLiteralExp e)
3139     {
3140         static if (LOGSEMANTIC)
3141         {
3142             printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3143         }
3144         if (e.type)
3145         {
3146             result = e;
3147             return;
3148         }
3149 
3150         // Run semantic() on each element
3151         bool err_keys = arrayExpressionSemantic(e.keys, sc);
3152         bool err_vals = arrayExpressionSemantic(e.values, sc);
3153         if (err_keys || err_vals)
3154             return setError();
3155 
3156         expandTuples(e.keys);
3157         expandTuples(e.values);
3158         if (e.keys.dim != e.values.dim)
3159         {
3160             e.error("number of keys is %llu, must match number of values %llu",
3161                         cast(ulong) e.keys.dim, cast(ulong) e.values.dim);
3162             return setError();
3163         }
3164 
3165         Type tkey = arrayExpressionToCommonType(sc, *e.keys);
3166         Type tvalue = arrayExpressionToCommonType(sc, *e.values);
3167         if (tkey is null || tvalue is null)
3168             return setError();
3169 
3170         e.type = new TypeAArray(tvalue, tkey);
3171         e.type = e.type.typeSemantic(e.loc, sc);
3172 
3173         semanticTypeInfo(sc, e.type);
3174 
3175         if (global.params.useDIP1000 == FeatureState.enabled)
3176         {
3177             if (checkAssocArrayLiteralEscape(sc, e, false))
3178                 return setError();
3179         }
3180 
3181         result = e;
3182     }
3183 
visit(StructLiteralExp e)3184     override void visit(StructLiteralExp e)
3185     {
3186         static if (LOGSEMANTIC)
3187         {
3188             printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3189         }
3190         if (e.type)
3191         {
3192             result = e;
3193             return;
3194         }
3195 
3196         e.sd.size(e.loc);
3197         if (e.sd.sizeok != Sizeok.done)
3198             return setError();
3199 
3200         // run semantic() on each element
3201         if (arrayExpressionSemantic(e.elements, sc))
3202             return setError();
3203 
3204         expandTuples(e.elements);
3205 
3206         /* Fit elements[] to the corresponding type of field[].
3207          */
3208         if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3209             return setError();
3210 
3211         /* Fill out remainder of elements[] with default initializers for fields[]
3212          */
3213         if (!e.sd.fill(e.loc, e.elements, false))
3214         {
3215             /* An error in the initializer needs to be recorded as an error
3216              * in the enclosing function or template, since the initializer
3217              * will be part of the stuct declaration.
3218              */
3219             global.increaseErrorCount();
3220             return setError();
3221         }
3222 
3223         if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
3224             return setError();
3225 
3226         e.type = e.stype ? e.stype : e.sd.type;
3227         result = e;
3228     }
3229 
visit(CompoundLiteralExp cle)3230     override void visit(CompoundLiteralExp cle)
3231     {
3232         static if (LOGSEMANTIC)
3233         {
3234             printf("CompoundLiteralExp::semantic('%s')\n", cle.toChars());
3235         }
3236         Type t = cle.type.typeSemantic(cle.loc, sc);
3237         auto init = initializerSemantic(cle.initializer, sc, t, INITnointerpret);
3238         auto e = initializerToExpression(init, t, (sc.flags & SCOPE.Cfile) != 0);
3239         if (!e)
3240         {
3241             error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars());
3242             return setError();
3243         }
3244         result = e;
3245         return;
3246     }
3247 
visit(TypeExp exp)3248     override void visit(TypeExp exp)
3249     {
3250         if (exp.type.ty == Terror)
3251             return setError();
3252 
3253         //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3254         Expression e;
3255         Type t;
3256         Dsymbol s;
3257 
3258         dmd.typesem.resolve(exp.type, exp.loc, sc, e, t, s, true);
3259         if (e)
3260         {
3261             // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3262             // then rewrite as `(this.var)` in case it would be followed by a DotVar
3263             // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3264             VarExp ve = e.isVarExp();
3265             if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3266                 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
3267             {
3268                 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3269                 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3270             }
3271             //printf("e = %s %s\n", Token.toChars(e.op), e.toChars());
3272             e = e.expressionSemantic(sc);
3273         }
3274         else if (t)
3275         {
3276             //printf("t = %d %s\n", t.ty, t.toChars());
3277             exp.type = t.typeSemantic(exp.loc, sc);
3278             e = exp;
3279         }
3280         else if (s)
3281         {
3282             //printf("s = %s %s\n", s.kind(), s.toChars());
3283             e = symbolToExp(s, exp.loc, sc, true);
3284         }
3285         else
3286             assert(0);
3287 
3288         exp.type.checkComplexTransition(exp.loc, sc);
3289 
3290         result = e;
3291     }
3292 
visit(ScopeExp exp)3293     override void visit(ScopeExp exp)
3294     {
3295         static if (LOGSEMANTIC)
3296         {
3297             printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3298         }
3299         if (exp.type)
3300         {
3301             result = exp;
3302             return;
3303         }
3304 
3305         ScopeDsymbol sds2 = exp.sds;
3306         TemplateInstance ti = sds2.isTemplateInstance();
3307         while (ti)
3308         {
3309             WithScopeSymbol withsym;
3310             if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3311                 return setError();
3312             if (withsym && withsym.withstate.wthis)
3313             {
3314                 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3315                 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3316                 result = e.expressionSemantic(sc);
3317                 return;
3318             }
3319             if (ti.needsTypeInference(sc))
3320             {
3321                 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3322                 {
3323                     Dsymbol p = td.toParentLocal();
3324                     FuncDeclaration fdthis = hasThis(sc);
3325                     AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3326                     if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3327                     {
3328                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3329                         result = e.expressionSemantic(sc);
3330                         return;
3331                     }
3332                 }
3333                 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3334                 {
3335                     FuncDeclaration fdthis = hasThis(sc);
3336                     AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3337                     if (fdthis && ad && fdthis.isMemberLocal() == ad)
3338                     {
3339                         Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3340                         result = e.expressionSemantic(sc);
3341                         return;
3342                     }
3343                 }
3344                 // ti is an instance which requires IFTI.
3345                 exp.sds = ti;
3346                 exp.type = Type.tvoid;
3347                 result = exp;
3348                 return;
3349             }
3350             ti.dsymbolSemantic(sc);
3351             if (!ti.inst || ti.errors)
3352                 return setError();
3353 
3354             Dsymbol s = ti.toAlias();
3355             if (s == ti)
3356             {
3357                 exp.sds = ti;
3358                 exp.type = Type.tvoid;
3359                 result = exp;
3360                 return;
3361             }
3362             sds2 = s.isScopeDsymbol();
3363             if (sds2)
3364             {
3365                 ti = sds2.isTemplateInstance();
3366                 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3367                 continue;
3368             }
3369 
3370             if (auto v = s.isVarDeclaration())
3371             {
3372                 if (!v.type)
3373                 {
3374                     exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3375                     return setError();
3376                 }
3377                 if ((v.storage_class & STC.manifest) && v._init)
3378                 {
3379                     /* When an instance that will be converted to a constant exists,
3380                      * the instance representation "foo!tiargs" is treated like a
3381                      * variable name, and its recursive appearance check (note that
3382                      * it's equivalent with a recursive instantiation of foo) is done
3383                      * separately from the circular initialization check for the
3384                      * eponymous enum variable declaration.
3385                      *
3386                      *  template foo(T) {
3387                      *    enum bool foo = foo;    // recursive definition check (v.inuse)
3388                      *  }
3389                      *  template bar(T) {
3390                      *    enum bool bar = bar!T;  // recursive instantiation check (ti.inuse)
3391                      *  }
3392                      */
3393                     if (ti.inuse)
3394                     {
3395                         exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3396                         return setError();
3397                     }
3398                     v.checkDeprecated(exp.loc, sc);
3399                     auto e = v.expandInitializer(exp.loc);
3400                     ti.inuse++;
3401                     e = e.expressionSemantic(sc);
3402                     ti.inuse--;
3403                     result = e;
3404                     return;
3405                 }
3406             }
3407 
3408             //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3409             auto e = symbolToExp(s, exp.loc, sc, true);
3410             //printf("-1ScopeExp::semantic()\n");
3411             result = e;
3412             return;
3413         }
3414 
3415         //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3416         //printf("\tparent = '%s'\n", sds2.parent.toChars());
3417         sds2.dsymbolSemantic(sc);
3418 
3419         // (Aggregate|Enum)Declaration
3420         if (auto t = sds2.getType())
3421         {
3422             result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3423             return;
3424         }
3425 
3426         if (auto td = sds2.isTemplateDeclaration())
3427         {
3428             result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3429             return;
3430         }
3431 
3432         exp.sds = sds2;
3433         exp.type = Type.tvoid;
3434         //printf("-2ScopeExp::semantic() %s\n", toChars());
3435         result = exp;
3436     }
3437 
visit(NewExp exp)3438     override void visit(NewExp exp)
3439     {
3440         static if (LOGSEMANTIC)
3441         {
3442             printf("NewExp::semantic() %s\n", exp.toChars());
3443             if (exp.thisexp)
3444                 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3445             printf("\tnewtype: %s\n", exp.newtype.toChars());
3446         }
3447         if (exp.type) // if semantic() already run
3448         {
3449             result = exp;
3450             return;
3451         }
3452 
3453         //for error messages if the argument in [] is not convertible to size_t
3454         const originalNewtype = exp.newtype;
3455 
3456         // https://issues.dlang.org/show_bug.cgi?id=11581
3457         // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3458         // T should be analyzed first and edim should go into arguments iff it's
3459         // not a tuple.
3460         Expression edim = null;
3461         if (!exp.arguments && exp.newtype.isTypeSArray())
3462         {
3463             auto ts = exp.newtype.isTypeSArray();
3464             edim = ts.dim;
3465             exp.newtype = ts.next;
3466         }
3467 
3468         ClassDeclaration cdthis = null;
3469         if (exp.thisexp)
3470         {
3471             exp.thisexp = exp.thisexp.expressionSemantic(sc);
3472             if (exp.thisexp.op == EXP.error)
3473                 return setError();
3474 
3475             cdthis = exp.thisexp.type.isClassHandle();
3476             if (!cdthis)
3477             {
3478                 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3479                 return setError();
3480             }
3481 
3482             sc = sc.push(cdthis);
3483             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3484             sc = sc.pop();
3485         }
3486         else
3487         {
3488             exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3489         }
3490         if (exp.type.ty == Terror)
3491             return setError();
3492 
3493         if (edim)
3494         {
3495             if (exp.type.toBasetype().ty == Ttuple)
3496             {
3497                 // --> new T[edim]
3498                 exp.type = new TypeSArray(exp.type, edim);
3499                 exp.type = exp.type.typeSemantic(exp.loc, sc);
3500                 if (exp.type.ty == Terror)
3501                     return setError();
3502             }
3503             else
3504             {
3505                 // --> new T[](edim)
3506                 exp.arguments = new Expressions();
3507                 exp.arguments.push(edim);
3508                 exp.type = exp.type.arrayOf();
3509             }
3510         }
3511 
3512         exp.newtype = exp.type; // in case type gets cast to something else
3513         Type tb = exp.type.toBasetype();
3514         //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3515         if (arrayExpressionSemantic(exp.arguments, sc))
3516         {
3517             return setError();
3518         }
3519         //https://issues.dlang.org/show_bug.cgi?id=20547
3520         //exp.arguments are the "parameters" to [], not to a real function
3521         //so the errors that come from preFunctionParameters are misleading
3522         if (originalNewtype.ty == Tsarray)
3523         {
3524             if (preFunctionParameters(sc, exp.arguments, false))
3525             {
3526                 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
3527                 return setError();
3528             }
3529         }
3530         else if (preFunctionParameters(sc, exp.arguments))
3531         {
3532             return setError();
3533         }
3534 
3535         if (exp.thisexp && tb.ty != Tclass)
3536         {
3537             exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3538             return setError();
3539         }
3540 
3541         const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
3542         Expression newprefix = null;
3543 
3544         if (auto tc = tb.isTypeClass())
3545         {
3546             auto cd = tc.sym;
3547             cd.size(exp.loc);
3548             if (cd.sizeok != Sizeok.done)
3549                 return setError();
3550             if (!cd.ctor)
3551                 cd.ctor = cd.searchCtor();
3552             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3553             {
3554                 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3555                 return setError();
3556             }
3557 
3558             if (cd.isInterfaceDeclaration())
3559             {
3560                 exp.error("cannot create instance of interface `%s`", cd.toChars());
3561                 return setError();
3562             }
3563 
3564             if (cd.isAbstract())
3565             {
3566                 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3567                 for (size_t i = 0; i < cd.vtbl.dim; i++)
3568                 {
3569                     FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3570                     if (fd && fd.isAbstract())
3571                     {
3572                         errorSupplemental(exp.loc, "function `%s` is not implemented",
3573                             fd.toFullSignature());
3574                     }
3575                 }
3576                 return setError();
3577             }
3578             // checkDeprecated() is already done in newtype.typeSemantic().
3579 
3580             if (cd.isNested())
3581             {
3582                 /* We need a 'this' pointer for the nested class.
3583                  * Ensure we have the right one.
3584                  */
3585                 Dsymbol s = cd.toParentLocal();
3586 
3587                 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3588                 if (auto cdn = s.isClassDeclaration())
3589                 {
3590                     if (!cdthis)
3591                     {
3592                         if (!sc.hasThis)
3593                         {
3594                             string msg = "cannot construct " ~
3595                             (cd.isAnonymous ? "anonymous nested class" : "nested class `%s`") ~
3596                             " because no implicit `this` reference to outer class" ~
3597                             (cdn.isAnonymous ? "" : " `%s`") ~ " is available\0";
3598 
3599                             exp.error(msg.ptr, cd.toChars, cdn.toChars);
3600                             return setError();
3601                         }
3602 
3603                         // Supply an implicit 'this' and try again
3604                         exp.thisexp = new ThisExp(exp.loc);
3605                         for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3606                         {
3607                             ClassDeclaration cdp = sp.isClassDeclaration();
3608                             if (!cdp)
3609                                 continue;
3610                             if (cdp == cdn || cdn.isBaseOf(cdp, null))
3611                                 break;
3612                             // Add a '.outer' and try again
3613                             exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3614                         }
3615 
3616                         exp.thisexp = exp.thisexp.expressionSemantic(sc);
3617                         if (exp.thisexp.op == EXP.error)
3618                             return setError();
3619                         cdthis = exp.thisexp.type.isClassHandle();
3620                     }
3621                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3622                     {
3623                         //printf("cdthis = %s\n", cdthis.toChars());
3624                         exp.error("`this` for nested class must be of type `%s`, not `%s`",
3625                             cdn.toChars(), exp.thisexp.type.toChars());
3626                         return setError();
3627                     }
3628                     if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3629                     {
3630                         exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3631                             exp.newtype.toChars(), exp.thisexp.type.toChars());
3632                         return setError();
3633                     }
3634                 }
3635                 else if (exp.thisexp)
3636                 {
3637                     exp.error("`.new` is only for allocating nested classes");
3638                     return setError();
3639                 }
3640                 else if (auto fdn = s.isFuncDeclaration())
3641                 {
3642                     // make sure the parent context fdn of cd is reachable from sc
3643                     if (!ensureStaticLinkTo(sc.parent, fdn))
3644                     {
3645                         exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3646                             fdn.toPrettyChars(), cd.toPrettyChars());
3647                         return setError();
3648                     }
3649                 }
3650                 else
3651                     assert(0);
3652             }
3653             else if (exp.thisexp)
3654             {
3655                 exp.error("`.new` is only for allocating nested classes");
3656                 return setError();
3657             }
3658 
3659             if (cd.vthis2)
3660             {
3661                 if (AggregateDeclaration ad2 = cd.isMember2())
3662                 {
3663                     Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3664                     if (te.op != EXP.error)
3665                         te = getRightThis(exp.loc, sc, ad2, te, cd);
3666                     if (te.op == EXP.error)
3667                     {
3668                         exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3669                         return setError();
3670                     }
3671                 }
3672             }
3673 
3674             if (cd.disableNew)
3675             {
3676                 exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
3677                           originalNewtype.toChars());
3678                 return setError();
3679             }
3680 
3681             if (cd.ctor)
3682             {
3683                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3684                 if (!f || f.errors)
3685                     return setError();
3686 
3687                 checkFunctionAttributes(exp, sc, f);
3688                 checkAccess(cd, exp.loc, sc, f);
3689 
3690                 TypeFunction tf = f.type.isTypeFunction();
3691                 if (!exp.arguments)
3692                     exp.arguments = new Expressions();
3693                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3694                     return setError();
3695 
3696                 exp.member = f.isCtorDeclaration();
3697                 assert(exp.member);
3698             }
3699             else
3700             {
3701                 if (nargs)
3702                 {
3703                     exp.error("no constructor for `%s`", cd.toChars());
3704                     return setError();
3705                 }
3706 
3707                 // https://issues.dlang.org/show_bug.cgi?id=19941
3708                 // Run semantic on all field initializers to resolve any forward
3709                 // references. This is the same as done for structs in sd.fill().
3710                 for (ClassDeclaration c = cd; c; c = c.baseClass)
3711                 {
3712                     foreach (v; c.fields)
3713                     {
3714                         if (v.inuse || v._scope is null || v._init is null ||
3715                             v._init.isVoidInitializer())
3716                             continue;
3717                         v.inuse++;
3718                         v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3719                         v.inuse--;
3720                     }
3721                 }
3722             }
3723         }
3724         else if (auto ts = tb.isTypeStruct())
3725         {
3726             auto sd = ts.sym;
3727             sd.size(exp.loc);
3728             if (sd.sizeok != Sizeok.done)
3729                 return setError();
3730             if (!sd.ctor)
3731                 sd.ctor = sd.searchCtor();
3732             if (sd.noDefaultCtor && !nargs)
3733             {
3734                 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3735                 return setError();
3736             }
3737             // checkDeprecated() is already done in newtype.typeSemantic().
3738 
3739             if (sd.disableNew)
3740             {
3741                 exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
3742                           originalNewtype.toChars());
3743                 return setError();
3744             }
3745 
3746             // https://issues.dlang.org/show_bug.cgi?id=22639
3747             // If the new expression has arguments, we either should call a
3748             // regular constructor of a copy constructor if the first argument
3749             // is the same type as the struct
3750             if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf())))
3751             {
3752                 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3753                 if (!f || f.errors)
3754                     return setError();
3755 
3756                 checkFunctionAttributes(exp, sc, f);
3757                 checkAccess(sd, exp.loc, sc, f);
3758 
3759                 TypeFunction tf = f.type.isTypeFunction();
3760                 if (!exp.arguments)
3761                     exp.arguments = new Expressions();
3762                 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3763                     return setError();
3764 
3765                 exp.member = f.isCtorDeclaration();
3766                 assert(exp.member);
3767 
3768                 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
3769                     return setError();
3770             }
3771             else
3772             {
3773                 if (!exp.arguments)
3774                     exp.arguments = new Expressions();
3775 
3776                 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3777                     return setError();
3778 
3779                 if (!sd.fill(exp.loc, exp.arguments, false))
3780                     return setError();
3781 
3782                 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
3783                     return setError();
3784 
3785                 /* Since a `new` allocation may escape, check each of the arguments for escaping
3786                  */
3787                 if (global.params.useDIP1000 == FeatureState.enabled)
3788                 {
3789                     foreach (arg; *exp.arguments)
3790                     {
3791                         if (arg && checkNewEscape(sc, arg, false))
3792                             return setError();
3793                     }
3794                 }
3795             }
3796 
3797             exp.type = exp.type.pointerTo();
3798         }
3799         else if (tb.ty == Tarray)
3800         {
3801             if (!nargs)
3802             {
3803                 // https://issues.dlang.org/show_bug.cgi?id=20422
3804                 // Without this check the compiler would give a misleading error
3805                 exp.error("missing length argument for array");
3806                 return setError();
3807             }
3808 
3809             Type tn = tb.nextOf().baseElemOf();
3810             Dsymbol s = tn.toDsymbol(sc);
3811             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3812             if (ad && ad.noDefaultCtor)
3813             {
3814                 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3815                 return setError();
3816             }
3817             for (size_t i = 0; i < nargs; i++)
3818             {
3819                 if (tb.ty != Tarray)
3820                 {
3821                     exp.error("too many arguments for array");
3822                     return setError();
3823                 }
3824 
3825                 Expression arg = (*exp.arguments)[i];
3826                 arg = resolveProperties(sc, arg);
3827                 arg = arg.implicitCastTo(sc, Type.tsize_t);
3828                 if (arg.op == EXP.error)
3829                     return setError();
3830                 arg = arg.optimize(WANTvalue);
3831                 if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
3832                 {
3833                     exp.error("negative array index `%s`", arg.toChars());
3834                     return setError();
3835                 }
3836                 (*exp.arguments)[i] = arg;
3837                 tb = tb.isTypeDArray().next.toBasetype();
3838             }
3839         }
3840         else if (tb.isscalar())
3841         {
3842             if (!nargs)
3843             {
3844             }
3845             else if (nargs == 1)
3846             {
3847                 Expression e = (*exp.arguments)[0];
3848                 e = e.implicitCastTo(sc, tb);
3849                 (*exp.arguments)[0] = e;
3850             }
3851             else
3852             {
3853                 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3854                 return setError();
3855             }
3856 
3857             exp.type = exp.type.pointerTo();
3858         }
3859         else
3860         {
3861             exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3862             return setError();
3863         }
3864 
3865         //printf("NewExp: '%s'\n", toChars());
3866         //printf("NewExp:type '%s'\n", type.toChars());
3867         semanticTypeInfo(sc, exp.type);
3868 
3869         if (newprefix)
3870         {
3871             result = Expression.combine(newprefix, exp);
3872             return;
3873         }
3874         result = exp;
3875     }
3876 
visit(NewAnonClassExp e)3877     override void visit(NewAnonClassExp e)
3878     {
3879         static if (LOGSEMANTIC)
3880         {
3881             printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3882             //printf("thisexp = %p\n", thisexp);
3883             //printf("type: %s\n", type.toChars());
3884         }
3885 
3886         Expression d = new DeclarationExp(e.loc, e.cd);
3887         sc = sc.push(); // just create new scope
3888         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3889         d = d.expressionSemantic(sc);
3890         sc = sc.pop();
3891 
3892         if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3893         {
3894             ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3895             if (!sds.members)
3896                 sds.members = new Dsymbols();
3897             sds.members.push(e.cd);
3898         }
3899 
3900         Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
3901 
3902         Expression c = new CommaExp(e.loc, d, n);
3903         result = c.expressionSemantic(sc);
3904     }
3905 
visit(SymOffExp e)3906     override void visit(SymOffExp e)
3907     {
3908         static if (LOGSEMANTIC)
3909         {
3910             printf("SymOffExp::semantic('%s')\n", e.toChars());
3911         }
3912         //var.dsymbolSemantic(sc);
3913         if (!e.type)
3914             e.type = e.var.type.pointerTo();
3915 
3916         if (auto v = e.var.isVarDeclaration())
3917         {
3918             if (v.checkNestedReference(sc, e.loc))
3919                 return setError();
3920         }
3921         else if (auto f = e.var.isFuncDeclaration())
3922         {
3923             if (f.checkNestedReference(sc, e.loc))
3924                 return setError();
3925         }
3926 
3927         result = e;
3928     }
3929 
visit(VarExp e)3930     override void visit(VarExp e)
3931     {
3932         static if (LOGSEMANTIC)
3933         {
3934             printf("VarExp::semantic(%s)\n", e.toChars());
3935         }
3936 
3937         auto vd = e.var.isVarDeclaration();
3938         auto fd = e.var.isFuncDeclaration();
3939 
3940         if (fd)
3941         {
3942             //printf("L%d fd = %s\n", __LINE__, f.toChars());
3943             if (!fd.functionSemantic())
3944                 return setError();
3945         }
3946 
3947         if (!e.type)
3948             e.type = e.var.type;
3949         if (e.type && !e.type.deco)
3950         {
3951             auto decl = e.var.isDeclaration();
3952             if (decl)
3953                 decl.inuse++;
3954             e.type = e.type.typeSemantic(e.loc, sc);
3955             if (decl)
3956                 decl.inuse--;
3957         }
3958 
3959         /* Fix for 1161 doesn't work because it causes visibility
3960          * problems when instantiating imported templates passing private
3961          * variables as alias template parameters.
3962          */
3963         //checkAccess(loc, sc, NULL, var);
3964 
3965         if (vd)
3966         {
3967             if (vd.checkNestedReference(sc, e.loc))
3968                 return setError();
3969 
3970             // https://issues.dlang.org/show_bug.cgi?id=12025
3971             // If the variable is not actually used in runtime code,
3972             // the purity violation error is redundant.
3973             //checkPurity(sc, vd);
3974         }
3975         else if (fd)
3976         {
3977             // TODO: If fd isn't yet resolved its overload, the checkNestedReference
3978             // call would cause incorrect validation.
3979             // Maybe here should be moved in CallExp, or AddrExp for functions.
3980             if (fd.checkNestedReference(sc, e.loc))
3981                 return setError();
3982         }
3983         else if (auto od = e.var.isOverDeclaration())
3984         {
3985             e.type = Type.tvoid; // ambiguous type?
3986         }
3987 
3988         result = e;
3989     }
3990 
visit(FuncExp exp)3991     override void visit(FuncExp exp)
3992     {
3993         static if (LOGSEMANTIC)
3994         {
3995             printf("FuncExp::semantic(%s)\n", exp.toChars());
3996             if (exp.fd.treq)
3997                 printf("  treq = %s\n", exp.fd.treq.toChars());
3998         }
3999 
4000         if (exp.type)
4001         {
4002             result = exp;
4003             return;
4004         }
4005 
4006         Expression e = exp;
4007         uint olderrors;
4008 
4009         sc = sc.push(); // just create new scope
4010         sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4011         sc.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4012 
4013         /* fd.treq might be incomplete type,
4014             * so should not semantic it.
4015             * void foo(T)(T delegate(int) dg){}
4016             * foo(a=>a); // in IFTI, treq == T delegate(int)
4017             */
4018         //if (fd.treq)
4019         //    fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4020 
4021         exp.genIdent(sc);
4022 
4023         // Set target of return type inference
4024         if (exp.fd.treq && !exp.fd.type.nextOf())
4025         {
4026             TypeFunction tfv = null;
4027             if (exp.fd.treq.ty == Tdelegate || exp.fd.treq.isPtrToFunction())
4028                 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4029             if (tfv)
4030             {
4031                 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4032                 tfl.next = tfv.nextOf();
4033             }
4034         }
4035 
4036         //printf("td = %p, treq = %p\n", td, fd.treq);
4037         if (exp.td)
4038         {
4039             assert(exp.td.parameters && exp.td.parameters.dim);
4040             exp.td.dsymbolSemantic(sc);
4041             exp.type = Type.tvoid; // temporary type
4042 
4043             if (exp.fd.treq) // defer type determination
4044             {
4045                 FuncExp fe;
4046                 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4047                     e = fe;
4048                 else
4049                     e = ErrorExp.get();
4050             }
4051             goto Ldone;
4052         }
4053 
4054         olderrors = global.errors;
4055         exp.fd.dsymbolSemantic(sc);
4056         if (olderrors == global.errors)
4057         {
4058             exp.fd.semantic2(sc);
4059             if (olderrors == global.errors)
4060                 exp.fd.semantic3(sc);
4061         }
4062         if (olderrors != global.errors)
4063         {
4064             if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4065                 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4066             e = ErrorExp.get();
4067             goto Ldone;
4068         }
4069 
4070         // Type is a "delegate to" or "pointer to" the function literal
4071         if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4072         {
4073             // https://issues.dlang.org/show_bug.cgi?id=22686
4074             // if the delegate return type is an error
4075             // abort semantic of the FuncExp and propagate
4076             // the error
4077             if (exp.fd.type.isTypeError())
4078             {
4079                 e = ErrorExp.get();
4080                 goto Ldone;
4081             }
4082             exp.type = new TypeDelegate(exp.fd.type.isTypeFunction());
4083             exp.type = exp.type.typeSemantic(exp.loc, sc);
4084 
4085             exp.fd.tok = TOK.delegate_;
4086         }
4087         else
4088         {
4089             exp.type = new TypePointer(exp.fd.type);
4090             exp.type = exp.type.typeSemantic(exp.loc, sc);
4091             //type = fd.type.pointerTo();
4092 
4093             /* A lambda expression deduced to function pointer might become
4094                 * to a delegate literal implicitly.
4095                 *
4096                 *   auto foo(void function() fp) { return 1; }
4097                 *   assert(foo({}) == 1);
4098                 *
4099                 * So, should keep fd.tok == TOK.reserve if fd.treq == NULL.
4100                 */
4101             if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4102             {
4103                 // change to non-nested
4104                 exp.fd.tok = TOK.function_;
4105                 exp.fd.vthis = null;
4106             }
4107         }
4108         exp.fd.tookAddressOf++;
4109 
4110     Ldone:
4111         sc = sc.pop();
4112         result = e;
4113     }
4114 
4115     /**
4116      * Perform semantic analysis on function literals
4117      *
4118      * Test the following construct:
4119      * ---
4120      * (x, y, z) { return x + y + z; }(42, 84, 1992);
4121      * ---
4122      */
callExpSemantic(FuncExp exp,Scope * sc,Expressions * arguments)4123     Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4124     {
4125         if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
4126         {
4127             for (size_t k = 0; k < arguments.dim; k++)
4128             {
4129                 Expression checkarg = (*arguments)[k];
4130                 if (checkarg.op == EXP.error)
4131                     return checkarg;
4132             }
4133 
4134             exp.genIdent(sc);
4135 
4136             assert(exp.td.parameters && exp.td.parameters.dim);
4137             exp.td.dsymbolSemantic(sc);
4138 
4139             TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4140             size_t dim = tfl.parameterList.length;
4141             if (arguments.dim < dim)
4142             {
4143                 // Default arguments are always typed, so they don't need inference.
4144                 Parameter p = tfl.parameterList[arguments.dim];
4145                 if (p.defaultArg)
4146                     dim = arguments.dim;
4147             }
4148 
4149             if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
4150                 arguments.dim < dim)
4151             {
4152                 OutBuffer buf;
4153                 foreach (idx, ref arg; *arguments)
4154                     buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4155                 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4156                           exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4157                           buf.peekChars());
4158                 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
4159                                       arguments.dim < dim ? "few".ptr : "many".ptr,
4160                                       cast(int)dim, cast(int)arguments.dim);
4161                 return ErrorExp.get();
4162             }
4163 
4164             auto tiargs = new Objects();
4165             tiargs.reserve(exp.td.parameters.dim);
4166 
4167             for (size_t i = 0; i < exp.td.parameters.dim; i++)
4168             {
4169                 TemplateParameter tp = (*exp.td.parameters)[i];
4170                 assert(dim <= tfl.parameterList.length);
4171                 foreach (u, p; tfl.parameterList)
4172                 {
4173                     if (u == dim)
4174                         break;
4175 
4176                     if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4177                     {
4178                         Expression e = (*arguments)[u];
4179                         tiargs.push(e.type);
4180                         break;
4181                     }
4182                 }
4183             }
4184 
4185             auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4186             return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4187         }
4188         return exp.expressionSemantic(sc);
4189     }
4190 
visit(CallExp exp)4191     override void visit(CallExp exp)
4192     {
4193         static if (LOGSEMANTIC)
4194         {
4195             printf("CallExp::semantic() %s\n", exp.toChars());
4196         }
4197         if (exp.type)
4198         {
4199             result = exp;
4200             return; // semantic() already run
4201         }
4202 
4203         Objects* tiargs = null; // initial list of template arguments
4204         Expression ethis = null;
4205         Type tthis = null;
4206         Expression e1org = exp.e1;
4207 
4208         if (auto ce = exp.e1.isCommaExp())
4209         {
4210             /* Rewrite (a,b)(args) as (a,(b(args)))
4211              */
4212             exp.e1 = ce.e2;
4213             ce.e2 = exp;
4214             result = ce.expressionSemantic(sc);
4215             return;
4216         }
4217         if (DelegateExp de = exp.e1.isDelegateExp())
4218         {
4219             exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4220             visit(exp);
4221             return;
4222         }
4223         if (FuncExp fe = exp.e1.isFuncExp())
4224         {
4225             if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4226                 return setError();
4227 
4228             // Run e1 semantic even if arguments have any errors
4229             exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4230             if (exp.e1.op == EXP.error)
4231             {
4232                 result = exp.e1;
4233                 return;
4234             }
4235         }
4236         if (sc.flags & SCOPE.Cfile)
4237         {
4238             /* See if need to rewrite the AST because of cast/call ambiguity
4239              */
4240             if (auto e = castCallAmbiguity(exp, sc))
4241             {
4242                 result = expressionSemantic(e, sc);
4243                 return;
4244             }
4245         }
4246 
4247         if (Expression ex = resolveUFCS(sc, exp))
4248         {
4249             result = ex;
4250             return;
4251         }
4252 
4253         /* This recognizes:
4254          *  foo!(tiargs)(funcargs)
4255          */
4256         if (ScopeExp se = exp.e1.isScopeExp())
4257         {
4258             TemplateInstance ti = se.sds.isTemplateInstance();
4259             if (ti)
4260             {
4261                 /* Attempt to instantiate ti. If that works, go with it.
4262                  * If not, go with partial explicit specialization.
4263                  */
4264                 WithScopeSymbol withsym;
4265                 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4266                     return setError();
4267                 if (withsym && withsym.withstate.wthis)
4268                 {
4269                     exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4270                     exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4271                     goto Ldotti;
4272                 }
4273                 if (ti.needsTypeInference(sc, 1))
4274                 {
4275                     /* Go with partial explicit specialization
4276                      */
4277                     tiargs = ti.tiargs;
4278                     assert(ti.tempdecl);
4279                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4280                         exp.e1 = new TemplateExp(exp.loc, td);
4281                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4282                         exp.e1 = new VarExp(exp.loc, od);
4283                     else
4284                         exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4285                 }
4286                 else
4287                 {
4288                     Expression e1x = exp.e1.expressionSemantic(sc);
4289                     if (e1x.op == EXP.error)
4290                     {
4291                         result = e1x;
4292                         return;
4293                     }
4294                     exp.e1 = e1x;
4295                 }
4296             }
4297         }
4298 
4299         /* This recognizes:
4300          *  expr.foo!(tiargs)(funcargs)
4301          */
4302     Ldotti:
4303         if (DotTemplateInstanceExp se = exp.e1.isDotTemplateInstanceExp())
4304         {
4305             TemplateInstance ti = se.ti;
4306             {
4307                 /* Attempt to instantiate ti. If that works, go with it.
4308                  * If not, go with partial explicit specialization.
4309                  */
4310                 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4311                     return setError();
4312                 if (ti.needsTypeInference(sc, 1))
4313                 {
4314                     /* Go with partial explicit specialization
4315                      */
4316                     tiargs = ti.tiargs;
4317                     assert(ti.tempdecl);
4318                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4319                         exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4320                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4321                     {
4322                         exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4323                     }
4324                     else
4325                         exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4326                 }
4327                 else
4328                 {
4329                     Expression e1x = exp.e1.expressionSemantic(sc);
4330                     if (e1x.op == EXP.error)
4331                     {
4332                         result = e1x;
4333                         return;
4334                     }
4335                     exp.e1 = e1x;
4336                 }
4337             }
4338         }
4339 
4340     Lagain:
4341         //printf("Lagain: %s\n", toChars());
4342         exp.f = null;
4343         if (exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_)
4344         {
4345             // semantic() run later for these
4346         }
4347         else
4348         {
4349             if (DotIdExp die = exp.e1.isDotIdExp())
4350             {
4351                 exp.e1 = die.expressionSemantic(sc);
4352                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4353                  * We handle such earlier, so go back.
4354                  * Note that in the rewrite, we carefully did not run semantic() on e1
4355                  */
4356                 if (exp.e1.op == EXP.dotTemplateInstance)
4357                 {
4358                     goto Ldotti;
4359                 }
4360             }
4361             else
4362             {
4363                 __gshared int nest;
4364                 if (++nest > global.recursionLimit)
4365                 {
4366                     exp.error("recursive evaluation of `%s`", exp.toChars());
4367                     --nest;
4368                     return setError();
4369                 }
4370                 Expression ex = unaSemantic(exp, sc);
4371                 --nest;
4372                 if (ex)
4373                 {
4374                     result = ex;
4375                     return;
4376                 }
4377             }
4378 
4379             /* Look for e1 being a lazy parameter
4380              */
4381             if (VarExp ve = exp.e1.isVarExp())
4382             {
4383                 if (ve.var.storage_class & STC.lazy_)
4384                 {
4385                     // lazy parameters can be called without violating purity and safety
4386                     Type tw = ve.var.type;
4387                     Type tc = ve.var.type.substWildTo(MODFlags.const_);
4388                     auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4389                     (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4390                     auto t = new TypeDelegate(tf);
4391                     ve.type = t.typeSemantic(exp.loc, sc);
4392                 }
4393                 VarDeclaration v = ve.var.isVarDeclaration();
4394                 if (v && ve.checkPurity(sc, v))
4395                     return setError();
4396             }
4397 
4398             if (exp.e1.op == EXP.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4399             {
4400                 SymOffExp se = cast(SymOffExp)exp.e1;
4401                 exp.e1 = new VarExp(se.loc, se.var, true);
4402                 exp.e1 = exp.e1.expressionSemantic(sc);
4403             }
4404             else if (DotExp de = exp.e1.isDotExp())
4405             {
4406                 if (de.e2.op == EXP.overloadSet)
4407                 {
4408                     ethis = de.e1;
4409                     tthis = de.e1.type;
4410                     exp.e1 = de.e2;
4411                 }
4412             }
4413             else if (exp.e1.op == EXP.star && exp.e1.type.ty == Tfunction)
4414             {
4415                 // Rewrite (*fp)(arguments) to fp(arguments)
4416                 exp.e1 = (cast(PtrExp)exp.e1).e1;
4417             }
4418             else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
4419             {
4420                 const numArgs = exp.arguments ? exp.arguments.length : 0;
4421 
4422                 /* Ambiguous cases arise from CParser where there is not enough
4423                  * information to determine if we have a function call or declaration.
4424                  *   type-name ( identifier ) ;
4425                  *   identifier ( identifier ) ;
4426                  * If exp.e1 is a type-name, then this is a declaration. C11 does not
4427                  * have type construction syntax, so don't convert this to a cast().
4428                  */
4429                 if (numArgs == 1)
4430                 {
4431                     Expression arg = (*exp.arguments)[0];
4432                     if (auto ie = (*exp.arguments)[0].isIdentifierExp())
4433                     {
4434                         TypeExp te = cast(TypeExp)exp.e1;
4435                         auto initializer = new VoidInitializer(ie.loc);
4436                         Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
4437                         auto decls = new Dsymbols(1);
4438                         (*decls)[0] = s;
4439                         s = new LinkDeclaration(s.loc, LINK.c, decls);
4440                         result = new DeclarationExp(exp.loc, s);
4441                         result = result.expressionSemantic(sc);
4442                     }
4443                     else
4444                     {
4445                         arg.error("identifier or `(` expected");
4446                         result = ErrorExp.get();
4447                     }
4448                     return;
4449                 }
4450                 exp.error("identifier or `(` expected before `)`");
4451                 result = ErrorExp.get();
4452                 return;
4453             }
4454         }
4455 
4456         Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4457 
4458         if (exp.e1.op == EXP.error)
4459         {
4460             result = exp.e1;
4461             return;
4462         }
4463         if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4464             return setError();
4465 
4466         // Check for call operator overload
4467         if (t1)
4468         {
4469             if (t1.ty == Tstruct)
4470             {
4471                 auto sd = (cast(TypeStruct)t1).sym;
4472                 sd.size(exp.loc); // Resolve forward references to construct object
4473                 if (sd.sizeok != Sizeok.done)
4474                     return setError();
4475                 if (!sd.ctor)
4476                     sd.ctor = sd.searchCtor();
4477                 /* If `sd.ctor` is a generated copy constructor, this means that it
4478                    is the single constructor that this struct has. In order to not
4479                    disable default construction, the ctor is nullified. The side effect
4480                    of this is that the generated copy constructor cannot be called
4481                    explicitly, but that is ok, because when calling a constructor the
4482                    default constructor should have priority over the generated copy
4483                    constructor.
4484                 */
4485                 if (sd.ctor)
4486                 {
4487                     auto ctor = sd.ctor.isCtorDeclaration();
4488                     if (ctor && ctor.isCpCtor && ctor.isGenerated())
4489                         sd.ctor = null;
4490                 }
4491 
4492                 // First look for constructor
4493                 if (exp.e1.op == EXP.type && sd.ctor)
4494                 {
4495                     if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
4496                         goto Lx;
4497 
4498                     /* https://issues.dlang.org/show_bug.cgi?id=20695
4499                        If all constructors are copy constructors, then
4500                        try default construction.
4501                      */
4502                     if (!sd.hasRegularCtor &&
4503                         // https://issues.dlang.org/show_bug.cgi?id=22639
4504                         // we might still have a copy constructor that could be called
4505                         (*exp.arguments)[0].type.mutableOf != sd.type.mutableOf())
4506                         goto Lx;
4507 
4508                     auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4509                     if (!sd.fill(exp.loc, sle.elements, true))
4510                         return setError();
4511                     if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
4512                         return setError();
4513 
4514                     // https://issues.dlang.org/show_bug.cgi?id=14556
4515                     // Set concrete type to avoid further redundant semantic().
4516                     sle.type = exp.e1.type;
4517 
4518                     /* Constructor takes a mutable object, so don't use
4519                      * the immutable initializer symbol.
4520                      */
4521                     sle.useStaticInit = false;
4522 
4523                     Expression e = sle;
4524                     if (auto cf = sd.ctor.isCtorDeclaration())
4525                     {
4526                         e = new DotVarExp(exp.loc, e, cf, true);
4527                     }
4528                     else if (auto td = sd.ctor.isTemplateDeclaration())
4529                     {
4530                         e = new DotIdExp(exp.loc, e, td.ident);
4531                     }
4532                     else if (auto os = sd.ctor.isOverloadSet())
4533                     {
4534                         e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4535                     }
4536                     else
4537                         assert(0);
4538                     e = new CallExp(exp.loc, e, exp.arguments);
4539                     e = e.expressionSemantic(sc);
4540                     result = e;
4541                     return;
4542                 }
4543                 // No constructor, look for overload of opCall
4544                 if (search_function(sd, Id.call))
4545                     goto L1;
4546                 // overload of opCall, therefore it's a call
4547                 if (exp.e1.op != EXP.type)
4548                 {
4549                     if (sd.aliasthis && !isRecursiveAliasThis(exp.att1, exp.e1.type))
4550                     {
4551                         exp.e1 = resolveAliasThis(sc, exp.e1);
4552                         goto Lagain;
4553                     }
4554                     exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4555                     return setError();
4556                 }
4557 
4558                 /* It's a struct literal
4559                  */
4560             Lx:
4561                 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4562                 e = e.expressionSemantic(sc);
4563                 result = e;
4564                 return;
4565             }
4566             else if (t1.ty == Tclass)
4567             {
4568             L1:
4569                 // Rewrite as e1.call(arguments)
4570                 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4571                 e = new CallExp(exp.loc, e, exp.arguments);
4572                 e = e.expressionSemantic(sc);
4573                 result = e;
4574                 return;
4575             }
4576             else if (exp.e1.op == EXP.type && t1.isscalar())
4577             {
4578                 Expression e;
4579 
4580                 // Make sure to use the the enum type itself rather than its
4581                 // base type
4582                 // https://issues.dlang.org/show_bug.cgi?id=16346
4583                 if (exp.e1.type.ty == Tenum)
4584                 {
4585                     t1 = exp.e1.type;
4586                 }
4587 
4588                 if (!exp.arguments || exp.arguments.dim == 0)
4589                 {
4590                     e = t1.defaultInitLiteral(exp.loc);
4591                 }
4592                 else if (exp.arguments.dim == 1)
4593                 {
4594                     e = (*exp.arguments)[0];
4595                     e = e.implicitCastTo(sc, t1);
4596                     e = new CastExp(exp.loc, e, t1);
4597                 }
4598                 else
4599                 {
4600                     exp.error("more than one argument for construction of `%s`", t1.toChars());
4601                     return setError();
4602                 }
4603                 e = e.expressionSemantic(sc);
4604                 result = e;
4605                 return;
4606             }
4607         }
4608 
4609         static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4610             OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4611         {
4612             FuncDeclaration f = null;
4613             foreach (s; os.a)
4614             {
4615                 if (tiargs && s.isFuncDeclaration())
4616                     continue;
4617                 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4618                 {
4619                     if (f2.errors)
4620                         return null;
4621                     if (f)
4622                     {
4623                         /* Error if match in more than one overload set,
4624                          * even if one is a 'better' match than the other.
4625                          */
4626                         ScopeDsymbol.multiplyDefined(loc, f, f2);
4627                     }
4628                     else
4629                         f = f2;
4630                 }
4631             }
4632             if (!f)
4633                 .error(loc, "no overload matches for `%s`", os.toChars());
4634             else if (f.errors)
4635                 f = null;
4636             return f;
4637         }
4638 
4639         bool isSuper = false;
4640         if (exp.e1.op == EXP.dotVariable && t1.ty == Tfunction || exp.e1.op == EXP.dotTemplateDeclaration)
4641         {
4642             UnaExp ue = cast(UnaExp)exp.e1;
4643 
4644             Expression ue1old = ue.e1; // need for 'right this' check
4645             DotVarExp dve;
4646             DotTemplateExp dte;
4647             Dsymbol s;
4648             if (exp.e1.op == EXP.dotVariable)
4649             {
4650                 dve = cast(DotVarExp)exp.e1;
4651                 dte = null;
4652                 s = dve.var;
4653                 tiargs = null;
4654             }
4655             else
4656             {
4657                 dve = null;
4658                 dte = cast(DotTemplateExp)exp.e1;
4659                 s = dte.td;
4660             }
4661 
4662             // Do overload resolution
4663             exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
4664             if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4665                 return setError();
4666 
4667             if (exp.f.interfaceVirtual)
4668             {
4669                 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4670                  */
4671                 auto b = exp.f.interfaceVirtual;
4672                 auto ad2 = b.sym;
4673                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4674                 ue.e1 = ue.e1.expressionSemantic(sc);
4675                 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
4676                 assert(vi >= 0);
4677                 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4678                 assert(exp.f);
4679             }
4680             if (exp.f.needThis())
4681             {
4682                 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
4683                 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4684                 if (ue.e1.op == EXP.error)
4685                 {
4686                     result = ue.e1;
4687                     return;
4688                 }
4689                 ethis = ue.e1;
4690                 tthis = ue.e1.type;
4691                 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4692                 {
4693                     if (global.params.useDIP1000 == FeatureState.enabled && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
4694                         return setError();
4695                 }
4696             }
4697 
4698             /* Cannot call public functions from inside invariant
4699              * (because then the invariant would have infinite recursion)
4700              */
4701             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
4702             {
4703                 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4704                 return setError();
4705             }
4706 
4707             if (!exp.ignoreAttributes)
4708                 checkFunctionAttributes(exp, sc, exp.f);
4709             checkAccess(exp.loc, sc, ue.e1, exp.f);
4710             if (!exp.f.needThis())
4711             {
4712                 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4713             }
4714             else
4715             {
4716                 if (ue1old.checkRightThis(sc))
4717                     return setError();
4718                 if (exp.e1.op == EXP.dotVariable)
4719                 {
4720                     dve.var = exp.f;
4721                     exp.e1.type = exp.f.type;
4722                 }
4723                 else
4724                 {
4725                     exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4726                     exp.e1 = exp.e1.expressionSemantic(sc);
4727                     if (exp.e1.op == EXP.error)
4728                         return setError();
4729                     ue = cast(UnaExp)exp.e1;
4730                 }
4731                 version (none)
4732                 {
4733                     printf("ue.e1 = %s\n", ue.e1.toChars());
4734                     printf("f = %s\n", exp.f.toChars());
4735                     printf("t1 = %s\n", t1.toChars());
4736                     printf("e1 = %s\n", exp.e1.toChars());
4737                     printf("e1.type = %s\n", exp.e1.type.toChars());
4738                 }
4739 
4740                 // See if we need to adjust the 'this' pointer
4741                 AggregateDeclaration ad = exp.f.isThis();
4742                 ClassDeclaration cd = ue.e1.type.isClassHandle();
4743                 if (ad && cd && ad.isClassDeclaration())
4744                 {
4745                     if (ue.e1.op == EXP.dotType)
4746                     {
4747                         ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4748                         exp.directcall = true;
4749                     }
4750                     else if (ue.e1.op == EXP.super_)
4751                         exp.directcall = true;
4752                     else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4753                         exp.directcall = true;
4754 
4755                     if (ad != cd)
4756                     {
4757                         ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4758                         ue.e1 = ue.e1.expressionSemantic(sc);
4759                     }
4760                 }
4761             }
4762             // If we've got a pointer to a function then deference it
4763             // https://issues.dlang.org/show_bug.cgi?id=16483
4764             if (exp.e1.type.isPtrToFunction())
4765             {
4766                 Expression e = new PtrExp(exp.loc, exp.e1);
4767                 e.type = exp.e1.type.nextOf();
4768                 exp.e1 = e;
4769             }
4770             t1 = exp.e1.type;
4771         }
4772         else if (exp.e1.op == EXP.super_ || exp.e1.op == EXP.this_)
4773         {
4774             auto ad = sc.func ? sc.func.isThis() : null;
4775             auto cd = ad ? ad.isClassDeclaration() : null;
4776 
4777             isSuper = exp.e1.op == EXP.super_;
4778             if (isSuper)
4779             {
4780                 // Base class constructor call
4781                 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4782                 {
4783                     exp.error("super class constructor call must be in a constructor");
4784                     return setError();
4785                 }
4786                 if (!cd.baseClass.ctor)
4787                 {
4788                     exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4789                     return setError();
4790                 }
4791             }
4792             else
4793             {
4794                 // `this` call expression must be inside a
4795                 // constructor
4796                 if (!ad || !sc.func.isCtorDeclaration())
4797                 {
4798                     exp.error("constructor call must be in a constructor");
4799                     return setError();
4800                 }
4801 
4802                 // https://issues.dlang.org/show_bug.cgi?id=18719
4803                 // If `exp` is a call expression to another constructor
4804                 // then it means that all struct/class fields will be
4805                 // initialized after this call.
4806                 foreach (ref field; sc.ctorflow.fieldinit)
4807                 {
4808                     field.csx |= CSX.this_ctor;
4809                 }
4810             }
4811 
4812             if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4813             {
4814                 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4815                     exp.error("constructor calls not allowed in loops or after labels");
4816                 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4817                     exp.error("multiple constructor calls");
4818                 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4819                     exp.error("an earlier `return` statement skips constructor");
4820                 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4821             }
4822 
4823             tthis = ad.type.addMod(sc.func.type.mod);
4824             auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4825             if (auto os = ctor.isOverloadSet())
4826                 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4827             else
4828                 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4829 
4830             if (!exp.f || exp.f.errors)
4831                 return setError();
4832 
4833             checkFunctionAttributes(exp, sc, exp.f);
4834             checkAccess(exp.loc, sc, null, exp.f);
4835 
4836             exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4837             exp.e1 = exp.e1.expressionSemantic(sc);
4838             // https://issues.dlang.org/show_bug.cgi?id=21095
4839             if (exp.e1.op == EXP.error)
4840                 return setError();
4841             t1 = exp.e1.type;
4842 
4843             // BUG: this should really be done by checking the static
4844             // call graph
4845             if (exp.f == sc.func)
4846             {
4847                 exp.error("cyclic constructor call");
4848                 return setError();
4849             }
4850         }
4851         else if (auto oe = exp.e1.isOverExp())
4852         {
4853             exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments);
4854             if (!exp.f)
4855                 return setError();
4856             if (ethis)
4857                 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4858             else
4859                 exp.e1 = new VarExp(exp.loc, exp.f, false);
4860             goto Lagain;
4861         }
4862         else if (!t1)
4863         {
4864             exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4865             return setError();
4866         }
4867         else if (t1.ty == Terror)
4868         {
4869             return setError();
4870         }
4871         else if (t1.ty != Tfunction)
4872         {
4873             TypeFunction tf;
4874             const(char)* p;
4875             Dsymbol s;
4876             exp.f = null;
4877             if (auto fe = exp.e1.isFuncExp())
4878             {
4879                 // function literal that direct called is always inferred.
4880                 assert(fe.fd);
4881                 exp.f = fe.fd;
4882                 tf = cast(TypeFunction)exp.f.type;
4883                 p = "function literal";
4884             }
4885             else if (t1.ty == Tdelegate)
4886             {
4887                 TypeDelegate td = cast(TypeDelegate)t1;
4888                 assert(td.next.ty == Tfunction);
4889                 tf = cast(TypeFunction)td.next;
4890                 p = "delegate";
4891             }
4892             else if (auto tfx = t1.isPtrToFunction())
4893             {
4894                 tf = tfx;
4895                 p = "function pointer";
4896             }
4897             else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4898             {
4899                 DotVarExp dve = cast(DotVarExp)exp.e1;
4900                 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4901                 if (!exp.f)
4902                     return setError();
4903                 if (exp.f.needThis())
4904                 {
4905                     dve.var = exp.f;
4906                     dve.type = exp.f.type;
4907                     dve.hasOverloads = false;
4908                     goto Lagain;
4909                 }
4910                 exp.e1 = new VarExp(dve.loc, exp.f, false);
4911                 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4912                 result = e.expressionSemantic(sc);
4913                 return;
4914             }
4915             else if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4916             {
4917                 s = (cast(VarExp)exp.e1).var;
4918                 goto L2;
4919             }
4920             else if (exp.e1.op == EXP.template_)
4921             {
4922                 s = (cast(TemplateExp)exp.e1).td;
4923             L2:
4924                 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
4925                 if (!exp.f || exp.f.errors)
4926                     return setError();
4927                 if (exp.f.needThis())
4928                 {
4929                     if (hasThis(sc))
4930                     {
4931                         // Supply an implicit 'this', as in
4932                         //    this.ident
4933                         exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
4934                         goto Lagain;
4935                     }
4936                     else if (isNeedThisScope(sc, exp.f))
4937                     {
4938                         exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4939                         return setError();
4940                     }
4941                 }
4942                 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
4943                 goto Lagain;
4944             }
4945             else
4946             {
4947                 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
4948                 return setError();
4949             }
4950 
4951             const(char)* failMessage;
4952             Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4953             if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4954             {
4955                 OutBuffer buf;
4956                 buf.writeByte('(');
4957                 argExpTypesToCBuffer(&buf, exp.arguments);
4958                 buf.writeByte(')');
4959                 if (tthis)
4960                     tthis.modToBuffer(&buf);
4961 
4962                 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4963                 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4964                     p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4965                 if (failMessage)
4966                     errorSupplemental(exp.loc, "%s", failMessage);
4967                 return setError();
4968             }
4969             // Purity and safety check should run after testing arguments matching
4970             if (exp.f)
4971             {
4972                 exp.checkPurity(sc, exp.f);
4973                 exp.checkSafety(sc, exp.f);
4974                 exp.checkNogc(sc, exp.f);
4975                 if (exp.f.checkNestedReference(sc, exp.loc))
4976                     return setError();
4977             }
4978             else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
4979             {
4980                 bool err = false;
4981                 if (!tf.purity && sc.func.setImpure())
4982                 {
4983                     exp.error("`pure` %s `%s` cannot call impure %s `%s`",
4984                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4985                     err = true;
4986                 }
4987                 if (!tf.isnogc && sc.func.setGC())
4988                 {
4989                     exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
4990                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4991                     err = true;
4992                 }
4993                 if (tf.trust <= TRUST.system && sc.func.setUnsafe())
4994                 {
4995                     exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
4996                         sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
4997                     err = true;
4998                 }
4999                 if (err)
5000                     return setError();
5001             }
5002 
5003             if (t1.ty == Tpointer)
5004             {
5005                 Expression e = new PtrExp(exp.loc, exp.e1);
5006                 e.type = tf;
5007                 exp.e1 = e;
5008             }
5009             t1 = tf;
5010         }
5011         else if (VarExp ve = exp.e1.isVarExp())
5012         {
5013             // Do overload resolution
5014             exp.f = ve.var.isFuncDeclaration();
5015             assert(exp.f);
5016             tiargs = null;
5017 
5018             if (exp.f.overnext)
5019                 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
5020             else
5021             {
5022                 exp.f = exp.f.toAliasFunc();
5023                 TypeFunction tf = cast(TypeFunction)exp.f.type;
5024                 const(char)* failMessage;
5025                 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5026                 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5027                 {
5028                     OutBuffer buf;
5029                     buf.writeByte('(');
5030                     argExpTypesToCBuffer(&buf, exp.arguments);
5031                     buf.writeByte(')');
5032 
5033                     //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5034                     .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5035                         exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5036                     if (failMessage)
5037                         errorSupplemental(exp.loc, "%s", failMessage);
5038                     exp.f = null;
5039                 }
5040             }
5041             if (!exp.f || exp.f.errors)
5042                 return setError();
5043 
5044             if (exp.f.needThis())
5045             {
5046                 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5047                 if (exp.f.checkNestedReference(sc, exp.loc))
5048                     return setError();
5049 
5050                 if (hasThis(sc))
5051                 {
5052                     // Supply an implicit 'this', as in
5053                     //    this.ident
5054                     exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5055                     // Note: we cannot use f directly, because further overload resolution
5056                     // through the supplied 'this' may cause different result.
5057                     goto Lagain;
5058                 }
5059                 else if (isNeedThisScope(sc, exp.f))
5060                 {
5061                     // At this point it is possible that `exp.f` had an ambiguity error that was
5062                     // silenced because the previous call to `resolveFuncCall` was done using
5063                     // `FuncResolveFlag.overloadOnly`. To make sure that a proper error message
5064                     // is printed, redo the call with `FuncResolveFlag.standard`.
5065                     //
5066                     // https://issues.dlang.org/show_bug.cgi?id=22157
5067                     if (exp.f.overnext)
5068                         exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5069 
5070                     if (!exp.f || exp.f.errors)
5071                         return setError();
5072 
5073                     // If no error is printed, it means that `f` is the single matching overload
5074                     // and it needs `this`.
5075                     exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5076                     return setError();
5077                 }
5078             }
5079 
5080             checkFunctionAttributes(exp, sc, exp.f);
5081             checkAccess(exp.loc, sc, null, exp.f);
5082             if (exp.f.checkNestedReference(sc, exp.loc))
5083                 return setError();
5084 
5085             ethis = null;
5086             tthis = null;
5087 
5088             if (ve.hasOverloads)
5089             {
5090                 exp.e1 = new VarExp(ve.loc, exp.f, false);
5091                 exp.e1.type = exp.f.type;
5092             }
5093             t1 = exp.f.type;
5094         }
5095         assert(t1.ty == Tfunction);
5096 
5097         Expression argprefix;
5098         if (!exp.arguments)
5099             exp.arguments = new Expressions();
5100         if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5101             return setError();
5102 
5103         if (!exp.type)
5104         {
5105             exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5106                         // avoid recursive expression printing
5107             exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5108             return setError();
5109         }
5110 
5111         if (exp.f && exp.f.tintro)
5112         {
5113             Type t = exp.type;
5114             int offset = 0;
5115             TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5116             if (tf.next.isBaseOf(t, &offset) && offset)
5117             {
5118                 exp.type = tf.next;
5119                 result = Expression.combine(argprefix, exp.castTo(sc, t));
5120                 return;
5121             }
5122         }
5123 
5124         // Handle the case of a direct lambda call
5125         if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5126         {
5127             exp.f.tookAddressOf = 0;
5128         }
5129 
5130         result = Expression.combine(argprefix, exp);
5131 
5132         if (isSuper)
5133         {
5134             auto ad = sc.func ? sc.func.isThis() : null;
5135             auto cd = ad ? ad.isClassDeclaration() : null;
5136             if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5137             {
5138                 // if super is defined in C++, it sets the vtable pointer to the base class
5139                 // so we have to restore it, but still return 'this' from super() call:
5140                 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5141                 Loc loc = exp.loc;
5142 
5143                 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5144                 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5145                 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5146 
5147                 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5148                 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5149 
5150                 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5151 
5152                 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5153 
5154                 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5155                 result = e.expressionSemantic(sc);
5156             }
5157         }
5158 
5159         // declare dual-context container
5160         if (exp.f && exp.f.hasDualContext() && !sc.intypeof && sc.func)
5161         {
5162             // check access to second `this`
5163             if (AggregateDeclaration ad2 = exp.f.isMember2())
5164             {
5165                 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5166                 if (te.op != EXP.error)
5167                     te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5168                 if (te.op == EXP.error)
5169                 {
5170                     exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5171                     return setError();
5172                 }
5173             }
5174             exp.vthis2 = makeThis2Argument(exp.loc, sc, exp.f);
5175             Expression de = new DeclarationExp(exp.loc, exp.vthis2);
5176             result = Expression.combine(de, result);
5177             result = result.expressionSemantic(sc);
5178         }
5179     }
5180 
visit(DeclarationExp e)5181     override void visit(DeclarationExp e)
5182     {
5183         if (e.type)
5184         {
5185             result = e;
5186             return;
5187         }
5188         static if (LOGSEMANTIC)
5189         {
5190             printf("DeclarationExp::semantic() %s\n", e.toChars());
5191         }
5192 
5193         uint olderrors = global.errors;
5194 
5195         /* This is here to support extern(linkage) declaration,
5196          * where the extern(linkage) winds up being an AttribDeclaration
5197          * wrapper.
5198          */
5199         Dsymbol s = e.declaration;
5200 
5201         while (1)
5202         {
5203             AttribDeclaration ad = s.isAttribDeclaration();
5204             if (ad)
5205             {
5206                 if (ad.decl && ad.decl.dim == 1)
5207                 {
5208                     s = (*ad.decl)[0];
5209                     continue;
5210                 }
5211             }
5212             break;
5213         }
5214 
5215         //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5216         // Insert into both local scope and function scope.
5217         // Must be unique in both.
5218         if (s.ident)
5219         {
5220             VarDeclaration v = s.isVarDeclaration();
5221             if (v)
5222             {
5223                 if (sc.flags & SCOPE.Cfile)
5224                 {
5225                     /* Do semantic() on the type before inserting v into the symbol table
5226                      */
5227                     if (!v.originalType)
5228                         v.originalType = v.type.syntaxCopy();
5229                     Scope* sc2 = sc.push();
5230                     sc2.stc |= v.storage_class & STC.FUNCATTR;
5231                     sc2.linkage = LINK.c;       // account for the extern(C) in front of the declaration
5232                     v.inuse++;
5233                     v.type = v.type.typeSemantic(v.loc, sc2);
5234                     v.inuse--;
5235                     sc2.pop();
5236                 }
5237                 else
5238                 {
5239                     /* Do semantic() on initializer first so this will be illegal:
5240                      *      int a = a;
5241                      */
5242                     e.declaration.dsymbolSemantic(sc);
5243                     s.parent = sc.parent;
5244                 }
5245             }
5246 
5247             if (!sc.insert(s))
5248             {
5249                 auto conflict = sc.search(Loc.initial, s.ident, null);
5250                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5251                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5252                                   conflict.kind(), conflict.toChars());
5253                 return setError();
5254             }
5255 
5256             if (v && (sc.flags & SCOPE.Cfile))
5257             {
5258                 /* Do semantic() on initializer last so this will be legal:
5259                  *      int a = a;
5260                  */
5261                 e.declaration.dsymbolSemantic(sc);
5262                 s.parent = sc.parent;
5263             }
5264 
5265             if (sc.func)
5266             {
5267                 // https://issues.dlang.org/show_bug.cgi?id=11720
5268                 if ((s.isFuncDeclaration() ||
5269                      s.isAggregateDeclaration() ||
5270                      s.isEnumDeclaration() ||
5271                      s.isTemplateDeclaration() ||
5272                      v
5273                     ) && !sc.func.localsymtab.insert(s))
5274                 {
5275                     // Get the previous symbol
5276                     Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5277 
5278                     // Perturb the name mangling so that the symbols can co-exist
5279                     // instead of colliding
5280                     s.localNum = cast(ushort)(originalSymbol.localNum + 1);
5281                     // 65535 should be enough for anyone
5282                     if (!s.localNum)
5283                     {
5284                         e.error("more than 65535 symbols with name `%s` generated", s.ident.toChars());
5285                         return setError();
5286                     }
5287 
5288                     // Replace originalSymbol with s, which updates the localCount
5289                     sc.func.localsymtab.update(s);
5290 
5291                     // The mangling change only works for D mangling
5292                 }
5293 
5294                 if (!(sc.flags & SCOPE.Cfile))
5295                 {
5296                     /* https://issues.dlang.org/show_bug.cgi?id=21272
5297                      * If we are in a foreach body we need to extract the
5298                      * function containing the foreach
5299                      */
5300                     FuncDeclaration fes_enclosing_func;
5301                     if (sc.func && sc.func.fes)
5302                         fes_enclosing_func = sc.enclosing.enclosing.func;
5303 
5304                     // Disallow shadowing
5305                     for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5306                     {
5307                         Dsymbol s2;
5308                         if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5309                         {
5310                             // allow STC.local symbols to be shadowed
5311                             // TODO: not really an optimal design
5312                             auto decl = s2.isDeclaration();
5313                             if (!decl || !(decl.storage_class & STC.local))
5314                             {
5315                                 if (sc.func.fes)
5316                                 {
5317                                     e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5318                                 }
5319                                 else
5320                                 {
5321                                     e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5322                                     return setError();
5323                                 }
5324                             }
5325                         }
5326                     }
5327                 }
5328             }
5329         }
5330         if (!s.isVarDeclaration())
5331         {
5332             Scope* sc2 = sc;
5333             if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5334                 sc2 = sc.push();
5335             sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5336             e.declaration.dsymbolSemantic(sc2);
5337             if (sc2 != sc)
5338                 sc2.pop();
5339             s.parent = sc.parent;
5340         }
5341         if (global.errors == olderrors)
5342         {
5343             e.declaration.semantic2(sc);
5344             if (global.errors == olderrors)
5345             {
5346                 e.declaration.semantic3(sc);
5347             }
5348         }
5349         // todo: error in declaration should be propagated.
5350 
5351         e.type = Type.tvoid;
5352         result = e;
5353     }
5354 
visit(TypeidExp exp)5355     override void visit(TypeidExp exp)
5356     {
5357         static if (LOGSEMANTIC)
5358         {
5359             printf("TypeidExp::semantic() %s\n", exp.toChars());
5360         }
5361         Type ta = isType(exp.obj);
5362         Expression ea = isExpression(exp.obj);
5363         Dsymbol sa = isDsymbol(exp.obj);
5364         //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5365 
5366         if (ta)
5367         {
5368             dmd.typesem.resolve(ta, exp.loc, sc, ea, ta, sa, true);
5369         }
5370 
5371         if (ea)
5372         {
5373             if (auto sym = getDsymbol(ea))
5374                 ea = symbolToExp(sym, exp.loc, sc, false);
5375             else
5376                 ea = ea.expressionSemantic(sc);
5377             ea = resolveProperties(sc, ea);
5378             ta = ea.type;
5379             if (ea.op == EXP.type)
5380                 ea = null;
5381         }
5382 
5383         if (!ta)
5384         {
5385             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5386             exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5387             return setError();
5388         }
5389 
5390         ta.checkComplexTransition(exp.loc, sc);
5391 
5392         Expression e;
5393         auto tb = ta.toBasetype();
5394         if (ea && tb.ty == Tclass)
5395         {
5396             if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5397             {
5398                 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
5399                 e = ErrorExp.get();
5400             }
5401             else if (!Type.typeinfoclass)
5402             {
5403                 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5404                 e = ErrorExp.get();
5405             }
5406             else
5407             {
5408                 /* Get the dynamic type, which is .classinfo
5409                 */
5410                 ea = ea.expressionSemantic(sc);
5411                 e = new TypeidExp(ea.loc, ea);
5412                 e.type = Type.typeinfoclass.type;
5413             }
5414         }
5415         else if (ta.ty == Terror)
5416         {
5417             e = ErrorExp.get();
5418         }
5419         else
5420         {
5421             // Handle this in the glue layer
5422             e = new TypeidExp(exp.loc, ta);
5423             e.type = getTypeInfoType(exp.loc, ta, sc);
5424 
5425             semanticTypeInfo(sc, ta);
5426 
5427             if (ea)
5428             {
5429                 e = new CommaExp(exp.loc, ea, e); // execute ea
5430                 e = e.expressionSemantic(sc);
5431             }
5432         }
5433         result = e;
5434     }
5435 
visit(TraitsExp e)5436     override void visit(TraitsExp e)
5437     {
5438         result = semanticTraits(e, sc);
5439     }
5440 
visit(HaltExp e)5441     override void visit(HaltExp e)
5442     {
5443         static if (LOGSEMANTIC)
5444         {
5445             printf("HaltExp::semantic()\n");
5446         }
5447         e.type = Type.tnoreturn;
5448         result = e;
5449     }
5450 
visit(IsExp e)5451     override void visit(IsExp e)
5452     {
5453         /* is(targ id tok tspec)
5454          * is(targ id :  tok2)
5455          * is(targ id == tok2)
5456          */
5457         Type tded = null;
5458 
5459         void yes()
5460         {
5461             //printf("yes\n");
5462             if (!e.id)
5463             {
5464                 result = IntegerExp.createBool(true);
5465                 return;
5466             }
5467 
5468             Dsymbol s;
5469             Tuple tup = isTuple(tded);
5470             if (tup)
5471                 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5472             else
5473                 s = new AliasDeclaration(e.loc, e.id, tded);
5474             s.dsymbolSemantic(sc);
5475 
5476             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5477              * More investigation is needed.
5478              */
5479             if (!tup && !sc.insert(s))
5480             {
5481                 auto conflict = sc.search(Loc.initial, s.ident, null);
5482                 e.error("declaration `%s` is already defined", s.toPrettyChars());
5483                 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5484                                   conflict.kind(), conflict.toChars());
5485             }
5486 
5487             unSpeculative(sc, s);
5488 
5489             result = IntegerExp.createBool(true);
5490         }
5491         void no()
5492         {
5493             result = IntegerExp.createBool(false);
5494             //printf("no\n");
5495         }
5496 
5497         static if (LOGSEMANTIC)
5498         {
5499             printf("IsExp::semantic(%s)\n", e.toChars());
5500         }
5501         if (e.id && !(sc.flags & SCOPE.condition))
5502         {
5503             e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5504             return setError();
5505         }
5506 
5507         if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5508         {
5509             const oldErrors = global.startGagging();
5510             Dsymbol sym = e.targ.toDsymbol(sc);
5511             global.endGagging(oldErrors);
5512 
5513             if (sym is null)
5514                 return no();
5515             Package p = resolveIsPackage(sym);
5516             if (p is null)
5517                 return no();
5518             if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5519                 return no();
5520             else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5521                 return no();
5522             tded = e.targ;
5523             return yes();
5524         }
5525 
5526         {
5527             Scope* sc2 = sc.copy(); // keep sc.flags
5528             sc2.tinst = null;
5529             sc2.minst = null;
5530             sc2.flags |= SCOPE.fullinst;
5531             Type t = e.targ.trySemantic(e.loc, sc2);
5532             sc2.pop();
5533             if (!t) // errors, so condition is false
5534                 return no();
5535             e.targ = t;
5536         }
5537 
5538         if (e.tok2 != TOK.reserved)
5539         {
5540             switch (e.tok2)
5541             {
5542             case TOK.struct_:
5543                 if (e.targ.ty != Tstruct)
5544                     return no();
5545                 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5546                     return no();
5547                 tded = e.targ;
5548                 break;
5549 
5550             case TOK.union_:
5551                 if (e.targ.ty != Tstruct)
5552                     return no();
5553                 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5554                     return no();
5555                 tded = e.targ;
5556                 break;
5557 
5558             case TOK.class_:
5559                 if (e.targ.ty != Tclass)
5560                     return no();
5561                 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5562                     return no();
5563                 tded = e.targ;
5564                 break;
5565 
5566             case TOK.interface_:
5567                 if (e.targ.ty != Tclass)
5568                     return no();
5569                 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5570                     return no();
5571                 tded = e.targ;
5572                 break;
5573 
5574             case TOK.const_:
5575                 if (!e.targ.isConst())
5576                     return no();
5577                 tded = e.targ;
5578                 break;
5579 
5580             case TOK.immutable_:
5581                 if (!e.targ.isImmutable())
5582                     return no();
5583                 tded = e.targ;
5584                 break;
5585 
5586             case TOK.shared_:
5587                 if (!e.targ.isShared())
5588                     return no();
5589                 tded = e.targ;
5590                 break;
5591 
5592             case TOK.inout_:
5593                 if (!e.targ.isWild())
5594                     return no();
5595                 tded = e.targ;
5596                 break;
5597 
5598             case TOK.super_:
5599                 // If class or interface, get the base class and interfaces
5600                 if (e.targ.ty != Tclass)
5601                     return no();
5602                 else
5603                 {
5604                     ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5605                     auto args = new Parameters();
5606                     args.reserve(cd.baseclasses.dim);
5607                     if (cd.semanticRun < PASS.semanticdone)
5608                         cd.dsymbolSemantic(null);
5609                     for (size_t i = 0; i < cd.baseclasses.dim; i++)
5610                     {
5611                         BaseClass* b = (*cd.baseclasses)[i];
5612                         args.push(new Parameter(STC.in_, b.type, null, null, null));
5613                     }
5614                     tded = new TypeTuple(args);
5615                 }
5616                 break;
5617 
5618             case TOK.enum_:
5619                 if (e.targ.ty != Tenum)
5620                     return no();
5621                 if (e.id)
5622                     tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5623                 else
5624                     tded = e.targ;
5625 
5626                 if (tded.ty == Terror)
5627                     return setError();
5628                 break;
5629 
5630             case TOK.delegate_:
5631                 if (e.targ.ty != Tdelegate)
5632                     return no();
5633                 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5634                 break;
5635 
5636             case TOK.function_:
5637             case TOK.parameters:
5638                 {
5639                     if (e.targ.ty != Tfunction)
5640                         return no();
5641                     tded = e.targ;
5642 
5643                     /* Generate tuple from function parameter types.
5644                      */
5645                     assert(tded.ty == Tfunction);
5646                     auto tdedf = tded.isTypeFunction();
5647                     auto args = new Parameters();
5648                     foreach (i, arg; tdedf.parameterList)
5649                     {
5650                         assert(arg && arg.type);
5651                         /* If one of the default arguments was an error,
5652                            don't return an invalid tuple
5653                          */
5654                         if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
5655                             return setError();
5656                         args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5657                     }
5658                     tded = new TypeTuple(args);
5659                     break;
5660                 }
5661             case TOK.return_:
5662                 /* Get the 'return type' for the function,
5663                  * delegate, or pointer to function.
5664                  */
5665                 if (auto tf = e.targ.isFunction_Delegate_PtrToFunction())
5666                     tded = tf.next;
5667                 else
5668                     return no();
5669                 break;
5670 
5671             case TOK.argumentTypes:
5672                 /* Generate a type tuple of the equivalent types used to determine if a
5673                  * function argument of this type can be passed in registers.
5674                  * The results of this are highly platform dependent, and intended
5675                  * primarly for use in implementing va_arg().
5676                  */
5677                 tded = target.toArgTypes(e.targ);
5678                 if (!tded)
5679                     return no();
5680                 // not valid for a parameter
5681                 break;
5682 
5683             case TOK.vector:
5684                 if (e.targ.ty != Tvector)
5685                     return no();
5686                 tded = (cast(TypeVector)e.targ).basetype;
5687                 break;
5688 
5689             default:
5690                 assert(0);
5691             }
5692 
5693             // https://issues.dlang.org/show_bug.cgi?id=18753
5694             if (tded)
5695                 return yes();
5696             return no();
5697         }
5698         else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
5699         {
5700             /* Evaluate to true if targ matches tspec
5701              * is(targ == tspec)
5702              * is(targ : tspec)
5703              */
5704             e.tspec = e.tspec.typeSemantic(e.loc, sc);
5705             //printf("targ  = %s, %s\n", e.targ.toChars(), e.targ.deco);
5706             //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5707 
5708             if (e.tok == TOK.colon)
5709             {
5710                 // current scope is itself deprecated, or deprecations are not errors
5711                 const bool deprecationAllowed = sc.isDeprecated
5712                     || global.params.useDeprecated != DiagnosticReporting.error;
5713                 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5714 
5715                 if (preventAliasThis && e.targ.ty == Tstruct)
5716                 {
5717                     if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5718                         return yes();
5719                     else
5720                         return no();
5721                 }
5722                 else if (preventAliasThis && e.targ.ty == Tclass)
5723                 {
5724                     if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5725                         return yes();
5726                     else
5727                         return no();
5728                 }
5729                 else if (e.targ.implicitConvTo(e.tspec))
5730                     return yes();
5731                 else
5732                     return no();
5733             }
5734             else /* == */
5735             {
5736                 if (e.targ.equals(e.tspec))
5737                     return yes();
5738                 else
5739                     return no();
5740             }
5741         }
5742         else if (e.tspec)
5743         {
5744             /* Evaluate to true if targ matches tspec.
5745              * If true, declare id as an alias for the specialized type.
5746              * is(targ == tspec, tpl)
5747              * is(targ : tspec, tpl)
5748              * is(targ id == tspec)
5749              * is(targ id : tspec)
5750              * is(targ id == tspec, tpl)
5751              * is(targ id : tspec, tpl)
5752              */
5753             Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5754             e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5755 
5756             Objects dedtypes = Objects(e.parameters.dim);
5757             dedtypes.zero();
5758 
5759             MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5760             //printf("targ: %s\n", targ.toChars());
5761             //printf("tspec: %s\n", tspec.toChars());
5762             if (m == MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5763             {
5764                 return no();
5765             }
5766             else
5767             {
5768                 tded = cast(Type)dedtypes[0];
5769                 if (!tded)
5770                     tded = e.targ;
5771                 Objects tiargs = Objects(1);
5772                 tiargs[0] = e.targ;
5773 
5774                 /* Declare trailing parameters
5775                  */
5776                 for (size_t i = 1; i < e.parameters.dim; i++)
5777                 {
5778                     TemplateParameter tp = (*e.parameters)[i];
5779                     Declaration s = null;
5780 
5781                     m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5782                     if (m == MATCH.nomatch)
5783                         return no();
5784                     s.dsymbolSemantic(sc);
5785                     if (!sc.insert(s))
5786                     {
5787                         auto conflict = sc.search(Loc.initial, s.ident, null);
5788                         e.error("declaration `%s` is already defined", s.toPrettyChars());
5789                         errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5790                                           conflict.kind(), conflict.toChars());
5791                     }
5792 
5793                     unSpeculative(sc, s);
5794                 }
5795                 return yes();
5796             }
5797         }
5798         else if (e.id)
5799         {
5800             /* Declare id as an alias for type targ. Evaluate to true
5801              * is(targ id)
5802              */
5803             tded = e.targ;
5804         }
5805         return yes();
5806     }
5807 
visit(BinAssignExp exp)5808     override void visit(BinAssignExp exp)
5809     {
5810         if (exp.type)
5811         {
5812             result = exp;
5813             return;
5814         }
5815 
5816         Expression e = exp.op_overload(sc);
5817         if (e)
5818         {
5819             result = e;
5820             return;
5821         }
5822 
5823         if (exp.e1.op == EXP.arrayLength)
5824         {
5825             // arr.length op= e2;
5826             e = rewriteOpAssign(exp);
5827             e = e.expressionSemantic(sc);
5828             result = e;
5829             return;
5830         }
5831         if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5832         {
5833             if (checkNonAssignmentArrayOp(exp.e1))
5834                 return setError();
5835 
5836             if (exp.e1.op == EXP.slice)
5837                 (cast(SliceExp)exp.e1).arrayop = true;
5838 
5839             // T[] op= ...
5840             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5841             {
5842                 // T[] op= T
5843                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5844             }
5845             else if (Expression ex = typeCombine(exp, sc))
5846             {
5847                 result = ex;
5848                 return;
5849             }
5850             exp.type = exp.e1.type;
5851             result = arrayOp(exp, sc);
5852             return;
5853         }
5854 
5855         exp.e1 = exp.e1.expressionSemantic(sc);
5856         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5857         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
5858         exp.type = exp.e1.type;
5859 
5860         if (auto ad = isAggregate(exp.e1.type))
5861         {
5862             if (const s = search_function(ad, Id.opOpAssign))
5863             {
5864                 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());
5865                 return setError();
5866             }
5867         }
5868         if (exp.e1.checkScalar() ||
5869             exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5870             exp.e1.checkSharedAccess(sc))
5871             return setError();
5872 
5873         int arith = (exp.op == EXP.addAssign || exp.op == EXP.minAssign || exp.op == EXP.mulAssign || exp.op == EXP.divAssign || exp.op == EXP.modAssign || exp.op == EXP.powAssign);
5874         int bitwise = (exp.op == EXP.andAssign || exp.op == EXP.orAssign || exp.op == EXP.xorAssign);
5875         int shift = (exp.op == EXP.leftShiftAssign || exp.op == EXP.rightShiftAssign || exp.op == EXP.unsignedRightShiftAssign);
5876 
5877         if (bitwise && exp.type.toBasetype().ty == Tbool)
5878             exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5879         else if (exp.checkNoBool())
5880             return setError();
5881 
5882         if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5883         {
5884             result = scaleFactor(exp, sc);
5885             return;
5886         }
5887 
5888         if (Expression ex = typeCombine(exp, sc))
5889         {
5890             result = ex;
5891             return;
5892         }
5893 
5894         if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5895             return setError();
5896         if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5897             return setError();
5898 
5899         if (shift)
5900         {
5901             if (exp.e2.type.toBasetype().ty != Tvector)
5902                 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5903         }
5904 
5905         if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5906         {
5907             result = exp.incompatibleTypes();
5908             return;
5909         }
5910 
5911         if (exp.e1.op == EXP.error || exp.e2.op == EXP.error)
5912             return setError();
5913 
5914         e = exp.checkOpAssignTypes(sc);
5915         if (e.op == EXP.error)
5916         {
5917             result = e;
5918             return;
5919         }
5920 
5921         assert(e.op == EXP.assign || e == exp);
5922         result = (cast(BinExp)e).reorderSettingAAElem(sc);
5923     }
5924 
compileIt(MixinExp exp)5925     private Expression compileIt(MixinExp exp)
5926     {
5927         OutBuffer buf;
5928         if (expressionsToString(buf, sc, exp.exps))
5929             return null;
5930 
5931         uint errors = global.errors;
5932         const len = buf.length;
5933         const str = buf.extractChars()[0 .. len];
5934         scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
5935         p.nextToken();
5936         //printf("p.loc.linnum = %d\n", p.loc.linnum);
5937 
5938         Expression e = p.parseExpression();
5939         if (global.errors != errors)
5940             return null;
5941 
5942         if (p.token.value != TOK.endOfFile)
5943         {
5944             exp.error("incomplete mixin expression `%s`", str.ptr);
5945             return null;
5946         }
5947         return e;
5948     }
5949 
visit(MixinExp exp)5950     override void visit(MixinExp exp)
5951     {
5952         /* https://dlang.org/spec/expression.html#mixin_expressions
5953          */
5954 
5955         static if (LOGSEMANTIC)
5956         {
5957             printf("MixinExp::semantic('%s')\n", exp.toChars());
5958         }
5959 
5960         auto e = compileIt(exp);
5961         if (!e)
5962             return setError();
5963         result = e.expressionSemantic(sc);
5964     }
5965 
visit(ImportExp e)5966     override void visit(ImportExp e)
5967     {
5968         static if (LOGSEMANTIC)
5969         {
5970             printf("ImportExp::semantic('%s')\n", e.toChars());
5971         }
5972 
5973         auto se = semanticString(sc, e.e1, "file name argument");
5974         if (!se)
5975             return setError();
5976         se = se.toUTF8(sc);
5977 
5978         auto namez = se.toStringz().ptr;
5979         if (!global.filePath)
5980         {
5981             e.error("need `-J` switch to import text file `%s`", namez);
5982             return setError();
5983         }
5984 
5985         /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5986          * ('Path Traversal') attacks.
5987          * https://cwe.mitre.org/data/definitions/22.html
5988          */
5989 
5990         if (FileName.absolute(namez))
5991         {
5992             e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
5993             return setError();
5994         }
5995 
5996         auto idxReserved = FileName.findReservedChar(namez);
5997         if (idxReserved != size_t.max)
5998         {
5999             e.error("`%s` is  not a valid filename on this platform", se.toChars());
6000             e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
6001             return setError();
6002         }
6003 
6004         if (FileName.refersToParentDir(namez))
6005         {
6006             e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
6007             return setError();
6008         }
6009 
6010         auto name = FileName.searchPath(global.filePath, namez, false);
6011         if (!name)
6012         {
6013             e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
6014             e.errorSupplemental("Path(s) searched (as provided by `-J`):");
6015             foreach (idx, path; *global.filePath)
6016             {
6017                 const attr = FileName.exists(path);
6018                 const(char)* err = attr == 2 ? "" :
6019                     (attr == 1 ? " (not a directory)" : " (path not found)");
6020                 e.errorSupplemental("[%llu]: `%s`%s", cast(ulong)idx, path, err);
6021             }
6022             return setError();
6023         }
6024 
6025         sc._module.contentImportedFiles.push(name);
6026         if (global.params.verbose)
6027         {
6028             const slice = se.peekString();
6029             message("file      %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
6030         }
6031         if (global.params.moduleDeps !is null)
6032         {
6033             OutBuffer* ob = global.params.moduleDeps;
6034             Module imod = sc._module;
6035 
6036             if (!global.params.moduleDepsFile)
6037                 ob.writestring("depsFile ");
6038             ob.writestring(imod.toPrettyChars());
6039             ob.writestring(" (");
6040             escapePath(ob, imod.srcfile.toChars());
6041             ob.writestring(") : ");
6042             if (global.params.moduleDepsFile)
6043                 ob.writestring("string : ");
6044             ob.write(se.peekString());
6045             ob.writestring(" (");
6046             escapePath(ob, name);
6047             ob.writestring(")");
6048             ob.writenl();
6049         }
6050         if (global.params.emitMakeDeps)
6051         {
6052             global.params.makeDeps.push(name);
6053         }
6054 
6055         {
6056             auto fileName = FileName(name.toDString);
6057             if (auto fmResult = global.fileManager.lookup(fileName))
6058             {
6059                 se = new StringExp(e.loc, fmResult);
6060             }
6061             else
6062             {
6063                 auto readResult = File.read(name.toDString);
6064                 if (!readResult.success)
6065                 {
6066                     e.error("cannot read file `%s`", name);
6067                     return setError();
6068                 }
6069                 else
6070                 {
6071                     // take ownership of buffer (probably leaking)
6072                     auto data = readResult.extractSlice();
6073                     se = new StringExp(e.loc, data);
6074                     global.fileManager.add(fileName, data);
6075                 }
6076             }
6077         }
6078         result = se.expressionSemantic(sc);
6079     }
6080 
visit(AssertExp exp)6081     override void visit(AssertExp exp)
6082     {
6083         // https://dlang.org/spec/expression.html#assert_expressions
6084         static if (LOGSEMANTIC)
6085         {
6086             printf("AssertExp::semantic('%s')\n", exp.toChars());
6087         }
6088 
6089         const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context && global.params.useAssert == CHECKENABLE.on;
6090         Expression temporariesPrefix;
6091 
6092         if (generateMsg)
6093         // no message - use assert expression as msg
6094         {
6095             if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
6096                 return setError();
6097 
6098             /*
6099             {
6100               auto a = e1, b = e2;
6101               assert(a == b, _d_assert_fail!"=="(a, b));
6102             }()
6103             */
6104 
6105             /*
6106             Stores the result of an operand expression into a temporary
6107             if necessary, e.g. if it is an impure fuction call containing side
6108             effects as in https://issues.dlang.org/show_bug.cgi?id=20114
6109 
6110             Params:
6111                 op = an expression which may require a temporary (added to
6112                      `temporariesPrefix`: `auto tmp = op`) and will be replaced
6113                      by `tmp` if necessary
6114 
6115             Returns: (possibly replaced) `op`
6116             */
6117             Expression maybePromoteToTmp(ref Expression op)
6118             {
6119                 // https://issues.dlang.org/show_bug.cgi?id=20989
6120                 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6121                 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6122                 {
6123                     auto die = op.isDotIdExp();
6124                     if (die && die.ident == Id.ptr)
6125                         die.noderef = true;
6126                 }
6127 
6128                 op = op.expressionSemantic(sc);
6129                 op = resolveProperties(sc, op);
6130 
6131                 // Detect assert's using static operator overloads (e.g. `"var" in environment`)
6132                 if (auto te = op.isTypeExp())
6133                 {
6134                     // Replace the TypeExp with it's textual representation
6135                     // Including "..." in the error message isn't quite right but
6136                     // proper solutions require more drastic changes, e.g. directly
6137                     // using miniFormat and combine instead of calling _d_assert_fail
6138                     auto name = new StringExp(te.loc, te.toString());
6139                     return name.expressionSemantic(sc);
6140                 }
6141 
6142                 // Create a temporary for expressions with side effects
6143                 // Defensively assume that function calls may have side effects even
6144                 // though it's not detected by hasSideEffect (e.g. `debug puts("Hello")` )
6145                 // Rewriting CallExp's also avoids some issues with the inliner/debug generation
6146                 if (op.hasSideEffect(true))
6147                 {
6148                     // Don't create an invalid temporary for void-expressions
6149                     // Further semantic will issue an appropriate error
6150                     if (op.type.ty == Tvoid)
6151                         return op;
6152 
6153                     // https://issues.dlang.org/show_bug.cgi?id=21590
6154                     // Don't create unnecessary temporaries and detect `assert(a = b)`
6155                     if (op.isAssignExp() || op.isBinAssignExp())
6156                     {
6157                         auto left = (cast(BinExp) op).e1;
6158 
6159                         // Find leftmost expression to handle other rewrites,
6160                         // e.g. --(++a) => a += 1 -= 1
6161                         while (left.isAssignExp() || left.isBinAssignExp())
6162                             left = (cast(BinExp) left).e1;
6163 
6164                         // Only use the assignee if it's a variable and skip
6165                         // other lvalues (e.g. ref's returned by functions)
6166                         if (left.isVarExp())
6167                             return left;
6168 
6169                         // Sanity check that `op` can be converted to boolean
6170                         // But don't raise errors for assignments enclosed in another expression
6171                         if (op is exp.e1)
6172                             op.toBoolean(sc);
6173                     }
6174 
6175                     // Tuples with side-effects already receive a temporary during semantic
6176                     if (op.type.isTypeTuple())
6177                     {
6178                         auto te = op.isTupleExp();
6179                         assert(te);
6180 
6181                         // Create a new tuple without the associated temporary
6182                         auto res = new TupleExp(op.loc, te.exps);
6183                         return res.expressionSemantic(sc);
6184                     }
6185 
6186                     const stc = op.isLvalue() ? STC.ref_ : 0;
6187                     auto tmp = copyToTemp(stc, "__assertOp", op);
6188                     tmp.dsymbolSemantic(sc);
6189 
6190                     auto decl = new DeclarationExp(op.loc, tmp);
6191                     temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6192 
6193                     op = new VarExp(op.loc, tmp);
6194                     op = op.expressionSemantic(sc);
6195                 }
6196                 return op;
6197             }
6198 
6199             // if the assert condition is a mixin expression, try to compile it
6200             if (auto ce = exp.e1.isMixinExp())
6201             {
6202                 if (auto e1 = compileIt(ce))
6203                     exp.e1 = e1;
6204             }
6205 
6206             Expressions* es;
6207             Objects* tiargs;
6208             Loc loc = exp.e1.loc;
6209 
6210             const op = exp.e1.op;
6211             bool isEqualsCallExpression;
6212             if (const callExp = exp.e1.isCallExp())
6213             {
6214                 // https://issues.dlang.org/show_bug.cgi?id=20331
6215                 // callExp.f may be null if the assert contains a call to
6216                 // a function pointer or literal
6217                 if (const callExpFunc = callExp.f)
6218                 {
6219                     const callExpIdent = callExpFunc.ident;
6220                     isEqualsCallExpression = callExpIdent == Id.__equals ||
6221                                              callExpIdent == Id.eq;
6222                 }
6223             }
6224             if (op == EXP.equal || op == EXP.notEqual ||
6225                 op == EXP.lessThan || op == EXP.greaterThan ||
6226                 op == EXP.lessOrEqual || op == EXP.greaterOrEqual ||
6227                 op == EXP.identity || op == EXP.notIdentity ||
6228                 op == EXP.in_ ||
6229                 isEqualsCallExpression)
6230             {
6231                 es = new Expressions(3);
6232                 tiargs = new Objects(1);
6233 
6234                 if (isEqualsCallExpression)
6235                 {
6236                     auto callExp = cast(CallExp) exp.e1;
6237                     auto args = callExp.arguments;
6238 
6239                     // structs with opEquals get rewritten to a DotVarExp:
6240                     // a.opEquals(b)
6241                     // https://issues.dlang.org/show_bug.cgi?id=20100
6242                     if (args.length == 1)
6243                     {
6244                         auto dv = callExp.e1.isDotVarExp();
6245                         assert(dv);
6246 
6247                         // runtime args
6248                         (*es)[1] = maybePromoteToTmp(dv.e1);
6249                         (*es)[2] = maybePromoteToTmp((*args)[0]);
6250                     }
6251                     else
6252                     {
6253                         // runtime args
6254                         (*es)[1] = maybePromoteToTmp((*args)[0]);
6255                         (*es)[2] = maybePromoteToTmp((*args)[1]);
6256                     }
6257                 }
6258                 else
6259                 {
6260                     auto binExp = cast(EqualExp) exp.e1;
6261 
6262                     // runtime args
6263                     (*es)[1] = maybePromoteToTmp(binExp.e1);
6264                     (*es)[2] = maybePromoteToTmp(binExp.e2);
6265                 }
6266 
6267                 // template args
6268                 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : EXPtoString(exp.e1.op));
6269                 comp = comp.expressionSemantic(sc);
6270                 (*es)[0] = comp;
6271                 (*tiargs)[0] = (*es)[1].type;
6272             }
6273 
6274             // Format exp.e1 before any additional boolean conversion
6275             // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
6276             else if (op != EXP.andAnd && op != EXP.orOr)
6277             {
6278                 es = new Expressions(2);
6279                 tiargs = new Objects(1);
6280 
6281                 if (auto ne = exp.e1.isNotExp())
6282                 {
6283                     // Fetch the (potential non-bool) expression and fold
6284                     // (n) negations into (n % 2) negations, e.g. !!a => a
6285                     for (bool neg = true; ; neg = !neg)
6286                     {
6287                         if (auto ne2 = ne.e1.isNotExp())
6288                             ne = ne2;
6289                         else
6290                         {
6291                             (*es)[0] = new StringExp(loc, neg ? "!" : "");
6292                             (*es)[1] = maybePromoteToTmp(ne.e1);
6293                             break;
6294                         }
6295                     }
6296                 }
6297                 else
6298                 {   // Simply format exp.e1
6299                     (*es)[0] = new StringExp(loc, "");
6300                     (*es)[1] = maybePromoteToTmp(exp.e1);
6301                 }
6302 
6303                 (*tiargs)[0] = (*es)[1].type;
6304 
6305                 // Passing __ctfe to auto ref infers ref and aborts compilation:
6306                 // "cannot modify compiler-generated variable __ctfe"
6307                 auto ve = (*es)[1].isVarExp();
6308                 if (ve && ve.var.ident == Id.ctfe)
6309                 {
6310                     exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6311                     goto LSkip;
6312                 }
6313             }
6314             else
6315             {
6316                 OutBuffer buf;
6317                 buf.printf("%s failed", exp.toChars());
6318                 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6319                 goto LSkip;
6320             }
6321 
6322             Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6323             auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6324 
6325             auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6326             auto ec = CallExp.create(loc, dt, es);
6327             exp.msg = ec;
6328         }
6329 
6330         LSkip:
6331         if (Expression ex = unaSemantic(exp, sc))
6332         {
6333             result = ex;
6334             return;
6335         }
6336 
6337         exp.e1 = resolveProperties(sc, exp.e1);
6338         // BUG: see if we can do compile time elimination of the Assert
6339         exp.e1 = exp.e1.optimize(WANTvalue);
6340         exp.e1 = exp.e1.toBoolean(sc);
6341 
6342         if (exp.e1.op == EXP.error)
6343         {
6344             result = exp.e1;
6345             return;
6346         }
6347 
6348         if (exp.msg)
6349         {
6350             exp.msg = expressionSemantic(exp.msg, sc);
6351             exp.msg = resolveProperties(sc, exp.msg);
6352             exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6353             exp.msg = exp.msg.optimize(WANTvalue);
6354             checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
6355         }
6356 
6357         if (exp.msg && exp.msg.op == EXP.error)
6358         {
6359             result = exp.msg;
6360             return;
6361         }
6362 
6363         auto f1 = checkNonAssignmentArrayOp(exp.e1);
6364         auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6365         if (f1 || f2)
6366             return setError();
6367 
6368         if (exp.e1.toBool().hasValue(false))
6369         {
6370             /* This is an `assert(0)` which means halt program execution
6371              */
6372             FuncDeclaration fd = sc.parent.isFuncDeclaration();
6373             if (fd)
6374                 fd.hasReturnExp |= 4;
6375             sc.ctorflow.orCSX(CSX.halt);
6376 
6377             if (global.params.useAssert == CHECKENABLE.off)
6378             {
6379                 Expression e = new HaltExp(exp.loc);
6380                 e = e.expressionSemantic(sc);
6381                 result = e;
6382                 return;
6383             }
6384 
6385             // Only override the type when it isn't already some flavour of noreturn,
6386             // e.g. when this assert was generated by defaultInitLiteral
6387             if (!exp.type || !exp.type.isTypeNoreturn())
6388                 exp.type = Type.tnoreturn;
6389         }
6390         else
6391             exp.type = Type.tvoid;
6392 
6393         result = !temporariesPrefix
6394             ? exp
6395             : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6396     }
6397 
visit(ThrowExp te)6398     override void visit(ThrowExp te)
6399     {
6400         import dmd.statementsem;
6401 
6402         if (StatementSemanticVisitor.throwSemantic(te.loc, te.e1, sc))
6403             result = te;
6404         else
6405             setError();
6406     }
6407 
visit(DotIdExp exp)6408     override void visit(DotIdExp exp)
6409     {
6410         static if (LOGSEMANTIC)
6411         {
6412             printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6413             //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
6414         }
6415 
6416         if (sc.flags & SCOPE.Cfile)
6417         {
6418             /* See if need to rewrite the AST because of cast/call ambiguity
6419              */
6420             if (auto e = castCallAmbiguity(exp, sc))
6421             {
6422                 result = expressionSemantic(e, sc);
6423                 return;
6424             }
6425         }
6426 
6427         if (exp.arrow) // ImportC only
6428             exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
6429 
6430         if (sc.flags & SCOPE.Cfile)
6431         {
6432             if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
6433             {
6434                 // C11 6.5.3 says _Alignof only applies to types
6435                 Expression e;
6436                 Type t;
6437                 Dsymbol s;
6438                 dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
6439                 if (e)
6440                 {
6441                     exp.e1.error("argument to `_Alignof` must be a type");
6442                     return setError();
6443                 }
6444                 else if (t)
6445                 {
6446                     // Note similarity to getProperty() implementation of __xalignof
6447                     const explicitAlignment = t.alignment();
6448                     const naturalAlignment = t.alignsize();
6449                     const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
6450                     result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
6451                 }
6452                 else if (s)
6453                 {
6454                     exp.e1.error("argument to `_Alignof` must be a type");
6455                     return setError();
6456                 }
6457                 else
6458                     assert(0);
6459                 return;
6460             }
6461         }
6462 
6463         if (sc.flags & SCOPE.Cfile && exp.ident != Id.__sizeof)
6464         {
6465             result = fieldLookup(exp.e1, sc, exp.ident);
6466             return;
6467         }
6468 
6469         Expression e = exp.semanticY(sc, 1);
6470 
6471         if (e && isDotOpDispatch(e))
6472         {
6473             auto ode = e;
6474             uint errors = global.startGagging();
6475             e = resolvePropertiesX(sc, e);
6476             // Any error or if 'e' is not resolved, go to UFCS
6477             if (global.endGagging(errors) || e is ode)
6478                 e = null; /* fall down to UFCS */
6479             else
6480             {
6481                 result = e;
6482                 return;
6483             }
6484         }
6485         if (!e) // if failed to find the property
6486         {
6487             /* If ident is not a valid property, rewrite:
6488              *   e1.ident
6489              * as:
6490              *   .ident(e1)
6491              */
6492             e = resolveUFCSProperties(sc, exp);
6493         }
6494         result = e;
6495     }
6496 
visit(DotTemplateExp e)6497     override void visit(DotTemplateExp e)
6498     {
6499         if (e.type)
6500         {
6501             result = e;
6502             return;
6503         }
6504         if (Expression ex = unaSemantic(e, sc))
6505         {
6506             result = ex;
6507             return;
6508         }
6509         // 'void' like TemplateExp
6510         e.type = Type.tvoid;
6511         result = e;
6512     }
6513 
visit(DotVarExp exp)6514     override void visit(DotVarExp exp)
6515     {
6516         static if (LOGSEMANTIC)
6517         {
6518             printf("DotVarExp::semantic('%s')\n", exp.toChars());
6519         }
6520         if (exp.type)
6521         {
6522             result = exp;
6523             return;
6524         }
6525 
6526         exp.var = exp.var.toAlias().isDeclaration();
6527 
6528         exp.e1 = exp.e1.expressionSemantic(sc);
6529 
6530         if (auto tup = exp.var.isTupleDeclaration())
6531         {
6532             /* Replace:
6533              *  e1.tuple(a, b, c)
6534              * with:
6535              *  tuple(e1.a, e1.b, e1.c)
6536              */
6537             Expression e0;
6538             Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6539 
6540             auto exps = new Expressions();
6541             exps.reserve(tup.objects.dim);
6542             for (size_t i = 0; i < tup.objects.dim; i++)
6543             {
6544                 RootObject o = (*tup.objects)[i];
6545                 Expression e;
6546                 Declaration var;
6547                 if (o.dyncast() == DYNCAST.expression)
6548                 {
6549                     e = cast(Expression)o;
6550                     if (auto se = e.isDsymbolExp())
6551                         var = se.s.isDeclaration();
6552                     else if (auto ve = e.isVarExp())
6553                         if (!ve.var.isFuncDeclaration())
6554                             // Exempt functions for backwards compatibility reasons.
6555                             // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6556                             var = ve.var;
6557                 }
6558                 else if (o.dyncast() == DYNCAST.dsymbol)
6559                 {
6560                     Dsymbol s = cast(Dsymbol) o;
6561                     Declaration d = s.isDeclaration();
6562                     if (!d || d.isFuncDeclaration())
6563                         // Exempt functions for backwards compatibility reasons.
6564                         // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6565                         e = new DsymbolExp(exp.loc, s);
6566                     else
6567                         var = d;
6568                 }
6569                 else if (o.dyncast() == DYNCAST.type)
6570                 {
6571                     e = new TypeExp(exp.loc, cast(Type)o);
6572                 }
6573                 else
6574                 {
6575                     exp.error("`%s` is not an expression", o.toChars());
6576                     return setError();
6577                 }
6578                 if (var)
6579                     e = new DotVarExp(exp.loc, ev, var);
6580                 exps.push(e);
6581             }
6582 
6583             Expression e = new TupleExp(exp.loc, e0, exps);
6584             e = e.expressionSemantic(sc);
6585             result = e;
6586             return;
6587         }
6588 
6589         exp.e1 = exp.e1.addDtorHook(sc);
6590 
6591         Type t1 = exp.e1.type;
6592 
6593         if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6594         {
6595             // for functions, do checks after overload resolution
6596             if (!fd.functionSemantic())
6597                 return setError();
6598 
6599             /* https://issues.dlang.org/show_bug.cgi?id=13843
6600              * If fd obviously has no overloads, we should
6601              * normalize AST, and it will give a chance to wrap fd with FuncExp.
6602              */
6603             if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6604             {
6605                 // (e1, fd)
6606                 auto e = symbolToExp(fd, exp.loc, sc, false);
6607                 result = Expression.combine(exp.e1, e);
6608                 return;
6609             }
6610 
6611             exp.type = fd.type;
6612             assert(exp.type);
6613         }
6614         else if (OverDeclaration od = exp.var.isOverDeclaration())
6615         {
6616             exp.type = Type.tvoid; // ambiguous type?
6617         }
6618         else
6619         {
6620             exp.type = exp.var.type;
6621             if (!exp.type && global.errors) // var is goofed up, just return error.
6622                 return setError();
6623             assert(exp.type);
6624 
6625             if (t1.ty == Tpointer)
6626                 t1 = t1.nextOf();
6627 
6628             exp.type = exp.type.addMod(t1.mod);
6629 
6630             // https://issues.dlang.org/show_bug.cgi?id=23109
6631             // Run semantic on the DotVarExp type
6632             if (auto handle = exp.type.isClassHandle())
6633             {
6634                 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
6635                     handle.dsymbolSemantic(null);
6636             }
6637 
6638             Dsymbol vparent = exp.var.toParent();
6639             AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6640             if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6641                 exp.e1 = e1x;
6642             else
6643             {
6644                 /* Later checkRightThis will report correct error for invalid field variable access.
6645                  */
6646                 Expression e = new VarExp(exp.loc, exp.var);
6647                 e = e.expressionSemantic(sc);
6648                 result = e;
6649                 return;
6650             }
6651             checkAccess(exp.loc, sc, exp.e1, exp.var);
6652 
6653             VarDeclaration v = exp.var.isVarDeclaration();
6654             if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6655             {
6656                 Expression e = expandVar(WANTvalue, v);
6657                 if (e)
6658                 {
6659                     result = e;
6660                     return;
6661                 }
6662             }
6663 
6664             if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6665                       (!v.needThis() && v.semanticRun > PASS.initial)))  // fix https://issues.dlang.org/show_bug.cgi?id=17258
6666             {
6667                 // (e1, v)
6668                 checkAccess(exp.loc, sc, exp.e1, v);
6669                 Expression e = new VarExp(exp.loc, v);
6670                 e = new CommaExp(exp.loc, exp.e1, e);
6671                 e = e.expressionSemantic(sc);
6672                 result = e;
6673                 return;
6674             }
6675         }
6676         //printf("-DotVarExp::semantic('%s')\n", toChars());
6677         result = exp;
6678     }
6679 
visit(DotTemplateInstanceExp exp)6680     override void visit(DotTemplateInstanceExp exp)
6681     {
6682         static if (LOGSEMANTIC)
6683         {
6684             printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6685         }
6686         if (exp.type)
6687         {
6688             result = exp;
6689             return;
6690         }
6691         // Indicate we need to resolve by UFCS.
6692         Expression e = exp.semanticY(sc, 1);
6693         if (!e)
6694             e = resolveUFCSProperties(sc, exp);
6695         if (e is exp)
6696             e.type = Type.tvoid; // Unresolved type, because it needs inference
6697         result = e;
6698     }
6699 
visit(DelegateExp e)6700     override void visit(DelegateExp e)
6701     {
6702         static if (LOGSEMANTIC)
6703         {
6704             printf("DelegateExp::semantic('%s')\n", e.toChars());
6705         }
6706         if (e.type)
6707         {
6708             result = e;
6709             return;
6710         }
6711 
6712         e.e1 = e.e1.expressionSemantic(sc);
6713 
6714         e.type = new TypeDelegate(e.func.type.isTypeFunction());
6715         e.type = e.type.typeSemantic(e.loc, sc);
6716 
6717         FuncDeclaration f = e.func.toAliasFunc();
6718         AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
6719         if (f.needThis())
6720             e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6721         if (e.e1.op == EXP.error)
6722             return setError();
6723 
6724         /* A delegate takes the address of e.e1 in order to set the .ptr field
6725          * https://issues.dlang.org/show_bug.cgi?id=18575
6726          */
6727         if (global.params.useDIP1000 == FeatureState.enabled && e.e1.type.toBasetype().ty == Tstruct)
6728         {
6729             if (auto v = expToVariable(e.e1))
6730             {
6731                 if (!checkAddressVar(sc, e.e1, v))
6732                     return setError();
6733             }
6734         }
6735 
6736         if (f.type.ty == Tfunction)
6737         {
6738             TypeFunction tf = cast(TypeFunction)f.type;
6739             if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6740             {
6741                 OutBuffer thisBuf, funcBuf;
6742                 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6743                 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6744                 e.error("%smethod `%s` is not callable using a %s`%s`",
6745                     funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6746                 return setError();
6747             }
6748         }
6749         if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6750         {
6751             // A downcast is required for interfaces
6752             // https://issues.dlang.org/show_bug.cgi?id=3706
6753             e.e1 = new CastExp(e.loc, e.e1, ad.type);
6754             e.e1 = e.e1.expressionSemantic(sc);
6755         }
6756         result = e;
6757         // declare dual-context container
6758         if (f.hasDualContext() && !sc.intypeof && sc.func)
6759         {
6760             // check access to second `this`
6761             if (AggregateDeclaration ad2 = f.isMember2())
6762             {
6763                 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6764                 if (te.op != EXP.error)
6765                     te = getRightThis(e.loc, sc, ad2, te, f);
6766                 if (te.op == EXP.error)
6767                 {
6768                     e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6769                     return setError();
6770                 }
6771             }
6772             VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6773             e.vthis2 = vthis2;
6774             Expression de = new DeclarationExp(e.loc, vthis2);
6775             result = Expression.combine(de, result);
6776             result = result.expressionSemantic(sc);
6777         }
6778     }
6779 
visit(DotTypeExp exp)6780     override void visit(DotTypeExp exp)
6781     {
6782         static if (LOGSEMANTIC)
6783         {
6784             printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6785         }
6786         if (exp.type)
6787         {
6788             result = exp;
6789             return;
6790         }
6791 
6792         if (auto e = unaSemantic(exp, sc))
6793         {
6794             result = e;
6795             return;
6796         }
6797 
6798         exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6799         result = exp;
6800     }
6801 
visit(AddrExp exp)6802     override void visit(AddrExp exp)
6803     {
6804         static if (LOGSEMANTIC)
6805         {
6806             printf("AddrExp::semantic('%s')\n", exp.toChars());
6807         }
6808         if (exp.type)
6809         {
6810             result = exp;
6811             return;
6812         }
6813 
6814         if (Expression ex = unaSemantic(exp, sc))
6815         {
6816             result = ex;
6817             return;
6818         }
6819 
6820         if (sc.flags & SCOPE.Cfile)
6821         {
6822             /* Special handling for &"string"
6823              * since C regards a string literal as an lvalue
6824              */
6825             if (auto se = exp.e1.isStringExp())
6826             {
6827                 if (auto tp = se.type.toBasetype().isTypePointer())
6828                 {
6829                     /* Switch from pointer-to-char to pointer-to-static-array-of-char
6830                      */
6831                     auto ts = new TypeSArray(tp.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
6832                     se.type = typeSemantic(ts, Loc.initial, sc).pointerTo();
6833                     result = se;
6834                     return;
6835                 }
6836             }
6837         }
6838 
6839         int wasCond = exp.e1.op == EXP.question;
6840 
6841         if (exp.e1.op == EXP.dotTemplateInstance)
6842         {
6843             DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6844             TemplateInstance ti = dti.ti;
6845             {
6846                 //assert(ti.needsTypeInference(sc));
6847                 ti.dsymbolSemantic(sc);
6848                 if (!ti.inst || ti.errors) // if template failed to expand
6849                     return setError();
6850 
6851                 Dsymbol s = ti.toAlias();
6852                 FuncDeclaration f = s.isFuncDeclaration();
6853                 if (f)
6854                 {
6855                     exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6856                     exp.e1 = exp.e1.expressionSemantic(sc);
6857                 }
6858             }
6859         }
6860         else if (exp.e1.op == EXP.scope_)
6861         {
6862             TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6863             if (ti)
6864             {
6865                 //assert(ti.needsTypeInference(sc));
6866                 ti.dsymbolSemantic(sc);
6867                 if (!ti.inst || ti.errors) // if template failed to expand
6868                     return setError();
6869 
6870                 Dsymbol s = ti.toAlias();
6871                 FuncDeclaration f = s.isFuncDeclaration();
6872                 if (f)
6873                 {
6874                     exp.e1 = new VarExp(exp.e1.loc, f);
6875                     exp.e1 = exp.e1.expressionSemantic(sc);
6876                 }
6877             }
6878         }
6879         /* https://issues.dlang.org/show_bug.cgi?id=809
6880          *
6881          * If the address of a lazy variable is taken,
6882          * the expression is rewritten so that the type
6883          * of it is the delegate type. This means that
6884          * the symbol is not going to represent a call
6885          * to the delegate anymore, but rather, the
6886          * actual symbol.
6887          */
6888         if (auto ve = exp.e1.isVarExp())
6889         {
6890             if (ve.var.storage_class & STC.lazy_)
6891             {
6892                 exp.e1 = exp.e1.expressionSemantic(sc);
6893                 exp.e1 = resolveProperties(sc, exp.e1);
6894                 if (auto callExp = exp.e1.isCallExp())
6895                 {
6896                     if (callExp.e1.type.toBasetype().ty == Tdelegate)
6897                     {
6898                         /* https://issues.dlang.org/show_bug.cgi?id=20551
6899                          *
6900                          * Cannot take address of lazy parameter in @safe code
6901                          * because it might end up being a pointer to undefined
6902                          * memory.
6903                          */
6904                         if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6905                         {
6906                             exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
6907                                      ve.toChars(), sc.func.toChars());
6908                             setError();
6909                         }
6910                         else
6911                         {
6912                             VarExp ve2 = callExp.e1.isVarExp();
6913                             ve2.delegateWasExtracted = true;
6914                             ve2.var.storage_class |= STC.scope_;
6915                             result = ve2;
6916                         }
6917                         return;
6918                     }
6919                 }
6920             }
6921         }
6922 
6923         exp.e1 = exp.e1.toLvalue(sc, null);
6924         if (exp.e1.op == EXP.error)
6925         {
6926             result = exp.e1;
6927             return;
6928         }
6929         if (checkNonAssignmentArrayOp(exp.e1))
6930             return setError();
6931 
6932         if (!exp.e1.type)
6933         {
6934             exp.error("cannot take address of `%s`", exp.e1.toChars());
6935             return setError();
6936         }
6937         if (auto dve = exp.e1.isDotVarExp())
6938         {
6939             /* https://issues.dlang.org/show_bug.cgi?id=22749
6940              * Error about taking address of any bit-field, regardless of
6941              * whether SCOPE.Cfile is set.
6942              */
6943             if (auto bf = dve.var.isBitFieldDeclaration())
6944             {
6945                 exp.error("cannot take address of bit-field `%s`", bf.toChars());
6946                 return setError();
6947             }
6948         }
6949 
6950         bool hasOverloads;
6951         if (auto f = isFuncAddress(exp, &hasOverloads))
6952         {
6953             if (!hasOverloads && f.checkForwardRef(exp.loc))
6954                 return setError();
6955         }
6956         else if (!exp.e1.type.deco)
6957         {
6958             // try to resolve the type
6959             exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null);
6960             if (!exp.e1.type.deco)  // still couldn't resolve it
6961             {
6962                 if (auto ve = exp.e1.isVarExp())
6963                 {
6964                     Declaration d = ve.var;
6965                     exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
6966                 }
6967                 else
6968                     exp.error("forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
6969                 return setError();
6970             }
6971         }
6972 
6973         exp.type = exp.e1.type.pointerTo();
6974 
6975         // See if this should really be a delegate
6976         if (exp.e1.op == EXP.dotVariable)
6977         {
6978             DotVarExp dve = cast(DotVarExp)exp.e1;
6979             FuncDeclaration f = dve.var.isFuncDeclaration();
6980             if (f)
6981             {
6982                 f = f.toAliasFunc(); // FIXME, should see overloads
6983                                      // https://issues.dlang.org/show_bug.cgi?id=1983
6984                 if (!dve.hasOverloads)
6985                     f.tookAddressOf++;
6986 
6987                 Expression e;
6988                 if (f.needThis())
6989                     e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
6990                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
6991                     e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
6992                 e = e.expressionSemantic(sc);
6993                 result = e;
6994                 return;
6995             }
6996 
6997             // Look for misaligned pointer in @safe mode
6998             if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
6999                 return setError();
7000 
7001             if (global.params.useDIP1000 == FeatureState.enabled)
7002             {
7003                 if (VarDeclaration v = expToVariable(dve.e1))
7004                 {
7005                     if (!checkAddressVar(sc, exp.e1, v))
7006                         return setError();
7007                 }
7008             }
7009         }
7010         else if (exp.e1.op == EXP.variable)
7011         {
7012             VarExp ve = cast(VarExp)exp.e1;
7013             VarDeclaration v = ve.var.isVarDeclaration();
7014             if (v)
7015             {
7016                 if (!checkAddressVar(sc, exp.e1, v))
7017                     return setError();
7018 
7019                 ve.checkPurity(sc, v);
7020             }
7021             FuncDeclaration f = ve.var.isFuncDeclaration();
7022             if (f)
7023             {
7024                 /* Because nested functions cannot be overloaded,
7025                  * mark here that we took its address because castTo()
7026                  * may not be called with an exact match.
7027                  */
7028                 if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
7029                     f.tookAddressOf++;
7030                 if (f.isNested() && !f.needThis())
7031                 {
7032                     if (f.isFuncLiteralDeclaration())
7033                     {
7034                         if (!f.FuncDeclaration.isNested())
7035                         {
7036                             /* Supply a 'null' for a this pointer if no this is available
7037                              */
7038                             Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
7039                             e = e.expressionSemantic(sc);
7040                             result = e;
7041                             return;
7042                         }
7043                     }
7044                     Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
7045                     e = e.expressionSemantic(sc);
7046                     result = e;
7047                     return;
7048                 }
7049                 if (f.needThis())
7050                 {
7051                     if (hasThis(sc))
7052                     {
7053                         /* Should probably supply 'this' after overload resolution,
7054                          * not before.
7055                          */
7056                         Expression ethis = new ThisExp(exp.loc);
7057                         Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
7058                         e = e.expressionSemantic(sc);
7059                         result = e;
7060                         return;
7061                     }
7062                     if (sc.func && !sc.intypeof)
7063                     {
7064                         if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7065                         {
7066                             exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
7067                         }
7068                     }
7069                 }
7070             }
7071         }
7072         else if ((exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_) && global.params.useDIP1000 == FeatureState.enabled)
7073         {
7074             if (VarDeclaration v = expToVariable(exp.e1))
7075             {
7076                 if (!checkAddressVar(sc, exp.e1, v))
7077                     return setError();
7078             }
7079         }
7080         else if (auto ce = exp.e1.isCallExp())
7081         {
7082             if (!checkAddressCall(sc, ce, "take address of"))
7083                 return setError();
7084         }
7085         else if (exp.e1.op == EXP.index)
7086         {
7087             /* For:
7088              *   int[3] a;
7089              *   &a[i]
7090              * check 'a' the same as for a regular variable
7091              */
7092             if (VarDeclaration v = expToVariable(exp.e1))
7093             {
7094                 if (global.params.useDIP1000 == FeatureState.enabled && !checkAddressVar(sc, exp.e1, v))
7095                     return setError();
7096 
7097                 exp.e1.checkPurity(sc, v);
7098             }
7099         }
7100         else if (wasCond)
7101         {
7102             /* a ? b : c was transformed to *(a ? &b : &c), but we still
7103              * need to do safety checks
7104              */
7105             assert(exp.e1.op == EXP.star);
7106             PtrExp pe = cast(PtrExp)exp.e1;
7107             assert(pe.e1.op == EXP.question);
7108             CondExp ce = cast(CondExp)pe.e1;
7109             assert(ce.e1.op == EXP.address);
7110             assert(ce.e2.op == EXP.address);
7111 
7112             // Re-run semantic on the address expressions only
7113             ce.e1.type = null;
7114             ce.e1 = ce.e1.expressionSemantic(sc);
7115             ce.e2.type = null;
7116             ce.e2 = ce.e2.expressionSemantic(sc);
7117         }
7118         result = exp.optimize(WANTvalue);
7119     }
7120 
visit(PtrExp exp)7121     override void visit(PtrExp exp)
7122     {
7123         static if (LOGSEMANTIC)
7124         {
7125             printf("PtrExp::semantic('%s')\n", exp.toChars());
7126         }
7127         if (exp.type)
7128         {
7129             result = exp;
7130             return;
7131         }
7132 
7133         Expression e = exp.op_overload(sc);
7134         if (e)
7135         {
7136             result = e;
7137             return;
7138         }
7139 
7140         exp.e1 = exp.e1.arrayFuncConv(sc);
7141 
7142         Type tb = exp.e1.type.toBasetype();
7143         switch (tb.ty)
7144         {
7145         case Tpointer:
7146             exp.type = (cast(TypePointer)tb).next;
7147             break;
7148 
7149         case Tsarray:
7150         case Tarray:
7151             if (isNonAssignmentArrayOp(exp.e1))
7152                 goto default;
7153             exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
7154             exp.type = (cast(TypeArray)tb).next;
7155             exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
7156             break;
7157 
7158         case Terror:
7159             return setError();
7160 
7161         case Tnull:
7162             exp.type = Type.tnoreturn;  // typeof(*null) is bottom type
7163             break;
7164 
7165         default:
7166             exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
7167             goto case Terror;
7168         }
7169 
7170         if (exp.checkValue())
7171             return setError();
7172 
7173         result = exp;
7174     }
7175 
visit(NegExp exp)7176     override void visit(NegExp exp)
7177     {
7178         static if (LOGSEMANTIC)
7179         {
7180             printf("NegExp::semantic('%s')\n", exp.toChars());
7181         }
7182         if (exp.type)
7183         {
7184             result = exp;
7185             return;
7186         }
7187 
7188         Expression e = exp.op_overload(sc);
7189         if (e)
7190         {
7191             result = e;
7192             return;
7193         }
7194 
7195         fix16997(sc, exp);
7196         exp.type = exp.e1.type;
7197         Type tb = exp.type.toBasetype();
7198         if (tb.ty == Tarray || tb.ty == Tsarray)
7199         {
7200             if (!isArrayOpValid(exp.e1))
7201             {
7202                 result = arrayOpInvalidError(exp);
7203                 return;
7204             }
7205             result = exp;
7206             return;
7207         }
7208         if (!target.isVectorOpSupported(tb, exp.op))
7209         {
7210             result = exp.incompatibleTypes();
7211             return;
7212         }
7213         if (exp.e1.checkNoBool())
7214             return setError();
7215         if (exp.e1.checkArithmetic() ||
7216             exp.e1.checkSharedAccess(sc))
7217             return setError();
7218 
7219         result = exp;
7220     }
7221 
visit(UAddExp exp)7222     override void visit(UAddExp exp)
7223     {
7224         static if (LOGSEMANTIC)
7225         {
7226             printf("UAddExp::semantic('%s')\n", exp.toChars());
7227         }
7228         assert(!exp.type);
7229 
7230         Expression e = exp.op_overload(sc);
7231         if (e)
7232         {
7233             result = e;
7234             return;
7235         }
7236 
7237         fix16997(sc, exp);
7238         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
7239         {
7240             result = exp.incompatibleTypes();
7241             return;
7242         }
7243         if (exp.e1.checkNoBool())
7244             return setError();
7245         if (exp.e1.checkArithmetic())
7246             return setError();
7247         if (exp.e1.checkSharedAccess(sc))
7248             return setError();
7249 
7250         result = exp.e1;
7251     }
7252 
visit(ComExp exp)7253     override void visit(ComExp exp)
7254     {
7255         if (exp.type)
7256         {
7257             result = exp;
7258             return;
7259         }
7260 
7261         Expression e = exp.op_overload(sc);
7262         if (e)
7263         {
7264             result = e;
7265             return;
7266         }
7267 
7268         fix16997(sc, exp);
7269         exp.type = exp.e1.type;
7270         Type tb = exp.type.toBasetype();
7271         if (tb.ty == Tarray || tb.ty == Tsarray)
7272         {
7273             if (!isArrayOpValid(exp.e1))
7274             {
7275                 result = arrayOpInvalidError(exp);
7276                 return;
7277             }
7278             result = exp;
7279             return;
7280         }
7281         if (!target.isVectorOpSupported(tb, exp.op))
7282         {
7283             result = exp.incompatibleTypes();
7284             return;
7285         }
7286         if (exp.e1.checkNoBool())
7287             return setError();
7288         if (exp.e1.checkIntegral() ||
7289             exp.e1.checkSharedAccess(sc))
7290             return setError();
7291 
7292         result = exp;
7293     }
7294 
visit(NotExp e)7295     override void visit(NotExp e)
7296     {
7297         if (e.type)
7298         {
7299             result = e;
7300             return;
7301         }
7302 
7303         e.setNoderefOperand();
7304 
7305         // Note there is no operator overload
7306         if (Expression ex = unaSemantic(e, sc))
7307         {
7308             result = ex;
7309             return;
7310         }
7311 
7312         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7313         if (e.e1.op == EXP.type)
7314             e.e1 = resolveAliasThis(sc, e.e1);
7315 
7316         e.e1 = resolveProperties(sc, e.e1);
7317         e.e1 = e.e1.toBoolean(sc);
7318         if (e.e1.type == Type.terror)
7319         {
7320             result = e.e1;
7321             return;
7322         }
7323 
7324         if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7325         {
7326             result = e.incompatibleTypes();
7327         }
7328         // https://issues.dlang.org/show_bug.cgi?id=13910
7329         // Today NotExp can take an array as its operand.
7330         if (checkNonAssignmentArrayOp(e.e1))
7331             return setError();
7332 
7333         e.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
7334         result = e;
7335     }
7336 
visit(DeleteExp exp)7337     override void visit(DeleteExp exp)
7338     {
7339         // @@@DEPRECATED_2.109@@@
7340         // 1. Deprecated since 2.079
7341         // 2. Error since 2.099
7342         // 3. Removal of keyword, "delete" can be used for other identities
7343         if (!exp.isRAII)
7344         {
7345             error(exp.loc, "the `delete` keyword is obsolete");
7346             errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead");
7347             return setError();
7348         }
7349 
7350         Expression e = exp;
7351 
7352         if (Expression ex = unaSemantic(exp, sc))
7353         {
7354             result = ex;
7355             return;
7356         }
7357         exp.e1 = resolveProperties(sc, exp.e1);
7358         exp.e1 = exp.e1.modifiableLvalue(sc, null);
7359         if (exp.e1.op == EXP.error)
7360         {
7361             result = exp.e1;
7362             return;
7363         }
7364         exp.type = Type.tvoid;
7365 
7366         Type tb = exp.e1.type.toBasetype();
7367 
7368         /* Now that `delete` in user code is an error, we only get here when
7369          * `isRAII` has been set to true for the deletion of a `scope class`.  */
7370         if (tb.ty != Tclass)
7371         {
7372             exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7373             return setError();
7374         }
7375 
7376         ClassDeclaration cd = (cast(TypeClass)tb).sym;
7377         if (cd.isCOMinterface())
7378         {
7379             /* Because COM classes are deleted by IUnknown.Release()
7380              */
7381             exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7382             return setError();
7383         }
7384 
7385         bool err = false;
7386         if (cd.dtor)
7387         {
7388             err |= !cd.dtor.functionSemantic();
7389             err |= exp.checkPurity(sc, cd.dtor);
7390             err |= exp.checkSafety(sc, cd.dtor);
7391             err |= exp.checkNogc(sc, cd.dtor);
7392         }
7393         if (err)
7394             return setError();
7395 
7396         result = e;
7397     }
7398 
visit(CastExp exp)7399     override void visit(CastExp exp)
7400     {
7401         static if (LOGSEMANTIC)
7402         {
7403             printf("CastExp::semantic('%s')\n", exp.toChars());
7404         }
7405         //static int x; assert(++x < 10);
7406         if (exp.type)
7407         {
7408             result = exp;
7409             return;
7410         }
7411 
7412         if ((sc && sc.flags & SCOPE.Cfile) &&
7413             exp.to && (exp.to.ty == Tident || exp.to.ty == Tsarray) &&
7414             (exp.e1.op == EXP.address || exp.e1.op == EXP.star ||
7415              exp.e1.op == EXP.uadd || exp.e1.op == EXP.negate))
7416         {
7417             /* Ambiguous cases arise from CParser if type-name is just an identifier.
7418              *   ( identifier ) cast-expression
7419              *   ( identifier [expression]) cast-expression
7420              * If we determine that `identifier` is a variable, and cast-expression
7421              * is one of the unary operators (& * + -), then rewrite this cast
7422              * as a binary expression.
7423              */
7424             Loc loc = exp.loc;
7425             Type t;
7426             Expression e;
7427             Dsymbol s;
7428             exp.to.resolve(loc, sc, e, t, s);
7429             if (e !is null)
7430             {
7431                 if (auto ex = exp.e1.isAddrExp())       // (ident) &exp -> (ident & exp)
7432                     result = new AndExp(loc, e, ex.e1);
7433                 else if (auto ex = exp.e1.isPtrExp())   // (ident) *exp -> (ident * exp)
7434                     result = new MulExp(loc, e, ex.e1);
7435                 else if (auto ex = exp.e1.isUAddExp())  // (ident) +exp -> (ident + exp)
7436                     result = new AddExp(loc, e, ex.e1);
7437                 else if (auto ex = exp.e1.isNegExp())   // (ident) -exp -> (ident - exp)
7438                     result = new MinExp(loc, e, ex.e1);
7439 
7440                 assert(result);
7441                 result = result.expressionSemantic(sc);
7442                 return;
7443             }
7444         }
7445 
7446         if (exp.to)
7447         {
7448             exp.to = exp.to.typeSemantic(exp.loc, sc);
7449             if (exp.to == Type.terror)
7450                 return setError();
7451 
7452             if (!exp.to.hasPointers())
7453                 exp.setNoderefOperand();
7454 
7455             // When e1 is a template lambda, this cast may instantiate it with
7456             // the type 'to'.
7457             exp.e1 = inferType(exp.e1, exp.to);
7458         }
7459 
7460         if (auto e = unaSemantic(exp, sc))
7461         {
7462             result = e;
7463             return;
7464         }
7465 
7466         if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
7467             exp.e1 = exp.e1.arrayFuncConv(sc);
7468 
7469         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7470         if (exp.e1.op == EXP.type)
7471             exp.e1 = resolveAliasThis(sc, exp.e1);
7472 
7473         auto e1x = resolveProperties(sc, exp.e1);
7474         if (e1x.op == EXP.error)
7475         {
7476             result = e1x;
7477             return;
7478         }
7479         if (e1x.checkType())
7480             return setError();
7481         exp.e1 = e1x;
7482 
7483         if (!exp.e1.type)
7484         {
7485             exp.error("cannot cast `%s`", exp.e1.toChars());
7486             return setError();
7487         }
7488 
7489         // https://issues.dlang.org/show_bug.cgi?id=19954
7490         if (exp.e1.type.ty == Ttuple)
7491         {
7492             if (exp.to)
7493             {
7494                 if (TypeTuple tt = exp.to.isTypeTuple())
7495                 {
7496                     if (exp.e1.type.implicitConvTo(tt))
7497                     {
7498                         result = exp.e1.castTo(sc, tt);
7499                         return;
7500                     }
7501                 }
7502             }
7503             TupleExp te = exp.e1.isTupleExp();
7504             if (te.exps.dim == 1)
7505                 exp.e1 = (*te.exps)[0];
7506         }
7507 
7508         // only allow S(x) rewrite if cast specified S explicitly.
7509         // See https://issues.dlang.org/show_bug.cgi?id=18545
7510         const bool allowImplicitConstruction = exp.to !is null;
7511 
7512         if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7513         {
7514             exp.to = exp.e1.type.castMod(exp.mod);
7515             exp.to = exp.to.typeSemantic(exp.loc, sc);
7516 
7517             if (exp.to == Type.terror)
7518                 return setError();
7519         }
7520 
7521         if (exp.to.ty == Ttuple)
7522         {
7523             exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
7524             return setError();
7525         }
7526 
7527         // cast(void) is used to mark e1 as unused, so it is safe
7528         if (exp.to.ty == Tvoid)
7529         {
7530             exp.type = exp.to;
7531             result = exp;
7532             return;
7533         }
7534 
7535         if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7536         {
7537             if (Expression e = exp.op_overload(sc))
7538             {
7539                 result = e.implicitCastTo(sc, exp.to);
7540                 return;
7541             }
7542         }
7543 
7544         Type t1b = exp.e1.type.toBasetype();
7545         Type tob = exp.to.toBasetype();
7546 
7547         if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7548         {
7549             /* Look to replace:
7550              *  cast(S)t
7551              * with:
7552              *  S(t)
7553              */
7554 
7555             // Rewrite as to.call(e1)
7556             Expression e = new TypeExp(exp.loc, exp.to);
7557             e = new CallExp(exp.loc, e, exp.e1);
7558             e = e.trySemantic(sc);
7559             if (e)
7560             {
7561                 result = e;
7562                 return;
7563             }
7564         }
7565 
7566         if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7567         {
7568             if (checkNonAssignmentArrayOp(exp.e1))
7569                 return setError();
7570         }
7571 
7572         // Look for casting to a vector type
7573         if (tob.ty == Tvector && t1b.ty != Tvector)
7574         {
7575             result = new VectorExp(exp.loc, exp.e1, exp.to);
7576             result = result.expressionSemantic(sc);
7577             return;
7578         }
7579 
7580         Expression ex = exp.e1.castTo(sc, exp.to);
7581         if (ex.op == EXP.error)
7582         {
7583             result = ex;
7584             return;
7585         }
7586 
7587         // Check for unsafe casts
7588         if (!sc.intypeof &&
7589             !(sc.flags & SCOPE.debug_) &&
7590             !isSafeCast(ex, t1b, tob) &&
7591             (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe()))
7592         {
7593             exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
7594             return setError();
7595         }
7596 
7597         // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7598         // to handle certain casts.  Those casts which `object.__ArrayCast` does not support are filtered out.
7599         // See `e2ir.toElemCast` for other types of casts.  If `object.__ArrayCast` is improved to support more
7600         // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7601         if (tob.ty == Tarray)
7602         {
7603             // https://issues.dlang.org/show_bug.cgi?id=19840
7604             if (auto ad = isAggregate(t1b))
7605             {
7606                 if (ad.aliasthis)
7607                 {
7608                     Expression e = resolveAliasThis(sc, exp.e1);
7609                     e = new CastExp(exp.loc, e, exp.to);
7610                     result = e.expressionSemantic(sc);
7611                     return;
7612                 }
7613             }
7614 
7615             if(t1b.ty == Tarray && exp.e1.op != EXP.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7616             {
7617                 auto tFrom = t1b.nextOf();
7618                 auto tTo = tob.nextOf();
7619 
7620                 // https://issues.dlang.org/show_bug.cgi?id=20130
7621                 if (exp.e1.op != EXP.string_ || !ex.isStringExp)
7622                 {
7623                     const uint fromSize = cast(uint)tFrom.size();
7624                     const uint toSize = cast(uint)tTo.size();
7625                     if (fromSize == SIZE_INVALID || toSize == SIZE_INVALID)
7626                         return setError();
7627 
7628                     // If array element sizes do not match, we must adjust the dimensions
7629                     if (fromSize != toSize)
7630                     {
7631                         if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7632                             return setError();
7633 
7634                         // A runtime check is needed in case arrays don't line up.  That check should
7635                         // be done in the implementation of `object.__ArrayCast`
7636                         if (toSize == 0 || (fromSize % toSize) != 0)
7637                         {
7638                             // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7639 
7640                             // fully qualify as `object.__ArrayCast`
7641                             Expression id = new IdentifierExp(exp.loc, Id.empty);
7642                             auto dotid = new DotIdExp(exp.loc, id, Id.object);
7643 
7644                             auto tiargs = new Objects();
7645                             tiargs.push(tFrom);
7646                             tiargs.push(tTo);
7647                             auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7648 
7649                             auto arguments = new Expressions();
7650                             arguments.push(exp.e1);
7651                             Expression ce = new CallExp(exp.loc, dt, arguments);
7652 
7653                             result = expressionSemantic(ce, sc);
7654                             return;
7655                         }
7656                     }
7657                 }
7658             }
7659         }
7660 
7661         if (sc && sc.flags & SCOPE.Cfile)
7662         {
7663             /* C11 6.5.4-5: A cast does not yield an lvalue.
7664              * So ensure that castTo does not strip away the cast so that this
7665              * can be enforced in other semantic visitor methods.
7666              */
7667             if (!ex.isCastExp())
7668             {
7669                 ex = new CastExp(exp.loc, ex, exp.to);
7670                 ex.type = exp.to;
7671             }
7672         }
7673         result = ex;
7674     }
7675 
visit(VectorExp exp)7676     override void visit(VectorExp exp)
7677     {
7678         static if (LOGSEMANTIC)
7679         {
7680             printf("VectorExp::semantic('%s')\n", exp.toChars());
7681         }
7682         if (exp.type)
7683         {
7684             result = exp;
7685             return;
7686         }
7687 
7688         exp.e1 = exp.e1.expressionSemantic(sc);
7689         exp.type = exp.to.typeSemantic(exp.loc, sc);
7690         if (exp.e1.op == EXP.error || exp.type.ty == Terror)
7691         {
7692             result = exp.e1;
7693             return;
7694         }
7695 
7696         Type tb = exp.type.toBasetype();
7697         assert(tb.ty == Tvector);
7698         TypeVector tv = cast(TypeVector)tb;
7699         Type te = tv.elementType();
7700         exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7701 
7702         bool checkElem(Expression elem)
7703         {
7704             if (elem.isConst() == 1)
7705                 return false;
7706 
7707              exp.error("constant expression expected, not `%s`", elem.toChars());
7708              return true;
7709         }
7710 
7711         exp.e1 = exp.e1.optimize(WANTvalue);
7712         bool res;
7713         if (exp.e1.op == EXP.arrayLiteral)
7714         {
7715             foreach (i; 0 .. exp.dim)
7716             {
7717                 // Do not stop on first error - check all AST nodes even if error found
7718                 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7719             }
7720         }
7721         else if (exp.e1.type.ty == Tvoid)
7722             checkElem(exp.e1);
7723 
7724         result = res ? ErrorExp.get() : exp;
7725     }
7726 
visit(VectorArrayExp e)7727     override void visit(VectorArrayExp e)
7728     {
7729         static if (LOGSEMANTIC)
7730         {
7731             printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7732         }
7733         if (!e.type)
7734         {
7735             unaSemantic(e, sc);
7736             e.e1 = resolveProperties(sc, e.e1);
7737 
7738             if (e.e1.op == EXP.error)
7739             {
7740                 result = e.e1;
7741                 return;
7742             }
7743             assert(e.e1.type.ty == Tvector);
7744             e.type = e.e1.type.isTypeVector().basetype;
7745         }
7746         result = e;
7747     }
7748 
visit(SliceExp exp)7749     override void visit(SliceExp exp)
7750     {
7751         static if (LOGSEMANTIC)
7752         {
7753             printf("SliceExp::semantic('%s')\n", exp.toChars());
7754         }
7755         if (exp.type)
7756         {
7757             result = exp;
7758             return;
7759         }
7760 
7761         // operator overloading should be handled in ArrayExp already.
7762         if (Expression ex = unaSemantic(exp, sc))
7763         {
7764             result = ex;
7765             return;
7766         }
7767         exp.e1 = resolveProperties(sc, exp.e1);
7768         if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
7769         {
7770             if (exp.lwr || exp.upr)
7771             {
7772                 exp.error("cannot slice type `%s`", exp.e1.toChars());
7773                 return setError();
7774             }
7775             Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7776             result = e.expressionSemantic(sc);
7777             return;
7778         }
7779         if (!exp.lwr && !exp.upr)
7780         {
7781             if (exp.e1.op == EXP.arrayLiteral)
7782             {
7783                 // Convert [a,b,c][] to [a,b,c]
7784                 Type t1b = exp.e1.type.toBasetype();
7785                 Expression e = exp.e1;
7786                 if (t1b.ty == Tsarray)
7787                 {
7788                     e = e.copy();
7789                     e.type = t1b.nextOf().arrayOf();
7790                 }
7791                 result = e;
7792                 return;
7793             }
7794             if (exp.e1.op == EXP.slice)
7795             {
7796                 // Convert e[][] to e[]
7797                 SliceExp se = cast(SliceExp)exp.e1;
7798                 if (!se.lwr && !se.upr)
7799                 {
7800                     result = se;
7801                     return;
7802                 }
7803             }
7804             if (isArrayOpOperand(exp.e1))
7805             {
7806                 // Convert (a[]+b[])[] to a[]+b[]
7807                 result = exp.e1;
7808                 return;
7809             }
7810         }
7811         if (exp.e1.op == EXP.error)
7812         {
7813             result = exp.e1;
7814             return;
7815         }
7816         if (exp.e1.type.ty == Terror)
7817             return setError();
7818 
7819         Type t1b = exp.e1.type.toBasetype();
7820         if (auto tp = t1b.isTypePointer())
7821         {
7822             if (t1b.isPtrToFunction())
7823             {
7824                 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7825                 return setError();
7826             }
7827             if (!exp.lwr || !exp.upr)
7828             {
7829                 exp.error("upper and lower bounds are needed to slice a pointer");
7830                 if (auto ad = isAggregate(tp.next.toBasetype()))
7831                 {
7832                     auto s = search_function(ad, Id.index);
7833                     if (!s) s = search_function(ad, Id.slice);
7834                     if (s)
7835                     {
7836                         auto fd = s.isFuncDeclaration();
7837                         if ((fd && !fd.getParameterList().length) || s.isTemplateDeclaration())
7838                         {
7839                             exp.errorSupplemental(
7840                                 "pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`",
7841                                 exp.e1.toChars(),
7842                                 s.ident.toChars(),
7843                                 exp.e1.toChars()
7844                             );
7845                         }
7846 
7847                     }
7848                 }
7849 
7850                 return setError();
7851             }
7852             if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7853             {
7854                 exp.error("pointer slicing not allowed in safe functions");
7855                 return setError();
7856             }
7857         }
7858         else if (t1b.ty == Tarray)
7859         {
7860         }
7861         else if (t1b.ty == Tsarray)
7862         {
7863             if (!exp.arrayop && global.params.useDIP1000 == FeatureState.enabled)
7864             {
7865                 /* Slicing a static array is like taking the address of it.
7866                  * Perform checks as if e[] was &e
7867                  */
7868                 if (VarDeclaration v = expToVariable(exp.e1))
7869                 {
7870                     if (DotVarExp dve = exp.e1.isDotVarExp())
7871                     {
7872 
7873                         if ((dve.e1.op == EXP.this_ || dve.e1.op == EXP.super_) &&
7874                             !(v.storage_class & STC.ref_))
7875                         {
7876                             // because it's a class
7877                             v = null;
7878                         }
7879                     }
7880 
7881                     if (v && !checkAddressVar(sc, exp.e1, v))
7882                         return setError();
7883                 }
7884                 // https://issues.dlang.org/show_bug.cgi?id=22539
7885                 if (auto ce = exp.e1.isCallExp())
7886                 {
7887                     if (!checkAddressCall(sc, ce, "slice static array of"))
7888                         return setError();
7889                 }
7890             }
7891         }
7892         else if (t1b.ty == Ttuple)
7893         {
7894             if (!exp.lwr && !exp.upr)
7895             {
7896                 result = exp.e1;
7897                 return;
7898             }
7899             if (!exp.lwr || !exp.upr)
7900             {
7901                 exp.error("need upper and lower bound to slice tuple");
7902                 return setError();
7903             }
7904         }
7905         else if (t1b.ty == Tvector)
7906         {
7907             // Convert e1 to corresponding static array
7908             TypeVector tv1 = cast(TypeVector)t1b;
7909             t1b = tv1.basetype;
7910             t1b = t1b.castMod(tv1.mod);
7911             exp.e1.type = t1b;
7912         }
7913         else
7914         {
7915             exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7916             return setError();
7917         }
7918 
7919         /* Run semantic on lwr and upr.
7920          */
7921         Scope* scx = sc;
7922         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7923         {
7924             // Create scope for 'length' variable
7925             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7926             sym.parent = sc.scopesym;
7927             sc = sc.push(sym);
7928         }
7929         if (exp.lwr)
7930         {
7931             if (t1b.ty == Ttuple)
7932                 sc = sc.startCTFE();
7933             exp.lwr = exp.lwr.expressionSemantic(sc);
7934             exp.lwr = resolveProperties(sc, exp.lwr);
7935             if (t1b.ty == Ttuple)
7936                 sc = sc.endCTFE();
7937             exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7938         }
7939         if (exp.upr)
7940         {
7941             if (t1b.ty == Ttuple)
7942                 sc = sc.startCTFE();
7943             exp.upr = exp.upr.expressionSemantic(sc);
7944             exp.upr = resolveProperties(sc, exp.upr);
7945             if (t1b.ty == Ttuple)
7946                 sc = sc.endCTFE();
7947             exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7948         }
7949         if (sc != scx)
7950             sc = sc.pop();
7951         if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7952             return setError();
7953 
7954         if (t1b.ty == Ttuple)
7955         {
7956             exp.lwr = exp.lwr.ctfeInterpret();
7957             exp.upr = exp.upr.ctfeInterpret();
7958             uinteger_t i1 = exp.lwr.toUInteger();
7959             uinteger_t i2 = exp.upr.toUInteger();
7960 
7961             TupleExp te;
7962             TypeTuple tup;
7963             size_t length;
7964             if (exp.e1.op == EXP.tuple) // slicing an expression tuple
7965             {
7966                 te = cast(TupleExp)exp.e1;
7967                 tup = null;
7968                 length = te.exps.dim;
7969             }
7970             else if (exp.e1.op == EXP.type) // slicing a type tuple
7971             {
7972                 te = null;
7973                 tup = cast(TypeTuple)t1b;
7974                 length = Parameter.dim(tup.arguments);
7975             }
7976             else
7977                 assert(0);
7978 
7979             if (i2 < i1 || length < i2)
7980             {
7981                 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7982                 return setError();
7983             }
7984 
7985             size_t j1 = cast(size_t)i1;
7986             size_t j2 = cast(size_t)i2;
7987             Expression e;
7988             if (exp.e1.op == EXP.tuple)
7989             {
7990                 auto exps = new Expressions(j2 - j1);
7991                 for (size_t i = 0; i < j2 - j1; i++)
7992                 {
7993                     (*exps)[i] = (*te.exps)[j1 + i];
7994                 }
7995                 e = new TupleExp(exp.loc, te.e0, exps);
7996             }
7997             else
7998             {
7999                 auto args = new Parameters();
8000                 args.reserve(j2 - j1);
8001                 for (size_t i = j1; i < j2; i++)
8002                 {
8003                     Parameter arg = Parameter.getNth(tup.arguments, i);
8004                     args.push(arg);
8005                 }
8006                 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
8007             }
8008             e = e.expressionSemantic(sc);
8009             result = e;
8010             return;
8011         }
8012 
8013         exp.type = t1b.nextOf().arrayOf();
8014         // Allow typedef[] -> typedef[]
8015         if (exp.type.equals(t1b))
8016             exp.type = exp.e1.type;
8017 
8018         // We might know $ now
8019         setLengthVarIfKnown(exp.lengthVar, t1b);
8020 
8021         if (exp.lwr && exp.upr)
8022         {
8023             exp.lwr = exp.lwr.optimize(WANTvalue);
8024             exp.upr = exp.upr.optimize(WANTvalue);
8025 
8026             IntRange lwrRange = getIntRange(exp.lwr);
8027             IntRange uprRange = getIntRange(exp.upr);
8028 
8029             if (t1b.ty == Tsarray || t1b.ty == Tarray)
8030             {
8031                 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8032                 el = el.expressionSemantic(sc);
8033                 el = el.optimize(WANTvalue);
8034                 if (el.op == EXP.int64 && t1b.ty == Tsarray)
8035                 {
8036                     // Array length is known at compile-time. Upper is in bounds if it fits length.
8037                     dinteger_t length = el.toInteger();
8038                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
8039                     exp.upperIsInBounds = bounds.contains(uprRange);
8040                     if (exp.lwr.op == EXP.int64 && exp.upr.op == EXP.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
8041                     {
8042                         exp.error("in slice `%s[%llu .. %llu]`, lower bound is greater than upper bound", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger());
8043                         return setError();
8044                     }
8045                     if (exp.upr.op == EXP.int64 && exp.upr.toInteger() > length)
8046                     {
8047                         exp.error("in slice `%s[%llu .. %llu]`, upper bound is greater than array length `%llu`", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger(), length);
8048                         return setError();
8049                     }
8050                 }
8051                 else if (exp.upr.op == EXP.int64 && exp.upr.toInteger() == 0)
8052                 {
8053                     // Upper slice expression is '0'. Value is always in bounds.
8054                     exp.upperIsInBounds = true;
8055                 }
8056                 else if (exp.upr.op == EXP.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
8057                 {
8058                     // Upper slice expression is '$'. Value is always in bounds.
8059                     exp.upperIsInBounds = true;
8060                 }
8061             }
8062             else if (t1b.ty == Tpointer)
8063             {
8064                 exp.upperIsInBounds = true;
8065             }
8066             else
8067                 assert(0);
8068 
8069             exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
8070 
8071             //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
8072         }
8073 
8074         result = exp;
8075     }
8076 
visit(ArrayLengthExp e)8077     override void visit(ArrayLengthExp e)
8078     {
8079         static if (LOGSEMANTIC)
8080         {
8081             printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
8082         }
8083         if (e.type)
8084         {
8085             result = e;
8086             return;
8087         }
8088 
8089         if (Expression ex = unaSemantic(e, sc))
8090         {
8091             result = ex;
8092             return;
8093         }
8094         e.e1 = resolveProperties(sc, e.e1);
8095 
8096         e.type = Type.tsize_t;
8097         result = e;
8098     }
8099 
visit(ArrayExp exp)8100     override void visit(ArrayExp exp)
8101     {
8102         static if (LOGSEMANTIC)
8103         {
8104             printf("ArrayExp::semantic('%s')\n", exp.toChars());
8105         }
8106         assert(!exp.type);
8107 
8108         if (sc.flags & SCOPE.Cfile)
8109         {
8110             /* See if need to rewrite the AST because of cast/call ambiguity
8111              */
8112             if (auto e = castCallAmbiguity(exp, sc))
8113             {
8114                 result = expressionSemantic(e, sc);
8115                 return;
8116             }
8117         }
8118 
8119         result = exp.carraySemantic(sc);  // C semantics
8120         if (result)
8121             return;
8122 
8123         Expression e = exp.op_overload(sc);
8124         if (e)
8125         {
8126             result = e;
8127             return;
8128         }
8129 
8130         if (isAggregate(exp.e1.type))
8131             exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
8132         else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8133             exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
8134         else if (isIndexableNonAggregate(exp.e1.type))
8135             exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
8136         else
8137             exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
8138 
8139         result = ErrorExp.get();
8140     }
8141 
visit(DotExp exp)8142     override void visit(DotExp exp)
8143     {
8144         static if (LOGSEMANTIC)
8145         {
8146             printf("DotExp::semantic('%s')\n", exp.toChars());
8147             if (exp.type)
8148                 printf("\ttype = %s\n", exp.type.toChars());
8149         }
8150         exp.e1 = exp.e1.expressionSemantic(sc);
8151         exp.e2 = exp.e2.expressionSemantic(sc);
8152 
8153         if (exp.e1.op == EXP.type)
8154         {
8155             result = exp.e2;
8156             return;
8157         }
8158         if (exp.e2.op == EXP.type)
8159         {
8160             result = exp.e2;
8161             return;
8162         }
8163         if (auto te = exp.e2.isTemplateExp())
8164         {
8165             Expression e = new DotTemplateExp(exp.loc, exp.e1, te.td);
8166             result = e.expressionSemantic(sc);
8167             return;
8168         }
8169         if (!exp.type)
8170             exp.type = exp.e2.type;
8171         result = exp;
8172     }
8173 
visit(CommaExp e)8174     override void visit(CommaExp e)
8175     {
8176         //printf("Semantic.CommaExp() %s\n", e.toChars());
8177         if (e.type)
8178         {
8179             result = e;
8180             return;
8181         }
8182 
8183         // Allow `((a,b),(x,y))`
8184         if (e.allowCommaExp)
8185         {
8186             CommaExp.allow(e.e1);
8187             CommaExp.allow(e.e2);
8188         }
8189 
8190         if (Expression ex = binSemanticProp(e, sc))
8191         {
8192             result = ex;
8193             return;
8194         }
8195         e.e1 = e.e1.addDtorHook(sc);
8196 
8197         if (checkNonAssignmentArrayOp(e.e1))
8198             return setError();
8199 
8200         // Comma expressions trigger this conversion
8201         e.e2 = e.e2.arrayFuncConv(sc);
8202 
8203         e.type = e.e2.type;
8204         result = e;
8205 
8206         if (sc.flags & SCOPE.Cfile)
8207             return;
8208 
8209         if (e.type is Type.tvoid)
8210         {
8211             checkMustUse(e.e1, sc);
8212             discardValue(e.e1);
8213         }
8214         else if (!e.allowCommaExp && !e.isGenerated)
8215             e.error("Using the result of a comma expression is not allowed");
8216     }
8217 
visit(IntervalExp e)8218     override void visit(IntervalExp e)
8219     {
8220         static if (LOGSEMANTIC)
8221         {
8222             printf("IntervalExp::semantic('%s')\n", e.toChars());
8223         }
8224         if (e.type)
8225         {
8226             result = e;
8227             return;
8228         }
8229 
8230         Expression le = e.lwr;
8231         le = le.expressionSemantic(sc);
8232         le = resolveProperties(sc, le);
8233 
8234         Expression ue = e.upr;
8235         ue = ue.expressionSemantic(sc);
8236         ue = resolveProperties(sc, ue);
8237 
8238         if (le.op == EXP.error)
8239         {
8240             result = le;
8241             return;
8242         }
8243         if (ue.op == EXP.error)
8244         {
8245             result = ue;
8246             return;
8247         }
8248 
8249         e.lwr = le;
8250         e.upr = ue;
8251 
8252         e.type = Type.tvoid;
8253         result = e;
8254     }
8255 
visit(DelegatePtrExp e)8256     override void visit(DelegatePtrExp e)
8257     {
8258         static if (LOGSEMANTIC)
8259         {
8260             printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
8261         }
8262         if (!e.type)
8263         {
8264             unaSemantic(e, sc);
8265             e.e1 = resolveProperties(sc, e.e1);
8266 
8267             if (e.e1.op == EXP.error)
8268             {
8269                 result = e.e1;
8270                 return;
8271             }
8272             e.type = Type.tvoidptr;
8273         }
8274         result = e;
8275     }
8276 
visit(DelegateFuncptrExp e)8277     override void visit(DelegateFuncptrExp e)
8278     {
8279         static if (LOGSEMANTIC)
8280         {
8281             printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
8282         }
8283         if (!e.type)
8284         {
8285             unaSemantic(e, sc);
8286             e.e1 = resolveProperties(sc, e.e1);
8287             if (e.e1.op == EXP.error)
8288             {
8289                 result = e.e1;
8290                 return;
8291             }
8292             e.type = e.e1.type.nextOf().pointerTo();
8293         }
8294         result = e;
8295     }
8296 
visit(IndexExp exp)8297     override void visit(IndexExp exp)
8298     {
8299         static if (LOGSEMANTIC)
8300         {
8301             printf("IndexExp::semantic('%s')\n", exp.toChars());
8302         }
8303         if (exp.type)
8304         {
8305             result = exp;
8306             return;
8307         }
8308 
8309         // operator overloading should be handled in ArrayExp already.
8310         if (!exp.e1.type)
8311             exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
8312         assert(exp.e1.type); // semantic() should already be run on it
8313         if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8314         {
8315             exp.e2 = exp.e2.expressionSemantic(sc);
8316             exp.e2 = resolveProperties(sc, exp.e2);
8317             Type nt;
8318             if (exp.e2.op == EXP.type)
8319                 nt = new TypeAArray(exp.e1.type, exp.e2.type);
8320             else
8321                 nt = new TypeSArray(exp.e1.type, exp.e2);
8322             Expression e = new TypeExp(exp.loc, nt);
8323             result = e.expressionSemantic(sc);
8324             return;
8325         }
8326         if (exp.e1.op == EXP.error)
8327         {
8328             result = exp.e1;
8329             return;
8330         }
8331         if (exp.e1.type.ty == Terror)
8332             return setError();
8333 
8334         // Note that unlike C we do not implement the int[ptr]
8335 
8336         Type t1b = exp.e1.type.toBasetype();
8337 
8338         if (t1b.ty == Tvector)
8339         {
8340             // Convert e1 to corresponding static array
8341             TypeVector tv1 = cast(TypeVector)t1b;
8342             t1b = tv1.basetype;
8343             t1b = t1b.castMod(tv1.mod);
8344             exp.e1.type = t1b;
8345         }
8346 
8347         /* Run semantic on e2
8348          */
8349         Scope* scx = sc;
8350         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
8351         {
8352             // Create scope for 'length' variable
8353             ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
8354             sym.parent = sc.scopesym;
8355             sc = sc.push(sym);
8356         }
8357         if (t1b.ty == Ttuple)
8358             sc = sc.startCTFE();
8359         exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
8360         exp.e2 = resolveProperties(sc, exp.e2);
8361         if (t1b.ty == Ttuple)
8362             sc = sc.endCTFE();
8363         if (exp.e2.op == EXP.tuple)
8364         {
8365             TupleExp te = cast(TupleExp)exp.e2;
8366             if (te.exps && te.exps.dim == 1)
8367                 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
8368         }
8369         if (sc != scx)
8370             sc = sc.pop();
8371         if (exp.e2.type == Type.terror)
8372             return setError();
8373 
8374         if (checkNonAssignmentArrayOp(exp.e1))
8375             return setError();
8376 
8377         switch (t1b.ty)
8378         {
8379         case Tpointer:
8380             if (t1b.isPtrToFunction())
8381             {
8382                 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
8383                 return setError();
8384             }
8385             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8386             if (exp.e2.type == Type.terror)
8387                 return setError();
8388             exp.e2 = exp.e2.optimize(WANTvalue);
8389             if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
8390             {
8391             }
8392             else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
8393             {
8394                 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
8395                 return setError();
8396             }
8397             exp.type = (cast(TypeNext)t1b).next;
8398             break;
8399 
8400         case Tarray:
8401             exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8402             if (exp.e2.type == Type.terror)
8403                 return setError();
8404             exp.type = (cast(TypeNext)t1b).next;
8405             break;
8406 
8407         case Tsarray:
8408             {
8409                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8410                 if (exp.e2.type == Type.terror)
8411                     return setError();
8412                 exp.type = t1b.nextOf();
8413                 break;
8414             }
8415         case Taarray:
8416             {
8417                 TypeAArray taa = cast(TypeAArray)t1b;
8418                 /* We can skip the implicit conversion if they differ only by
8419                  * constness
8420                  * https://issues.dlang.org/show_bug.cgi?id=2684
8421                  * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8422                  */
8423                 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8424                 {
8425                     exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8426                     if (exp.e2.type == Type.terror)
8427                         return setError();
8428                 }
8429 
8430                 semanticTypeInfo(sc, taa);
8431 
8432                 exp.type = taa.next;
8433                 break;
8434             }
8435         case Ttuple:
8436             {
8437                 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8438                 if (exp.e2.type == Type.terror)
8439                     return setError();
8440 
8441                 exp.e2 = exp.e2.ctfeInterpret();
8442                 uinteger_t index = exp.e2.toUInteger();
8443 
8444                 TupleExp te;
8445                 TypeTuple tup;
8446                 size_t length;
8447                 if (exp.e1.op == EXP.tuple)
8448                 {
8449                     te = cast(TupleExp)exp.e1;
8450                     tup = null;
8451                     length = te.exps.dim;
8452                 }
8453                 else if (exp.e1.op == EXP.type)
8454                 {
8455                     te = null;
8456                     tup = cast(TypeTuple)t1b;
8457                     length = Parameter.dim(tup.arguments);
8458                 }
8459                 else
8460                     assert(0);
8461 
8462                 if (length <= index)
8463                 {
8464                     exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8465                     return setError();
8466                 }
8467                 Expression e;
8468                 if (exp.e1.op == EXP.tuple)
8469                 {
8470                     e = (*te.exps)[cast(size_t)index];
8471                     e = Expression.combine(te.e0, e);
8472                 }
8473                 else
8474                     e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8475                 result = e;
8476                 return;
8477             }
8478         default:
8479             exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8480             return setError();
8481         }
8482 
8483         // We might know $ now
8484         setLengthVarIfKnown(exp.lengthVar, t1b);
8485 
8486         if (t1b.ty == Tsarray || t1b.ty == Tarray)
8487         {
8488             Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8489             el = el.expressionSemantic(sc);
8490             el = el.optimize(WANTvalue);
8491             if (el.op == EXP.int64)
8492             {
8493                 exp.e2 = exp.e2.optimize(WANTvalue);
8494                 dinteger_t length = el.toInteger();
8495                 if (length)
8496                 {
8497                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8498                     // OR it in, because it might already be set for C array indexing
8499                     exp.indexIsInBounds |= bounds.contains(getIntRange(exp.e2));
8500                 }
8501                 else if (sc.flags & SCOPE.Cfile && t1b.ty == Tsarray)
8502                 {
8503                     if (auto ve = exp.e1.isVarExp())
8504                     {
8505                         /* Rewrite 0-length C array ve[exp.e2] as *(ve + exp.e2)
8506                          */
8507                         auto vp = ve.castTo(sc, t1b.isTypeSArray().next.pointerTo());
8508                         auto e = new AddExp(exp.loc, vp, exp.e2);
8509                         auto pe = new PtrExp(exp.loc, e);
8510                         result = pe.expressionSemantic(sc).optimize(WANTvalue);
8511                         return;
8512                     }
8513                 }
8514             }
8515         }
8516 
8517         result = exp;
8518     }
8519 
visit(PostExp exp)8520     override void visit(PostExp exp)
8521     {
8522         static if (LOGSEMANTIC)
8523         {
8524             printf("PostExp::semantic('%s')\n", exp.toChars());
8525         }
8526         if (exp.type)
8527         {
8528             result = exp;
8529             return;
8530         }
8531 
8532         if (sc.flags & SCOPE.Cfile)
8533         {
8534             /* See if need to rewrite the AST because of cast/call ambiguity
8535              */
8536             if (auto e = castCallAmbiguity(exp, sc))
8537             {
8538                 result = expressionSemantic(e, sc);
8539                 return;
8540             }
8541         }
8542 
8543         if (Expression ex = binSemantic(exp, sc))
8544         {
8545             result = ex;
8546             return;
8547         }
8548         Expression e1x = resolveProperties(sc, exp.e1);
8549         if (e1x.op == EXP.error)
8550         {
8551             result = e1x;
8552             return;
8553         }
8554         exp.e1 = e1x;
8555 
8556         Expression e = exp.op_overload(sc);
8557         if (e)
8558         {
8559             result = e;
8560             return;
8561         }
8562 
8563         if (exp.e1.checkReadModifyWrite(exp.op))
8564             return setError();
8565 
8566         if (exp.e1.op == EXP.slice)
8567         {
8568             const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
8569             exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8570             return setError();
8571         }
8572 
8573         Type t1 = exp.e1.type.toBasetype();
8574         if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == EXP.arrayLength)
8575         {
8576             /* Check for operator overloading,
8577              * but rewrite in terms of ++e instead of e++
8578              */
8579 
8580             /* If e1 is not trivial, take a reference to it
8581              */
8582             Expression de = null;
8583             if (exp.e1.op != EXP.variable && exp.e1.op != EXP.arrayLength)
8584             {
8585                 // ref v = e1;
8586                 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8587                 de = new DeclarationExp(exp.loc, v);
8588                 exp.e1 = new VarExp(exp.e1.loc, v);
8589             }
8590 
8591             /* Rewrite as:
8592              * auto tmp = e1; ++e1; tmp
8593              */
8594             auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8595             Expression ea = new DeclarationExp(exp.loc, tmp);
8596 
8597             Expression eb = exp.e1.syntaxCopy();
8598             eb = new PreExp(exp.op == EXP.plusPlus ? EXP.prePlusPlus : EXP.preMinusMinus, exp.loc, eb);
8599 
8600             Expression ec = new VarExp(exp.loc, tmp);
8601 
8602             // Combine de,ea,eb,ec
8603             if (de)
8604                 ea = new CommaExp(exp.loc, de, ea);
8605             e = new CommaExp(exp.loc, ea, eb);
8606             e = new CommaExp(exp.loc, e, ec);
8607             e = e.expressionSemantic(sc);
8608             result = e;
8609             return;
8610         }
8611 
8612         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8613         exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
8614 
8615         e = exp;
8616         if (exp.e1.checkScalar() ||
8617             exp.e1.checkSharedAccess(sc))
8618             return setError();
8619         if (exp.e1.checkNoBool())
8620             return setError();
8621 
8622         if (exp.e1.type.ty == Tpointer)
8623             e = scaleFactor(exp, sc);
8624         else
8625             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8626         e.type = exp.e1.type;
8627         result = e;
8628     }
8629 
visit(PreExp exp)8630     override void visit(PreExp exp)
8631     {
8632         Expression e = exp.op_overload(sc);
8633         // printf("PreExp::semantic('%s')\n", toChars());
8634         if (e)
8635         {
8636             result = e;
8637             return;
8638         }
8639 
8640         // Rewrite as e1+=1 or e1-=1
8641         if (exp.op == EXP.prePlusPlus)
8642             e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8643         else
8644             e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8645         result = e.expressionSemantic(sc);
8646     }
8647 
8648     /*
8649      * Get the expression initializer for a specific struct
8650      *
8651      * Params:
8652      *  sd = the struct for which the expression initializer is needed
8653      *  loc = the location of the initializer
8654      *  sc = the scope where the expression is located
8655      *  t = the type of the expression
8656      *
8657      * Returns:
8658      *  The expression initializer or error expression if any errors occured
8659      */
getInitExp(StructDeclaration sd,Loc loc,Scope * sc,Type t)8660     private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8661     {
8662         if (sd.zeroInit && !sd.isNested())
8663         {
8664             // https://issues.dlang.org/show_bug.cgi?id=14606
8665             // Always use BlitExp for the special expression: (struct = 0)
8666             return IntegerExp.literal!0;
8667         }
8668 
8669         if (sd.isNested())
8670         {
8671             auto sle = new StructLiteralExp(loc, sd, null, t);
8672             if (!sd.fill(loc, sle.elements, true))
8673                 return ErrorExp.get();
8674             if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
8675                 return ErrorExp.get();
8676 
8677             sle.type = t;
8678             return sle;
8679         }
8680 
8681         return t.defaultInit(loc);
8682     }
8683 
visit(AssignExp exp)8684     override void visit(AssignExp exp)
8685     {
8686         static if (LOGSEMANTIC)
8687         {
8688             if (exp.op == EXP.blit)      printf("BlitExp.toElem('%s')\n", exp.toChars());
8689             if (exp.op == EXP.assign)    printf("AssignExp.toElem('%s')\n", exp.toChars());
8690             if (exp.op == EXP.construct) printf("ConstructExp.toElem('%s')\n", exp.toChars());
8691         }
8692         //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, EXPtoString(exp.e1.op).ptr);
8693         //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, EXPtoString(exp.e2.op).ptr);
8694 
8695         void setResult(Expression e, int line = __LINE__)
8696         {
8697             //printf("line %d\n", line);
8698             result = e;
8699         }
8700 
8701         if (exp.type)
8702         {
8703             return setResult(exp);
8704         }
8705 
8706         Expression e1old = exp.e1;
8707 
8708         if (auto e2comma = exp.e2.isCommaExp())
8709         {
8710             if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
8711                 exp.error("Using the result of a comma expression is not allowed");
8712 
8713             /* Rewrite to get rid of the comma from rvalue
8714              *   e1=(e0,e2) => e0,(e1=e2)
8715              */
8716             Expression e0;
8717             exp.e2 = Expression.extractLast(e2comma, e0);
8718             Expression e = Expression.combine(e0, exp);
8719             return setResult(e.expressionSemantic(sc));
8720         }
8721 
8722         /* Look for operator overloading of a[arguments] = e2.
8723          * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8724          * converted to unary operator overloading already.
8725          */
8726         if (auto ae = exp.e1.isArrayExp())
8727         {
8728             Expression res;
8729 
8730             ae.e1 = ae.e1.expressionSemantic(sc);
8731             ae.e1 = resolveProperties(sc, ae.e1);
8732             Expression ae1old = ae.e1;
8733 
8734             const(bool) maybeSlice =
8735                 (ae.arguments.dim == 0 ||
8736                  ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
8737 
8738             IntervalExp ie = null;
8739             if (maybeSlice && ae.arguments.dim)
8740             {
8741                 assert((*ae.arguments)[0].op == EXP.interval);
8742                 ie = cast(IntervalExp)(*ae.arguments)[0];
8743             }
8744             while (true)
8745             {
8746                 if (ae.e1.op == EXP.error)
8747                     return setResult(ae.e1);
8748 
8749                 Expression e0 = null;
8750                 Expression ae1save = ae.e1;
8751                 ae.lengthVar = null;
8752 
8753                 Type t1b = ae.e1.type.toBasetype();
8754                 AggregateDeclaration ad = isAggregate(t1b);
8755                 if (!ad)
8756                     break;
8757                 if (search_function(ad, Id.indexass))
8758                 {
8759                     // Deal with $
8760                     res = resolveOpDollar(sc, ae, &e0);
8761                     if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8762                         goto Lfallback;
8763                     if (res.op == EXP.error)
8764                         return setResult(res);
8765 
8766                     res = exp.e2.expressionSemantic(sc);
8767                     if (res.op == EXP.error)
8768                         return setResult(res);
8769                     exp.e2 = res;
8770 
8771                     /* Rewrite (a[arguments] = e2) as:
8772                      *      a.opIndexAssign(e2, arguments)
8773                      */
8774                     Expressions* a = ae.arguments.copy();
8775                     a.insert(0, exp.e2);
8776                     res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8777                     res = new CallExp(exp.loc, res, a);
8778                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8779                         res = res.trySemantic(sc);
8780                     else
8781                         res = res.expressionSemantic(sc);
8782                     if (res)
8783                         return setResult(Expression.combine(e0, res));
8784                 }
8785 
8786             Lfallback:
8787                 if (maybeSlice && search_function(ad, Id.sliceass))
8788                 {
8789                     // Deal with $
8790                     res = resolveOpDollar(sc, ae, ie, &e0);
8791                     if (res.op == EXP.error)
8792                         return setResult(res);
8793 
8794                     res = exp.e2.expressionSemantic(sc);
8795                     if (res.op == EXP.error)
8796                         return setResult(res);
8797 
8798                     exp.e2 = res;
8799 
8800                     /* Rewrite (a[i..j] = e2) as:
8801                      *      a.opSliceAssign(e2, i, j)
8802                      */
8803                     auto a = new Expressions();
8804                     a.push(exp.e2);
8805                     if (ie)
8806                     {
8807                         a.push(ie.lwr);
8808                         a.push(ie.upr);
8809                     }
8810                     res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8811                     res = new CallExp(exp.loc, res, a);
8812                     res = res.expressionSemantic(sc);
8813                     return setResult(Expression.combine(e0, res));
8814                 }
8815 
8816                 // No operator overloading member function found yet, but
8817                 // there might be an alias this to try.
8818                 if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
8819                 {
8820                     /* Rewrite (a[arguments] op e2) as:
8821                      *      a.aliasthis[arguments] op e2
8822                      */
8823                     ae.e1 = resolveAliasThis(sc, ae1save, true);
8824                     if (ae.e1)
8825                         continue;
8826                 }
8827                 break;
8828             }
8829             ae.e1 = ae1old; // recovery
8830             ae.lengthVar = null;
8831         }
8832 
8833         /* Run this.e1 semantic.
8834          */
8835         {
8836             Expression e1x = exp.e1;
8837 
8838             /* With UFCS, e.f = value
8839              * Could mean:
8840              *      .f(e, value)
8841              * or:
8842              *      .f(e) = value
8843              */
8844             if (auto dti = e1x.isDotTemplateInstanceExp())
8845             {
8846                 Expression e = dti.semanticY(sc, 1);
8847                 if (!e)
8848                 {
8849                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8850                 }
8851 
8852                 e1x = e;
8853             }
8854             else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
8855             {
8856                 auto die = e1x.isDotIdExp();
8857                 e1x = fieldLookup(die.e1, sc, die.ident);
8858             }
8859             else if (auto die = e1x.isDotIdExp())
8860             {
8861                 Expression e = die.semanticY(sc, 1);
8862                 if (e && isDotOpDispatch(e))
8863                 {
8864                     /* https://issues.dlang.org/show_bug.cgi?id=19687
8865                      *
8866                      * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8867                      * but that call is done with gagged errors. That is the only time when
8868                      * semantic gets ran on e2, that is why the error never gets to be printed.
8869                      * In order to make sure that UFCS is tried with correct parameters, e2
8870                      * needs to have semantic ran on it.
8871                      */
8872                     auto ode = e;
8873                     exp.e2 = exp.e2.expressionSemantic(sc);
8874                     uint errors = global.startGagging();
8875                     e = resolvePropertiesX(sc, e, exp.e2);
8876                     // Any error or if 'e' is not resolved, go to UFCS
8877                     if (global.endGagging(errors) || e is ode)
8878                         e = null; /* fall down to UFCS */
8879                     else
8880                         return setResult(e);
8881                 }
8882                 if (!e)
8883                     return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8884                 e1x = e;
8885             }
8886             else
8887             {
8888                 if (auto se = e1x.isSliceExp())
8889                     se.arrayop = true;
8890 
8891                 e1x = e1x.expressionSemantic(sc);
8892             }
8893 
8894             /* We have f = value.
8895              * Could mean:
8896              *      f(value)
8897              * or:
8898              *      f() = value
8899              */
8900             if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8901                 return setResult(e);
8902 
8903             if (e1x.checkRightThis(sc))
8904             {
8905                 return setError();
8906             }
8907             exp.e1 = e1x;
8908             assert(exp.e1.type);
8909         }
8910         Type t1 = exp.e1.type.toBasetype();
8911 
8912         /* Run this.e2 semantic.
8913          * Different from other binary expressions, the analysis of e2
8914          * depends on the result of e1 in assignments.
8915          */
8916         {
8917             Expression e2x = inferType(exp.e2, t1.baseElemOf());
8918             e2x = e2x.expressionSemantic(sc);
8919             if (!t1.isTypeSArray())
8920                 e2x = e2x.arrayFuncConv(sc);
8921             e2x = resolveProperties(sc, e2x);
8922             if (e2x.op == EXP.type)
8923                 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8924             if (e2x.op == EXP.error)
8925                 return setResult(e2x);
8926             // We delay checking the value for structs/classes as these might have
8927             // an opAssign defined.
8928             if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
8929                 e2x.checkSharedAccess(sc))
8930                 return setError();
8931             exp.e2 = e2x;
8932         }
8933 
8934         /* Rewrite tuple assignment as a tuple of assignments.
8935          */
8936         {
8937             Expression e2x = exp.e2;
8938 
8939         Ltupleassign:
8940             if (exp.e1.op == EXP.tuple && e2x.op == EXP.tuple)
8941             {
8942                 TupleExp tup1 = cast(TupleExp)exp.e1;
8943                 TupleExp tup2 = cast(TupleExp)e2x;
8944                 size_t dim = tup1.exps.dim;
8945                 Expression e = null;
8946                 if (dim != tup2.exps.dim)
8947                 {
8948                     exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
8949                     return setError();
8950                 }
8951                 if (dim == 0)
8952                 {
8953                     e = IntegerExp.literal!0;
8954                     e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8955                     e = Expression.combine(tup1.e0, tup2.e0, e);
8956                 }
8957                 else
8958                 {
8959                     auto exps = new Expressions(dim);
8960                     for (size_t i = 0; i < dim; i++)
8961                     {
8962                         Expression ex1 = (*tup1.exps)[i];
8963                         Expression ex2 = (*tup2.exps)[i];
8964                         (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8965                     }
8966                     e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8967                 }
8968                 return setResult(e.expressionSemantic(sc));
8969             }
8970 
8971             /* Look for form: e1 = e2.aliasthis.
8972              */
8973             if (exp.e1.op == EXP.tuple)
8974             {
8975                 TupleDeclaration td = isAliasThisTuple(e2x);
8976                 if (!td)
8977                     goto Lnomatch;
8978 
8979                 assert(exp.e1.type.ty == Ttuple);
8980                 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8981 
8982                 Expression e0;
8983                 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8984 
8985                 auto iexps = new Expressions();
8986                 iexps.push(ev);
8987                 for (size_t u = 0; u < iexps.dim; u++)
8988                 {
8989                 Lexpand:
8990                     Expression e = (*iexps)[u];
8991 
8992                     Parameter arg = Parameter.getNth(tt.arguments, u);
8993                     //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
8994                     //printf("e = (%s %s, %s), ", Token.toChars[e.op], e.toChars(), e.type.toChars());
8995                     //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
8996 
8997                     if (!arg || !e.type.implicitConvTo(arg.type))
8998                     {
8999                         // expand initializer to tuple
9000                         if (expandAliasThisTuples(iexps, u) != -1)
9001                         {
9002                             if (iexps.dim <= u)
9003                                 break;
9004                             goto Lexpand;
9005                         }
9006                         goto Lnomatch;
9007                     }
9008                 }
9009                 e2x = new TupleExp(e2x.loc, e0, iexps);
9010                 e2x = e2x.expressionSemantic(sc);
9011                 if (e2x.op == EXP.error)
9012                 {
9013                     result = e2x;
9014                     return;
9015                 }
9016                 // Do not need to overwrite this.e2
9017                 goto Ltupleassign;
9018             }
9019         Lnomatch:
9020         }
9021 
9022         /* Inside constructor, if this is the first assignment of object field,
9023          * rewrite this to initializing the field.
9024          */
9025         if (exp.op == EXP.assign
9026             && exp.e1.checkModifiable(sc) == Modifiable.initialization)
9027         {
9028             //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
9029             auto t = exp.type;
9030             exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
9031             exp.type = t;
9032 
9033             // https://issues.dlang.org/show_bug.cgi?id=13515
9034             // set Index::modifiable flag for complex AA element initialization
9035             if (auto ie1 = exp.e1.isIndexExp())
9036             {
9037                 Expression e1x = ie1.markSettingAAElem();
9038                 if (e1x.op == EXP.error)
9039                 {
9040                     result = e1x;
9041                     return;
9042                 }
9043             }
9044         }
9045         else if (exp.op == EXP.construct && exp.e1.op == EXP.variable &&
9046                  (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
9047         {
9048             exp.memset = MemorySet.referenceInit;
9049         }
9050 
9051         if (exp.op == EXP.assign)  // skip EXP.blit and EXP.construct, which are initializations
9052         {
9053             exp.e1.checkSharedAccess(sc);
9054             checkUnsafeAccess(sc, exp.e1, false, true);
9055         }
9056 
9057         checkUnsafeAccess(sc, exp.e2, true, true); // Initializer must always be checked
9058 
9059         /* If it is an assignment from a 'foreign' type,
9060          * check for operator overloading.
9061          */
9062         if (exp.memset == MemorySet.referenceInit)
9063         {
9064             // If this is an initialization of a reference,
9065             // do nothing
9066         }
9067         else if (t1.ty == Tstruct)
9068         {
9069             auto e1x = exp.e1;
9070             auto e2x = exp.e2;
9071             auto sd = (cast(TypeStruct)t1).sym;
9072 
9073             if (exp.op == EXP.construct)
9074             {
9075                 Type t2 = e2x.type.toBasetype();
9076                 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
9077                 {
9078                     sd.size(exp.loc);
9079                     if (sd.sizeok != Sizeok.done)
9080                         return setError();
9081                     if (!sd.ctor)
9082                         sd.ctor = sd.searchCtor();
9083 
9084                     // https://issues.dlang.org/show_bug.cgi?id=15661
9085                     // Look for the form from last of comma chain.
9086                     auto e2y = lastComma(e2x);
9087 
9088                     CallExp ce = (e2y.op == EXP.call) ? cast(CallExp)e2y : null;
9089                     DotVarExp dve = (ce && ce.e1.op == EXP.dotVariable)
9090                         ? cast(DotVarExp)ce.e1 : null;
9091                     if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
9092                         // https://issues.dlang.org/show_bug.cgi?id=19389
9093                         dve.e1.op != EXP.dotVariable &&
9094                         e2y.type.implicitConvTo(t1))
9095                     {
9096                         /* Look for form of constructor call which is:
9097                          *    __ctmp.ctor(arguments...)
9098                          */
9099 
9100                         /* Before calling the constructor, initialize
9101                          * variable with a bit copy of the default
9102                          * initializer
9103                          */
9104                         Expression einit = getInitExp(sd, exp.loc, sc, t1);
9105                         if (einit.op == EXP.error)
9106                         {
9107                             result = einit;
9108                             return;
9109                         }
9110 
9111                         auto ae = new BlitExp(exp.loc, exp.e1, einit);
9112                         ae.type = e1x.type;
9113 
9114                         /* Replace __ctmp being constructed with e1.
9115                          * We need to copy constructor call expression,
9116                          * because it may be used in other place.
9117                          */
9118                         auto dvx = cast(DotVarExp)dve.copy();
9119                         dvx.e1 = e1x;
9120                         auto cx = cast(CallExp)ce.copy();
9121                         cx.e1 = dvx;
9122                         if (checkConstructorEscape(sc, cx, false))
9123                             return setError();
9124 
9125                         Expression e0;
9126                         Expression.extractLast(e2x, e0);
9127 
9128                         auto e = Expression.combine(e0, ae, cx);
9129                         e = e.expressionSemantic(sc);
9130                         result = e;
9131                         return;
9132                     }
9133                     // https://issues.dlang.org/show_bug.cgi?id=21586
9134                     // Rewrite CondExp or e1 will miss direct construction, e.g.
9135                     // e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
9136                     // a temporary created and an extra destructor call.
9137                     // AST will be rewritten to:
9138                     // a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
9139                     if (e2x.op == EXP.question)
9140                     {
9141                         /* Rewrite as:
9142                          *  a ? e1 = b : e1 = c;
9143                          */
9144                         CondExp econd = cast(CondExp)e2x;
9145                         Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
9146                         Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
9147                         Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
9148                         result = e.expressionSemantic(sc);
9149                         return;
9150                     }
9151                     if (sd.postblit || sd.hasCopyCtor)
9152                     {
9153                         /* We have a copy constructor for this
9154                          */
9155 
9156                         if (e2x.isLvalue())
9157                         {
9158                             if (sd.hasCopyCtor)
9159                             {
9160                                 /* Rewrite as:
9161                                  * e1 = init, e1.copyCtor(e2);
9162                                  */
9163                                 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
9164                                 einit.type = e1x.type;
9165 
9166                                 Expression e;
9167                                 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9168                                 e = new CallExp(exp.loc, e, e2x);
9169                                 e = new CommaExp(exp.loc, einit, e);
9170 
9171                                 //printf("e: %s\n", e.toChars());
9172 
9173                                 result = e.expressionSemantic(sc);
9174                                 return;
9175                             }
9176                             else
9177                             {
9178                                 if (!e2x.type.implicitConvTo(e1x.type))
9179                                 {
9180                                     exp.error("conversion error from `%s` to `%s`",
9181                                         e2x.type.toChars(), e1x.type.toChars());
9182                                     return setError();
9183                                 }
9184 
9185                                 /* Rewrite as:
9186                                  *  (e1 = e2).postblit();
9187                                  *
9188                                  * Blit assignment e1 = e2 returns a reference to the original e1,
9189                                  * then call the postblit on it.
9190                                  */
9191                                 Expression e = e1x.copy();
9192                                 e.type = e.type.mutableOf();
9193                                 if (e.type.isShared && !sd.type.isShared)
9194                                     e.type = e.type.unSharedOf();
9195                                 e = new BlitExp(exp.loc, e, e2x);
9196                                 e = new DotVarExp(exp.loc, e, sd.postblit, false);
9197                                 e = new CallExp(exp.loc, e);
9198                                 result = e.expressionSemantic(sc);
9199                                 return;
9200                             }
9201                         }
9202                         else
9203                         {
9204                             /* The struct value returned from the function is transferred
9205                              * so should not call the destructor on it.
9206                              */
9207                             e2x = valueNoDtor(e2x);
9208                         }
9209                     }
9210 
9211                     // https://issues.dlang.org/show_bug.cgi?id=19251
9212                     // if e2 cannot be converted to e1.type, maybe there is an alias this
9213                     if (!e2x.implicitConvTo(t1))
9214                     {
9215                         AggregateDeclaration ad2 = isAggregate(e2x.type);
9216                         if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9217                         {
9218                             /* Rewrite (e1 op e2) as:
9219                              *      (e1 op e2.aliasthis)
9220                              */
9221                             exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9222                             result = exp.expressionSemantic(sc);
9223                             return;
9224                         }
9225                     }
9226                 }
9227                 else if (!e2x.implicitConvTo(t1))
9228                 {
9229                     sd.size(exp.loc);
9230                     if (sd.sizeok != Sizeok.done)
9231                         return setError();
9232                     if (!sd.ctor)
9233                         sd.ctor = sd.searchCtor();
9234 
9235                     if (sd.ctor)
9236                     {
9237                         /* Look for implicit constructor call
9238                          * Rewrite as:
9239                          *  e1 = init, e1.ctor(e2)
9240                          */
9241 
9242                         /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
9243                          * Using `new` to initialize a struct object is a common mistake, but
9244                          * the error message from the compiler is not very helpful in that
9245                          * case. If exp.e2 is a NewExp and the type of new is the same as
9246                          * the type as exp.e1 (struct in this case), then we know for sure
9247                          * that the user wants to instantiate a struct. This is done to avoid
9248                          * issuing an error when the user actually wants to call a constructor
9249                          * which receives a class object.
9250                          *
9251                          * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
9252                          * which receives an instance of a Foo2 class
9253                          */
9254                         if (exp.e2.op == EXP.new_)
9255                         {
9256                             auto newExp = cast(NewExp)(exp.e2);
9257                             if (newExp.newtype && newExp.newtype == t1)
9258                             {
9259                                 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
9260                                       newExp.toChars(), newExp.type.toChars(), t1.toChars());
9261                                 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
9262                                 return setError();
9263                             }
9264                         }
9265 
9266                         Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
9267                         einit.type = e1x.type;
9268 
9269                         Expression e;
9270                         e = new DotIdExp(exp.loc, e1x, Id.ctor);
9271                         e = new CallExp(exp.loc, e, e2x);
9272                         e = new CommaExp(exp.loc, einit, e);
9273                         e = e.expressionSemantic(sc);
9274                         result = e;
9275                         return;
9276                     }
9277                     if (search_function(sd, Id.call))
9278                     {
9279                         /* Look for static opCall
9280                          * https://issues.dlang.org/show_bug.cgi?id=2702
9281                          * Rewrite as:
9282                          *  e1 = typeof(e1).opCall(arguments)
9283                          */
9284                         e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
9285                         e2x = new CallExp(exp.loc, e2x, exp.e2);
9286 
9287                         e2x = e2x.expressionSemantic(sc);
9288                         e2x = resolveProperties(sc, e2x);
9289                         if (e2x.op == EXP.error)
9290                         {
9291                             result = e2x;
9292                             return;
9293                         }
9294                         if (e2x.checkValue() || e2x.checkSharedAccess(sc))
9295                             return setError();
9296                     }
9297                 }
9298                 else // https://issues.dlang.org/show_bug.cgi?id=11355
9299                 {
9300                     AggregateDeclaration ad2 = isAggregate(e2x.type);
9301                     if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9302                     {
9303                         /* Rewrite (e1 op e2) as:
9304                          *      (e1 op e2.aliasthis)
9305                          */
9306                         exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9307                         result = exp.expressionSemantic(sc);
9308                         return;
9309                     }
9310                 }
9311             }
9312             else if (exp.op == EXP.assign)
9313             {
9314                 if (e1x.op == EXP.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
9315                 {
9316                     /*
9317                      * Rewrite:
9318                      *      aa[key] = e2;
9319                      * as:
9320                      *      ref __aatmp = aa;
9321                      *      ref __aakey = key;
9322                      *      ref __aaval = e2;
9323                      *      (__aakey in __aatmp
9324                      *          ? __aatmp[__aakey].opAssign(__aaval)
9325                      *          : ConstructExp(__aatmp[__aakey], __aaval));
9326                      */
9327                     // ensure we keep the expr modifiable
9328                     Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
9329                     if (esetting.op == EXP.error)
9330                     {
9331                         result = esetting;
9332                         return;
9333                     }
9334                     assert(esetting.op == EXP.index);
9335                     IndexExp ie = cast(IndexExp) esetting;
9336                     Type t2 = e2x.type.toBasetype();
9337 
9338                     Expression e0 = null;
9339                     Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
9340                     Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
9341                     Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
9342 
9343                     AssignExp ae = cast(AssignExp)exp.copy();
9344                     ae.e1 = new IndexExp(exp.loc, ea, ek);
9345                     ae.e1 = ae.e1.expressionSemantic(sc);
9346                     ae.e1 = ae.e1.optimize(WANTvalue);
9347                     ae.e2 = ev;
9348                     Expression e = ae.op_overload(sc);
9349                     if (e)
9350                     {
9351                         Expression ey = null;
9352                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
9353                         {
9354                             ey = ev;
9355                         }
9356                         else if (!ev.implicitConvTo(ie.type) && sd.ctor)
9357                         {
9358                             // Look for implicit constructor call
9359                             // Rewrite as S().ctor(e2)
9360                             ey = new StructLiteralExp(exp.loc, sd, null);
9361                             ey = new DotIdExp(exp.loc, ey, Id.ctor);
9362                             ey = new CallExp(exp.loc, ey, ev);
9363                             ey = ey.trySemantic(sc);
9364                         }
9365                         if (ey)
9366                         {
9367                             Expression ex;
9368                             ex = new IndexExp(exp.loc, ea, ek);
9369                             ex = ex.expressionSemantic(sc);
9370                             ex = ex.modifiableLvalue(sc, ex); // allocate new slot
9371                             ex = ex.optimize(WANTvalue);
9372 
9373                             ey = new ConstructExp(exp.loc, ex, ey);
9374                             ey = ey.expressionSemantic(sc);
9375                             if (ey.op == EXP.error)
9376                             {
9377                                 result = ey;
9378                                 return;
9379                             }
9380                             ex = e;
9381 
9382                             // https://issues.dlang.org/show_bug.cgi?id=14144
9383                             // The whole expression should have the common type
9384                             // of opAssign() return and assigned AA entry.
9385                             // Even if there's no common type, expression should be typed as void.
9386                             if (!typeMerge(sc, EXP.question, ex, ey))
9387                             {
9388                                 ex = new CastExp(ex.loc, ex, Type.tvoid);
9389                                 ey = new CastExp(ey.loc, ey, Type.tvoid);
9390                             }
9391                             e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
9392                         }
9393                         e = Expression.combine(e0, e);
9394                         e = e.expressionSemantic(sc);
9395                         result = e;
9396                         return;
9397                     }
9398                 }
9399                 else
9400                 {
9401                     Expression e = exp.op_overload(sc);
9402                     if (e)
9403                     {
9404                         result = e;
9405                         return;
9406                     }
9407                 }
9408             }
9409             else
9410                 assert(exp.op == EXP.blit);
9411 
9412             if (e2x.checkValue())
9413                 return setError();
9414 
9415             exp.e1 = e1x;
9416             exp.e2 = e2x;
9417         }
9418         else if (t1.ty == Tclass)
9419         {
9420             // Disallow assignment operator overloads for same type
9421             if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
9422             {
9423                 Expression e = exp.op_overload(sc);
9424                 if (e)
9425                 {
9426                     result = e;
9427                     return;
9428                 }
9429             }
9430             if (exp.e2.checkValue())
9431                 return setError();
9432         }
9433         else if (t1.ty == Tsarray)
9434         {
9435             // SliceExp cannot have static array type without context inference.
9436             assert(exp.e1.op != EXP.slice);
9437             Expression e1x = exp.e1;
9438             Expression e2x = exp.e2;
9439 
9440             /* C strings come through as static arrays. May need to adjust the size of the
9441              * string to match the size of e1.
9442              */
9443             Type t2 = e2x.type.toBasetype();
9444             if (sc.flags & SCOPE.Cfile && e2x.isStringExp() && t2.isTypeSArray())
9445             {
9446                 uinteger_t dim1 = t1.isTypeSArray().dim.toInteger();
9447                 uinteger_t dim2 = t2.isTypeSArray().dim.toInteger();
9448                 if (dim1 + 1 == dim2 || dim2 < dim1)
9449                 {
9450                     auto tsa2 = t2.isTypeSArray();
9451                     auto newt = tsa2.next.sarrayOf(dim1).immutableOf();
9452                     e2x = castTo(e2x, sc, newt);
9453                     exp.e2 = e2x;
9454                 }
9455             }
9456 
9457             if (e2x.implicitConvTo(e1x.type))
9458             {
9459                 if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue()))
9460                 {
9461                     if (e1x.checkPostblit(sc, t1))
9462                         return setError();
9463                 }
9464 
9465                 // e2 matches to t1 because of the implicit length match, so
9466                 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9467                 {
9468                     // convert e1 to e1[]
9469                     // e.g. e1[] = a[] + b[];
9470                     auto sle = new SliceExp(e1x.loc, e1x, null, null);
9471                     sle.arrayop = true;
9472                     e1x = sle.expressionSemantic(sc);
9473                 }
9474                 else
9475                 {
9476                     // convert e2 to t1 later
9477                     // e.g. e1 = [1, 2, 3];
9478                 }
9479             }
9480             else
9481             {
9482                 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9483                 {
9484                     uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9485                     uinteger_t dim2 = dim1;
9486                     if (auto ale = e2x.isArrayLiteralExp())
9487                     {
9488                         dim2 = ale.elements ? ale.elements.dim : 0;
9489                     }
9490                     else if (auto se = e2x.isSliceExp())
9491                     {
9492                         Type tx = toStaticArrayType(se);
9493                         if (tx)
9494                             dim2 = (cast(TypeSArray)tx).dim.toInteger();
9495                     }
9496                     if (dim1 != dim2)
9497                     {
9498                         exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9499                         return setError();
9500                     }
9501                 }
9502 
9503                 // May be block or element-wise assignment, so
9504                 // convert e1 to e1[]
9505                 if (exp.op != EXP.assign)
9506                 {
9507                     // If multidimensional static array, treat as one large array
9508                     //
9509                     // Find the appropriate array type depending on the assignment, e.g.
9510                     // int[3] = int => int[3]
9511                     // int[3][2] = int => int[6]
9512                     // int[3][2] = int[] => int[3][2]
9513                     // int[3][2][4] + int => int[24]
9514                     // int[3][2][4] + int[] => int[3][8]
9515                     ulong dim = t1.isTypeSArray().dim.toUInteger();
9516                     auto type = t1.nextOf();
9517 
9518                     for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9519                     {
9520                         import core.checkedint : mulu;
9521 
9522                         // Accumulate skipped dimensions
9523                         bool overflow = false;
9524                         dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9525                         if (overflow || dim >= uint.max)
9526                         {
9527                             // dym exceeds maximum array size
9528                             exp.error("static array `%s` size overflowed to %llu",
9529                                         e1x.type.toChars(), cast(ulong) dim);
9530                             return setError();
9531                         }
9532 
9533                         // Move to the element type
9534                         type = tsa.nextOf().toBasetype();
9535 
9536                         // Rewrite ex1 as a static array if a matching type was found
9537                         if (e2x.implicitConvTo(type) > MATCH.nomatch)
9538                         {
9539                             e1x.type = type.sarrayOf(dim);
9540                             break;
9541                         }
9542                     }
9543                 }
9544                 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9545                 sle.arrayop = true;
9546                 e1x = sle.expressionSemantic(sc);
9547             }
9548             if (e1x.op == EXP.error)
9549                 return setResult(e1x);
9550             if (e2x.op == EXP.error)
9551                 return setResult(e2x);
9552 
9553             exp.e1 = e1x;
9554             exp.e2 = e2x;
9555             t1 = e1x.type.toBasetype();
9556         }
9557         /* Check the mutability of e1.
9558          */
9559         if (auto ale = exp.e1.isArrayLengthExp())
9560         {
9561             // e1 is not an lvalue, but we let code generator handle it
9562 
9563             auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9564             if (ale1x.op == EXP.error)
9565                 return setResult(ale1x);
9566             ale.e1 = ale1x;
9567 
9568             Type tn = ale.e1.type.toBasetype().nextOf();
9569             checkDefCtor(ale.loc, tn);
9570 
9571             Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9572             if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9573                 return setError();
9574 
9575             exp.e2 = exp.e2.expressionSemantic(sc);
9576             auto lc = lastComma(exp.e2);
9577             lc = lc.optimize(WANTvalue);
9578             // use slice expression when arr.length = 0 to avoid runtime call
9579             if(lc.op == EXP.int64 && lc.toInteger() == 0)
9580             {
9581                 Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
9582                 Expression as = new AssignExp(ale.loc, ale.e1, se);
9583                 as = as.expressionSemantic(sc);
9584                 auto res = Expression.combine(as, exp.e2);
9585                 res.type = ale.type;
9586                 return setResult(res);
9587             }
9588 
9589             // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9590             Expression id = new IdentifierExp(ale.loc, Id.empty);
9591             id = new DotIdExp(ale.loc, id, Id.object);
9592             auto tiargs = new Objects();
9593             tiargs.push(ale.e1.type);
9594             id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9595             id = new DotIdExp(ale.loc, id, hook);
9596             id = id.expressionSemantic(sc);
9597 
9598             auto arguments = new Expressions();
9599             arguments.reserve(5);
9600             if (global.params.tracegc)
9601             {
9602                 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9603                 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9604                 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9605                 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9606             }
9607             arguments.push(ale.e1);
9608             arguments.push(exp.e2);
9609 
9610             Expression ce = new CallExp(ale.loc, id, arguments);
9611             auto res = ce.expressionSemantic(sc);
9612             // if (global.params.verbose)
9613             //     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
9614             return setResult(res);
9615         }
9616         else if (auto se = exp.e1.isSliceExp())
9617         {
9618             Type tn = se.type.nextOf();
9619             const fun = sc.func;
9620             if (exp.op == EXP.assign && !tn.isMutable() &&
9621                 // allow modifiation in module ctor, see
9622                 // https://issues.dlang.org/show_bug.cgi?id=9884
9623                 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9624             {
9625                 exp.error("slice `%s` is not mutable", se.toChars());
9626                 return setError();
9627             }
9628 
9629             if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
9630             {
9631                 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9632                     exp.e1.toChars(), tn.baseElemOf().toChars());
9633                 result = ErrorExp.get();
9634                 return;
9635             }
9636 
9637             // For conditional operator, both branches need conversion.
9638             while (se.e1.op == EXP.slice)
9639                 se = cast(SliceExp)se.e1;
9640             if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray)
9641             {
9642                 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9643                 if (se.e1.op == EXP.error)
9644                     return setResult(se.e1);
9645             }
9646         }
9647         else
9648         {
9649             if (t1.ty == Tsarray && exp.op == EXP.assign)
9650             {
9651                 Type tn = exp.e1.type.nextOf();
9652                 if (tn && !tn.baseElemOf().isAssignable())
9653                 {
9654                     exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9655                         exp.e1.toChars(), tn.baseElemOf().toChars());
9656                     result = ErrorExp.get();
9657                     return;
9658                 }
9659             }
9660 
9661             Expression e1x = exp.e1;
9662 
9663             // Try to do a decent error message with the expression
9664             // before it gets constant folded
9665             if (exp.op == EXP.assign)
9666                 e1x = e1x.modifiableLvalue(sc, e1old);
9667 
9668             e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
9669 
9670             if (e1x.op == EXP.error)
9671             {
9672                 result = e1x;
9673                 return;
9674             }
9675             exp.e1 = e1x;
9676         }
9677 
9678         /* Tweak e2 based on the type of e1.
9679          */
9680         Expression e2x = exp.e2;
9681         Type t2 = e2x.type.toBasetype();
9682 
9683         // If it is a array, get the element type. Note that it may be
9684         // multi-dimensional.
9685         Type telem = t1;
9686         while (telem.ty == Tarray)
9687             telem = telem.nextOf();
9688 
9689         if (exp.e1.op == EXP.slice && t1.nextOf() &&
9690             (telem.ty != Tvoid || e2x.op == EXP.null_) &&
9691             e2x.implicitConvTo(t1.nextOf()))
9692         {
9693             // Check for block assignment. If it is of type void[], void[][], etc,
9694             // '= null' is the only allowable block assignment (Bug 7493)
9695             exp.memset = MemorySet.blockAssign;    // make it easy for back end to tell what this is
9696             e2x = e2x.implicitCastTo(sc, t1.nextOf());
9697             if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9698                 return setError();
9699         }
9700         else if (exp.e1.op == EXP.slice &&
9701                  (t2.ty == Tarray || t2.ty == Tsarray) &&
9702                  t2.nextOf().implicitConvTo(t1.nextOf()))
9703         {
9704             // Check element-wise assignment.
9705 
9706             /* If assigned elements number is known at compile time,
9707              * check the mismatch.
9708              */
9709             SliceExp se1 = cast(SliceExp)exp.e1;
9710             TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9711             TypeSArray tsa2 = null;
9712             if (auto ale = e2x.isArrayLiteralExp())
9713                 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
9714             else if (auto se = e2x.isSliceExp())
9715                 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9716             else
9717                 tsa2 = t2.isTypeSArray();
9718 
9719             if (tsa1 && tsa2)
9720             {
9721                 uinteger_t dim1 = tsa1.dim.toInteger();
9722                 uinteger_t dim2 = tsa2.dim.toInteger();
9723                 if (dim1 != dim2)
9724                 {
9725                     exp.error("mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
9726                     return setError();
9727                 }
9728             }
9729 
9730             if (exp.op != EXP.blit &&
9731                 (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9732                  e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9733                  e2x.op != EXP.slice && e2x.isLvalue()))
9734             {
9735                 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9736                     return setError();
9737             }
9738 
9739             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9740                 e2x.op != EXP.slice && e2x.op != EXP.assign &&
9741                 e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
9742                 !(e2x.op == EXP.add || e2x.op == EXP.min ||
9743                   e2x.op == EXP.mul || e2x.op == EXP.div ||
9744                   e2x.op == EXP.mod || e2x.op == EXP.xor ||
9745                   e2x.op == EXP.and || e2x.op == EXP.or ||
9746                   e2x.op == EXP.pow ||
9747                   e2x.op == EXP.tilde || e2x.op == EXP.negate))
9748             {
9749                 const(char)* e1str = exp.e1.toChars();
9750                 const(char)* e2str = e2x.toChars();
9751                 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9752             }
9753 
9754             Type t2n = t2.nextOf();
9755             Type t1n = t1.nextOf();
9756             int offset;
9757             if (t2n.equivalent(t1n) ||
9758                 t1n.isBaseOf(t2n, &offset) && offset == 0)
9759             {
9760                 /* Allow copy of distinct qualifier elements.
9761                  * eg.
9762                  *  char[] dst;  const(char)[] src;
9763                  *  dst[] = src;
9764                  *
9765                  *  class C {}   class D : C {}
9766                  *  C[2] ca;  D[] da;
9767                  *  ca[] = da;
9768                  */
9769                 if (isArrayOpValid(e2x))
9770                 {
9771                     // Don't add CastExp to keep AST for array operations
9772                     e2x = e2x.copy();
9773                     e2x.type = exp.e1.type.constOf();
9774                 }
9775                 else
9776                     e2x = e2x.castTo(sc, exp.e1.type.constOf());
9777             }
9778             else
9779             {
9780                 /* https://issues.dlang.org/show_bug.cgi?id=15778
9781                  * A string literal has an array type of immutable
9782                  * elements by default, and normally it cannot be convertible to
9783                  * array type of mutable elements. But for element-wise assignment,
9784                  * elements need to be const at best. So we should give a chance
9785                  * to change code unit size for polysemous string literal.
9786                  */
9787                 if (e2x.op == EXP.string_)
9788                     e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9789                 else
9790                     e2x = e2x.implicitCastTo(sc, exp.e1.type);
9791             }
9792             if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9793             {
9794                 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
9795                 {
9796                     exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
9797                     return setError();
9798                 }
9799             }
9800         }
9801         else
9802         {
9803             if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9804                 t1.ty == Tarray && t2.ty == Tsarray &&
9805                 e2x.op != EXP.slice &&
9806                 t2.implicitConvTo(t1))
9807             {
9808                 // Disallow ar[] = sa (Converted to ar[] = sa[])
9809                 // Disallow da   = sa (Converted to da   = sa[])
9810                 const(char)* e1str = exp.e1.toChars();
9811                 const(char)* e2str = e2x.toChars();
9812                 const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
9813                 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9814             }
9815             if (exp.op == EXP.blit)
9816                 e2x = e2x.castTo(sc, exp.e1.type);
9817             else
9818             {
9819                 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9820 
9821                 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9822 
9823                 // If the implicit cast has failed and the assign expression is
9824                 // the initialization of a struct member field
9825                 if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
9826                 {
9827                     scope sd = (cast(TypeStruct)t1).sym;
9828                     Dsymbol opAssign = search_function(sd, Id.assign);
9829 
9830                     // and the struct defines an opAssign
9831                     if (opAssign)
9832                     {
9833                         // offer more information about the cause of the problem
9834                         errorSupplemental(exp.loc,
9835                                           "`%s` is the first assignment of `%s` therefore it represents its initialization",
9836                                           exp.toChars(), exp.e1.toChars());
9837                         errorSupplemental(exp.loc,
9838                                           "`opAssign` methods are not used for initialization, but for subsequent assignments");
9839                     }
9840                 }
9841             }
9842         }
9843         if (e2x.op == EXP.error)
9844         {
9845             result = e2x;
9846             return;
9847         }
9848         exp.e2 = e2x;
9849         t2 = exp.e2.type.toBasetype();
9850 
9851         /* Look for array operations
9852          */
9853         if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9854         {
9855             // Look for valid array operations
9856             if (exp.memset != MemorySet.blockAssign &&
9857                 exp.e1.op == EXP.slice &&
9858                 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9859             {
9860                 exp.type = exp.e1.type;
9861                 if (exp.op == EXP.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9862                                         // tweak mutability of e1 element
9863                     exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9864                 result = arrayOp(exp, sc);
9865                 return;
9866             }
9867 
9868             // Drop invalid array operations in e2
9869             //  d = a[] + b[], d = (a[] + b[])[0..2], etc
9870             if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == EXP.assign))
9871                 return setError();
9872 
9873             // Remains valid array assignments
9874             //  d = d[], d = [1,2,3], etc
9875         }
9876 
9877         /* Don't allow assignment to classes that were allocated on the stack with:
9878          *      scope Class c = new Class();
9879          */
9880         if (exp.e1.op == EXP.variable && exp.op == EXP.assign)
9881         {
9882             VarExp ve = cast(VarExp)exp.e1;
9883             VarDeclaration vd = ve.var.isVarDeclaration();
9884             if (vd && vd.onstack)
9885             {
9886                 assert(t1.ty == Tclass);
9887                 exp.error("cannot rebind scope variables");
9888             }
9889         }
9890 
9891         if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9892         {
9893             exp.error("cannot modify compiler-generated variable `__ctfe`");
9894         }
9895 
9896         exp.type = exp.e1.type;
9897         assert(exp.type);
9898         auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
9899         Expression tmp;
9900         /* https://issues.dlang.org/show_bug.cgi?id=22366
9901          *
9902          * `reorderSettingAAElem` creates a tree of comma expressions, however,
9903          * `checkAssignExp` expects only AssignExps.
9904          */
9905         checkAssignEscape(sc, Expression.extractLast(res, tmp), false, false);
9906 
9907         if (auto ae = res.isConstructExp())
9908         {
9909             Type t1b = ae.e1.type.toBasetype();
9910             if (t1b.ty != Tsarray && t1b.ty != Tarray)
9911                 return setResult(res);
9912 
9913             /* Do not lower Rvalues and references, as they need to be moved,
9914              * not copied.
9915              * Skip the lowering when the RHS is an array literal, as e2ir
9916              * already handles such cases more elegantly.
9917              */
9918             const isArrayCtor =
9919                 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
9920                 ae.e2.isLvalue &&
9921                 !(ae.e1.isVarExp &&
9922                     ae.e1.isVarExp.var.isVarDeclaration.isReference) &&
9923                 (ae.e2.isVarExp ||
9924                     ae.e2.isSliceExp ||
9925                     (ae.e2.type.ty == Tsarray && !ae.e2.isArrayLiteralExp)) &&
9926                 ae.e1.type.nextOf &&
9927                 ae.e2.type.nextOf &&
9928                 ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
9929 
9930             /* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
9931              * then we do want to make a temporary for it and call its destructor.
9932              */
9933             const isArraySetCtor =
9934                 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
9935                 (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
9936                 ae.e1.type.nextOf &&
9937                 ae.e1.type.nextOf.equivalent(ae.e2.type);
9938 
9939             if (isArrayCtor || isArraySetCtor)
9940             {
9941                 const ts = t1b.nextOf().baseElemOf().isTypeStruct();
9942                 if (!ts || (!ts.sym.postblit && !ts.sym.dtor))
9943                     return setResult(res);
9944 
9945                 auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
9946                 const other = isArrayCtor ? "other array" : "value";
9947                 if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
9948                     return setError();
9949 
9950                 // Lower to object._d_array{,set}ctor(e1, e2)
9951                 Expression id = new IdentifierExp(exp.loc, Id.empty);
9952                 id = new DotIdExp(exp.loc, id, Id.object);
9953                 id = new DotIdExp(exp.loc, id, func);
9954 
9955                 auto arguments = new Expressions();
9956                 arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
9957                 if (isArrayCtor)
9958                 {
9959                     arguments.push(new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf).expressionSemantic(sc));
9960                     Expression ce = new CallExp(exp.loc, id, arguments);
9961                     res = ce.expressionSemantic(sc);
9962                 }
9963                 else
9964                 {
9965                     Expression e0;
9966                     // If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access
9967                     if (!ae.e2.isVarExp)
9968                     {
9969                         auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
9970                         e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
9971                         arguments.push(new VarExp(vd.loc, vd).expressionSemantic(sc));
9972                     }
9973                     else
9974                         arguments.push(ae.e2);
9975 
9976                     Expression ce = new CallExp(exp.loc, id, arguments);
9977                     res = Expression.combine(e0, ce).expressionSemantic(sc);
9978                 }
9979 
9980                 if (global.params.verbose)
9981                     message("lowered   %s =>\n          %s", exp.toChars(), res.toChars());
9982             }
9983         }
9984 
9985         return setResult(res);
9986     }
9987 
visit(PowAssignExp exp)9988     override void visit(PowAssignExp exp)
9989     {
9990         if (exp.type)
9991         {
9992             result = exp;
9993             return;
9994         }
9995 
9996         Expression e = exp.op_overload(sc);
9997         if (e)
9998         {
9999             result = e;
10000             return;
10001         }
10002 
10003         if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
10004             return setError();
10005 
10006         assert(exp.e1.type && exp.e2.type);
10007         if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
10008         {
10009             if (checkNonAssignmentArrayOp(exp.e1))
10010                 return setError();
10011 
10012             // T[] ^^= ...
10013             if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
10014             {
10015                 // T[] ^^= T
10016                 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
10017             }
10018             else if (Expression ex = typeCombine(exp, sc))
10019             {
10020                 result = ex;
10021                 return;
10022             }
10023 
10024             // Check element types are arithmetic
10025             Type tb1 = exp.e1.type.nextOf().toBasetype();
10026             Type tb2 = exp.e2.type.toBasetype();
10027             if (tb2.ty == Tarray || tb2.ty == Tsarray)
10028                 tb2 = tb2.nextOf().toBasetype();
10029             if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
10030             {
10031                 exp.type = exp.e1.type;
10032                 result = arrayOp(exp, sc);
10033                 return;
10034             }
10035         }
10036         else
10037         {
10038             exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10039         }
10040 
10041         if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
10042         {
10043             Expression e0 = null;
10044             e = exp.reorderSettingAAElem(sc);
10045             e = Expression.extractLast(e, e0);
10046             assert(e == exp);
10047 
10048             if (exp.e1.op == EXP.variable)
10049             {
10050                 // Rewrite: e1 = e1 ^^ e2
10051                 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
10052                 e = new AssignExp(exp.loc, exp.e1, e);
10053             }
10054             else
10055             {
10056                 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
10057                 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
10058                 auto de = new DeclarationExp(exp.e1.loc, v);
10059                 auto ve = new VarExp(exp.e1.loc, v);
10060                 e = new PowExp(exp.loc, ve, exp.e2);
10061                 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
10062                 e = new CommaExp(exp.loc, de, e);
10063             }
10064             e = Expression.combine(e0, e);
10065             e = e.expressionSemantic(sc);
10066             result = e;
10067             return;
10068         }
10069         result = exp.incompatibleTypes();
10070     }
10071 
visit(CatAssignExp exp)10072     override void visit(CatAssignExp exp)
10073     {
10074         if (exp.type)
10075         {
10076             result = exp;
10077             return;
10078         }
10079 
10080         //printf("CatAssignExp::semantic() %s\n", exp.toChars());
10081         Expression e = exp.op_overload(sc);
10082         if (e)
10083         {
10084             result = e;
10085             return;
10086         }
10087 
10088         if (SliceExp se = exp.e1.isSliceExp())
10089         {
10090             if (se.e1.type.toBasetype().ty == Tsarray)
10091             {
10092                 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
10093                 return setError();
10094             }
10095         }
10096 
10097         exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10098         if (exp.e1.op == EXP.error)
10099         {
10100             result = exp.e1;
10101             return;
10102         }
10103         if (exp.e2.op == EXP.error)
10104         {
10105             result = exp.e2;
10106             return;
10107         }
10108 
10109         if (checkNonAssignmentArrayOp(exp.e2))
10110             return setError();
10111 
10112         Type tb1 = exp.e1.type.toBasetype();
10113         Type tb1next = tb1.nextOf();
10114         Type tb2 = exp.e2.type.toBasetype();
10115 
10116         /* Possibilities:
10117          * EXP.concatenateAssign: appending T[] to T[]
10118          * EXP.concatenateElemAssign: appending T to T[]
10119          * EXP.concatenateDcharAssign: appending dchar to T[]
10120          */
10121         if ((tb1.ty == Tarray) &&
10122             (tb2.ty == Tarray || tb2.ty == Tsarray) &&
10123             (exp.e2.implicitConvTo(exp.e1.type) ||
10124              (tb2.nextOf().implicitConvTo(tb1next) &&
10125               (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
10126         {
10127             // EXP.concatenateAssign
10128             assert(exp.op == EXP.concatenateAssign);
10129             if (exp.e1.checkPostblit(sc, tb1next))
10130                 return setError();
10131 
10132             exp.e2 = exp.e2.castTo(sc, exp.e1.type);
10133         }
10134         else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
10135         {
10136             /* https://issues.dlang.org/show_bug.cgi?id=19782
10137              *
10138              * If e2 is implicitly convertible to tb1next, the conversion
10139              * might be done through alias this, in which case, e2 needs to
10140              * be modified accordingly (e2 => e2.aliasthis).
10141              */
10142             if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
10143                 goto Laliasthis;
10144             if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
10145                 goto Laliasthis;
10146             // Append element
10147             if (exp.e2.checkPostblit(sc, tb2))
10148                 return setError();
10149 
10150             if (checkNewEscape(sc, exp.e2, false))
10151                 return setError();
10152 
10153             exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
10154             exp.e2 = doCopyOrMove(sc, exp.e2);
10155         }
10156         else if (tb1.ty == Tarray &&
10157                  (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
10158                  exp.e2.type.ty != tb1next.ty &&
10159                  exp.e2.implicitConvTo(Type.tdchar))
10160         {
10161             // Append dchar to char[] or wchar[]
10162             exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
10163 
10164             /* Do not allow appending wchar to char[] because if wchar happens
10165              * to be a surrogate pair, nothing good can result.
10166              */
10167         }
10168         else
10169         {
10170             // Try alias this on first operand
10171             static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
10172             {
10173                 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
10174                 if (!ad1 || !ad1.aliasthis)
10175                     return null;
10176 
10177                 /* Rewrite (e1 op e2) as:
10178                  *      (e1.aliasthis op e2)
10179                  */
10180                 if (isRecursiveAliasThis(exp.att1, exp.e1.type))
10181                     return null;
10182                 //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars());
10183                 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
10184                 BinExp be = cast(BinExp)exp.copy();
10185                 be.e1 = e1;
10186                 return be.trySemantic(sc);
10187             }
10188 
10189             // Try alias this on second operand
10190             static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
10191             {
10192                 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
10193                 if (!ad2 || !ad2.aliasthis)
10194                     return null;
10195                 /* Rewrite (e1 op e2) as:
10196                  *      (e1 op e2.aliasthis)
10197                  */
10198                 if (isRecursiveAliasThis(exp.att2, exp.e2.type))
10199                     return null;
10200                 //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars());
10201                 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
10202                 BinExp be = cast(BinExp)exp.copy();
10203                 be.e2 = e2;
10204                 return be.trySemantic(sc);
10205             }
10206 
10207     Laliasthis:
10208             result = tryAliasThisForLhs(exp, sc);
10209             if (result)
10210                 return;
10211 
10212             result = tryAliasThisForRhs(exp, sc);
10213             if (result)
10214                 return;
10215 
10216             exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
10217             return setError();
10218         }
10219 
10220         if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
10221             return setError();
10222 
10223         exp.type = exp.e1.type;
10224         auto res = exp.reorderSettingAAElem(sc);
10225         if ((exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign) &&
10226             global.params.useDIP1000 == FeatureState.enabled)
10227             checkAssignEscape(sc, res, false, false);
10228         result = res;
10229     }
10230 
visit(AddExp exp)10231     override void visit(AddExp exp)
10232     {
10233         static if (LOGSEMANTIC)
10234         {
10235             printf("AddExp::semantic('%s')\n", exp.toChars());
10236         }
10237         if (exp.type)
10238         {
10239             result = exp;
10240             return;
10241         }
10242 
10243         if (Expression ex = binSemanticProp(exp, sc))
10244         {
10245             result = ex;
10246             return;
10247         }
10248         Expression e = exp.op_overload(sc);
10249         if (e)
10250         {
10251             result = e;
10252             return;
10253         }
10254 
10255         /* ImportC: convert arrays to pointers, functions to pointers to functions
10256          */
10257         exp.e1 = exp.e1.arrayFuncConv(sc);
10258         exp.e2 = exp.e2.arrayFuncConv(sc);
10259 
10260         Type tb1 = exp.e1.type.toBasetype();
10261         Type tb2 = exp.e2.type.toBasetype();
10262 
10263         bool err = false;
10264         if (tb1.ty == Tdelegate || tb1.isPtrToFunction())
10265         {
10266             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10267         }
10268         if (tb2.ty == Tdelegate || tb2.isPtrToFunction())
10269         {
10270             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10271         }
10272         if (err)
10273             return setError();
10274 
10275         if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
10276         {
10277             result = scaleFactor(exp, sc);
10278             return;
10279         }
10280 
10281         if (tb1.ty == Tpointer && tb2.ty == Tpointer)
10282         {
10283             result = exp.incompatibleTypes();
10284             return;
10285         }
10286 
10287         if (Expression ex = typeCombine(exp, sc))
10288         {
10289             result = ex;
10290             return;
10291         }
10292 
10293         Type tb = exp.type.toBasetype();
10294         if (tb.ty == Tarray || tb.ty == Tsarray)
10295         {
10296             if (!isArrayOpValid(exp))
10297             {
10298                 result = arrayOpInvalidError(exp);
10299                 return;
10300             }
10301             result = exp;
10302             return;
10303         }
10304 
10305         tb1 = exp.e1.type.toBasetype();
10306         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
10307         {
10308             result = exp.incompatibleTypes();
10309             return;
10310         }
10311         if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
10312         {
10313             switch (exp.type.toBasetype().ty)
10314             {
10315             case Tfloat32:
10316             case Timaginary32:
10317                 exp.type = Type.tcomplex32;
10318                 break;
10319 
10320             case Tfloat64:
10321             case Timaginary64:
10322                 exp.type = Type.tcomplex64;
10323                 break;
10324 
10325             case Tfloat80:
10326             case Timaginary80:
10327                 exp.type = Type.tcomplex80;
10328                 break;
10329 
10330             default:
10331                 assert(0);
10332             }
10333         }
10334         result = exp;
10335     }
10336 
visit(MinExp exp)10337     override void visit(MinExp exp)
10338     {
10339         static if (LOGSEMANTIC)
10340         {
10341             printf("MinExp::semantic('%s')\n", exp.toChars());
10342         }
10343         if (exp.type)
10344         {
10345             result = exp;
10346             return;
10347         }
10348 
10349         if (Expression ex = binSemanticProp(exp, sc))
10350         {
10351             result = ex;
10352             return;
10353         }
10354         Expression e = exp.op_overload(sc);
10355         if (e)
10356         {
10357             result = e;
10358             return;
10359         }
10360 
10361         /* ImportC: convert arrays to pointers, functions to pointers to functions
10362          */
10363         exp.e1 = exp.e1.arrayFuncConv(sc);
10364         exp.e2 = exp.e2.arrayFuncConv(sc);
10365 
10366         Type t1 = exp.e1.type.toBasetype();
10367         Type t2 = exp.e2.type.toBasetype();
10368 
10369         bool err = false;
10370         if (t1.ty == Tdelegate || t1.isPtrToFunction())
10371         {
10372             err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10373         }
10374         if (t2.ty == Tdelegate || t2.isPtrToFunction())
10375         {
10376             err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10377         }
10378         if (err)
10379             return setError();
10380 
10381         if (t1.ty == Tpointer)
10382         {
10383             if (t2.ty == Tpointer)
10384             {
10385                 // https://dlang.org/spec/expression.html#add_expressions
10386                 // "If both operands are pointers, and the operator is -, the pointers are
10387                 // subtracted and the result is divided by the size of the type pointed to
10388                 // by the operands. It is an error if the pointers point to different types."
10389                 Type p1 = t1.nextOf();
10390                 Type p2 = t2.nextOf();
10391 
10392                 if (!p1.equivalent(p2))
10393                 {
10394                     // Deprecation to remain for at least a year, after which this should be
10395                     // changed to an error
10396                     // See https://github.com/dlang/dmd/pull/7332
10397                     deprecation(exp.loc,
10398                         "cannot subtract pointers to different types: `%s` and `%s`.",
10399                         t1.toChars(), t2.toChars());
10400                 }
10401 
10402                 // Need to divide the result by the stride
10403                 // Replace (ptr - ptr) with (ptr - ptr) / stride
10404                 long stride;
10405 
10406                 // make sure pointer types are compatible
10407                 if (Expression ex = typeCombine(exp, sc))
10408                 {
10409                     result = ex;
10410                     return;
10411                 }
10412 
10413                 exp.type = Type.tptrdiff_t;
10414                 stride = t2.nextOf().size();
10415                 if (stride == 0)
10416                 {
10417                     e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
10418                 }
10419                 else if (stride == cast(long)SIZE_INVALID)
10420                     e = ErrorExp.get();
10421                 else
10422                 {
10423                     e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
10424                     e.type = Type.tptrdiff_t;
10425                 }
10426             }
10427             else if (t2.isintegral())
10428                 e = scaleFactor(exp, sc);
10429             else
10430             {
10431                 exp.error("can't subtract `%s` from pointer", t2.toChars());
10432                 e = ErrorExp.get();
10433             }
10434             result = e;
10435             return;
10436         }
10437         if (t2.ty == Tpointer)
10438         {
10439             exp.type = exp.e2.type;
10440             exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
10441             return setError();
10442         }
10443 
10444         if (Expression ex = typeCombine(exp, sc))
10445         {
10446             result = ex;
10447             return;
10448         }
10449 
10450         Type tb = exp.type.toBasetype();
10451         if (tb.ty == Tarray || tb.ty == Tsarray)
10452         {
10453             if (!isArrayOpValid(exp))
10454             {
10455                 result = arrayOpInvalidError(exp);
10456                 return;
10457             }
10458             result = exp;
10459             return;
10460         }
10461 
10462         t1 = exp.e1.type.toBasetype();
10463         t2 = exp.e2.type.toBasetype();
10464         if (!target.isVectorOpSupported(t1, exp.op, t2))
10465         {
10466             result = exp.incompatibleTypes();
10467             return;
10468         }
10469         if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
10470         {
10471             switch (exp.type.ty)
10472             {
10473             case Tfloat32:
10474             case Timaginary32:
10475                 exp.type = Type.tcomplex32;
10476                 break;
10477 
10478             case Tfloat64:
10479             case Timaginary64:
10480                 exp.type = Type.tcomplex64;
10481                 break;
10482 
10483             case Tfloat80:
10484             case Timaginary80:
10485                 exp.type = Type.tcomplex80;
10486                 break;
10487 
10488             default:
10489                 assert(0);
10490             }
10491         }
10492         result = exp;
10493         return;
10494     }
10495 
visit(CatExp exp)10496     override void visit(CatExp exp)
10497     {
10498         // https://dlang.org/spec/expression.html#cat_expressions
10499         //printf("CatExp.semantic() %s\n", toChars());
10500         if (exp.type)
10501         {
10502             result = exp;
10503             return;
10504         }
10505 
10506         if (Expression ex = binSemanticProp(exp, sc))
10507         {
10508             result = ex;
10509             return;
10510         }
10511         Expression e = exp.op_overload(sc);
10512         if (e)
10513         {
10514             result = e;
10515             return;
10516         }
10517 
10518         Type tb1 = exp.e1.type.toBasetype();
10519         Type tb2 = exp.e2.type.toBasetype();
10520 
10521         auto f1 = checkNonAssignmentArrayOp(exp.e1);
10522         auto f2 = checkNonAssignmentArrayOp(exp.e2);
10523         if (f1 || f2)
10524             return setError();
10525 
10526         Type tb1next = tb1.nextOf();
10527         Type tb2next = tb2.nextOf();
10528 
10529         // Check for: array ~ array
10530         if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1)))
10531         {
10532             /* https://issues.dlang.org/show_bug.cgi?id=9248
10533              * Here to avoid the case of:
10534              *    void*[] a = [cast(void*)1];
10535              *    void*[] b = [cast(void*)2];
10536              *    a ~ b;
10537              * becoming:
10538              *    a ~ [cast(void*)b];
10539              */
10540 
10541             /* https://issues.dlang.org/show_bug.cgi?id=14682
10542              * Also to avoid the case of:
10543              *    int[][] a;
10544              *    a ~ [];
10545              * becoming:
10546              *    a ~ cast(int[])[];
10547              */
10548             goto Lpeer;
10549         }
10550 
10551         // Check for: array ~ element
10552         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10553         {
10554             if (exp.e1.op == EXP.arrayLiteral)
10555             {
10556                 exp.e2 = doCopyOrMove(sc, exp.e2);
10557                 // https://issues.dlang.org/show_bug.cgi?id=14686
10558                 // Postblit call appears in AST, and this is
10559                 // finally translated  to an ArrayLiteralExp in below optimize().
10560             }
10561             else if (exp.e1.op == EXP.string_)
10562             {
10563                 // No postblit call exists on character (integer) value.
10564             }
10565             else
10566             {
10567                 if (exp.e2.checkPostblit(sc, tb2))
10568                     return setError();
10569                 // Postblit call will be done in runtime helper function
10570             }
10571 
10572             if (exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
10573             {
10574                 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10575                 exp.type = tb2.arrayOf();
10576                 goto L2elem;
10577             }
10578             if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10579             {
10580                 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10581                 exp.type = tb1next.arrayOf();
10582             L2elem:
10583                 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10584                 {
10585                     // Make e2 into [e2]
10586                     exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10587                 }
10588                 else if (checkNewEscape(sc, exp.e2, false))
10589                     return setError();
10590                 result = exp.optimize(WANTvalue);
10591                 return;
10592             }
10593         }
10594         // Check for: element ~ array
10595         if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10596         {
10597             if (exp.e2.op == EXP.arrayLiteral)
10598             {
10599                 exp.e1 = doCopyOrMove(sc, exp.e1);
10600             }
10601             else if (exp.e2.op == EXP.string_)
10602             {
10603             }
10604             else
10605             {
10606                 if (exp.e1.checkPostblit(sc, tb1))
10607                     return setError();
10608             }
10609 
10610             if (exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
10611             {
10612                 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10613                 exp.type = tb1.arrayOf();
10614                 goto L1elem;
10615             }
10616             if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10617             {
10618                 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10619                 exp.type = tb2next.arrayOf();
10620             L1elem:
10621                 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10622                 {
10623                     // Make e1 into [e1]
10624                     exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10625                 }
10626                 else if (checkNewEscape(sc, exp.e1, false))
10627                     return setError();
10628                 result = exp.optimize(WANTvalue);
10629                 return;
10630             }
10631         }
10632 
10633     Lpeer:
10634         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10635         {
10636             Type t1 = tb1next.mutableOf().constOf().arrayOf();
10637             Type t2 = tb2next.mutableOf().constOf().arrayOf();
10638             if (exp.e1.op == EXP.string_ && !(cast(StringExp)exp.e1).committed)
10639                 exp.e1.type = t1;
10640             else
10641                 exp.e1 = exp.e1.castTo(sc, t1);
10642             if (exp.e2.op == EXP.string_ && !(cast(StringExp)exp.e2).committed)
10643                 exp.e2.type = t2;
10644             else
10645                 exp.e2 = exp.e2.castTo(sc, t2);
10646         }
10647 
10648         if (Expression ex = typeCombine(exp, sc))
10649         {
10650             result = ex;
10651             return;
10652         }
10653         exp.type = exp.type.toHeadMutable();
10654 
10655         Type tb = exp.type.toBasetype();
10656         if (tb.ty == Tsarray)
10657             exp.type = tb.nextOf().arrayOf();
10658         if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10659         {
10660             exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10661         }
10662         if (Type tbn = tb.nextOf())
10663         {
10664             if (exp.checkPostblit(sc, tbn))
10665                 return setError();
10666         }
10667         Type t1 = exp.e1.type.toBasetype();
10668         Type t2 = exp.e2.type.toBasetype();
10669         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10670             (t2.ty == Tarray || t2.ty == Tsarray))
10671         {
10672             // Normalize to ArrayLiteralExp or StringExp as far as possible
10673             e = exp.optimize(WANTvalue);
10674         }
10675         else
10676         {
10677             //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10678             result = exp.incompatibleTypes();
10679             return;
10680         }
10681 
10682         result = e;
10683     }
10684 
visit(MulExp exp)10685     override void visit(MulExp exp)
10686     {
10687         version (none)
10688         {
10689             printf("MulExp::semantic() %s\n", exp.toChars());
10690         }
10691         if (exp.type)
10692         {
10693             result = exp;
10694             return;
10695         }
10696 
10697         if (Expression ex = binSemanticProp(exp, sc))
10698         {
10699             result = ex;
10700             return;
10701         }
10702         Expression e = exp.op_overload(sc);
10703         if (e)
10704         {
10705             result = e;
10706             return;
10707         }
10708 
10709         if (Expression ex = typeCombine(exp, sc))
10710         {
10711             result = ex;
10712             return;
10713         }
10714 
10715         Type tb = exp.type.toBasetype();
10716         if (tb.ty == Tarray || tb.ty == Tsarray)
10717         {
10718             if (!isArrayOpValid(exp))
10719             {
10720                 result = arrayOpInvalidError(exp);
10721                 return;
10722             }
10723             result = exp;
10724             return;
10725         }
10726 
10727         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10728             return setError();
10729 
10730         if (exp.type.isfloating())
10731         {
10732             Type t1 = exp.e1.type;
10733             Type t2 = exp.e2.type;
10734 
10735             if (t1.isreal())
10736             {
10737                 exp.type = t2;
10738             }
10739             else if (t2.isreal())
10740             {
10741                 exp.type = t1;
10742             }
10743             else if (t1.isimaginary())
10744             {
10745                 if (t2.isimaginary())
10746                 {
10747                     switch (t1.toBasetype().ty)
10748                     {
10749                     case Timaginary32:
10750                         exp.type = Type.tfloat32;
10751                         break;
10752 
10753                     case Timaginary64:
10754                         exp.type = Type.tfloat64;
10755                         break;
10756 
10757                     case Timaginary80:
10758                         exp.type = Type.tfloat80;
10759                         break;
10760 
10761                     default:
10762                         assert(0);
10763                     }
10764 
10765                     // iy * iv = -yv
10766                     exp.e1.type = exp.type;
10767                     exp.e2.type = exp.type;
10768                     e = new NegExp(exp.loc, exp);
10769                     e = e.expressionSemantic(sc);
10770                     result = e;
10771                     return;
10772                 }
10773                 else
10774                     exp.type = t2; // t2 is complex
10775             }
10776             else if (t2.isimaginary())
10777             {
10778                 exp.type = t1; // t1 is complex
10779             }
10780         }
10781         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10782         {
10783             result = exp.incompatibleTypes();
10784             return;
10785         }
10786         result = exp;
10787     }
10788 
visit(DivExp exp)10789     override void visit(DivExp exp)
10790     {
10791         if (exp.type)
10792         {
10793             result = exp;
10794             return;
10795         }
10796 
10797         if (Expression ex = binSemanticProp(exp, sc))
10798         {
10799             result = ex;
10800             return;
10801         }
10802         Expression e = exp.op_overload(sc);
10803         if (e)
10804         {
10805             result = e;
10806             return;
10807         }
10808 
10809         if (Expression ex = typeCombine(exp, sc))
10810         {
10811             result = ex;
10812             return;
10813         }
10814 
10815         Type tb = exp.type.toBasetype();
10816         if (tb.ty == Tarray || tb.ty == Tsarray)
10817         {
10818             if (!isArrayOpValid(exp))
10819             {
10820                 result = arrayOpInvalidError(exp);
10821                 return;
10822             }
10823             result = exp;
10824             return;
10825         }
10826 
10827         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10828             return setError();
10829 
10830         if (exp.type.isfloating())
10831         {
10832             Type t1 = exp.e1.type;
10833             Type t2 = exp.e2.type;
10834 
10835             if (t1.isreal())
10836             {
10837                 exp.type = t2;
10838                 if (t2.isimaginary())
10839                 {
10840                     // x/iv = i(-x/v)
10841                     exp.e2.type = t1;
10842                     e = new NegExp(exp.loc, exp);
10843                     e = e.expressionSemantic(sc);
10844                     result = e;
10845                     return;
10846                 }
10847             }
10848             else if (t2.isreal())
10849             {
10850                 exp.type = t1;
10851             }
10852             else if (t1.isimaginary())
10853             {
10854                 if (t2.isimaginary())
10855                 {
10856                     switch (t1.toBasetype().ty)
10857                     {
10858                     case Timaginary32:
10859                         exp.type = Type.tfloat32;
10860                         break;
10861 
10862                     case Timaginary64:
10863                         exp.type = Type.tfloat64;
10864                         break;
10865 
10866                     case Timaginary80:
10867                         exp.type = Type.tfloat80;
10868                         break;
10869 
10870                     default:
10871                         assert(0);
10872                     }
10873                 }
10874                 else
10875                     exp.type = t2; // t2 is complex
10876             }
10877             else if (t2.isimaginary())
10878             {
10879                 exp.type = t1; // t1 is complex
10880             }
10881         }
10882         else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10883         {
10884             result = exp.incompatibleTypes();
10885             return;
10886         }
10887         result = exp;
10888     }
10889 
visit(ModExp exp)10890     override void visit(ModExp exp)
10891     {
10892         if (exp.type)
10893         {
10894             result = exp;
10895             return;
10896         }
10897 
10898         if (Expression ex = binSemanticProp(exp, sc))
10899         {
10900             result = ex;
10901             return;
10902         }
10903         Expression e = exp.op_overload(sc);
10904         if (e)
10905         {
10906             result = e;
10907             return;
10908         }
10909 
10910         if (Expression ex = typeCombine(exp, sc))
10911         {
10912             result = ex;
10913             return;
10914         }
10915 
10916         Type tb = exp.type.toBasetype();
10917         if (tb.ty == Tarray || tb.ty == Tsarray)
10918         {
10919             if (!isArrayOpValid(exp))
10920             {
10921                 result = arrayOpInvalidError(exp);
10922                 return;
10923             }
10924             result = exp;
10925             return;
10926         }
10927         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10928         {
10929             result = exp.incompatibleTypes();
10930             return;
10931         }
10932 
10933         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10934             return setError();
10935 
10936         if (exp.type.isfloating())
10937         {
10938             exp.type = exp.e1.type;
10939             if (exp.e2.type.iscomplex())
10940             {
10941                 exp.error("cannot perform modulo complex arithmetic");
10942                 return setError();
10943             }
10944         }
10945         result = exp;
10946     }
10947 
visit(PowExp exp)10948     override void visit(PowExp exp)
10949     {
10950         if (exp.type)
10951         {
10952             result = exp;
10953             return;
10954         }
10955 
10956         //printf("PowExp::semantic() %s\n", toChars());
10957         if (Expression ex = binSemanticProp(exp, sc))
10958         {
10959             result = ex;
10960             return;
10961         }
10962         Expression e = exp.op_overload(sc);
10963         if (e)
10964         {
10965             result = e;
10966             return;
10967         }
10968 
10969         if (Expression ex = typeCombine(exp, sc))
10970         {
10971             result = ex;
10972             return;
10973         }
10974 
10975         Type tb = exp.type.toBasetype();
10976         if (tb.ty == Tarray || tb.ty == Tsarray)
10977         {
10978             if (!isArrayOpValid(exp))
10979             {
10980                 result = arrayOpInvalidError(exp);
10981                 return;
10982             }
10983             result = exp;
10984             return;
10985         }
10986 
10987         if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10988             return setError();
10989 
10990         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10991         {
10992             result = exp.incompatibleTypes();
10993             return;
10994         }
10995 
10996         // First, attempt to fold the expression.
10997         e = exp.optimize(WANTvalue);
10998         if (e.op != EXP.pow)
10999         {
11000             e = e.expressionSemantic(sc);
11001             result = e;
11002             return;
11003         }
11004 
11005         Module mmath = loadStdMath();
11006         if (!mmath)
11007         {
11008             e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
11009             return setError();
11010         }
11011         e = new ScopeExp(exp.loc, mmath);
11012 
11013         if (exp.e2.op == EXP.float64 && exp.e2.toReal() == CTFloat.half)
11014         {
11015             // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
11016             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
11017         }
11018         else
11019         {
11020             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
11021             e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
11022         }
11023         e = e.expressionSemantic(sc);
11024         result = e;
11025         return;
11026     }
11027 
visit(ShlExp exp)11028     override void visit(ShlExp exp)
11029     {
11030         //printf("ShlExp::semantic(), type = %p\n", type);
11031         if (exp.type)
11032         {
11033             result = exp;
11034             return;
11035         }
11036 
11037         if (Expression ex = binSemanticProp(exp, sc))
11038         {
11039             result = ex;
11040             return;
11041         }
11042         Expression e = exp.op_overload(sc);
11043         if (e)
11044         {
11045             result = e;
11046             return;
11047         }
11048 
11049         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11050             return setError();
11051 
11052         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11053         {
11054             result = exp.incompatibleTypes();
11055             return;
11056         }
11057         exp.e1 = integralPromotions(exp.e1, sc);
11058         if (exp.e2.type.toBasetype().ty != Tvector)
11059             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11060 
11061         exp.type = exp.e1.type;
11062         result = exp;
11063     }
11064 
visit(ShrExp exp)11065     override void visit(ShrExp exp)
11066     {
11067         if (exp.type)
11068         {
11069             result = exp;
11070             return;
11071         }
11072 
11073         if (Expression ex = binSemanticProp(exp, sc))
11074         {
11075             result = ex;
11076             return;
11077         }
11078         Expression e = exp.op_overload(sc);
11079         if (e)
11080         {
11081             result = e;
11082             return;
11083         }
11084 
11085         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11086             return setError();
11087 
11088         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11089         {
11090             result = exp.incompatibleTypes();
11091             return;
11092         }
11093         exp.e1 = integralPromotions(exp.e1, sc);
11094         if (exp.e2.type.toBasetype().ty != Tvector)
11095             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11096 
11097         exp.type = exp.e1.type;
11098         result = exp;
11099     }
11100 
visit(UshrExp exp)11101     override void visit(UshrExp exp)
11102     {
11103         if (exp.type)
11104         {
11105             result = exp;
11106             return;
11107         }
11108 
11109         if (Expression ex = binSemanticProp(exp, sc))
11110         {
11111             result = ex;
11112             return;
11113         }
11114         Expression e = exp.op_overload(sc);
11115         if (e)
11116         {
11117             result = e;
11118             return;
11119         }
11120 
11121         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11122             return setError();
11123 
11124         if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11125         {
11126             result = exp.incompatibleTypes();
11127             return;
11128         }
11129         exp.e1 = integralPromotions(exp.e1, sc);
11130         if (exp.e2.type.toBasetype().ty != Tvector)
11131             exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11132 
11133         exp.type = exp.e1.type;
11134         result = exp;
11135     }
11136 
visit(AndExp exp)11137     override void visit(AndExp exp)
11138     {
11139         if (exp.type)
11140         {
11141             result = exp;
11142             return;
11143         }
11144 
11145         if (Expression ex = binSemanticProp(exp, sc))
11146         {
11147             result = ex;
11148             return;
11149         }
11150         Expression e = exp.op_overload(sc);
11151         if (e)
11152         {
11153             result = e;
11154             return;
11155         }
11156 
11157         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11158         {
11159             exp.type = exp.e1.type;
11160             result = exp;
11161             return;
11162         }
11163 
11164         if (Expression ex = typeCombine(exp, sc))
11165         {
11166             result = ex;
11167             return;
11168         }
11169 
11170         Type tb = exp.type.toBasetype();
11171         if (tb.ty == Tarray || tb.ty == Tsarray)
11172         {
11173             if (!isArrayOpValid(exp))
11174             {
11175                 result = arrayOpInvalidError(exp);
11176                 return;
11177             }
11178             result = exp;
11179             return;
11180         }
11181         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11182         {
11183             result = exp.incompatibleTypes();
11184             return;
11185         }
11186         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11187             return setError();
11188 
11189         result = exp;
11190     }
11191 
visit(OrExp exp)11192     override void visit(OrExp exp)
11193     {
11194         if (exp.type)
11195         {
11196             result = exp;
11197             return;
11198         }
11199 
11200         if (Expression ex = binSemanticProp(exp, sc))
11201         {
11202             result = ex;
11203             return;
11204         }
11205         Expression e = exp.op_overload(sc);
11206         if (e)
11207         {
11208             result = e;
11209             return;
11210         }
11211 
11212         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11213         {
11214             exp.type = exp.e1.type;
11215             result = exp;
11216             return;
11217         }
11218 
11219         if (Expression ex = typeCombine(exp, sc))
11220         {
11221             result = ex;
11222             return;
11223         }
11224 
11225         Type tb = exp.type.toBasetype();
11226         if (tb.ty == Tarray || tb.ty == Tsarray)
11227         {
11228             if (!isArrayOpValid(exp))
11229             {
11230                 result = arrayOpInvalidError(exp);
11231                 return;
11232             }
11233             result = exp;
11234             return;
11235         }
11236         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11237         {
11238             result = exp.incompatibleTypes();
11239             return;
11240         }
11241         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11242             return setError();
11243 
11244         result = exp;
11245     }
11246 
visit(XorExp exp)11247     override void visit(XorExp exp)
11248     {
11249         if (exp.type)
11250         {
11251             result = exp;
11252             return;
11253         }
11254 
11255         if (Expression ex = binSemanticProp(exp, sc))
11256         {
11257             result = ex;
11258             return;
11259         }
11260         Expression e = exp.op_overload(sc);
11261         if (e)
11262         {
11263             result = e;
11264             return;
11265         }
11266 
11267         if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11268         {
11269             exp.type = exp.e1.type;
11270             result = exp;
11271             return;
11272         }
11273 
11274         if (Expression ex = typeCombine(exp, sc))
11275         {
11276             result = ex;
11277             return;
11278         }
11279 
11280         Type tb = exp.type.toBasetype();
11281         if (tb.ty == Tarray || tb.ty == Tsarray)
11282         {
11283             if (!isArrayOpValid(exp))
11284             {
11285                 result = arrayOpInvalidError(exp);
11286                 return;
11287             }
11288             result = exp;
11289             return;
11290         }
11291         if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11292         {
11293             result = exp.incompatibleTypes();
11294             return;
11295         }
11296         if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11297             return setError();
11298 
11299         result = exp;
11300     }
11301 
visit(LogicalExp exp)11302     override void visit(LogicalExp exp)
11303     {
11304         static if (LOGSEMANTIC)
11305         {
11306             printf("LogicalExp::semantic() %s\n", exp.toChars());
11307         }
11308 
11309         if (exp.type)
11310         {
11311             result = exp;
11312             return;
11313         }
11314 
11315         exp.setNoderefOperands();
11316 
11317         Expression e1x = exp.e1.expressionSemantic(sc);
11318 
11319         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11320         if (e1x.op == EXP.type)
11321             e1x = resolveAliasThis(sc, e1x);
11322 
11323         e1x = resolveProperties(sc, e1x);
11324         e1x = e1x.toBoolean(sc);
11325 
11326         if (sc.flags & SCOPE.condition)
11327         {
11328             /* If in static if, don't evaluate e2 if we don't have to.
11329              */
11330             e1x = e1x.optimize(WANTvalue);
11331             if (e1x.toBool().hasValue(exp.op == EXP.orOr))
11332             {
11333                 if (sc.flags & SCOPE.Cfile)
11334                     result = new IntegerExp(exp.op == EXP.orOr);
11335                 else
11336                     result = IntegerExp.createBool(exp.op == EXP.orOr);
11337                 return;
11338             }
11339         }
11340 
11341         CtorFlow ctorflow = sc.ctorflow.clone();
11342         Expression e2x = exp.e2.expressionSemantic(sc);
11343         sc.merge(exp.loc, ctorflow);
11344         ctorflow.freeFieldinit();
11345 
11346         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11347         if (e2x.op == EXP.type)
11348             e2x = resolveAliasThis(sc, e2x);
11349 
11350         e2x = resolveProperties(sc, e2x);
11351 
11352         auto f1 = checkNonAssignmentArrayOp(e1x);
11353         auto f2 = checkNonAssignmentArrayOp(e2x);
11354         if (f1 || f2)
11355             return setError();
11356 
11357         // Unless the right operand is 'void', the expression is converted to 'bool'.
11358         if (e2x.type.ty != Tvoid)
11359             e2x = e2x.toBoolean(sc);
11360 
11361         if (e2x.op == EXP.type || e2x.op == EXP.scope_)
11362         {
11363             exp.error("`%s` is not an expression", exp.e2.toChars());
11364             return setError();
11365         }
11366         if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
11367         {
11368             result = e1x;
11369             return;
11370         }
11371         if (e2x.op == EXP.error)
11372         {
11373             result = e2x;
11374             return;
11375         }
11376 
11377         // The result type is 'bool', unless the right operand has type 'void'.
11378         if (e2x.type.ty == Tvoid)
11379             exp.type = Type.tvoid;
11380         else
11381             exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11382 
11383         exp.e1 = e1x;
11384         exp.e2 = e2x;
11385         result = exp;
11386     }
11387 
11388 
visit(CmpExp exp)11389     override void visit(CmpExp exp)
11390     {
11391         static if (LOGSEMANTIC)
11392         {
11393             printf("CmpExp::semantic('%s')\n", exp.toChars());
11394         }
11395         if (exp.type)
11396         {
11397             result = exp;
11398             return;
11399         }
11400 
11401         exp.setNoderefOperands();
11402 
11403         if (Expression ex = binSemanticProp(exp, sc))
11404         {
11405             result = ex;
11406             return;
11407         }
11408         Type t1 = exp.e1.type.toBasetype();
11409         Type t2 = exp.e2.type.toBasetype();
11410         if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
11411         {
11412             exp.error("do not use `null` when comparing class types");
11413             return setError();
11414         }
11415 
11416 
11417         EXP cmpop = exp.op;
11418         if (auto e = exp.op_overload(sc, &cmpop))
11419         {
11420             if (!e.type.isscalar() && e.type.equals(exp.e1.type))
11421             {
11422                 exp.error("recursive `opCmp` expansion");
11423                 return setError();
11424             }
11425             if (e.op == EXP.call)
11426             {
11427 
11428                 if (t1.ty == Tclass && t2.ty == Tclass)
11429                 {
11430                     // Lower to object.__cmp(e1, e2)
11431                     Expression cl = new IdentifierExp(exp.loc, Id.empty);
11432                     cl = new DotIdExp(exp.loc, cl, Id.object);
11433                     cl = new DotIdExp(exp.loc, cl, Id.__cmp);
11434                     cl = cl.expressionSemantic(sc);
11435 
11436                     auto arguments = new Expressions();
11437                     // Check if op_overload found a better match by calling e2.opCmp(e1)
11438                     // If the operands were swapped, then the result must be reversed
11439                     // e1.opCmp(e2) == -e2.opCmp(e1)
11440                     // cmpop takes care of this
11441                     if (exp.op == cmpop)
11442                     {
11443                         arguments.push(exp.e1);
11444                         arguments.push(exp.e2);
11445                     }
11446                     else
11447                     {
11448                         // Use better match found by op_overload
11449                         arguments.push(exp.e2);
11450                         arguments.push(exp.e1);
11451                     }
11452 
11453                     cl = new CallExp(exp.loc, cl, arguments);
11454                     cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
11455                     result = cl.expressionSemantic(sc);
11456                     return;
11457                 }
11458 
11459                 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
11460                 e = e.expressionSemantic(sc);
11461             }
11462             result = e;
11463             return;
11464         }
11465 
11466 
11467         if (Expression ex = typeCombine(exp, sc))
11468         {
11469             result = ex;
11470             return;
11471         }
11472 
11473         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11474         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11475         if (f1 || f2)
11476             return setError();
11477 
11478         exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11479 
11480         // Special handling for array comparisons
11481         Expression arrayLowering = null;
11482         t1 = exp.e1.type.toBasetype();
11483         t2 = exp.e2.type.toBasetype();
11484         if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
11485         {
11486             Type t1next = t1.nextOf();
11487             Type t2next = t2.nextOf();
11488             if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
11489             {
11490                 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
11491                 return setError();
11492             }
11493             if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
11494             {
11495                 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
11496                     return setError();
11497 
11498                 // Lower to object.__cmp(e1, e2)
11499                 Expression al = new IdentifierExp(exp.loc, Id.empty);
11500                 al = new DotIdExp(exp.loc, al, Id.object);
11501                 al = new DotIdExp(exp.loc, al, Id.__cmp);
11502                 al = al.expressionSemantic(sc);
11503 
11504                 auto arguments = new Expressions(2);
11505                 (*arguments)[0] = exp.e1;
11506                 (*arguments)[1] = exp.e2;
11507 
11508                 al = new CallExp(exp.loc, al, arguments);
11509                 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
11510 
11511                 arrayLowering = al;
11512             }
11513         }
11514         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
11515         {
11516             if (t2.ty == Tstruct)
11517                 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
11518             else
11519                 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
11520             return setError();
11521         }
11522         else if (t1.iscomplex() || t2.iscomplex())
11523         {
11524             exp.error("compare not defined for complex operands");
11525             return setError();
11526         }
11527         else if (t1.ty == Taarray || t2.ty == Taarray)
11528         {
11529             exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
11530             return setError();
11531         }
11532         else if (!target.isVectorOpSupported(t1, exp.op, t2))
11533         {
11534             result = exp.incompatibleTypes();
11535             return;
11536         }
11537         else
11538         {
11539             bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
11540             bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
11541             if (r1 || r2)
11542                 return setError();
11543         }
11544 
11545         //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
11546         if (arrayLowering)
11547         {
11548             arrayLowering = arrayLowering.expressionSemantic(sc);
11549             result = arrayLowering;
11550             return;
11551         }
11552         result = exp;
11553         return;
11554     }
11555 
visit(InExp exp)11556     override void visit(InExp exp)
11557     {
11558         if (exp.type)
11559         {
11560             result = exp;
11561             return;
11562         }
11563 
11564         if (Expression ex = binSemanticProp(exp, sc))
11565         {
11566             result = ex;
11567             return;
11568         }
11569         Expression e = exp.op_overload(sc);
11570         if (e)
11571         {
11572             result = e;
11573             return;
11574         }
11575 
11576         Type t2b = exp.e2.type.toBasetype();
11577         switch (t2b.ty)
11578         {
11579         case Taarray:
11580             {
11581                 TypeAArray ta = cast(TypeAArray)t2b;
11582 
11583                 // Special handling for array keys
11584                 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11585                 {
11586                     // Convert key to type of key
11587                     exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11588                 }
11589 
11590                 semanticTypeInfo(sc, ta.index);
11591 
11592                 // Return type is pointer to value
11593                 exp.type = ta.nextOf().pointerTo();
11594                 break;
11595             }
11596 
11597         case Terror:
11598             return setError();
11599 
11600         default:
11601             result = exp.incompatibleTypes();
11602             return;
11603         }
11604         result = exp;
11605     }
11606 
visit(RemoveExp e)11607     override void visit(RemoveExp e)
11608     {
11609         if (Expression ex = binSemantic(e, sc))
11610         {
11611             result = ex;
11612             return;
11613         }
11614         result = e;
11615     }
11616 
visit(EqualExp exp)11617     override void visit(EqualExp exp)
11618     {
11619         //printf("EqualExp::semantic('%s')\n", exp.toChars());
11620         if (exp.type)
11621         {
11622             result = exp;
11623             return;
11624         }
11625 
11626         exp.setNoderefOperands();
11627 
11628         if (auto e = binSemanticProp(exp, sc))
11629         {
11630             result = e;
11631             return;
11632         }
11633         if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
11634         {
11635             /* https://issues.dlang.org/show_bug.cgi?id=12520
11636              * empty tuples are represented as types so special cases are added
11637              * so that they can be compared for equality with tuples of values.
11638              */
11639             static auto extractTypeTupAndExpTup(Expression e)
11640             {
11641                 static struct Result { bool ttEmpty; bool te; }
11642                 auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
11643                 return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
11644             }
11645             auto tups1 = extractTypeTupAndExpTup(exp.e1);
11646             auto tups2 = extractTypeTupAndExpTup(exp.e2);
11647             // AliasSeq!() == AliasSeq!(<at least a value>)
11648             if (tups1.ttEmpty && tups2.te)
11649             {
11650                 result = IntegerExp.createBool(exp.op != EXP.equal);
11651                 return;
11652             }
11653             // AliasSeq!(<at least a value>) == AliasSeq!()
11654             else if (tups1.te && tups2.ttEmpty)
11655             {
11656                 result = IntegerExp.createBool(exp.op != EXP.equal);
11657                 return;
11658             }
11659             // AliasSeq!() == AliasSeq!()
11660             else if (tups1.ttEmpty && tups2.ttEmpty)
11661             {
11662                 result = IntegerExp.createBool(exp.op == EXP.equal);
11663                 return;
11664             }
11665             // otherwise, two types are really not comparable
11666             result = exp.incompatibleTypes();
11667             return;
11668         }
11669 
11670         {
11671             auto t1 = exp.e1.type;
11672             auto t2 = exp.e2.type;
11673             if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11674                 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11675                     t1.toChars(), t2.toChars());
11676         }
11677 
11678         /* Before checking for operator overloading, check to see if we're
11679          * comparing the addresses of two statics. If so, we can just see
11680          * if they are the same symbol.
11681          */
11682         if (exp.e1.op == EXP.address && exp.e2.op == EXP.address)
11683         {
11684             AddrExp ae1 = cast(AddrExp)exp.e1;
11685             AddrExp ae2 = cast(AddrExp)exp.e2;
11686             if (ae1.e1.op == EXP.variable && ae2.e1.op == EXP.variable)
11687             {
11688                 VarExp ve1 = cast(VarExp)ae1.e1;
11689                 VarExp ve2 = cast(VarExp)ae2.e1;
11690                 if (ve1.var == ve2.var)
11691                 {
11692                     // They are the same, result is 'true' for ==, 'false' for !=
11693                     result = IntegerExp.createBool(exp.op == EXP.equal);
11694                     return;
11695                 }
11696             }
11697         }
11698 
11699         Type t1 = exp.e1.type.toBasetype();
11700         Type t2 = exp.e2.type.toBasetype();
11701 
11702         // Indicates whether the comparison of the 2 specified array types
11703         // requires an object.__equals() lowering.
11704         static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11705         {
11706             Type t1n = t1.nextOf().toBasetype();
11707             Type t2n = t2.nextOf().toBasetype();
11708             if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11709                 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11710             {
11711                 return false;
11712             }
11713             if (t1n.constOf() != t2n.constOf())
11714                 return true;
11715 
11716             Type t = t1n;
11717             while (t.toBasetype().nextOf())
11718                 t = t.nextOf().toBasetype();
11719             if (auto ts = t.isTypeStruct())
11720             {
11721                 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11722                 if (global.params.useTypeInfo && Type.dtypeinfo)
11723                     semanticTypeInfo(sc, ts);
11724 
11725                 return ts.sym.hasIdentityEquals; // has custom opEquals
11726             }
11727 
11728             return false;
11729         }
11730 
11731         if (auto e = exp.op_overload(sc))
11732         {
11733             result = e;
11734             return;
11735         }
11736 
11737 
11738         const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11739                                   (t2.ty == Tarray || t2.ty == Tsarray);
11740         const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11741 
11742         if (!needsArrayLowering)
11743         {
11744             if (auto e = typeCombine(exp, sc))
11745             {
11746                 result = e;
11747                 return;
11748             }
11749         }
11750 
11751         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11752         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11753         if (f1 || f2)
11754             return setError();
11755 
11756         exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11757 
11758         if (!isArrayComparison)
11759         {
11760             if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11761             {
11762                 // Cast both to complex
11763                 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11764                 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11765             }
11766         }
11767 
11768         // lower some array comparisons to object.__equals(e1, e2)
11769         if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
11770         {
11771             //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
11772 
11773             if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
11774                 return setError();
11775 
11776             Expression __equals = new IdentifierExp(exp.loc, Id.empty);
11777             Identifier id = Identifier.idPool("__equals");
11778             __equals = new DotIdExp(exp.loc, __equals, Id.object);
11779             __equals = new DotIdExp(exp.loc, __equals, id);
11780 
11781             auto arguments = new Expressions(2);
11782             (*arguments)[0] = exp.e1;
11783             (*arguments)[1] = exp.e2;
11784 
11785             __equals = new CallExp(exp.loc, __equals, arguments);
11786             if (exp.op == EXP.notEqual)
11787             {
11788                 __equals = new NotExp(exp.loc, __equals);
11789             }
11790             __equals = __equals.trySemantic(sc); // for better error message
11791             if (!__equals)
11792             {
11793                 exp.error("incompatible types for array comparison: `%s` and `%s`",
11794                           exp.e1.type.toChars(), exp.e2.type.toChars());
11795                 __equals = ErrorExp.get();
11796             }
11797 
11798             result = __equals;
11799             return;
11800         }
11801 
11802         if (exp.e1.type.toBasetype().ty == Taarray)
11803             semanticTypeInfo(sc, exp.e1.type.toBasetype());
11804 
11805 
11806         if (!target.isVectorOpSupported(t1, exp.op, t2))
11807         {
11808             result = exp.incompatibleTypes();
11809             return;
11810         }
11811 
11812         result = exp;
11813     }
11814 
visit(IdentityExp exp)11815     override void visit(IdentityExp exp)
11816     {
11817         if (exp.type)
11818         {
11819             result = exp;
11820             return;
11821         }
11822 
11823         exp.setNoderefOperands();
11824 
11825         if (auto e = binSemanticProp(exp, sc))
11826         {
11827             result = e;
11828             return;
11829         }
11830 
11831         if (auto e = typeCombine(exp, sc))
11832         {
11833             result = e;
11834             return;
11835         }
11836 
11837         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11838         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11839         if (f1 || f2)
11840             return setError();
11841 
11842         if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
11843         {
11844             result = exp.incompatibleTypes();
11845             return;
11846         }
11847 
11848         exp.type = Type.tbool;
11849 
11850         if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11851         {
11852             // Cast both to complex
11853             exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11854             exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11855         }
11856 
11857         auto tb1 = exp.e1.type.toBasetype();
11858         auto tb2 = exp.e2.type.toBasetype();
11859         if (!target.isVectorOpSupported(tb1, exp.op, tb2))
11860         {
11861             result = exp.incompatibleTypes();
11862             return;
11863         }
11864 
11865         if (exp.e1.op == EXP.call)
11866             exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
11867         if (exp.e2.op == EXP.call)
11868             exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
11869 
11870         if (exp.e1.type.toBasetype().ty == Tsarray ||
11871             exp.e2.type.toBasetype().ty == Tsarray)
11872             exp.deprecation("identity comparison of static arrays "
11873                 ~ "implicitly coerces them to slices, "
11874                 ~ "which are compared by reference");
11875 
11876         result = exp;
11877     }
11878 
visit(CondExp exp)11879     override void visit(CondExp exp)
11880     {
11881         static if (LOGSEMANTIC)
11882         {
11883             printf("CondExp::semantic('%s')\n", exp.toChars());
11884         }
11885         if (exp.type)
11886         {
11887             result = exp;
11888             return;
11889         }
11890 
11891         if (auto die = exp.econd.isDotIdExp())
11892             die.noderef = true;
11893 
11894         Expression ec = exp.econd.expressionSemantic(sc);
11895         ec = resolveProperties(sc, ec);
11896         ec = ec.toBoolean(sc);
11897 
11898         CtorFlow ctorflow_root = sc.ctorflow.clone();
11899         Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
11900         e1x = resolveProperties(sc, e1x);
11901 
11902         CtorFlow ctorflow1 = sc.ctorflow;
11903         sc.ctorflow = ctorflow_root;
11904         Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
11905         e2x = resolveProperties(sc, e2x);
11906 
11907         sc.merge(exp.loc, ctorflow1);
11908         ctorflow1.freeFieldinit();
11909 
11910         if (ec.op == EXP.error)
11911         {
11912             result = ec;
11913             return;
11914         }
11915         if (ec.type == Type.terror)
11916             return setError();
11917         exp.econd = ec;
11918 
11919         if (e1x.op == EXP.error)
11920         {
11921             result = e1x;
11922             return;
11923         }
11924         if (e1x.type == Type.terror)
11925             return setError();
11926         exp.e1 = e1x;
11927 
11928         if (e2x.op == EXP.error)
11929         {
11930             result = e2x;
11931             return;
11932         }
11933         if (e2x.type == Type.terror)
11934             return setError();
11935         exp.e2 = e2x;
11936 
11937         auto f0 = checkNonAssignmentArrayOp(exp.econd);
11938         auto f1 = checkNonAssignmentArrayOp(exp.e1);
11939         auto f2 = checkNonAssignmentArrayOp(exp.e2);
11940         if (f0 || f1 || f2)
11941             return setError();
11942 
11943         Type t1 = exp.e1.type;
11944         Type t2 = exp.e2.type;
11945         if (t1.ty == Tnoreturn)
11946         {
11947             exp.type = t2;
11948         }
11949         else if (t2.ty == Tnoreturn)
11950         {
11951             exp.type = t1;
11952         }
11953         // If either operand is void the result is void, we have to cast both
11954         // the expression to void so that we explicitly discard the expression
11955         // value if any
11956         // https://issues.dlang.org/show_bug.cgi?id=16598
11957         else if (t1.ty == Tvoid || t2.ty == Tvoid)
11958         {
11959             exp.type = Type.tvoid;
11960             exp.e1 = exp.e1.castTo(sc, exp.type);
11961             exp.e2 = exp.e2.castTo(sc, exp.type);
11962         }
11963         else if (t1 == t2)
11964             exp.type = t1;
11965         else
11966         {
11967             if (Expression ex = typeCombine(exp, sc))
11968             {
11969                 result = ex;
11970                 return;
11971             }
11972 
11973             switch (exp.e1.type.toBasetype().ty)
11974             {
11975             case Tcomplex32:
11976             case Tcomplex64:
11977             case Tcomplex80:
11978                 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
11979                 break;
11980             default:
11981                 break;
11982             }
11983             switch (exp.e2.type.toBasetype().ty)
11984             {
11985             case Tcomplex32:
11986             case Tcomplex64:
11987             case Tcomplex80:
11988                 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
11989                 break;
11990             default:
11991                 break;
11992             }
11993             if (exp.type.toBasetype().ty == Tarray)
11994             {
11995                 exp.e1 = exp.e1.castTo(sc, exp.type);
11996                 exp.e2 = exp.e2.castTo(sc, exp.type);
11997             }
11998         }
11999         exp.type = exp.type.merge2();
12000         version (none)
12001         {
12002             printf("res: %s\n", exp.type.toChars());
12003             printf("e1 : %s\n", exp.e1.type.toChars());
12004             printf("e2 : %s\n", exp.e2.type.toChars());
12005         }
12006 
12007         /* https://issues.dlang.org/show_bug.cgi?id=14696
12008          * If either e1 or e2 contain temporaries which need dtor,
12009          * make them conditional.
12010          * Rewrite:
12011          *      cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
12012          * to:
12013          *      (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
12014          * and replace edtors of __tmp1 and __tmp2 with:
12015          *      __tmp1.edtor --> __cond && __tmp1.dtor()
12016          *      __tmp2.edtor --> __cond || __tmp2.dtor()
12017          */
12018         exp.hookDtors(sc);
12019 
12020         result = exp;
12021     }
12022 
visit(GenericExp exp)12023     override void visit(GenericExp exp)
12024     {
12025         static if (LOGSEMANTIC)
12026         {
12027             printf("GenericExp::semantic('%s')\n", exp.toChars());
12028         }
12029         // C11 6.5.1.1 Generic Selection
12030 
12031         auto ec = exp.cntlExp.expressionSemantic(sc);
12032         bool errors = ec.isErrorExp() !is null;
12033         auto tc = ec.type;
12034 
12035         auto types = (*exp.types)[];
12036         foreach (i, ref t; types)
12037         {
12038             if (!t)
12039                 continue;       // `default:` case
12040             t = t.typeSemantic(ec.loc, sc);
12041             if (t.isTypeError())
12042             {
12043                 errors = true;
12044                 continue;
12045             }
12046 
12047             /* C11 6.5.1-2 duplicate check
12048              */
12049             /* C11 distinguishes int, long, and long long. But D doesn't, so depending on the
12050              * C target, a long may have the same type as `int` in the D type system.
12051              * So, skip checks when this may be the case. Later pick the first match
12052              */
12053             if (
12054                 (t.ty == Tint32 || t.ty == Tuns32) && target.c.longsize == 4 ||
12055                 (t.ty == Tint64 || t.ty == Tuns64) && target.c.longsize == 8 ||
12056                 (t.ty == Tfloat64 || t.ty == Timaginary64 || t.ty == Tcomplex64) && target.c.long_doublesize == 8
12057                )
12058                 continue;
12059 
12060             foreach (t2; types[0 .. i])
12061             {
12062                 if (t2 && t2.equals(t))
12063                 {
12064                     error(ec.loc, "generic association type `%s` can only appear once", t.toChars());
12065                     errors = true;
12066                     break;
12067                 }
12068             }
12069         }
12070 
12071         auto exps = (*exp.exps)[];
12072         foreach (ref e; exps)
12073         {
12074             e = e.expressionSemantic(sc);
12075             if (e.isErrorExp())
12076                 errors = true;
12077         }
12078 
12079         if (errors)
12080             return setError();
12081 
12082         enum size_t None = ~0;
12083         size_t imatch = None;
12084         size_t idefault = None;
12085         foreach (const i, t; types)
12086         {
12087             if (t)
12088             {
12089                 /* if tc is compatible with t, it's a match
12090                  * C11 6.2.7 defines a compatible type as being the same type, including qualifiers
12091                  */
12092                 if (tc.equals(t))
12093                 {
12094                     assert(imatch == None);
12095                     imatch = i;
12096                     break;              // pick first match
12097                 }
12098             }
12099             else
12100                 idefault = i;  // multiple defaults are not allowed, and are caught by cparse
12101         }
12102 
12103         if (imatch == None)
12104             imatch = idefault;
12105         if (imatch == None)
12106         {
12107             error(exp.loc, "no compatible generic association type for controlling expression type `%s`", tc.toChars());
12108             return setError();
12109         }
12110 
12111         result = exps[imatch];
12112     }
12113 
visit(FileInitExp e)12114     override void visit(FileInitExp e)
12115     {
12116         //printf("FileInitExp::semantic()\n");
12117         e.type = Type.tstring;
12118         result = e;
12119     }
12120 
visit(LineInitExp e)12121     override void visit(LineInitExp e)
12122     {
12123         e.type = Type.tint32;
12124         result = e;
12125     }
12126 
visit(ModuleInitExp e)12127     override void visit(ModuleInitExp e)
12128     {
12129         //printf("ModuleInitExp::semantic()\n");
12130         e.type = Type.tstring;
12131         result = e;
12132     }
12133 
visit(FuncInitExp e)12134     override void visit(FuncInitExp e)
12135     {
12136         //printf("FuncInitExp::semantic()\n");
12137         e.type = Type.tstring;
12138         if (sc.func)
12139         {
12140             result = e.resolveLoc(Loc.initial, sc);
12141             return;
12142         }
12143         result = e;
12144     }
12145 
visit(PrettyFuncInitExp e)12146     override void visit(PrettyFuncInitExp e)
12147     {
12148         //printf("PrettyFuncInitExp::semantic()\n");
12149         e.type = Type.tstring;
12150         if (sc.func)
12151         {
12152             result = e.resolveLoc(Loc.initial, sc);
12153             return;
12154         }
12155 
12156         result = e;
12157     }
12158 }
12159 
12160 /**********************************
12161  * Try to run semantic routines.
12162  * If they fail, return NULL.
12163  */
trySemantic(Expression exp,Scope * sc)12164 Expression trySemantic(Expression exp, Scope* sc)
12165 {
12166     //printf("+trySemantic(%s)\n", exp.toChars());
12167     uint errors = global.startGagging();
12168     Expression e = expressionSemantic(exp, sc);
12169     if (global.endGagging(errors))
12170     {
12171         e = null;
12172     }
12173     //printf("-trySemantic(%s)\n", exp.toChars());
12174     return e;
12175 }
12176 
12177 /**************************
12178  * Helper function for easy error propagation.
12179  * If error occurs, returns ErrorExp. Otherwise returns NULL.
12180  */
unaSemantic(UnaExp e,Scope * sc)12181 Expression unaSemantic(UnaExp e, Scope* sc)
12182 {
12183     static if (LOGSEMANTIC)
12184     {
12185         printf("UnaExp::semantic('%s')\n", e.toChars());
12186     }
12187     Expression e1x = e.e1.expressionSemantic(sc);
12188     if (e1x.op == EXP.error)
12189         return e1x;
12190     e.e1 = e1x;
12191     return null;
12192 }
12193 
12194 /**************************
12195  * Helper function for easy error propagation.
12196  * If error occurs, returns ErrorExp. Otherwise returns NULL.
12197  */
binSemantic(BinExp e,Scope * sc)12198 Expression binSemantic(BinExp e, Scope* sc)
12199 {
12200     static if (LOGSEMANTIC)
12201     {
12202         printf("BinExp::semantic('%s')\n", e.toChars());
12203     }
12204     Expression e1x = e.e1.expressionSemantic(sc);
12205     Expression e2x = e.e2.expressionSemantic(sc);
12206 
12207     // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
12208     if (e1x.op == EXP.type)
12209         e1x = resolveAliasThis(sc, e1x);
12210     if (e2x.op == EXP.type)
12211         e2x = resolveAliasThis(sc, e2x);
12212 
12213     if (e1x.op == EXP.error)
12214         return e1x;
12215     if (e2x.op == EXP.error)
12216         return e2x;
12217     e.e1 = e1x;
12218     e.e2 = e2x;
12219     return null;
12220 }
12221 
binSemanticProp(BinExp e,Scope * sc)12222 Expression binSemanticProp(BinExp e, Scope* sc)
12223 {
12224     if (Expression ex = binSemantic(e, sc))
12225         return ex;
12226     Expression e1x = resolveProperties(sc, e.e1);
12227     Expression e2x = resolveProperties(sc, e.e2);
12228     if (e1x.op == EXP.error)
12229         return e1x;
12230     if (e2x.op == EXP.error)
12231         return e2x;
12232     e.e1 = e1x;
12233     e.e2 = e2x;
12234     return null;
12235 }
12236 
12237 // entrypoint for semantic ExpressionSemanticVisitor
expressionSemantic(Expression e,Scope * sc)12238 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
12239 {
12240     scope v = new ExpressionSemanticVisitor(sc);
12241     e.accept(v);
12242     return v.result;
12243 }
12244 
semanticX(DotIdExp exp,Scope * sc)12245 Expression semanticX(DotIdExp exp, Scope* sc)
12246 {
12247     //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
12248     if (Expression ex = unaSemantic(exp, sc))
12249         return ex;
12250 
12251     if (!(sc.flags & SCOPE.Cfile) && exp.ident == Id._mangleof)
12252     {
12253         // symbol.mangleof
12254 
12255         // return mangleof as an Expression
12256         static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
12257         {
12258             assert(ds);
12259             if (auto f = ds.isFuncDeclaration())
12260             {
12261                 if (f.checkForwardRef(loc))
12262                     return ErrorExp.get();
12263 
12264                 if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
12265                                FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
12266                 {
12267                     f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
12268                     return ErrorExp.get();
12269                 }
12270             }
12271             OutBuffer buf;
12272             mangleToBuffer(ds, &buf);
12273             Expression e = new StringExp(loc, buf.extractSlice());
12274             return e.expressionSemantic(sc);
12275         }
12276 
12277         Dsymbol ds;
12278         switch (exp.e1.op)
12279         {
12280             case EXP.scope_:      return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
12281             case EXP.variable:    return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
12282             case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
12283             case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
12284             case EXP.template_:
12285             {
12286                 TemplateExp te = exp.e1.isTemplateExp();
12287                 return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
12288             }
12289 
12290             default:
12291                 break;
12292         }
12293     }
12294 
12295     if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
12296     {
12297         // bypass checkPurity
12298         return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
12299     }
12300 
12301     if (!exp.e1.isDotExp())
12302     {
12303         exp.e1 = resolvePropertiesX(sc, exp.e1);
12304     }
12305 
12306     if (auto te = exp.e1.isTupleExp())
12307     {
12308         if (exp.ident == Id.offsetof)
12309         {
12310             /* 'distribute' the .offsetof to each of the tuple elements.
12311              */
12312             auto exps = new Expressions(te.exps.dim);
12313             foreach (i, e; (*te.exps)[])
12314             {
12315                 (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
12316             }
12317             // Don't evaluate te.e0 in runtime
12318             Expression e = new TupleExp(exp.loc, null, exps);
12319             e = e.expressionSemantic(sc);
12320             return e;
12321         }
12322         if (exp.ident == Id.length)
12323         {
12324             // Don't evaluate te.e0 in runtime
12325             return new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
12326         }
12327     }
12328 
12329     // https://issues.dlang.org/show_bug.cgi?id=14416
12330     // Template has no built-in properties except for 'stringof'.
12331     if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
12332     {
12333         exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12334         return ErrorExp.get();
12335     }
12336     if (!exp.e1.type)
12337     {
12338         exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12339         return ErrorExp.get();
12340     }
12341 
12342     return exp;
12343 }
12344 
12345 /******************************
12346  * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
12347  * Params:
12348  *      exp = expression to resolve
12349  *      sc = context
12350  *      flag = if 1 then do not emit error messages, just return null
12351  * Returns:
12352  *      resolved expression, null if error
12353  */
semanticY(DotIdExp exp,Scope * sc,int flag)12354 Expression semanticY(DotIdExp exp, Scope* sc, int flag)
12355 {
12356     //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
12357 
12358     //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
12359 
12360     const cfile = (sc.flags & SCOPE.Cfile) != 0;
12361 
12362     /* Special case: rewrite this.id and super.id
12363      * to be classtype.id and baseclasstype.id
12364      * if we have no this pointer.
12365      */
12366     if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
12367     {
12368         if (AggregateDeclaration ad = sc.getStructClassScope())
12369         {
12370             if (exp.e1.isThisExp())
12371             {
12372                 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
12373             }
12374             else
12375             {
12376                 if (auto cd = ad.isClassDeclaration())
12377                 {
12378                     if (cd.baseClass)
12379                         exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
12380                 }
12381             }
12382         }
12383     }
12384 
12385     {
12386         Expression e = semanticX(exp, sc);
12387         if (e != exp)
12388             return e;
12389     }
12390 
12391     Expression eleft;
12392     Expression eright;
12393     if (auto de = exp.e1.isDotExp())
12394     {
12395         eleft = de.e1;
12396         eright = de.e2;
12397     }
12398     else
12399     {
12400         eleft = null;
12401         eright = exp.e1;
12402     }
12403 
12404     Type t1b = exp.e1.type.toBasetype();
12405 
12406     if (auto ie = eright.isScopeExp()) // also used for template alias's
12407     {
12408         auto flags = SearchLocalsOnly;
12409         /* Disable access to another module's private imports.
12410          * The check for 'is sds our current module' is because
12411          * the current module should have access to its own imports.
12412          */
12413         if (ie.sds.isModule() && ie.sds != sc._module)
12414             flags |= IgnorePrivateImports;
12415         if (sc.flags & SCOPE.ignoresymbolvisibility)
12416             flags |= IgnoreSymbolVisibility;
12417         Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
12418         /* Check for visibility before resolving aliases because public
12419          * aliases to private symbols are public.
12420          */
12421         if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
12422         {
12423             s = null;
12424         }
12425         if (s)
12426         {
12427             auto p = s.isPackage();
12428             if (p && checkAccess(sc, p))
12429             {
12430                 s = null;
12431             }
12432         }
12433         if (s)
12434         {
12435             // if 's' is a tuple variable, the tuple is returned.
12436             s = s.toAlias();
12437 
12438             exp.checkDeprecated(sc, s);
12439             exp.checkDisabled(sc, s);
12440 
12441             if (auto em = s.isEnumMember())
12442             {
12443                 return em.getVarExp(exp.loc, sc);
12444             }
12445             if (auto v = s.isVarDeclaration())
12446             {
12447                 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
12448                 if (!v.type ||
12449                     !v.type.deco && v.inuse)
12450                 {
12451                     if (v.inuse)
12452                         exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
12453                     else
12454                         exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
12455                     return ErrorExp.get();
12456                 }
12457                 if (v.type.isTypeError())
12458                     return ErrorExp.get();
12459 
12460                 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
12461                 {
12462                     /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
12463                      * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
12464                      * be reverted. `wantsym` is the hack to work around the problem.
12465                      */
12466                     if (v.inuse)
12467                     {
12468                         error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
12469                         return ErrorExp.get();
12470                     }
12471                     auto e = v.expandInitializer(exp.loc);
12472                     v.inuse++;
12473                     e = e.expressionSemantic(sc);
12474                     v.inuse--;
12475                     return e;
12476                 }
12477 
12478                 Expression e;
12479                 if (v.needThis())
12480                 {
12481                     if (!eleft)
12482                         eleft = new ThisExp(exp.loc);
12483                     e = new DotVarExp(exp.loc, eleft, v);
12484                     e = e.expressionSemantic(sc);
12485                 }
12486                 else
12487                 {
12488                     e = new VarExp(exp.loc, v);
12489                     if (eleft)
12490                     {
12491                         e = new CommaExp(exp.loc, eleft, e);
12492                         e.type = v.type;
12493                     }
12494                 }
12495                 e = e.deref();
12496                 return e.expressionSemantic(sc);
12497             }
12498 
12499             if (auto f = s.isFuncDeclaration())
12500             {
12501                 //printf("it's a function\n");
12502                 if (!f.functionSemantic())
12503                     return ErrorExp.get();
12504                 Expression e;
12505                 if (f.needThis())
12506                 {
12507                     if (!eleft)
12508                         eleft = new ThisExp(exp.loc);
12509                     e = new DotVarExp(exp.loc, eleft, f, true);
12510                     e = e.expressionSemantic(sc);
12511                 }
12512                 else
12513                 {
12514                     e = new VarExp(exp.loc, f, true);
12515                     if (eleft)
12516                     {
12517                         e = new CommaExp(exp.loc, eleft, e);
12518                         e.type = f.type;
12519                     }
12520                 }
12521                 return e;
12522             }
12523             if (auto td = s.isTemplateDeclaration())
12524             {
12525                 Expression e;
12526                 if (eleft)
12527                     e = new DotTemplateExp(exp.loc, eleft, td);
12528                 else
12529                     e = new TemplateExp(exp.loc, td);
12530                 e = e.expressionSemantic(sc);
12531                 return e;
12532             }
12533             if (OverDeclaration od = s.isOverDeclaration())
12534             {
12535                 Expression e = new VarExp(exp.loc, od, true);
12536                 if (eleft)
12537                 {
12538                     e = new CommaExp(exp.loc, eleft, e);
12539                     e.type = Type.tvoid; // ambiguous type?
12540                 }
12541                 return e.expressionSemantic(sc);
12542             }
12543             if (auto o = s.isOverloadSet())
12544             {
12545                 //printf("'%s' is an overload set\n", o.toChars());
12546                 return new OverExp(exp.loc, o);
12547             }
12548 
12549             if (auto t = s.getType())
12550             {
12551                 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
12552             }
12553 
12554             if (auto tup = s.isTupleDeclaration())
12555             {
12556                 if (eleft)
12557                 {
12558                     Expression e = new DotVarExp(exp.loc, eleft, tup);
12559                     e = e.expressionSemantic(sc);
12560                     return e;
12561                 }
12562                 Expression e = new TupleExp(exp.loc, tup);
12563                 e = e.expressionSemantic(sc);
12564                 return e;
12565             }
12566 
12567             if (auto sds = s.isScopeDsymbol())
12568             {
12569                 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
12570                 Expression e = new ScopeExp(exp.loc, sds);
12571                 e = e.expressionSemantic(sc);
12572                 if (eleft)
12573                     e = new DotExp(exp.loc, eleft, e);
12574                 return e;
12575             }
12576 
12577             if (auto imp = s.isImport())
12578             {
12579                 Expression se = new ScopeExp(exp.loc, imp.pkg);
12580                 return se.expressionSemantic(sc);
12581             }
12582             // BUG: handle other cases like in IdentifierExp::semantic()
12583             debug
12584             {
12585                 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
12586             }
12587             assert(0);
12588         }
12589         else if (exp.ident == Id.stringof)
12590         {
12591             Expression e = new StringExp(exp.loc, ie.toString());
12592             e = e.expressionSemantic(sc);
12593             return e;
12594         }
12595         if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
12596         {
12597             flag = 0;
12598         }
12599         if (flag)
12600             return null;
12601         s = ie.sds.search_correct(exp.ident);
12602         if (s && symbolIsVisible(sc, s))
12603         {
12604             if (s.isPackage())
12605                 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
12606             else
12607                 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());
12608         }
12609         else
12610             exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
12611         return ErrorExp.get();
12612     }
12613     else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum &&
12614              !(
12615                exp.ident == Id.__sizeof ||
12616                exp.ident == Id.__xalignof ||
12617                !cfile &&
12618                 (exp.ident == Id._mangleof ||
12619                  exp.ident == Id.offsetof ||
12620                  exp.ident == Id._init ||
12621                  exp.ident == Id.stringof)
12622               ))
12623     {
12624         Type t1bn = t1b.nextOf();
12625         if (flag)
12626         {
12627             if (AggregateDeclaration ad = isAggregate(t1bn))
12628             {
12629                 if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
12630                     return null;
12631             }
12632         }
12633 
12634         /* Rewrite:
12635          *   p.ident
12636          * as:
12637          *   (*p).ident
12638          */
12639         if (flag && t1bn.ty == Tvoid)
12640             return null;
12641         Expression e = new PtrExp(exp.loc, exp.e1);
12642         e = e.expressionSemantic(sc);
12643         return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12644     }
12645     else if (exp.ident == Id.__xalignof &&
12646              exp.e1.isVarExp() &&
12647              exp.e1.isVarExp().var.isVarDeclaration() &&
12648              !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
12649     {
12650         // For `x.alignof` get the alignment of the variable, not the alignment of its type
12651         const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
12652         const naturalAlignment = exp.e1.type.alignsize();
12653         const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
12654         Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
12655         return e;
12656     }
12657     else if (cfile && exp.ident == Id.__sizeof && exp.e1.isStringExp())
12658     {
12659         // Sizeof string literal includes the terminating 0
12660         auto se = exp.e1.isStringExp();
12661         Expression e = new IntegerExp(exp.loc, (se.len + 1) * se.sz, Type.tsize_t);
12662         return e;
12663     }
12664     else
12665     {
12666         if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
12667             flag = 0;
12668         Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12669         if (e)
12670             e = e.expressionSemantic(sc);
12671         return e;
12672     }
12673 }
12674 
12675 // Resolve e1.ident!tiargs without seeing UFCS.
12676 // If flag == 1, stop "not a property" error and return NULL.
semanticY(DotTemplateInstanceExp exp,Scope * sc,int flag)12677 Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
12678 {
12679     static if (LOGSEMANTIC)
12680     {
12681         printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
12682     }
12683 
12684     static Expression errorExp()
12685     {
12686         return ErrorExp.get();
12687     }
12688 
12689     Expression e1 = exp.e1;
12690 
12691     if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
12692     {
12693         // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
12694         // and do the symbol search in that context (Issue: 19476)
12695         auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
12696         e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12697     }
12698 
12699     auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12700 
12701     Expression e = die.semanticX(sc);
12702     if (e == die)
12703     {
12704         exp.e1 = die.e1; // take back
12705         Type t1b = exp.e1.type.toBasetype();
12706         if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12707         {
12708             /* No built-in type has templatized properties, so do shortcut.
12709              * It is necessary in: 1024.max!"a < b"
12710              */
12711             if (flag)
12712                 return null;
12713         }
12714         e = die.semanticY(sc, flag);
12715         if (flag)
12716         {
12717             if (!e ||
12718                 isDotOpDispatch(e))
12719             {
12720                 /* opDispatch!tiargs would be a function template that needs IFTI,
12721                  * so it's not a template
12722                  */
12723                 return null;
12724             }
12725         }
12726     }
12727     assert(e);
12728 
12729     if (e.op == EXP.error)
12730         return e;
12731     if (DotVarExp dve = e.isDotVarExp())
12732     {
12733         if (FuncDeclaration fd = dve.var.isFuncDeclaration())
12734         {
12735             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12736             {
12737                 e = new DotTemplateExp(dve.loc, dve.e1, td);
12738                 e = e.expressionSemantic(sc);
12739             }
12740         }
12741         else if (OverDeclaration od = dve.var.isOverDeclaration())
12742         {
12743             exp.e1 = dve.e1; // pull semantic() result
12744 
12745             if (!exp.findTempDecl(sc))
12746                 goto Lerr;
12747             if (exp.ti.needsTypeInference(sc))
12748                 return exp;
12749             exp.ti.dsymbolSemantic(sc);
12750             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12751                 return errorExp();
12752 
12753             if (Declaration v = exp.ti.toAlias().isDeclaration())
12754             {
12755                 if (v.type && !v.type.deco)
12756                     v.type = v.type.typeSemantic(v.loc, sc);
12757                 return new DotVarExp(exp.loc, exp.e1, v)
12758                        .expressionSemantic(sc);
12759             }
12760             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12761                    .expressionSemantic(sc);
12762         }
12763     }
12764     else if (e.op == EXP.variable)
12765     {
12766         VarExp ve = cast(VarExp)e;
12767         if (FuncDeclaration fd = ve.var.isFuncDeclaration())
12768         {
12769             if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12770             {
12771                 e = new TemplateExp(ve.loc, td)
12772                     .expressionSemantic(sc);
12773             }
12774         }
12775         else if (OverDeclaration od = ve.var.isOverDeclaration())
12776         {
12777             exp.ti.tempdecl = od;
12778             return new ScopeExp(exp.loc, exp.ti)
12779                    .expressionSemantic(sc);
12780         }
12781     }
12782 
12783     if (DotTemplateExp dte = e.isDotTemplateExp())
12784     {
12785         exp.e1 = dte.e1; // pull semantic() result
12786 
12787         exp.ti.tempdecl = dte.td;
12788         if (!exp.ti.semanticTiargs(sc))
12789             return errorExp();
12790         if (exp.ti.needsTypeInference(sc))
12791             return exp;
12792         exp.ti.dsymbolSemantic(sc);
12793         if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12794             return errorExp();
12795 
12796         if (Declaration v = exp.ti.toAlias().isDeclaration())
12797         {
12798             if (v.isFuncDeclaration() || v.isVarDeclaration())
12799             {
12800                 return new DotVarExp(exp.loc, exp.e1, v)
12801                        .expressionSemantic(sc);
12802             }
12803         }
12804         return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12805                .expressionSemantic(sc);
12806     }
12807     else if (e.op == EXP.template_)
12808     {
12809         exp.ti.tempdecl = (cast(TemplateExp)e).td;
12810         return new ScopeExp(exp.loc, exp.ti)
12811                .expressionSemantic(sc);
12812     }
12813     else if (DotExp de = e.isDotExp())
12814     {
12815         if (de.e2.op == EXP.overloadSet)
12816         {
12817             if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
12818             {
12819                 return errorExp();
12820             }
12821             if (exp.ti.needsTypeInference(sc))
12822                 return exp;
12823             exp.ti.dsymbolSemantic(sc);
12824             if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12825                 return errorExp();
12826 
12827             if (Declaration v = exp.ti.toAlias().isDeclaration())
12828             {
12829                 if (v.type && !v.type.deco)
12830                     v.type = v.type.typeSemantic(v.loc, sc);
12831                 return new DotVarExp(exp.loc, exp.e1, v)
12832                        .expressionSemantic(sc);
12833             }
12834             return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12835                    .expressionSemantic(sc);
12836         }
12837     }
12838     else if (OverExp oe = e.isOverExp())
12839     {
12840         exp.ti.tempdecl = oe.vars;
12841         return new ScopeExp(exp.loc, exp.ti)
12842                .expressionSemantic(sc);
12843     }
12844 
12845 Lerr:
12846     exp.error("`%s` isn't a template", e.toChars());
12847     return errorExp();
12848 }
12849 
12850 /***************************************
12851  * If expression is shared, check that we can access it.
12852  * Give error message if not.
12853  *
12854  * Params:
12855  *      e = expression to check
12856  *      sc = context
12857  *      returnRef = Whether this expression is for a `return` statement
12858  *                  off a `ref` function, in which case a single level
12859  *                  of dereference is allowed (e.g. `shared(int)*`).
12860  * Returns:
12861  *      true on error
12862  */
12863 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
12864 {
12865     if (!global.params.noSharedAccess ||
12866         sc.intypeof ||
12867         sc.flags & SCOPE.ctfe)
12868     {
12869         return false;
12870     }
12871 
12872     //printf("checkSharedAccess() `%s` returnRef: %d\n", e.toChars(), returnRef);
12873 
12874     /* In case we don't know which expression triggered it,
12875      * e.g. for `visit(Type)` overload
12876      */
12877     Expression original = e;
12878 
check(Expression e,bool allowRef)12879     bool check(Expression e, bool allowRef)
12880     {
12881         bool sharedError(Expression e)
12882         {
12883             // https://dlang.org/phobos/core_atomic.html
12884             e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
12885             return true;
12886         }
12887 
12888         // Error by default
12889         bool visit(Expression e)
12890         {
12891             if (e.type.isShared())
12892                 return sharedError(e);
12893             return false;
12894         }
12895 
12896         bool visitNew(NewExp e)
12897         {
12898             if (e.thisexp)
12899                 check(e.thisexp, false);
12900             // Note: This handles things like `new shared(Throwable).msg`,
12901             // where accessing `msg` would violate `shared`.
12902             if (e.newtype.isShared())
12903                 return sharedError(original);
12904             return false;
12905         }
12906 
12907         bool visitVar(VarExp e)
12908         {
12909             if (!allowRef && e.var.type.isShared())
12910                 return sharedError(e);
12911             return false;
12912         }
12913 
12914         bool visitAddr(AddrExp e)
12915         {
12916             return check(e.e1, true);
12917         }
12918 
12919         bool visitPtr(PtrExp e)
12920         {
12921             if (!allowRef && e.type.isShared())
12922                 return sharedError(e);
12923 
12924             if (e.e1.type.isShared())
12925                 return sharedError(e);
12926 
12927             return check(e.e1, false);
12928         }
12929 
12930         bool visitDotVar(DotVarExp e)
12931         {
12932             auto fd = e.var.isFuncDeclaration();
12933             const sharedFunc = fd && fd.type.isShared;
12934 
12935             if (!allowRef && e.type.isShared() && !sharedFunc)
12936                 return sharedError(e);
12937 
12938             // Allow using `DotVarExp` within value types
12939             if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
12940                 return check(e.e1, allowRef);
12941 
12942             // If we end up with a single `VarExp`, it might be a `ref` param
12943             // `shared ref T` param == `shared(T)*`.
12944             if (auto ve = e.e1.isVarExp())
12945             {
12946                 return check(e.e1, allowRef && (ve.var.storage_class & STC.ref_));
12947             }
12948 
12949             return check(e.e1, false);
12950         }
12951 
12952         bool visitIndex(IndexExp e)
12953         {
12954             if (!allowRef && e.type.isShared())
12955                 return sharedError(e);
12956 
12957             if (e.e1.type.isShared())
12958                 return sharedError(e);
12959 
12960             return check(e.e1, false);
12961         }
12962 
12963         bool visitComma(CommaExp e)
12964         {
12965             // Cannot be `return ref` since we can't use the return,
12966             // but it's better to show that error than an unrelated `shared` one
12967             return check(e.e2, true);
12968         }
12969 
12970         switch (e.op)
12971         {
12972             default:              return visit(e);
12973 
12974             // Those have no indirections / can be ignored
12975             case EXP.call:
12976             case EXP.error:
12977             case EXP.complex80:
12978             case EXP.int64:
12979             case EXP.null_:       return false;
12980 
12981             case EXP.variable:    return visitVar(e.isVarExp());
12982             case EXP.new_:        return visitNew(e.isNewExp());
12983             case EXP.address:     return visitAddr(e.isAddrExp());
12984             case EXP.star:        return visitPtr(e.isPtrExp());
12985             case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
12986             case EXP.index:       return visitIndex(e.isIndexExp());
12987         }
12988     }
12989 
12990     return check(e, returnRef);
12991 }
12992 
12993 
12994 
12995 /****************************************************
12996  * Determine if `exp`, which gets its address taken, can do so safely.
12997  * Params:
12998  *      sc = context
12999  *      exp = expression having its address taken
13000  *      v = the variable getting its address taken
13001  * Returns:
13002  *      `true` if ok, `false` for error
13003  */
checkAddressVar(Scope * sc,Expression exp,VarDeclaration v)13004 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
13005 {
13006     //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
13007     if (v)
13008     {
13009         if (!v.canTakeAddressOf())
13010         {
13011             exp.error("cannot take address of `%s`", exp.toChars());
13012             return false;
13013         }
13014         if (sc.func && !sc.intypeof && !v.isDataseg())
13015         {
13016             const(char)* p = v.isParameter() ? "parameter" : "local";
13017             if (global.params.useDIP1000 == FeatureState.enabled)
13018             {
13019                 // Taking the address of v means it cannot be set to 'scope' later
13020                 v.storage_class &= ~STC.maybescope;
13021                 v.doNotInferScope = true;
13022                 if (exp.type.hasPointers() && v.storage_class & STC.scope_ &&
13023                     !(v.storage_class & STC.temp) &&
13024                     !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
13025                 {
13026                     exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
13027                     return false;
13028                 }
13029             }
13030             else if (!(sc.flags & SCOPE.debug_) &&
13031                      !(v.storage_class & STC.temp) &&
13032                      sc.func.setUnsafe())
13033             {
13034                 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
13035                 return false;
13036             }
13037         }
13038     }
13039     return true;
13040 }
13041 
13042 /****************************************************
13043  * Determine if the address of a `ref return` value of
13044  * a function call with type `tf` can be taken safely.
13045  *
13046  * This is currently stricter than necessary: it can be safe to take the
13047  * address of a `ref` with pointer type when the pointer isn't `scope`, but
13048  * that involves inspecting the function arguments and parameter types, which
13049  * is left as a future enhancement.
13050  *
13051  * Params:
13052  *      sc = context
13053  *      ce = function call in question
13054  *      action = for the error message, how the pointer is taken, e.g. "slice static array of"
13055  * Returns:
13056  *      `true` if ok, `false` for error
13057  */
checkAddressCall(Scope * sc,CallExp ce,const (char)* action)13058 private bool checkAddressCall(Scope* sc, CallExp ce, const(char)* action)
13059 {
13060     if (auto tf = ce.e1.type.isTypeFunction())
13061     {
13062         if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
13063             && tf.next.hasPointers() && sc.func.setUnsafe())
13064         {
13065             ce.error("cannot %s `ref return` of `%s()` in `@safe` function `%s`",
13066                 action, ce.e1.toChars(), sc.func.toChars());
13067             ce.errorSupplemental("return type `%s` has pointers that may be `scope`", tf.next.toChars());
13068             return false;
13069         }
13070     }
13071     return true;
13072 }
13073 
13074 /*******************************
13075  * Checks the attributes of a function.
13076  * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
13077  * and usage of `deprecated` and `@disabled`-ed symbols are checked.
13078  *
13079  * Params:
13080  *  exp = expression to check attributes for
13081  *  sc  = scope of the function
13082  *  f   = function to be checked
13083  * Returns: `true` if error occur.
13084  */
checkFunctionAttributes(Expression exp,Scope * sc,FuncDeclaration f)13085 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
13086 {
13087     with(exp)
13088     {
13089         bool error = checkDisabled(sc, f);
13090         error |= checkDeprecated(sc, f);
13091         error |= checkPurity(sc, f);
13092         error |= checkSafety(sc, f);
13093         error |= checkNogc(sc, f);
13094         return error;
13095     }
13096 }
13097 
13098 /*******************************
13099  * Helper function for `getRightThis()`.
13100  * Gets `this` of the next outer aggregate.
13101  * Params:
13102  *      loc = location to use for error messages
13103  *      sc = context
13104  *      s = the parent symbol of the existing `this`
13105  *      ad = struct or class we need the correct `this` for
13106  *      e1 = existing `this`
13107  *      t = type of the existing `this`
13108  *      var = the specific member of ad we're accessing
13109  *      flag = if true, return `null` instead of throwing an error
13110  * Returns:
13111  *      Expression representing the `this` for the var
13112  */
13113 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
13114 {
13115     int n = 0;
13116     while (s && s.isFuncDeclaration())
13117     {
13118         FuncDeclaration f = s.isFuncDeclaration();
13119         if (f.vthis)
13120         {
13121             n++;
13122             e1 = new VarExp(loc, f.vthis);
13123             if (f.hasDualContext())
13124             {
13125                 // (*__this)[i]
13126                 if (n > 1)
13127                     e1 = e1.expressionSemantic(sc);
13128                 e1 = new PtrExp(loc, e1);
13129                 uint i = f.followInstantiationContext(ad);
13130                 e1 = new IndexExp(loc, e1, new IntegerExp(i));
13131                 s = f.toParentP(ad);
13132                 continue;
13133             }
13134         }
13135         else
13136         {
13137             if (flag)
13138                 return null;
13139             e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
13140             e1 = ErrorExp.get();
13141             return e1;
13142         }
13143         s = s.toParent2();
13144     }
13145     if (n > 1 || e1.op == EXP.index)
13146         e1 = e1.expressionSemantic(sc);
13147     if (s && e1.type.equivalent(Type.tvoidptr))
13148     {
13149         if (auto sad = s.isAggregateDeclaration())
13150         {
13151             Type ta = sad.handleType();
13152             if (ta.ty == Tstruct)
13153                 ta = ta.pointerTo();
13154             e1.type = ta;
13155         }
13156     }
13157     e1.type = e1.type.addMod(t.mod);
13158     return e1;
13159 }
13160 
13161 /*******************************
13162  * Make a dual-context container for use as a `this` argument.
13163  * Params:
13164  *      loc = location to use for error messages
13165  *      sc = current scope
13166  *      fd = target function that will take the `this` argument
13167  * Returns:
13168  *      Temporary closure variable.
13169  * Note:
13170  *      The function `fd` is added to the nested references of the
13171  *      newly created variable such that a closure is made for the variable when
13172  *      the address of `fd` is taken.
13173  */
makeThis2Argument(const ref Loc loc,Scope * sc,FuncDeclaration fd)13174 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
13175 {
13176     Type tthis2 = Type.tvoidptr.sarrayOf(2);
13177     VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
13178     vthis2.storage_class |= STC.temp;
13179     vthis2.dsymbolSemantic(sc);
13180     vthis2.parent = sc.parent;
13181     // make it a closure var
13182     assert(sc.func);
13183     sc.func.closureVars.push(vthis2);
13184     // add `fd` to the nested refs
13185     vthis2.nestedrefs.push(fd);
13186     return vthis2;
13187 }
13188 
13189 /*******************************
13190  * Make sure that the runtime hook `id` exists.
13191  * Params:
13192  *      loc = location to use for error messages
13193  *      sc = current scope
13194  *      id = the hook identifier
13195  *      description = what the hook does
13196  *      module_ = what module the hook is located in
13197  * Returns:
13198  *      a `bool` indicating if the hook is present.
13199  */
13200 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
13201 {
13202     auto rootSymbol = sc.search(loc, Id.empty, null);
13203     if (auto moduleSymbol = rootSymbol.search(loc, module_))
13204         if (moduleSymbol.search(loc, id))
13205           return true;
13206     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);
13207     return false;
13208 }
13209 
13210 /***************************************
13211  * Fit elements[] to the corresponding types of the `sd`'s fields.
13212  *
13213  * Params:
13214  *      sd = the struct declaration
13215  *      loc = location to use for error messages
13216  *      sc = context
13217  *      elements = explicit arguments used to construct object
13218  *      stype = the constructed object type.
13219  * Returns:
13220  *      false if any errors occur,
13221  *      otherwise true and elements[] are rewritten for the output.
13222  */
fit(StructDeclaration sd,const ref Loc loc,Scope * sc,Expressions * elements,Type stype)13223 private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
13224 {
13225     if (!elements)
13226         return true;
13227 
13228     const nfields = sd.nonHiddenFields();
13229     size_t offset = 0;
13230     for (size_t i = 0; i < elements.dim; i++)
13231     {
13232         Expression e = (*elements)[i];
13233         if (!e)
13234             continue;
13235 
13236         e = resolveProperties(sc, e);
13237         if (i >= nfields)
13238         {
13239             if (i < sd.fields.dim && e.op == EXP.null_)
13240             {
13241                 // CTFE sometimes creates null as hidden pointer; we'll allow this.
13242                 continue;
13243             }
13244                 .error(loc, "more initializers than fields (%llu) of `%s`", cast(ulong)nfields, sd.toChars());
13245             return false;
13246         }
13247         VarDeclaration v = sd.fields[i];
13248         if (v.offset < offset)
13249         {
13250             .error(loc, "overlapping initialization for `%s`", v.toChars());
13251             if (!sd.isUnionDeclaration())
13252             {
13253                 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
13254                     " must initialize only the first member of a `union`. All subsequent" ~
13255                     " non-overlapping fields are default initialized";
13256                 .errorSupplemental(loc, errorMsg);
13257             }
13258             return false;
13259         }
13260         const vsize = v.type.size();
13261         if (vsize == SIZE_INVALID)
13262             return false;
13263         offset = cast(uint)(v.offset + vsize);
13264 
13265         Type t = v.type;
13266         if (stype)
13267             t = t.addMod(stype.mod);
13268         Type origType = t;
13269         Type tb = t.toBasetype();
13270 
13271         const hasPointers = tb.hasPointers();
13272         if (hasPointers)
13273         {
13274             if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
13275                  (v.offset & (target.ptrsize - 1))) &&
13276                 (sc.func && sc.func.setUnsafe()))
13277             {
13278                 .error(loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
13279                        sd.toChars(), v.toChars());
13280                 return false;
13281             }
13282         }
13283 
13284         /* Look for case of initializing a static array with a too-short
13285          * string literal, such as:
13286          *  char[5] foo = "abc";
13287          * Allow this by doing an explicit cast, which will lengthen the string
13288          * literal.
13289          */
13290         if (e.op == EXP.string_ && tb.ty == Tsarray)
13291         {
13292             StringExp se = cast(StringExp)e;
13293             Type typeb = se.type.toBasetype();
13294             TY tynto = tb.nextOf().ty;
13295             if (!se.committed &&
13296                 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
13297                 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
13298             {
13299                 e = se.castTo(sc, t);
13300                 goto L1;
13301             }
13302         }
13303 
13304         while (!e.implicitConvTo(t) && tb.ty == Tsarray)
13305         {
13306             /* Static array initialization, as in:
13307              *  T[3][5] = e;
13308              */
13309             t = tb.nextOf();
13310             tb = t.toBasetype();
13311         }
13312         if (!e.implicitConvTo(t))
13313             t = origType; // restore type for better diagnostic
13314 
13315         e = e.implicitCastTo(sc, t);
13316     L1:
13317         if (e.op == EXP.error)
13318             return false;
13319 
13320         (*elements)[i] = doCopyOrMove(sc, e);
13321     }
13322     return true;
13323 }
13324 
13325 
13326 /**
13327  * Returns `em` as a VariableExp
13328  * Params:
13329  *     em = the EnumMember to wrap
13330  *     loc = location of use of em
13331  *     sc = scope of use of em
13332  * Returns:
13333  *     VarExp referenceing `em` or ErrorExp if `em` if disabled/deprecated
13334  */
getVarExp(EnumMember em,const ref Loc loc,Scope * sc)13335 Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
13336 {
13337     dsymbolSemantic(em, sc);
13338     if (em.errors)
13339         return ErrorExp.get();
13340     em.checkDisabled(loc, sc);
13341 
13342     if (em.depdecl && !em.depdecl._scope)
13343         em.depdecl._scope = sc;
13344     em.checkDeprecated(loc, sc);
13345 
13346     if (em.errors)
13347         return ErrorExp.get();
13348     Expression e = new VarExp(loc, em);
13349     e = e.expressionSemantic(sc);
13350     if (!(sc.flags & SCOPE.Cfile) && em.isCsymbol())
13351     {
13352         /* C11 types them as int. But if in D file,
13353          * type qualified names as the enum
13354          */
13355         e.type = em.parent.isEnumDeclaration().type;
13356         assert(e.type);
13357     }
13358     return e;
13359 }
13360 
13361 
13362 /*****************************
13363  * Try to treat `exp` as a boolean,
13364  * Params:
13365  *     exp = the expression
13366  *     sc = scope to evalute `exp` in
13367  * Returns:
13368  *     Modified expression on success, ErrorExp on error
13369  */
toBoolean(Expression exp,Scope * sc)13370 Expression toBoolean(Expression exp, Scope* sc)
13371 {
13372     switch(exp.op)
13373     {
13374         case EXP.delete_:
13375             exp.error("`delete` does not give a boolean result");
13376             return ErrorExp.get();
13377 
13378         case EXP.comma:
13379             auto ce = exp.isCommaExp();
13380             auto ex2 = ce.e2.toBoolean(sc);
13381             if (ex2.op == EXP.error)
13382                 return ex2;
13383             ce.e2 = ex2;
13384             ce.type = ce.e2.type;
13385             return ce;
13386 
13387         case EXP.assign:
13388         case EXP.construct:
13389         case EXP.blit:
13390             if (sc.flags & SCOPE.Cfile)
13391                 return exp;
13392             // Things like:
13393             //  if (a = b) ...
13394             // are usually mistakes.
13395             exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
13396             return ErrorExp.get();
13397 
13398         //LogicalExp
13399         case EXP.andAnd:
13400         case EXP.orOr:
13401             auto le = exp.isLogicalExp();
13402             auto ex2 = le.e2.toBoolean(sc);
13403             if (ex2.op == EXP.error)
13404                 return ex2;
13405             le.e2 = ex2;
13406             return le;
13407 
13408         case EXP.question:
13409             auto ce = exp.isCondExp();
13410             auto ex1 = ce.e1.toBoolean(sc);
13411             auto ex2 = ce.e2.toBoolean(sc);
13412             if (ex1.op == EXP.error)
13413                 return ex1;
13414             if (ex2.op == EXP.error)
13415                 return ex2;
13416             ce.e1 = ex1;
13417             ce.e2 = ex2;
13418             return ce;
13419 
13420 
13421         default:
13422             // Default is 'yes' - do nothing
13423             Expression e = arrayFuncConv(exp, sc);
13424             Type t = e.type;
13425             Type tb = t.toBasetype();
13426             Type att = null;
13427 
13428             while (1)
13429             {
13430                 // Structs can be converted to bool using opCast(bool)()
13431                 if (auto ts = tb.isTypeStruct())
13432                 {
13433                     AggregateDeclaration ad = ts.sym;
13434                     /* Don't really need to check for opCast first, but by doing so we
13435                      * get better error messages if it isn't there.
13436                      */
13437                     if (Dsymbol fd = search_function(ad, Id._cast))
13438                     {
13439                         e = new CastExp(exp.loc, e, Type.tbool);
13440                         e = e.expressionSemantic(sc);
13441                         return e;
13442                     }
13443 
13444                     // Forward to aliasthis.
13445                     if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
13446                     {
13447                         e = resolveAliasThis(sc, e);
13448                         t = e.type;
13449                         tb = e.type.toBasetype();
13450                         continue;
13451                     }
13452                 }
13453                 break;
13454             }
13455 
13456             if (!t.isBoolean())
13457             {
13458                 if (tb != Type.terror)
13459                     exp.error("expression `%s` of type `%s` does not have a boolean value",
13460                               exp.toChars(), t.toChars());
13461                 return ErrorExp.get();
13462             }
13463             return e;
13464     }
13465 }
13466