]> git.ipfire.org Git - people/ms/gcc.git/blob - gcc/d/dmd/expressionsem.d
63236cdb8826f861d7243723010168e276c51b01
[people/ms/gcc.git] / gcc / d / dmd / expressionsem.d
1 /**
2 * Semantic analysis of expressions.
3 *
4 * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5 *
6 * Copyright: Copyright (C) 1999-2023 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.location;
59 import dmd.mtype;
60 import dmd.mustuse;
61 import dmd.nspace;
62 import dmd.opover;
63 import dmd.optimize;
64 import dmd.parse;
65 import dmd.printast;
66 import dmd.root.array;
67 import dmd.root.ctfloat;
68 import dmd.root.file;
69 import dmd.root.filename;
70 import dmd.common.outbuffer;
71 import dmd.root.rootobject;
72 import dmd.root.string;
73 import dmd.root.utf;
74 import dmd.semantic2;
75 import dmd.semantic3;
76 import dmd.sideeffect;
77 import dmd.safe;
78 import dmd.target;
79 import dmd.tokens;
80 import dmd.traits;
81 import dmd.typesem;
82 import dmd.typinf;
83 import dmd.utils;
84 import dmd.visitor;
85
86 enum LOGSEMANTIC = false;
87
88 /********************************************************
89 * Perform semantic analysis and CTFE on expressions to produce
90 * a string.
91 * Params:
92 * buf = append generated string to buffer
93 * sc = context
94 * exps = array of Expressions
95 * Returns:
96 * true on error
97 */
98 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
99 {
100 if (!exps)
101 return false;
102
103 foreach (ex; *exps)
104 {
105 if (!ex)
106 continue;
107 auto sc2 = sc.startCTFE();
108 auto e2 = ex.expressionSemantic(sc2);
109 auto e3 = resolveProperties(sc2, e2);
110 sc2.endCTFE();
111
112 // allowed to contain types as well as expressions
113 auto e4 = ctfeInterpretForPragmaMsg(e3);
114 if (!e4 || e4.op == EXP.error)
115 return true;
116
117 // expand tuple
118 if (auto te = e4.isTupleExp())
119 {
120 if (expressionsToString(buf, sc, te.exps))
121 return true;
122 continue;
123 }
124 // char literals exp `.toStringExp` return `null` but we cant override it
125 // because in most contexts we don't want the conversion to succeed.
126 IntegerExp ie = e4.isIntegerExp();
127 const ty = (ie && ie.type) ? ie.type.ty : Terror;
128 if (ty.isSomeChar)
129 {
130 auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
131 e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
132 }
133
134 if (StringExp se = e4.toStringExp())
135 buf.writestring(se.toUTF8(sc).peekString());
136 else
137 buf.writestring(e4.toString());
138 }
139 return false;
140 }
141
142
143 /***********************************************************
144 * Resolve `exp` as a compile-time known string.
145 * Params:
146 * sc = scope
147 * exp = Expression which expected as a string
148 * s = What the string is expected for, will be used in error diagnostic.
149 * Returns:
150 * String literal, or `null` if error happens.
151 */
152 StringExp semanticString(Scope *sc, Expression exp, const char* s)
153 {
154 sc = sc.startCTFE();
155 exp = exp.expressionSemantic(sc);
156 exp = resolveProperties(sc, exp);
157 sc = sc.endCTFE();
158
159 if (exp.op == EXP.error)
160 return null;
161
162 auto e = exp;
163 if (exp.type.isString())
164 {
165 e = e.ctfeInterpret();
166 if (e.op == EXP.error)
167 return null;
168 }
169
170 auto se = e.toStringExp();
171 if (!se)
172 {
173 exp.error("`string` expected for %s, not `(%s)` of type `%s`",
174 s, exp.toChars(), exp.type.toChars());
175 return null;
176 }
177 return se;
178 }
179
180 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
181 {
182 Expression e0;
183 Expression e1 = Expression.extractLast(ue.e1, e0);
184 // https://issues.dlang.org/show_bug.cgi?id=12585
185 // Extract the side effect part if ue.e1 is comma.
186
187 if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
188 {
189 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
190 * Rewrite:
191 * e1.opIndex( ... use of $ ... )
192 * e1.opSlice( ... use of $ ... )
193 * as:
194 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
195 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
196 */
197 e1 = extractSideEffect(sc, "__dop", e0, e1, false);
198 assert(e1.isVarExp());
199 e1.isVarExp().var.storage_class |= STC.exptemp; // lifetime limited to expression
200 }
201 ue.e1 = e1;
202 return e0;
203 }
204
205 /**************************************
206 * Runs semantic on ae.arguments. Declares temporary variables
207 * if '$' was used.
208 */
209 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
210 {
211 assert(!ae.lengthVar);
212 *pe0 = null;
213 AggregateDeclaration ad = isAggregate(ae.e1.type);
214 Dsymbol slice = search_function(ad, Id.slice);
215 //printf("slice = %s %s\n", slice.kind(), slice.toChars());
216 foreach (i, e; *ae.arguments)
217 {
218 if (i == 0)
219 *pe0 = extractOpDollarSideEffect(sc, ae);
220
221 if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
222 {
223 Lfallback:
224 if (ae.arguments.length == 1)
225 return null;
226 ae.error("multi-dimensional slicing requires template `opSlice`");
227 return ErrorExp.get();
228 }
229 //printf("[%d] e = %s\n", i, e.toChars());
230
231 // Create scope for '$' variable for this dimension
232 auto sym = new ArrayScopeSymbol(sc, ae);
233 sym.parent = sc.scopesym;
234 sc = sc.push(sym);
235 ae.lengthVar = null; // Create it only if required
236 ae.currentDimension = i; // Dimension for $, if required
237
238 e = e.expressionSemantic(sc);
239 e = resolveProperties(sc, e);
240
241 if (ae.lengthVar && sc.func)
242 {
243 // If $ was used, declare it now
244 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
245 de = de.expressionSemantic(sc);
246 *pe0 = Expression.combine(*pe0, de);
247 }
248 sc = sc.pop();
249
250 if (auto ie = e.isIntervalExp())
251 {
252 auto tiargs = new Objects();
253 Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
254 edim = edim.expressionSemantic(sc);
255 tiargs.push(edim);
256
257 auto fargs = new Expressions(2);
258 (*fargs)[0] = ie.lwr;
259 (*fargs)[1] = ie.upr;
260
261 uint xerrors = global.startGagging();
262 sc = sc.push();
263 FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
264 sc = sc.pop();
265 global.endGagging(xerrors);
266 if (!fslice)
267 goto Lfallback;
268
269 e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
270 e = new CallExp(ae.loc, e, fargs);
271 e = e.expressionSemantic(sc);
272 }
273
274 if (!e.type)
275 {
276 ae.error("`%s` has no value", e.toChars());
277 e = ErrorExp.get();
278 }
279 if (e.op == EXP.error)
280 return e;
281
282 (*ae.arguments)[i] = e;
283 }
284 return ae;
285 }
286
287 /**************************************
288 * Runs semantic on se.lwr and se.upr. Declares a temporary variable
289 * if '$' was used.
290 * Returns:
291 * ae, or ErrorExp if errors occurred
292 */
293 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
294 {
295 //assert(!ae.lengthVar);
296 if (!ie)
297 return ae;
298
299 VarDeclaration lengthVar = ae.lengthVar;
300 bool errors = false;
301
302 // create scope for '$'
303 auto sym = new ArrayScopeSymbol(sc, ae);
304 sym.parent = sc.scopesym;
305 sc = sc.push(sym);
306
307 Expression sem(Expression e)
308 {
309 e = e.expressionSemantic(sc);
310 e = resolveProperties(sc, e);
311 if (!e.type)
312 {
313 ae.error("`%s` has no value", e.toChars());
314 errors = true;
315 }
316 return e;
317 }
318
319 ie.lwr = sem(ie.lwr);
320 ie.upr = sem(ie.upr);
321
322 if (ie.lwr.isErrorExp() || ie.upr.isErrorExp())
323 errors = true;
324
325 if (lengthVar != ae.lengthVar && sc.func)
326 {
327 // If $ was used, declare it now
328 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
329 de = de.expressionSemantic(sc);
330 *pe0 = Expression.combine(*pe0, de);
331 }
332
333 sc = sc.pop();
334
335 return errors ? ErrorExp.get() : ae;
336 }
337
338 /******************************
339 * Perform semantic() on an array of Expressions.
340 */
341 extern(D) bool arrayExpressionSemantic(
342 Expression[] exps, Scope* sc, bool preserveErrors = false)
343 {
344 bool err = false;
345 foreach (ref e; exps)
346 {
347 if (e is null) continue;
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 return err;
355 }
356
357 /*
358 Checks if `exp` contains a direct access to a `noreturn`
359 variable. If that is the case, an `assert(0)` expression
360 is generated and returned. This function should be called
361 only after semantic analysis has been performed on `exp`.
362
363 Params:
364 exp = expression that is checked
365
366 Returns:
367 An `assert(0)` expression if `exp` contains a `noreturn`
368 variable access, `exp` otherwise.
369 */
370
371 Expression checkNoreturnVarAccess(Expression exp)
372 {
373 assert(exp.type);
374
375 Expression result = exp;
376 if (exp.type.isTypeNoreturn() && !exp.isAssertExp() &&
377 !exp.isThrowExp() && !exp.isCallExp())
378 {
379 auto msg = new StringExp(exp.loc, "Accessed expression of type `noreturn`");
380 msg.type = Type.tstring;
381 result = new AssertExp(exp.loc, IntegerExp.literal!0, msg);
382 result.type = exp.type;
383 }
384
385 return result;
386 }
387
388 /******************************
389 * Check the tail CallExp is really property function call.
390 * Bugs:
391 * This doesn't appear to do anything.
392 */
393 private bool checkPropertyCall(Expression e)
394 {
395 e = lastComma(e);
396
397 if (auto ce = e.isCallExp())
398 {
399 if (ce.f)
400 {
401 auto tf = ce.f.type.isTypeFunction();
402 /* If a forward reference to ce.f, try to resolve it
403 */
404 if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
405 {
406 ce.f.dsymbolSemantic(null);
407 tf = ce.f.type.isTypeFunction();
408 }
409 }
410 else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
411 assert(0);
412 }
413 return false;
414 }
415
416 /******************************
417 * Find symbol in accordance with the UFCS name look up rule
418 */
419 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
420 {
421 //printf("searchUFCS(ident = %s)\n", ident.toChars());
422 Loc loc = ue.loc;
423
424 // TODO: merge with Scope.search.searchScopes()
425 Dsymbol searchScopes(int flags)
426 {
427 Dsymbol s = null;
428 for (Scope* scx = sc; scx; scx = scx.enclosing)
429 {
430 if (!scx.scopesym)
431 continue;
432 if (scx.scopesym.isModule())
433 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
434 s = scx.scopesym.search(loc, ident, flags);
435 if (s)
436 {
437 // overload set contains only module scope symbols.
438 if (s.isOverloadSet())
439 break;
440 // selective/renamed imports also be picked up
441 if (AliasDeclaration ad = s.isAliasDeclaration())
442 {
443 if (ad._import)
444 break;
445 }
446 // See only module scope symbols for UFCS target.
447 Dsymbol p = s.toParent2();
448 if (p && p.isModule())
449 break;
450 }
451 s = null;
452
453 // Stop when we hit a module, but keep going if that is not just under the global scope
454 if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
455 break;
456 }
457 return s;
458 }
459
460 int flags = 0;
461 Dsymbol s;
462
463 if (sc.flags & SCOPE.ignoresymbolvisibility)
464 flags |= IgnoreSymbolVisibility;
465
466 // First look in local scopes
467 s = searchScopes(flags | SearchLocalsOnly);
468 if (!s)
469 {
470 // Second look in imported modules
471 s = searchScopes(flags | SearchImportsOnly);
472 }
473
474 if (!s)
475 return ue.e1.type.getProperty(sc, loc, ident, 0, ue.e1);
476
477 FuncDeclaration f = s.isFuncDeclaration();
478 if (f)
479 {
480 TemplateDeclaration td = getFuncTemplateDecl(f);
481 if (td)
482 {
483 if (td.overroot)
484 td = td.overroot;
485 s = td;
486 }
487 }
488
489 if (auto dti = ue.isDotTemplateInstanceExp())
490 {
491 auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
492 if (!ti.updateTempDecl(sc, s))
493 return ErrorExp.get();
494 return new ScopeExp(loc, ti);
495 }
496 else
497 {
498 //printf("-searchUFCS() %s\n", s.toChars());
499 return new DsymbolExp(loc, s);
500 }
501 }
502
503 /******************************
504 * Pull out callable entity with UFCS.
505 */
506 private Expression resolveUFCS(Scope* sc, CallExp ce)
507 {
508 Loc loc = ce.loc;
509 Expression eleft;
510 Expression e;
511
512 if (auto die = ce.e1.isDotIdExp())
513 {
514 Identifier ident = die.ident;
515
516 Expression ex = die.dotIdSemanticPropX(sc);
517 if (ex != die)
518 {
519 ce.e1 = ex;
520 return null;
521 }
522 eleft = die.e1;
523
524 Type t = eleft.type.toBasetype();
525 if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
526 {
527 /* Built-in types and arrays have no callable properties, so do shortcut.
528 * It is necessary in: e.init()
529 */
530 }
531 else if (t.ty == Taarray)
532 {
533 if (ident == Id.remove)
534 {
535 /* Transform:
536 * aa.remove(arg) into delete aa[arg]
537 */
538 if (!ce.arguments || ce.arguments.length != 1)
539 {
540 ce.error("expected key as argument to `aa.remove()`");
541 return ErrorExp.get();
542 }
543 if (!eleft.type.isMutable())
544 {
545 ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
546 return ErrorExp.get();
547 }
548 Expression key = (*ce.arguments)[0];
549 key = key.expressionSemantic(sc);
550 key = resolveProperties(sc, key);
551
552 TypeAArray taa = t.isTypeAArray();
553 key = key.implicitCastTo(sc, taa.index);
554
555 if (key.checkValue() || key.checkSharedAccess(sc))
556 return ErrorExp.get();
557
558 semanticTypeInfo(sc, taa.index);
559
560 return new RemoveExp(loc, eleft, key);
561 }
562 }
563 else
564 {
565 if (Expression ey = die.dotIdSemanticProp(sc, 1))
566 {
567 if (ey.op == EXP.error)
568 return ey;
569 ce.e1 = ey;
570 if (isDotOpDispatch(ey))
571 {
572 // even opDispatch and UFCS must have valid arguments,
573 // so now that we've seen indication of a problem,
574 // check them for issues.
575 Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
576
577 uint errors = global.startGagging();
578 e = ce.expressionSemantic(sc);
579 if (!global.endGagging(errors))
580 return e;
581
582 if (arrayExpressionSemantic(originalArguments.peekSlice(), sc))
583 return ErrorExp.get();
584
585 /* fall down to UFCS */
586 }
587 else
588 return null;
589 }
590 }
591
592 /* https://issues.dlang.org/show_bug.cgi?id=13953
593 *
594 * If a struct has an alias this to an associative array
595 * and remove is used on a struct instance, we have to
596 * check first if there is a remove function that can be called
597 * on the struct. If not we must check the alias this.
598 *
599 * struct A
600 * {
601 * string[string] a;
602 * alias a this;
603 * }
604 *
605 * void fun()
606 * {
607 * A s;
608 * s.remove("foo");
609 * }
610 */
611 const errors = global.startGagging();
612 e = searchUFCS(sc, die, ident);
613 // if there were any errors and the identifier was remove
614 if (global.endGagging(errors))
615 {
616 if (ident == Id.remove)
617 {
618 // check alias this
619 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
620 if (alias_e && alias_e != die.e1)
621 {
622 die.e1 = alias_e;
623 CallExp ce2 = ce.syntaxCopy();
624 ce2.e1 = die;
625 e = ce2.isCallExp().trySemantic(sc);
626 if (e)
627 return e;
628 }
629 }
630 // if alias this did not work out, print the initial errors
631 searchUFCS(sc, die, ident);
632 }
633 }
634 else if (auto dti = ce.e1.isDotTemplateInstanceExp())
635 {
636 if (Expression ey = dti.dotTemplateSemanticProp(sc, 1))
637 {
638 ce.e1 = ey;
639 return null;
640 }
641 eleft = dti.e1;
642 e = searchUFCS(sc, dti, dti.ti.name);
643 }
644 else
645 return null;
646
647 // Rewrite
648 ce.e1 = e;
649 if (!ce.arguments)
650 ce.arguments = new Expressions();
651 ce.arguments.shift(eleft);
652
653 return null;
654 }
655
656 /******************************
657 * Pull out property with UFCS.
658 */
659 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
660 {
661 Loc loc = e1.loc;
662 Expression eleft;
663 Expression e;
664
665 if (auto die = e1.isDotIdExp())
666 {
667 eleft = die.e1;
668 e = searchUFCS(sc, die, die.ident);
669 }
670 else if (auto dti = e1.isDotTemplateInstanceExp())
671 {
672 eleft = dti.e1;
673 e = searchUFCS(sc, dti, dti.ti.name);
674 }
675 else
676 return null;
677
678 if (e is null)
679 return null;
680
681 // Rewrite
682 if (e2)
683 {
684 // run semantic without gagging
685 e2 = e2.expressionSemantic(sc);
686
687 /* f(e1) = e2
688 */
689 Expression ex = e.copy();
690 auto a1 = new Expressions(1);
691 (*a1)[0] = eleft;
692 ex = new CallExp(loc, ex, a1);
693 auto e1PassSemantic = ex.trySemantic(sc);
694
695 /* f(e1, e2)
696 */
697 auto a2 = new Expressions(2);
698 (*a2)[0] = eleft;
699 (*a2)[1] = e2;
700 e = new CallExp(loc, e, a2);
701 e = e.trySemantic(sc);
702 if (!e1PassSemantic && !e)
703 {
704 /* https://issues.dlang.org/show_bug.cgi?id=20448
705 *
706 * If both versions have failed to pass semantic,
707 * f(e1) = e2 gets priority in error printing
708 * because f might be a templated function that
709 * failed to instantiate and we have to print
710 * the instantiation errors.
711 */
712 return e1.expressionSemantic(sc);
713 }
714 else if (ex && !e)
715 {
716 checkPropertyCall(ex);
717 ex = new AssignExp(loc, ex, e2);
718 return ex.expressionSemantic(sc);
719 }
720 else
721 {
722 // strict setter prints errors if fails
723 e = e.expressionSemantic(sc);
724 }
725 checkPropertyCall(e);
726 return e;
727 }
728 else
729 {
730 /* f(e1)
731 */
732 auto arguments = new Expressions(1);
733 (*arguments)[0] = eleft;
734 e = new CallExp(loc, e, arguments);
735 e = e.expressionSemantic(sc);
736 checkPropertyCall(e);
737 return e.expressionSemantic(sc);
738 }
739 }
740
741 /******************************
742 * If e1 is a property function (template), resolve it.
743 */
744 Expression resolvePropertiesOnly(Scope* sc, Expression e1)
745 {
746 //printf("e1 = %s %s\n", Token.toChars(e1.op), e1.toChars());
747
748 Expression handleOverloadSet(OverloadSet os)
749 {
750 assert(os);
751 foreach (s; os.a)
752 {
753 auto fd = s.isFuncDeclaration();
754 auto td = s.isTemplateDeclaration();
755 if (fd)
756 {
757 if (fd.type.isTypeFunction().isproperty)
758 return resolveProperties(sc, e1);
759 }
760 else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
761 {
762 if (fd.type.isTypeFunction().isproperty ||
763 (fd.storage_class2 & STC.property) ||
764 (td._scope.stc & STC.property))
765 return resolveProperties(sc, e1);
766 }
767 }
768 return e1;
769 }
770
771 Expression handleTemplateDecl(TemplateDeclaration td)
772 {
773 assert(td);
774 if (td.onemember)
775 {
776 if (auto fd = td.onemember.isFuncDeclaration())
777 {
778 if (fd.type.isTypeFunction().isproperty ||
779 (fd.storage_class2 & STC.property) ||
780 (td._scope.stc & STC.property))
781 return resolveProperties(sc, e1);
782 }
783 }
784 return e1;
785 }
786
787 Expression handleFuncDecl(FuncDeclaration fd)
788 {
789 assert(fd);
790 if (fd.type.isTypeFunction().isproperty)
791 return resolveProperties(sc, e1);
792 return e1;
793 }
794
795 if (auto de = e1.isDotExp())
796 {
797 if (auto os = de.e2.isOverExp())
798 return handleOverloadSet(os.vars);
799 }
800 else if (auto oe = e1.isOverExp())
801 return handleOverloadSet(oe.vars);
802 else if (auto dti = e1.isDotTemplateInstanceExp())
803 {
804 if (dti.ti.tempdecl)
805 if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
806 return handleTemplateDecl(td);
807 }
808 else if (auto dte = e1.isDotTemplateExp())
809 return handleTemplateDecl(dte.td);
810 else if (auto se = e1.isScopeExp())
811 {
812 Dsymbol s = se.sds;
813 TemplateInstance ti = s.isTemplateInstance();
814 if (ti && !ti.semanticRun && ti.tempdecl)
815 if (auto td = ti.tempdecl.isTemplateDeclaration())
816 return handleTemplateDecl(td);
817 }
818 else if (auto et = e1.isTemplateExp())
819 return handleTemplateDecl(et.td);
820 else if (e1.isDotVarExp() && e1.type.isTypeFunction())
821 {
822 DotVarExp dve = e1.isDotVarExp();
823 return handleFuncDecl(dve.var.isFuncDeclaration());
824 }
825 else if (e1.isVarExp() && e1.type && e1.type.isTypeFunction() && (sc.intypeof || !e1.isVarExp().var.needThis()))
826 return handleFuncDecl(e1.isVarExp().var.isFuncDeclaration());
827 return e1;
828 }
829
830 /****************************************
831 * Turn symbol `s` into the expression it represents.
832 *
833 * Params:
834 * s = symbol to resolve
835 * loc = location of use of `s`
836 * sc = context
837 * hasOverloads = applies if `s` represents a function.
838 * true means it's overloaded and will be resolved later,
839 * false means it's the exact function symbol.
840 * Returns:
841 * `s` turned into an expression, `ErrorExp` if an error occurred
842 */
843 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
844 {
845 static if (LOGSEMANTIC)
846 {
847 printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
848 }
849
850 Lagain:
851 Expression e;
852
853 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
854 //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
855 Dsymbol olds = s;
856 Declaration d = s.isDeclaration();
857 if (d && (d.storage_class & STC.templateparameter))
858 {
859 s = s.toAlias();
860 }
861 else
862 {
863 // functions are checked after overloading
864 // templates are checked after matching constraints
865 if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
866 {
867 s.checkDeprecated(loc, sc);
868 if (d)
869 d.checkDisabled(loc, sc);
870 }
871
872 // https://issues.dlang.org/show_bug.cgi?id=12023
873 // if 's' is a tuple variable, the tuple is returned.
874 s = s.toAlias();
875
876 //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
877 if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration())
878 {
879 s.checkDeprecated(loc, sc);
880 if (d)
881 d.checkDisabled(loc, sc);
882 }
883
884 if (auto sd = s.isDeclaration())
885 {
886 if (sd.isSystem())
887 {
888 if (sc.setUnsafePreview(global.params.systemVariables, false, loc,
889 "cannot access `@system` variable `%s` in @safe code", sd))
890 {
891 return ErrorExp.get();
892 }
893 }
894 }
895 }
896
897 if (auto em = s.isEnumMember())
898 {
899 return em.getVarExp(loc, sc);
900 }
901 if (auto v = s.isVarDeclaration())
902 {
903 //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
904 if (sc.intypeof == 1 && !v.inuse)
905 v.dsymbolSemantic(sc);
906 if (!v.type || // during variable type inference
907 !v.type.deco && v.inuse) // during variable type semantic
908 {
909 if (v.inuse) // variable type depends on the variable itself
910 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
911 else // variable type cannot be determined
912 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
913 return ErrorExp.get();
914 }
915 if (v.type.ty == Terror)
916 return ErrorExp.get();
917
918 if ((v.storage_class & STC.manifest) && v._init)
919 {
920 if (v.inuse)
921 {
922 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
923 return ErrorExp.get();
924 }
925 e = v.expandInitializer(loc);
926 v.inuse++;
927 e = e.expressionSemantic(sc);
928 v.inuse--;
929 return e;
930 }
931
932 // We need to run semantics to correctly set 'STC.field' if it is a member variable
933 // that could be forward referenced. This is needed for 'v.needThis()' to work
934 if (v.isThis())
935 v.dsymbolSemantic(sc);
936
937 // Change the ancestor lambdas to delegate before hasThis(sc) call.
938 if (v.checkNestedReference(sc, loc))
939 return ErrorExp.get();
940
941 if (v.needThis() && hasThis(sc))
942 e = new DotVarExp(loc, new ThisExp(loc), v);
943 else
944 e = new VarExp(loc, v);
945 e = e.expressionSemantic(sc);
946 return e;
947 }
948 if (auto fld = s.isFuncLiteralDeclaration())
949 {
950 //printf("'%s' is a function literal\n", fld.toChars());
951 e = new FuncExp(loc, fld);
952 return e.expressionSemantic(sc);
953 }
954 if (auto f = s.isFuncDeclaration())
955 {
956 f = f.toAliasFunc();
957 if (!f.functionSemantic())
958 return ErrorExp.get();
959
960 if (!hasOverloads && f.checkForwardRef(loc))
961 return ErrorExp.get();
962
963 auto fd = s.isFuncDeclaration();
964 fd.type = f.type;
965 return new VarExp(loc, fd, hasOverloads);
966 }
967 if (OverDeclaration od = s.isOverDeclaration())
968 {
969 e = new VarExp(loc, od, true);
970 e.type = Type.tvoid;
971 return e;
972 }
973 if (OverloadSet o = s.isOverloadSet())
974 {
975 //printf("'%s' is an overload set\n", o.toChars());
976 return new OverExp(loc, o);
977 }
978
979 if (Import imp = s.isImport())
980 {
981 if (!imp.pkg)
982 {
983 .error(loc, "forward reference of import `%s`", imp.toChars());
984 return ErrorExp.get();
985 }
986 auto ie = new ScopeExp(loc, imp.pkg);
987 return ie.expressionSemantic(sc);
988 }
989 if (Package pkg = s.isPackage())
990 {
991 auto ie = new ScopeExp(loc, pkg);
992 return ie.expressionSemantic(sc);
993 }
994 if (Module mod = s.isModule())
995 {
996 auto ie = new ScopeExp(loc, mod);
997 return ie.expressionSemantic(sc);
998 }
999 if (Nspace ns = s.isNspace())
1000 {
1001 auto ie = new ScopeExp(loc, ns);
1002 return ie.expressionSemantic(sc);
1003 }
1004
1005 if (Type t = s.getType())
1006 {
1007 return (new TypeExp(loc, t)).expressionSemantic(sc);
1008 }
1009
1010 if (TupleDeclaration tup = s.isTupleDeclaration())
1011 {
1012 if (tup.needThis() && hasThis(sc))
1013 e = new DotVarExp(loc, new ThisExp(loc), tup);
1014 else
1015 e = new TupleExp(loc, tup);
1016 e = e.expressionSemantic(sc);
1017 return e;
1018 }
1019
1020 if (TemplateInstance ti = s.isTemplateInstance())
1021 {
1022 ti.dsymbolSemantic(sc);
1023 if (!ti.inst || ti.errors)
1024 return ErrorExp.get();
1025 s = ti.toAlias();
1026 if (!s.isTemplateInstance())
1027 goto Lagain;
1028 e = new ScopeExp(loc, ti);
1029 e = e.expressionSemantic(sc);
1030 return e;
1031 }
1032 if (TemplateDeclaration td = s.isTemplateDeclaration())
1033 {
1034 Dsymbol p = td.toParentLocal();
1035 FuncDeclaration fdthis = hasThis(sc);
1036 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
1037 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
1038 {
1039 e = new DotTemplateExp(loc, new ThisExp(loc), td);
1040 }
1041 else
1042 e = new TemplateExp(loc, td);
1043 e = e.expressionSemantic(sc);
1044 return e;
1045 }
1046
1047 .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1048 return ErrorExp.get();
1049 }
1050
1051 /*************************************************************
1052 * Given var, get the
1053 * right `this` pointer if var is in an outer class, but our
1054 * existing `this` pointer is in an inner class.
1055 * Params:
1056 * loc = location to use for error messages
1057 * sc = context
1058 * ad = struct or class we need the correct `this` for
1059 * e1 = existing `this`
1060 * var = the specific member of ad we're accessing
1061 * flag = if true, return `null` instead of throwing an error
1062 * Returns:
1063 * Expression representing the `this` for the var
1064 */
1065 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1066 {
1067 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1068 L1:
1069 Type t = e1.type.toBasetype();
1070 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1071
1072 if (e1.op == EXP.objcClassReference)
1073 {
1074 // We already have an Objective-C class reference, just use that as 'this'.
1075 return e1;
1076 }
1077 else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1078 var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1079 var.isFuncDeclaration.objc.selector)
1080 {
1081 return new ObjcClassReferenceExp(e1.loc, ad.isClassDeclaration());
1082 }
1083
1084 /* Access of a member which is a template parameter in dual-scope scenario
1085 * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1086 * class B {int m; inc() { new A().inc!m(); } }
1087 */
1088 if (e1.op == EXP.this_)
1089 {
1090 FuncDeclaration f = hasThis(sc);
1091 if (f && f.hasDualContext())
1092 {
1093 if (f.followInstantiationContext(ad))
1094 {
1095 e1 = new VarExp(loc, f.vthis);
1096 e1 = new PtrExp(loc, e1);
1097 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1098 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1099 if (e1.op == EXP.error)
1100 return e1;
1101 goto L1;
1102 }
1103 }
1104 }
1105
1106 /* If e1 is not the 'this' pointer for ad
1107 */
1108 if (ad &&
1109 !(t.isTypePointer() && t.nextOf().isTypeStruct() && t.nextOf().isTypeStruct().sym == ad) &&
1110 !(t.isTypeStruct() && t.isTypeStruct().sym == ad))
1111 {
1112 ClassDeclaration cd = ad.isClassDeclaration();
1113 ClassDeclaration tcd = t.isClassHandle();
1114
1115 /* e1 is the right this if ad is a base class of e1
1116 */
1117 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1118 {
1119 /* Only classes can be inner classes with an 'outer'
1120 * member pointing to the enclosing class instance
1121 */
1122 if (tcd && tcd.isNested())
1123 {
1124 /* e1 is the 'this' pointer for an inner class: tcd.
1125 * Rewrite it as the 'this' pointer for the outer class.
1126 */
1127 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1128 e1 = new DotVarExp(loc, e1, vthis);
1129 e1.type = vthis.type;
1130 e1.type = e1.type.addMod(t.mod);
1131 // Do not call ensureStaticLinkTo()
1132 //e1 = e1.semantic(sc);
1133
1134 // Skip up over nested functions, and get the enclosing
1135 // class type.
1136 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1137 if (e1.op == EXP.error)
1138 return e1;
1139 goto L1;
1140 }
1141
1142 /* Can't find a path from e1 to ad
1143 */
1144 if (flag)
1145 return null;
1146 e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1147 return ErrorExp.get();
1148 }
1149 }
1150 return e1;
1151 }
1152
1153 /***************************************
1154 * Pull out any properties.
1155 */
1156 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1157 {
1158 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
1159 Loc loc = e1.loc;
1160
1161 OverloadSet os;
1162 Dsymbol s;
1163 Objects* tiargs;
1164 Type tthis;
1165 if (auto de = e1.isDotExp())
1166 {
1167 if (auto oe = de.e2.isOverExp())
1168 {
1169 tiargs = null;
1170 tthis = de.e1.type;
1171 os = oe.vars;
1172 goto Los;
1173 }
1174 }
1175 else if (e1.isOverExp())
1176 {
1177 tiargs = null;
1178 tthis = null;
1179 os = e1.isOverExp().vars;
1180 Los:
1181 assert(os);
1182 FuncDeclaration fd = null;
1183 if (e2)
1184 {
1185 e2 = e2.expressionSemantic(sc);
1186 if (e2.op == EXP.error)
1187 return ErrorExp.get();
1188 e2 = resolveProperties(sc, e2);
1189
1190 Expressions a;
1191 a.push(e2);
1192
1193 for (size_t i = 0; i < os.a.length; i++)
1194 {
1195 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1196 {
1197 if (f.errors)
1198 return ErrorExp.get();
1199 fd = f;
1200 assert(fd.type.ty == Tfunction);
1201 }
1202 }
1203 if (fd)
1204 {
1205 Expression e = new CallExp(loc, e1, e2);
1206 return e.expressionSemantic(sc);
1207 }
1208 }
1209 {
1210 for (size_t i = 0; i < os.a.length; i++)
1211 {
1212 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1213 {
1214 if (f.errors)
1215 return ErrorExp.get();
1216 fd = f;
1217 assert(fd.type.ty == Tfunction);
1218 auto tf = fd.type.isTypeFunction();
1219 if (!tf.isref && e2)
1220 {
1221 error(loc, "%s is not an lvalue", e1.toChars());
1222 return ErrorExp.get();
1223 }
1224 }
1225 }
1226 if (fd)
1227 {
1228 Expression e = new CallExp(loc, e1);
1229 if (e2)
1230 e = new AssignExp(loc, e, e2);
1231 return e.expressionSemantic(sc);
1232 }
1233 }
1234 if (e2)
1235 goto Leprop;
1236 }
1237 else if (auto dti = e1.isDotTemplateInstanceExp())
1238 {
1239 if (!dti.findTempDecl(sc))
1240 goto Leprop;
1241 if (!dti.ti.semanticTiargs(sc))
1242 goto Leprop;
1243 tiargs = dti.ti.tiargs;
1244 tthis = dti.e1.type;
1245 if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1246 goto Los;
1247 if ((s = dti.ti.tempdecl) !is null)
1248 goto Lfd;
1249 }
1250 else if (auto dte = e1.isDotTemplateExp())
1251 {
1252 s = dte.td;
1253 tiargs = null;
1254 tthis = dte.e1.type;
1255 goto Lfd;
1256 }
1257 else if (auto se = e1.isScopeExp())
1258 {
1259 s = se.sds;
1260 TemplateInstance ti = s.isTemplateInstance();
1261 if (ti && !ti.semanticRun && ti.tempdecl)
1262 {
1263 //assert(ti.needsTypeInference(sc));
1264 if (!ti.semanticTiargs(sc))
1265 goto Leprop;
1266 tiargs = ti.tiargs;
1267 tthis = null;
1268 if ((os = ti.tempdecl.isOverloadSet()) !is null)
1269 goto Los;
1270 if ((s = ti.tempdecl) !is null)
1271 goto Lfd;
1272 }
1273 }
1274 else if (auto te = e1.isTemplateExp())
1275 {
1276 s = te.td;
1277 tiargs = null;
1278 tthis = null;
1279 goto Lfd;
1280 }
1281 else if (e1.isDotVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isDotVarExp().var.isOverDeclaration()))
1282 {
1283 DotVarExp dve = e1.isDotVarExp();
1284 s = dve.var;
1285 tiargs = null;
1286 tthis = dve.e1.type;
1287 goto Lfd;
1288 }
1289 else if (sc && sc.flags & SCOPE.Cfile && e1.isVarExp() && !e2)
1290 {
1291 // ImportC: do not implicitly call function if no ( ) are present
1292 }
1293 else if (e1.isVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isVarExp().var.isOverDeclaration()))
1294 {
1295 s = e1.isVarExp().var;
1296 tiargs = null;
1297 tthis = null;
1298 Lfd:
1299 assert(s);
1300 if (e2)
1301 {
1302 e2 = e2.expressionSemantic(sc);
1303 if (e2.op == EXP.error)
1304 return ErrorExp.get();
1305 e2 = resolveProperties(sc, e2);
1306
1307 Expressions a;
1308 a.push(e2);
1309
1310 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1311 if (fd && fd.type)
1312 {
1313 if (fd.errors)
1314 return ErrorExp.get();
1315 if (!checkSymbolAccess(sc, fd))
1316 {
1317 // @@@DEPRECATED_2.105@@@
1318 // When turning into error, uncomment the return statement
1319 TypeFunction tf = fd.type.isTypeFunction();
1320 deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
1321 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1322 //return ErrorExp.get();
1323 }
1324 assert(fd.type.ty == Tfunction);
1325 Expression e = new CallExp(loc, e1, e2);
1326 return e.expressionSemantic(sc);
1327 }
1328 }
1329 {
1330 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1331 if (fd && fd.type)
1332 {
1333 if (fd.errors)
1334 return ErrorExp.get();
1335 TypeFunction tf = fd.type.isTypeFunction();
1336 if (!e2 || tf.isref)
1337 {
1338 if (!checkSymbolAccess(sc, fd))
1339 {
1340 // @@@DEPRECATED_2.105@@@
1341 // When turning into error, uncomment the return statement
1342 deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
1343 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1344 //return ErrorExp.get();
1345 }
1346 Expression e = new CallExp(loc, e1);
1347 if (e2)
1348 e = new AssignExp(loc, e, e2);
1349 return e.expressionSemantic(sc);
1350 }
1351 }
1352 }
1353 if (FuncDeclaration fd = s.isFuncDeclaration())
1354 {
1355 // Keep better diagnostic message for invalid property usage of functions
1356 assert(fd.type.ty == Tfunction);
1357 Expression e = new CallExp(loc, e1, e2);
1358 return e.expressionSemantic(sc);
1359 }
1360 if (e2)
1361 goto Leprop;
1362 }
1363 if (auto ve = e1.isVarExp())
1364 {
1365 if (auto v = ve.var.isVarDeclaration())
1366 {
1367 if (ve.checkPurity(sc, v))
1368 return ErrorExp.get();
1369 }
1370 }
1371 if (e2)
1372 return null;
1373
1374 if (e1.type && !e1.isTypeExp()) // function type is not a property
1375 {
1376 /* Look for e1 being a lazy parameter; rewrite as delegate call
1377 * only if the symbol wasn't already treated as a delegate
1378 */
1379 auto ve = e1.isVarExp();
1380 if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1381 {
1382 Expression e = new CallExp(loc, e1);
1383 return e.expressionSemantic(sc);
1384 }
1385 else if (e1.isDotVarExp())
1386 {
1387 // Check for reading overlapped pointer field in @safe code.
1388 if (checkUnsafeAccess(sc, e1, true, true))
1389 return ErrorExp.get();
1390 }
1391 else if (auto ce = e1.isCallExp())
1392 {
1393 // Check for reading overlapped pointer field in @safe code.
1394 if (checkUnsafeAccess(sc, ce.e1, true, true))
1395 return ErrorExp.get();
1396 }
1397 }
1398
1399 if (!e1.type)
1400 {
1401 error(loc, "cannot resolve type for %s", e1.toChars());
1402 e1 = ErrorExp.get();
1403 }
1404 return e1;
1405
1406 Leprop:
1407 error(loc, "not a property %s", e1.toChars());
1408 return ErrorExp.get();
1409 }
1410
1411 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1412 {
1413 //printf("resolveProperties(%s)\n", e.toChars());
1414 e = resolvePropertiesX(sc, e);
1415 if (e.checkRightThis(sc))
1416 return ErrorExp.get();
1417 return e;
1418 }
1419
1420 /****************************************
1421 * The common type is determined by applying ?: to each pair.
1422 * Output:
1423 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1424 * Returns:
1425 * The common type, or `null` if an error has occured
1426 */
1427 private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
1428 {
1429 /* Still have a problem with:
1430 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1431 * which works if the array literal is initialized top down with the ubyte[][]
1432 * type, but fails with this function doing bottom up typing.
1433 */
1434
1435 //printf("arrayExpressionToCommonType()\n");
1436 scope IntegerExp integerexp = IntegerExp.literal!0;
1437 scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1438
1439 Type t0 = null;
1440 Expression e0 = null;
1441 bool foundType;
1442
1443 for (size_t i = 0; i < exps.length; i++)
1444 {
1445 Expression e = exps[i];
1446 if (!e)
1447 continue;
1448
1449 e = resolveProperties(sc, e);
1450 if (!e.type)
1451 {
1452 e.error("`%s` has no value", e.toChars());
1453 t0 = Type.terror;
1454 continue;
1455 }
1456 if (e.op == EXP.type)
1457 {
1458 foundType = true; // do not break immediately, there might be more errors
1459 e.checkValue(); // report an error "type T has no value"
1460 t0 = Type.terror;
1461 continue;
1462 }
1463 if (e.type.ty == Tvoid)
1464 {
1465 // void expressions do not concur to the determination of the common
1466 // type.
1467 continue;
1468 }
1469 if (checkNonAssignmentArrayOp(e))
1470 {
1471 t0 = Type.terror;
1472 continue;
1473 }
1474
1475 e = doCopyOrMove(sc, e);
1476
1477 if (!foundType && t0 && !t0.equals(e.type))
1478 {
1479 /* This applies ?: to merge the types. It's backwards;
1480 * ?: should call this function to merge types.
1481 */
1482 condexp.type = null;
1483 condexp.e1 = e0;
1484 condexp.e2 = e;
1485 condexp.loc = e.loc;
1486 Expression ex = condexp.expressionSemantic(sc);
1487 if (ex.op == EXP.error)
1488 e = ex;
1489 else
1490 {
1491 // Convert to common type
1492 exps[i] = condexp.e1.castTo(sc, condexp.type);
1493 e = condexp.e2.castTo(sc, condexp.type);
1494 }
1495 }
1496 e0 = e;
1497 t0 = e.type;
1498 if (e.op != EXP.error)
1499 exps[i] = e;
1500 }
1501
1502 // [] is typed as void[]
1503 if (!t0)
1504 return Type.tvoid;
1505
1506 // It's an error, don't do the cast
1507 if (t0.ty == Terror)
1508 return null;
1509
1510 for (size_t i = 0; i < exps.length; i++)
1511 {
1512 Expression e = exps[i];
1513 if (!e)
1514 continue;
1515
1516 e = e.implicitCastTo(sc, t0);
1517 if (e.op == EXP.error)
1518 {
1519 /* https://issues.dlang.org/show_bug.cgi?id=13024
1520 * a workaround for the bug in typeMerge -
1521 * it should paint e1 and e2 by deduced common type,
1522 * but doesn't in this particular case.
1523 */
1524 return null;
1525 }
1526 exps[i] = e;
1527 }
1528 return t0;
1529 }
1530
1531 private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expression e2)
1532 {
1533 Expression e;
1534 switch (op)
1535 {
1536 case EXP.addAssign:
1537 e = new AddExp(loc, e1, e2);
1538 break;
1539
1540 case EXP.minAssign:
1541 e = new MinExp(loc, e1, e2);
1542 break;
1543
1544 case EXP.mulAssign:
1545 e = new MulExp(loc, e1, e2);
1546 break;
1547
1548 case EXP.divAssign:
1549 e = new DivExp(loc, e1, e2);
1550 break;
1551
1552 case EXP.modAssign:
1553 e = new ModExp(loc, e1, e2);
1554 break;
1555
1556 case EXP.andAssign:
1557 e = new AndExp(loc, e1, e2);
1558 break;
1559
1560 case EXP.orAssign:
1561 e = new OrExp(loc, e1, e2);
1562 break;
1563
1564 case EXP.xorAssign:
1565 e = new XorExp(loc, e1, e2);
1566 break;
1567
1568 case EXP.leftShiftAssign:
1569 e = new ShlExp(loc, e1, e2);
1570 break;
1571
1572 case EXP.rightShiftAssign:
1573 e = new ShrExp(loc, e1, e2);
1574 break;
1575
1576 case EXP.unsignedRightShiftAssign:
1577 e = new UshrExp(loc, e1, e2);
1578 break;
1579
1580 default:
1581 assert(0);
1582 }
1583 return e;
1584 }
1585
1586 /*********************
1587 * Rewrite:
1588 * array.length op= e2
1589 * as:
1590 * array.length = array.length op e2
1591 * or:
1592 * auto tmp = &array;
1593 * (*tmp).length = (*tmp).length op e2
1594 */
1595 private Expression rewriteOpAssign(BinExp exp)
1596 {
1597 ArrayLengthExp ale = exp.e1.isArrayLengthExp();
1598 if (ale.e1.isVarExp())
1599 {
1600 Expression e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1601 e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1602 return e;
1603 }
1604 else
1605 {
1606 /* auto tmp = &array;
1607 * (*tmp).length = (*tmp).length op e2
1608 */
1609 auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1610
1611 Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1612 Expression elvalue = e1.syntaxCopy();
1613 Expression e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1614 e = new AssignExp(exp.loc, elvalue, e);
1615 e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1616 return e;
1617 }
1618 }
1619
1620 /****************************************
1621 * Preprocess arguments to function.
1622 * Input:
1623 * reportErrors whether or not to report errors here. Some callers are not
1624 * checking actual function params, so they'll do their own error reporting
1625 * Output:
1626 * exps[] tuples expanded, properties resolved, rewritten in place
1627 * Returns:
1628 * true a semantic error occurred
1629 */
1630 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1631 {
1632 bool err = false;
1633 if (exps)
1634 {
1635 expandTuples(exps);
1636
1637 for (size_t i = 0; i < exps.length; i++)
1638 {
1639 Expression arg = (*exps)[i];
1640 arg = resolveProperties(sc, arg);
1641 arg = arg.arrayFuncConv(sc);
1642 if (arg.op == EXP.type)
1643 {
1644 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1645 arg = resolveAliasThis(sc, arg);
1646
1647 if (arg.op == EXP.type)
1648 {
1649 if (reportErrors)
1650 {
1651 arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1652 arg = ErrorExp.get();
1653 }
1654 err = true;
1655 }
1656 }
1657 else if (arg.type.toBasetype().ty == Tfunction)
1658 {
1659 if (reportErrors)
1660 {
1661 arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1662 arg = ErrorExp.get();
1663 }
1664 err = true;
1665 }
1666 else if (checkNonAssignmentArrayOp(arg))
1667 {
1668 arg = ErrorExp.get();
1669 err = true;
1670 }
1671 (*exps)[i] = arg;
1672 }
1673 }
1674 return err;
1675 }
1676
1677 /********************************************
1678 * Issue an error if default construction is disabled for type t.
1679 * Default construction is required for arrays and 'out' parameters.
1680 * Returns:
1681 * true an error was issued
1682 */
1683 private bool checkDefCtor(Loc loc, Type t)
1684 {
1685 if (auto ts = t.baseElemOf().isTypeStruct())
1686 {
1687 StructDeclaration sd = ts.sym;
1688 if (sd.noDefaultCtor)
1689 {
1690 sd.error(loc, "default construction is disabled");
1691 return true;
1692 }
1693 }
1694 return false;
1695 }
1696
1697 /****************************************
1698 * Now that we know the exact type of the function we're calling,
1699 * the arguments[] need to be adjusted:
1700 * 1. implicitly convert argument to the corresponding parameter type
1701 * 2. add default arguments for any missing arguments
1702 * 3. do default promotions on arguments corresponding to ...
1703 * 4. add hidden _arguments[] argument
1704 * 5. call copy constructor for struct value arguments
1705 * Params:
1706 * loc = location of function call
1707 * sc = context
1708 * tf = type of the function
1709 * ethis = `this` argument, `null` if none or not known
1710 * tthis = type of `this` argument, `null` if no `this` argument
1711 * arguments = array of actual arguments to function call
1712 * fd = the function being called, `null` if called indirectly
1713 * prettype = set to return type of function
1714 * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none
1715 * Returns:
1716 * true errors happened
1717 */
1718 private bool functionParameters(const ref Loc loc, Scope* sc,
1719 TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1720 Type* prettype, Expression* peprefix)
1721 {
1722 //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1723 assert(arguments);
1724 assert(fd || tf.next);
1725 size_t nargs = arguments ? arguments.length : 0;
1726 const size_t nparams = tf.parameterList.length;
1727 const olderrors = global.errors;
1728 bool err = false;
1729 *prettype = Type.terror;
1730 Expression eprefix = null;
1731 *peprefix = null;
1732
1733 if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1734 {
1735 error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1736 return true;
1737 }
1738
1739 // If inferring return type, and semantic3() needs to be run if not already run
1740 if (!tf.next && fd.inferRetType)
1741 {
1742 fd.functionSemantic();
1743 }
1744 else if (fd && fd.parent)
1745 {
1746 TemplateInstance ti = fd.parent.isTemplateInstance();
1747 if (ti && ti.tempdecl)
1748 {
1749 fd.functionSemantic3();
1750 }
1751 }
1752
1753 /* If calling a pragma(inline, true) function,
1754 * set flag to later scan for inlines.
1755 */
1756 if (fd && fd.inlining == PINLINE.always)
1757 {
1758 if (sc._module)
1759 sc._module.hasAlwaysInlines = true;
1760 if (sc.func)
1761 sc.func.hasAlwaysInlines = true;
1762 }
1763
1764 const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1765
1766 const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1767
1768 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1769 * based on the actual argument types.
1770 * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1771 * of the arguments.
1772 */
1773 MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1774
1775 bool done = false;
1776 foreach (const i; 0 .. n)
1777 {
1778 Expression arg = (i < nargs) ? (*arguments)[i] : null;
1779
1780 if (i < nparams)
1781 {
1782 bool errorArgs()
1783 {
1784 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1785 return true;
1786 }
1787
1788 Parameter p = tf.parameterList[i];
1789
1790 if (!arg)
1791 {
1792 if (!p.defaultArg)
1793 {
1794 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1795 goto L2;
1796 return errorArgs();
1797 }
1798 arg = p.defaultArg;
1799 arg = inlineCopy(arg, sc);
1800 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1801 arg = arg.resolveLoc(loc, sc);
1802 arguments.push(arg);
1803 nargs++;
1804 }
1805 else
1806 {
1807 if (isDefaultInitOp(arg.op))
1808 {
1809 arg = arg.resolveLoc(loc, sc);
1810 (*arguments)[i] = arg;
1811 }
1812 }
1813
1814
1815 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1816 {
1817 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1818 {
1819 MATCH m;
1820 if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1821 {
1822 if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1823 goto L2;
1824 else if (nargs != nparams)
1825 return errorArgs();
1826 goto L1;
1827 }
1828 }
1829 L2:
1830 Type tb = p.type.toBasetype();
1831 switch (tb.ty)
1832 {
1833 case Tsarray:
1834 case Tarray:
1835 {
1836 /* Create a static array variable v of type arg.type:
1837 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1838 *
1839 * The array literal in the initializer of the hidden variable
1840 * is now optimized.
1841 * https://issues.dlang.org/show_bug.cgi?id=2356
1842 */
1843 Type tbn = (cast(TypeArray)tb).next; // array element type
1844 Type tret = p.isLazyArray();
1845
1846 auto elements = new Expressions(nargs - i);
1847 foreach (u; 0 .. elements.length)
1848 {
1849 Expression a = (*arguments)[i + u];
1850 if (tret && a.implicitConvTo(tret))
1851 {
1852 // p is a lazy array of delegates, tret is return type of the delegates
1853 a = a.implicitCastTo(sc, tret)
1854 .optimize(WANTvalue)
1855 .toDelegate(tret, sc);
1856 }
1857 else
1858 a = a.implicitCastTo(sc, tbn);
1859 a = a.addDtorHook(sc);
1860 (*elements)[u] = a;
1861 }
1862 // https://issues.dlang.org/show_bug.cgi?id=14395
1863 // Convert to a static array literal, or its slice.
1864 arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1865 if (tb.ty == Tarray)
1866 {
1867 arg = new SliceExp(loc, arg, null, null);
1868 arg.type = p.type;
1869 }
1870 break;
1871 }
1872 case Tclass:
1873 {
1874 /* Set arg to be:
1875 * new Tclass(arg0, arg1, ..., argn)
1876 */
1877 auto args = new Expressions(nargs - i);
1878 foreach (u; i .. nargs)
1879 (*args)[u - i] = (*arguments)[u];
1880 arg = new NewExp(loc, null, p.type, args);
1881 break;
1882 }
1883 default:
1884 if (!arg)
1885 {
1886 error(loc, "not enough arguments");
1887 return true;
1888 }
1889 break;
1890 }
1891 arg = arg.expressionSemantic(sc);
1892 //printf("\targ = '%s'\n", arg.toChars());
1893 arguments.setDim(i + 1);
1894 (*arguments)[i] = arg;
1895 nargs = i + 1;
1896 done = true;
1897 }
1898
1899 L1:
1900 if (!(p.isLazy() && p.type.ty == Tvoid))
1901 {
1902 if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
1903 {
1904 wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1905 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1906 }
1907 }
1908 }
1909 if (done)
1910 break;
1911 }
1912 if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1913 tf.next && tf.next.hasWild() &&
1914 (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1915 {
1916 bool errorInout(MOD wildmatch)
1917 {
1918 const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1919 error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1920 return true;
1921 }
1922
1923 if (fd)
1924 {
1925 /* If the called function may return the reference to
1926 * outer inout data, it should be rejected.
1927 *
1928 * void foo(ref inout(int) x) {
1929 * ref inout(int) bar(inout(int)) { return x; }
1930 * struct S {
1931 * ref inout(int) bar() inout { return x; }
1932 * ref inout(int) baz(alias a)() inout { return x; }
1933 * }
1934 * bar(int.init) = 1; // bad!
1935 * S().bar() = 1; // bad!
1936 * }
1937 * void test() {
1938 * int a;
1939 * auto s = foo(a);
1940 * s.baz!a() = 1; // bad!
1941 * }
1942 *
1943 */
1944 bool checkEnclosingWild(Dsymbol s)
1945 {
1946 bool checkWild(Dsymbol s)
1947 {
1948 if (!s)
1949 return false;
1950 if (auto ad = s.isAggregateDeclaration())
1951 {
1952 if (ad.isNested())
1953 return checkEnclosingWild(s);
1954 }
1955 else if (auto ff = s.isFuncDeclaration())
1956 {
1957 if (ff.type.isTypeFunction().iswild)
1958 return errorInout(wildmatch);
1959
1960 if (ff.isNested() || ff.isThis())
1961 return checkEnclosingWild(s);
1962 }
1963 return false;
1964 }
1965
1966 Dsymbol ctx0 = s.toParent2();
1967 Dsymbol ctx1 = s.toParentLocal();
1968 if (checkWild(ctx0))
1969 return true;
1970 if (ctx0 != ctx1)
1971 return checkWild(ctx1);
1972 return false;
1973 }
1974 if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1975 return true;
1976 }
1977 else if (tf.isWild())
1978 return errorInout(wildmatch);
1979 }
1980
1981 Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1982 tthis &&
1983 tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1984 tthis.hasPointers())
1985 ? ethis : null;
1986
1987 assert(nargs >= nparams);
1988 foreach (const i, arg; (*arguments)[0 .. nargs])
1989 {
1990 assert(arg);
1991 if (i < nparams)
1992 {
1993 Parameter p = tf.parameterList[i];
1994 Type targ = arg.type; // keep original type for isCopyable() because alias this
1995 // resolution may hide an uncopyable type
1996
1997 if (!(p.isLazy() && p.type.ty == Tvoid))
1998 {
1999 Type tprm = p.type.hasWild()
2000 ? p.type.substWildTo(wildmatch)
2001 : p.type;
2002
2003 const hasCopyCtor = arg.type.isTypeStruct() && arg.type.isTypeStruct().sym.hasCopyCtor;
2004 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
2005 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
2006 {
2007 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
2008 arg = arg.implicitCastTo(sc, tprm);
2009 arg = arg.optimize(WANTvalue, p.isReference());
2010 }
2011 }
2012
2013 // Support passing rvalue to `in` parameters
2014 if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
2015 {
2016 if (!arg.isLvalue())
2017 {
2018 auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
2019 Expression ev = new DeclarationExp(arg.loc, v);
2020 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2021 arg = ev.expressionSemantic(sc);
2022 }
2023 arg = arg.toLvalue(sc, arg);
2024
2025 // Look for mutable misaligned pointer, etc., in @safe mode
2026 err |= checkUnsafeAccess(sc, arg, false, true);
2027 }
2028 else if (p.storageClass & STC.ref_)
2029 {
2030 if (global.params.rvalueRefParam == FeatureState.enabled &&
2031 !arg.isLvalue() &&
2032 targ.isCopyable())
2033 { /* allow rvalues to be passed to ref parameters by copying
2034 * them to a temp, then pass the temp as the argument
2035 */
2036 auto v = copyToTemp(0, "__rvalue", arg);
2037 Expression ev = new DeclarationExp(arg.loc, v);
2038 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2039 arg = ev.expressionSemantic(sc);
2040 }
2041 arg = arg.toLvalue(sc, arg);
2042
2043 // Look for mutable misaligned pointer, etc., in @safe mode
2044 err |= checkUnsafeAccess(sc, arg, false, true);
2045 }
2046 else if (p.storageClass & STC.out_)
2047 {
2048 Type t = arg.type;
2049 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2050 {
2051 arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2052 err = true;
2053 }
2054 else
2055 {
2056 // Look for misaligned pointer, etc., in @safe mode
2057 err |= checkUnsafeAccess(sc, arg, false, true);
2058 err |= checkDefCtor(arg.loc, t); // t must be default constructible
2059 }
2060 arg = arg.toLvalue(sc, arg);
2061 }
2062 else if (p.isLazy())
2063 {
2064 // Convert lazy argument to a delegate
2065 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2066 arg = toDelegate(arg, t, sc);
2067 }
2068 //printf("arg: %s\n", arg.toChars());
2069 //printf("type: %s\n", arg.type.toChars());
2070 //printf("param: %s\n", p.toChars());
2071
2072 const pStc = tf.parameterStorageClass(tthis, p);
2073
2074 if (firstArg && (pStc & STC.return_))
2075 {
2076 /* Argument value can be assigned to firstArg.
2077 * Check arg to see if it matters.
2078 */
2079 err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
2080 }
2081 // Allow 'lazy' to imply 'scope' - lazy parameters can be passed along
2082 // as lazy parameters to the next function, but that isn't escaping.
2083 else if (!(pStc & STC.lazy_))
2084 {
2085 /* Argument value can escape from the called function.
2086 * Check arg to see if it matters.
2087 */
2088 VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null;
2089 err |= checkParamArgumentEscape(sc, fd, p.ident, vPar, cast(STC) pStc, arg, false, false);
2090 }
2091
2092 // Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
2093 // may be unreliable when scope violations only manifest as deprecation warnings.
2094 // However, existing `@nogc` code may rely on it, so still do it when the parameter is explicitly marked `scope`
2095 const explicitScope = p.isLazy() ||
2096 ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
2097 if ((pStc & (STC.scope_ | STC.lazy_)) &&
2098 ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
2099 !(pStc & STC.return_))
2100 {
2101 /* Argument value cannot escape from the called function.
2102 */
2103 Expression a = arg;
2104 if (auto ce = a.isCastExp())
2105 a = ce.e1;
2106
2107 ArrayLiteralExp ale;
2108 if (p.type.toBasetype().ty == Tarray &&
2109 (ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0)
2110 {
2111 // allocate the array literal as temporary static array on the stack
2112 ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
2113 auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2114 auto declareTmp = new DeclarationExp(ale.loc, tmp);
2115 auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
2116 p.type.substWildTo(MODFlags.mutable));
2117 arg = CommaExp.combine(declareTmp, castToSlice);
2118 arg = arg.expressionSemantic(sc);
2119 }
2120 else if (auto fe = a.isFuncExp())
2121 {
2122 /* Function literals can only appear once, so if this
2123 * appearance was scoped, there cannot be any others.
2124 */
2125 fe.fd.tookAddressOf = 0;
2126 }
2127 else if (auto de = a.isDelegateExp())
2128 {
2129 /* For passing a delegate to a scoped parameter,
2130 * this doesn't count as taking the address of it.
2131 * We only worry about 'escaping' references to the function.
2132 */
2133 if (auto ve = de.e1.isVarExp())
2134 {
2135 if (auto f = ve.var.isFuncDeclaration())
2136 {
2137 if (f.tookAddressOf)
2138 --f.tookAddressOf;
2139 //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2140 }
2141 }
2142 }
2143 }
2144 if (!p.isReference())
2145 err |= arg.checkSharedAccess(sc);
2146
2147 arg = arg.optimize(WANTvalue, p.isReference());
2148
2149 /* Determine if this parameter is the "first reference" parameter through which
2150 * later "return" arguments can be stored.
2151 */
2152 if (i == 0 && !tthis && p.isReference() && p.type &&
2153 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2154 {
2155 Type tb = p.type.baseElemOf();
2156 if (tb.isMutable() && tb.hasPointers())
2157 {
2158 firstArg = arg;
2159 }
2160 }
2161 }
2162 else
2163 {
2164 // These will be the trailing ... arguments
2165 // If not D linkage, do promotions
2166 if (tf.linkage != LINK.d)
2167 {
2168 // Promote bytes, words, etc., to ints
2169 arg = integralPromotions(arg, sc);
2170
2171 // Promote floats to doubles
2172 switch (arg.type.ty)
2173 {
2174 case Tfloat32:
2175 arg = arg.castTo(sc, Type.tfloat64);
2176 break;
2177
2178 case Timaginary32:
2179 arg = arg.castTo(sc, Type.timaginary64);
2180 break;
2181
2182 default:
2183 break;
2184 }
2185 if (tf.parameterList.varargs == VarArg.variadic)
2186 {
2187 const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2188 if (arg.type.ty == Tarray)
2189 {
2190 arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2191 err = true;
2192 }
2193 if (arg.type.ty == Tsarray)
2194 {
2195 arg.error("cannot pass static arrays to `%s` vararg functions", p);
2196 err = true;
2197 }
2198 }
2199 }
2200
2201 // Do not allow types that need destructors or copy constructors.
2202 if (arg.type.needsDestruction())
2203 {
2204 arg.error("cannot pass types that need destruction as variadic arguments");
2205 err = true;
2206 }
2207 if (arg.type.needsCopyOrPostblit())
2208 {
2209 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2210 err = true;
2211 }
2212
2213 // Convert static arrays to dynamic arrays
2214 // BUG: I don't think this is right for D2
2215 Type tb = arg.type.toBasetype();
2216 if (auto ts = tb.isTypeSArray())
2217 {
2218 Type ta = ts.next.arrayOf();
2219 if (ts.size(arg.loc) == 0)
2220 arg = new NullExp(arg.loc, ta);
2221 else
2222 arg = arg.castTo(sc, ta);
2223 }
2224 if (tb.ty == Tstruct)
2225 {
2226 //arg = callCpCtor(sc, arg);
2227 }
2228 // Give error for overloaded function addresses
2229 if (auto se = arg.isSymOffExp())
2230 {
2231 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2232 {
2233 arg.error("function `%s` is overloaded", arg.toChars());
2234 err = true;
2235 }
2236 }
2237 err |= arg.checkValue();
2238 err |= arg.checkSharedAccess(sc);
2239 arg = arg.optimize(WANTvalue);
2240 }
2241 (*arguments)[i] = arg;
2242 }
2243
2244 /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2245 */
2246 const isVa_list = tf.parameterList.varargs == VarArg.none;
2247 if (fd && fd.printf)
2248 {
2249 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2250 {
2251 checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2252 }
2253 }
2254 else if (fd && fd.scanf)
2255 {
2256 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2257 {
2258 checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2259 }
2260 }
2261 else
2262 {
2263 // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2264 }
2265
2266 /* Remaining problems:
2267 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2268 * implemented by calling a function) we'll defer this for now.
2269 * 2. value structs (or static arrays of them) that need to be copy constructed
2270 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2271 * function gets called.
2272 * 4. value structs need to be destructed after the function call for platforms where the caller destroys the arguments.
2273 * 2, 3 and 4 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2274 * up properly. Pushing arguments on the stack then cannot fail.
2275 */
2276 {
2277 /* TODO: tackle problem 1)
2278 */
2279 const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2280 if (!leftToRight)
2281 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2282
2283 /* Does Problem (4) apply?
2284 */
2285 const bool callerDestroysArgs = !target.isCalleeDestroyingArgs(tf);
2286
2287 const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2288 const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2289 const ptrdiff_t step = (leftToRight ? 1 : -1);
2290
2291 /* Compute indices of last throwing argument and first arg needing destruction.
2292 * Used to not set up destructors unless an arg needs destruction on a throw
2293 * in a later argument.
2294 */
2295 ptrdiff_t lastthrow = -1; // last argument that may throw
2296 ptrdiff_t firstdtor = -1; // first argument that needs destruction
2297 ptrdiff_t lastdtor = -1; // last argument that needs destruction
2298 for (ptrdiff_t i = start; i != end; i += step)
2299 {
2300 Expression arg = (*arguments)[i];
2301 if (canThrow(arg, sc.func, false))
2302 lastthrow = i;
2303 if (arg.type.needsDestruction())
2304 {
2305 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2306 if (!(p && (p.isLazy() || p.isReference())))
2307 {
2308 if (firstdtor == -1)
2309 firstdtor = i;
2310 lastdtor = i;
2311 }
2312 }
2313 }
2314
2315 /* Do we need 'eprefix' for problems 3 or 4?
2316 */
2317 const bool needsPrefix = callerDestroysArgs
2318 ? firstdtor >= 0 // true if any argument needs destruction
2319 : firstdtor >= 0 && lastthrow >= 0 &&
2320 (lastthrow - firstdtor) * step > 0; // last throw after first destruction
2321 const ptrdiff_t lastPrefix = callerDestroysArgs
2322 ? lastdtor // up to last argument requiring destruction
2323 : lastthrow; // up to last potentially throwing argument
2324
2325 /* Problem 3: initialize 'eprefix' by declaring the gate
2326 */
2327 VarDeclaration gate;
2328 if (needsPrefix && !callerDestroysArgs)
2329 {
2330 // eprefix => bool __gate [= false]
2331 Identifier idtmp = Identifier.generateId("__gate");
2332 gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2333 gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2334 gate.dsymbolSemantic(sc);
2335
2336 auto ae = new DeclarationExp(loc, gate);
2337 eprefix = ae.expressionSemantic(sc);
2338 }
2339
2340 for (ptrdiff_t i = start; i != end; i += step)
2341 {
2342 Expression arg = (*arguments)[i];
2343 //printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
2344
2345 Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2346 const bool isRef = parameter && parameter.isReference();
2347 const bool isLazy = parameter && parameter.isLazy();
2348
2349 /* Skip lazy parameters
2350 */
2351 if (isLazy)
2352 continue;
2353
2354 /* Do we have 'eprefix' and aren't past 'lastPrefix' yet?
2355 * Then declare a temporary variable for this arg and append that declaration
2356 * to 'eprefix', which will implicitly take care of potential problem 2) for
2357 * this arg.
2358 * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
2359 * excluding all lazy parameters.
2360 */
2361 if (needsPrefix && (lastPrefix - i) * step >= 0)
2362 {
2363 const bool needsDtor = !isRef && arg.type.needsDestruction() &&
2364 // Problem 3: last throwing arg doesn't require dtor patching
2365 (callerDestroysArgs || i != lastPrefix);
2366
2367 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2368 */
2369 auto tmp = copyToTemp(
2370 (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_),
2371 needsDtor ? "__pfx" : "__pfy",
2372 !isRef ? arg : arg.addressOf());
2373 tmp.dsymbolSemantic(sc);
2374
2375 if (callerDestroysArgs)
2376 {
2377 /* Problem 4: Normal temporary, destructed after the call
2378 */
2379 if (needsDtor)
2380 tmp.isArgDtorVar = true; // mark it so that the backend passes it by ref to the function being called
2381 }
2382 else
2383 {
2384 /* Problem 3: Modify the destructor so it only runs if gate==false,
2385 * i.e., only if there was a throw while constructing the args
2386 */
2387 if (!needsDtor)
2388 {
2389 if (tmp.edtor)
2390 {
2391 assert(i == lastPrefix);
2392 tmp.edtor = null;
2393 }
2394 }
2395 else
2396 {
2397 // edtor => (__gate || edtor)
2398 assert(tmp.edtor);
2399 Expression e = tmp.edtor;
2400 e = new LogicalExp(e.loc, EXP.orOr, new VarExp(e.loc, gate), e);
2401 tmp.edtor = e.expressionSemantic(sc);
2402 //printf("edtor: %s\n", tmp.edtor.toChars());
2403 }
2404 }
2405
2406 // eprefix => (eprefix, auto __pfx/y = arg)
2407 auto ae = new DeclarationExp(loc, tmp);
2408 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2409
2410 // arg => __pfx/y
2411 arg = new VarExp(loc, tmp);
2412 arg = arg.expressionSemantic(sc);
2413 if (isRef)
2414 {
2415 arg = new PtrExp(loc, arg);
2416 arg = arg.expressionSemantic(sc);
2417 }
2418
2419 /* Problem 3: Last throwing arg?
2420 * Then finalize eprefix => (eprefix, gate = true), i.e., disable the
2421 * dtors right after constructing the last throwing arg.
2422 * From now on, the callee will take care of destructing the args because
2423 * the args are implicitly moved into function parameters.
2424 */
2425 if (!callerDestroysArgs && i == lastPrefix)
2426 {
2427 auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2428 eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2429 }
2430 }
2431 else // not part of 'eprefix'
2432 {
2433 /* Handle problem 2) by calling the copy constructor for value structs
2434 * (or static arrays of them) if appropriate.
2435 */
2436 Type tv = arg.type.baseElemOf();
2437 if (!isRef && tv.ty == Tstruct)
2438 arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2439 }
2440
2441 (*arguments)[i] = arg;
2442 }
2443 }
2444 //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2445
2446 /* Test compliance with DIP1021
2447 */
2448 if (global.params.useDIP1021 &&
2449 tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2450 err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2451
2452 // If D linkage and variadic, add _arguments[] as first argument
2453 if (tf.isDstyleVariadic())
2454 {
2455 assert(arguments.length >= nparams);
2456
2457 auto args = new Parameters(arguments.length - nparams);
2458 for (size_t i = 0; i < arguments.length - nparams; i++)
2459 {
2460 auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2461 (*args)[i] = arg;
2462 }
2463 auto tup = new TypeTuple(args);
2464 Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2465 arguments.insert(0, e);
2466 }
2467
2468 /* Determine function return type: tret
2469 */
2470 Type tret = tf.next;
2471 if (isCtorCall)
2472 {
2473 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2474 // wildmatch, tf.isWild(), fd.isReturnIsolated());
2475 if (!tthis)
2476 {
2477 assert(sc.intypeof || global.errors);
2478 tthis = fd.isThis().type.addMod(fd.type.mod);
2479 }
2480 if (tf.isWild() && !fd.isReturnIsolated())
2481 {
2482 if (wildmatch)
2483 tret = tret.substWildTo(wildmatch);
2484 int offset;
2485 if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2486 {
2487 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2488 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2489 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2490 err = true;
2491 }
2492 }
2493 tret = tthis;
2494 }
2495 else if (wildmatch && tret)
2496 {
2497 /* Adjust function return type based on wildmatch
2498 */
2499 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2500 tret = tret.substWildTo(wildmatch);
2501 }
2502
2503 *prettype = tret;
2504 *peprefix = eprefix;
2505 return (err || olderrors != global.errors);
2506 }
2507
2508 /**
2509 * Determines whether a symbol represents a module or package
2510 * (Used as a helper for is(type == module) and is(type == package))
2511 *
2512 * Params:
2513 * sym = the symbol to be checked
2514 *
2515 * Returns:
2516 * the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2517 */
2518 Package resolveIsPackage(Dsymbol sym)
2519 {
2520 Package pkg;
2521 if (Import imp = sym.isImport())
2522 {
2523 if (imp.pkg is null)
2524 {
2525 .error(sym.loc, "internal compiler error: unable to process forward-referenced import `%s`",
2526 imp.toChars());
2527 assert(0);
2528 }
2529 pkg = imp.pkg;
2530 }
2531 else if (auto mod = sym.isModule())
2532 pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2533 else
2534 pkg = sym.isPackage();
2535 if (pkg)
2536 pkg.resolvePKGunknown();
2537 return pkg;
2538 }
2539
2540
2541 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2542 {
2543 alias visit = Visitor.visit;
2544
2545 Scope* sc;
2546 Expression result;
2547
2548 this(Scope* sc)
2549 {
2550 this.sc = sc;
2551 }
2552
2553 private void setError()
2554 {
2555 result = ErrorExp.get();
2556 }
2557
2558 /**************************
2559 * Semantically analyze Expression.
2560 * Determine types, fold constants, etc.
2561 */
2562 override void visit(Expression e)
2563 {
2564 static if (LOGSEMANTIC)
2565 {
2566 printf("Expression::semantic() %s\n", e.toChars());
2567 }
2568 if (e.type)
2569 e.type = e.type.typeSemantic(e.loc, sc);
2570 else
2571 e.type = Type.tvoid;
2572 result = e;
2573 }
2574
2575 override void visit(IntegerExp e)
2576 {
2577 assert(e.type);
2578 if (e.type.ty == Terror)
2579 return setError();
2580
2581 assert(e.type.deco);
2582 e.setInteger(e.getInteger());
2583 result = e;
2584 }
2585
2586 override void visit(RealExp e)
2587 {
2588 if (!e.type)
2589 e.type = Type.tfloat64;
2590 else
2591 e.type = e.type.typeSemantic(e.loc, sc);
2592 result = e;
2593 }
2594
2595 override void visit(ComplexExp e)
2596 {
2597 if (!e.type)
2598 e.type = Type.tcomplex80;
2599 else
2600 e.type = e.type.typeSemantic(e.loc, sc);
2601 result = e;
2602 }
2603
2604 override void visit(IdentifierExp exp)
2605 {
2606 static if (LOGSEMANTIC)
2607 {
2608 printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2609 }
2610 if (exp.type) // This is used as the dummy expression
2611 {
2612 result = exp;
2613 return;
2614 }
2615
2616 Dsymbol scopesym;
2617 Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2618 if (s)
2619 {
2620 if (s.errors)
2621 return setError();
2622
2623 Expression e;
2624
2625 /* See if the symbol was a member of an enclosing 'with'
2626 */
2627 WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2628 if (withsym && withsym.withstate.wthis && symbolIsVisible(sc, s))
2629 {
2630 /* Disallow shadowing
2631 */
2632 // First find the scope of the with
2633 Scope* scwith = sc;
2634 while (scwith.scopesym != scopesym)
2635 {
2636 scwith = scwith.enclosing;
2637 assert(scwith);
2638 }
2639 // Look at enclosing scopes for symbols with the same name,
2640 // in the same function
2641 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2642 {
2643 Dsymbol s2;
2644 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2645 {
2646 exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2647 return setError();
2648 }
2649 }
2650 s = s.toAlias();
2651
2652 // Same as wthis.ident
2653 // TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2654 // The redudancy should be removed.
2655 e = new VarExp(exp.loc, withsym.withstate.wthis);
2656 e = new DotIdExp(exp.loc, e, exp.ident);
2657 e = e.expressionSemantic(sc);
2658 }
2659 else
2660 {
2661 if (withsym)
2662 {
2663 if (withsym.withstate.exp.type.ty != Tvoid)
2664 {
2665 // 'with (exp)' is a type expression
2666 // or 's' is not visible there (for error message)
2667 e = new TypeExp(exp.loc, withsym.withstate.exp.type);
2668 }
2669 else
2670 {
2671 // 'with (exp)' is a Package/Module
2672 e = withsym.withstate.exp;
2673 }
2674 e = new DotIdExp(exp.loc, e, exp.ident);
2675 result = e.expressionSemantic(sc);
2676 return;
2677 }
2678
2679 /* If f is really a function template,
2680 * then replace f with the function template declaration.
2681 */
2682 FuncDeclaration f = s.isFuncDeclaration();
2683 if (f)
2684 {
2685 TemplateDeclaration td = getFuncTemplateDecl(f);
2686 if (td)
2687 {
2688 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2689 td = td.overroot; // then get the start
2690 e = new TemplateExp(exp.loc, td, f);
2691 e = e.expressionSemantic(sc);
2692 result = e;
2693 return;
2694 }
2695 }
2696
2697 if (global.params.fixAliasThis)
2698 {
2699 ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2700 if (expDsym)
2701 {
2702 //printf("expDsym = %s\n", expDsym.exp.toChars());
2703 result = expDsym.exp.expressionSemantic(sc);
2704 return;
2705 }
2706 }
2707 // Haven't done overload resolution yet, so pass 1
2708 e = symbolToExp(s, exp.loc, sc, true);
2709 }
2710 result = e;
2711 return;
2712 }
2713
2714 if (!global.params.fixAliasThis && hasThis(sc))
2715 {
2716 for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2717 {
2718 if (ad.aliasthis)
2719 {
2720 Expression e;
2721 e = new ThisExp(exp.loc);
2722 e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2723 e = new DotIdExp(exp.loc, e, exp.ident);
2724 e = e.trySemantic(sc);
2725 if (e)
2726 {
2727 result = e;
2728 return;
2729 }
2730 }
2731
2732 auto cd = ad.isClassDeclaration();
2733 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2734 {
2735 ad = cd.baseClass;
2736 continue;
2737 }
2738 break;
2739 }
2740 }
2741
2742 if (exp.ident == Id.ctfe)
2743 {
2744 if (sc.flags & SCOPE.ctfe)
2745 {
2746 exp.error("variable `__ctfe` cannot be read at compile time");
2747 return setError();
2748 }
2749
2750 // Create the magic __ctfe bool variable
2751 auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2752 vd.storage_class |= STC.temp;
2753 vd.semanticRun = PASS.semanticdone;
2754 Expression e = new VarExp(exp.loc, vd);
2755 e = e.expressionSemantic(sc);
2756 result = e;
2757 return;
2758 }
2759
2760 // If we've reached this point and are inside a with() scope then we may
2761 // try one last attempt by checking whether the 'wthis' object supports
2762 // dynamic dispatching via opDispatch.
2763 // This is done by rewriting this expression as wthis.ident.
2764 // The innermost with() scope of the hierarchy to satisfy the condition
2765 // above wins.
2766 // https://issues.dlang.org/show_bug.cgi?id=6400
2767 for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2768 {
2769 if (!sc2.scopesym)
2770 continue;
2771
2772 if (auto ss = sc2.scopesym.isWithScopeSymbol())
2773 {
2774 if (ss.withstate.wthis)
2775 {
2776 Expression e;
2777 e = new VarExp(exp.loc, ss.withstate.wthis);
2778 e = new DotIdExp(exp.loc, e, exp.ident);
2779 e = e.trySemantic(sc);
2780 if (e)
2781 {
2782 result = e;
2783 return;
2784 }
2785 }
2786 // Try Type.opDispatch (so the static version)
2787 else if (ss.withstate.exp && ss.withstate.exp.op == EXP.type)
2788 {
2789 if (Type t = ss.withstate.exp.isTypeExp().type)
2790 {
2791 Expression e;
2792 e = new TypeExp(exp.loc, t);
2793 e = new DotIdExp(exp.loc, e, exp.ident);
2794 e = e.trySemantic(sc);
2795 if (e)
2796 {
2797 result = e;
2798 return;
2799 }
2800 }
2801 }
2802 }
2803 }
2804
2805 /* Look for what user might have meant
2806 */
2807 if (const n = importHint(exp.ident.toString()))
2808 exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2809 else if (auto s2 = sc.search_correct(exp.ident))
2810 exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2811 else if (const p = Scope.search_correct_C(exp.ident))
2812 exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2813 else if (exp.ident == Id.dollar)
2814 exp.error("undefined identifier `$`");
2815 else
2816 exp.error("undefined identifier `%s`", exp.ident.toChars());
2817
2818 result = ErrorExp.get();
2819 }
2820
2821 override void visit(DsymbolExp e)
2822 {
2823 result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2824 }
2825
2826 override void visit(ThisExp e)
2827 {
2828 static if (LOGSEMANTIC)
2829 {
2830 printf("ThisExp::semantic()\n");
2831 }
2832 if (e.type)
2833 {
2834 result = e;
2835 return;
2836 }
2837
2838 FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2839 AggregateDeclaration ad;
2840
2841 /* Special case for typeof(this) and typeof(super) since both
2842 * should work even if they are not inside a non-static member function
2843 */
2844 if (!fd && sc.intypeof == 1)
2845 {
2846 // Find enclosing struct or class
2847 for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2848 {
2849 if (!s)
2850 {
2851 e.error("`%s` is not in a class or struct scope", e.toChars());
2852 goto Lerr;
2853 }
2854 ClassDeclaration cd = s.isClassDeclaration();
2855 if (cd)
2856 {
2857 e.type = cd.type;
2858 result = e;
2859 return;
2860 }
2861 StructDeclaration sd = s.isStructDeclaration();
2862 if (sd)
2863 {
2864 e.type = sd.type;
2865 result = e;
2866 return;
2867 }
2868 }
2869 }
2870 if (!fd)
2871 goto Lerr;
2872
2873 assert(fd.vthis);
2874 e.var = fd.vthis;
2875 assert(e.var.parent);
2876 ad = fd.isMemberLocal();
2877 if (!ad)
2878 ad = fd.isMember2();
2879 assert(ad);
2880 e.type = ad.type.addMod(e.var.type.mod);
2881
2882 if (e.var.checkNestedReference(sc, e.loc))
2883 return setError();
2884
2885 result = e;
2886 return;
2887
2888 Lerr:
2889 e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2890 result = ErrorExp.get();
2891 }
2892
2893 override void visit(SuperExp e)
2894 {
2895 static if (LOGSEMANTIC)
2896 {
2897 printf("SuperExp::semantic('%s')\n", e.toChars());
2898 }
2899 if (e.type)
2900 {
2901 result = e;
2902 return;
2903 }
2904
2905 FuncDeclaration fd = hasThis(sc);
2906 ClassDeclaration cd;
2907 Dsymbol s;
2908
2909 /* Special case for typeof(this) and typeof(super) since both
2910 * should work even if they are not inside a non-static member function
2911 */
2912 if (!fd && sc.intypeof == 1)
2913 {
2914 // Find enclosing class
2915 for (s = sc.getStructClassScope(); 1; s = s.parent)
2916 {
2917 if (!s)
2918 {
2919 e.error("`%s` is not in a class scope", e.toChars());
2920 goto Lerr;
2921 }
2922 cd = s.isClassDeclaration();
2923 if (cd)
2924 {
2925 cd = cd.baseClass;
2926 if (!cd)
2927 {
2928 e.error("class `%s` has no `super`", s.toChars());
2929 goto Lerr;
2930 }
2931 e.type = cd.type;
2932 result = e;
2933 return;
2934 }
2935 }
2936 }
2937 if (!fd)
2938 goto Lerr;
2939
2940 e.var = fd.vthis;
2941 assert(e.var && e.var.parent);
2942
2943 s = fd.toParentDecl();
2944 if (s.isTemplateDeclaration()) // allow inside template constraint
2945 s = s.toParent();
2946 assert(s);
2947 cd = s.isClassDeclaration();
2948 //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2949 if (!cd)
2950 goto Lerr;
2951 if (!cd.baseClass)
2952 {
2953 e.error("no base class for `%s`", cd.toChars());
2954 e.type = cd.type.addMod(e.var.type.mod);
2955 }
2956 else
2957 {
2958 e.type = cd.baseClass.type;
2959 e.type = e.type.castMod(e.var.type.mod);
2960 }
2961
2962 if (e.var.checkNestedReference(sc, e.loc))
2963 return setError();
2964
2965 result = e;
2966 return;
2967
2968 Lerr:
2969 e.error("`super` is only allowed in non-static class member functions");
2970 result = ErrorExp.get();
2971 }
2972
2973 override void visit(NullExp e)
2974 {
2975 static if (LOGSEMANTIC)
2976 {
2977 printf("NullExp::semantic('%s')\n", e.toChars());
2978 }
2979 // NULL is the same as (void *)0
2980 if (e.type)
2981 {
2982 result = e;
2983 return;
2984 }
2985 e.type = Type.tnull;
2986 result = e;
2987 }
2988
2989 override void visit(StringExp e)
2990 {
2991 static if (LOGSEMANTIC)
2992 {
2993 printf("StringExp::semantic() %s\n", e.toChars());
2994 }
2995 if (e.type)
2996 {
2997 result = e;
2998 return;
2999 }
3000
3001 OutBuffer buffer;
3002 size_t newlen = 0;
3003 size_t u;
3004 dchar c;
3005
3006 switch (e.postfix)
3007 {
3008 case 'd':
3009 for (u = 0; u < e.len;)
3010 {
3011 if (const p = utf_decodeChar(e.peekString(), u, c))
3012 {
3013 e.error("%.*s", cast(int)p.length, p.ptr);
3014 return setError();
3015 }
3016 else
3017 {
3018 buffer.write4(c);
3019 newlen++;
3020 }
3021 }
3022 buffer.write4(0);
3023 e.setData(buffer.extractData(), newlen, 4);
3024 if (sc && sc.flags & SCOPE.Cfile)
3025 e.type = Type.tuns32.sarrayOf(e.len + 1);
3026 else
3027 e.type = Type.tdchar.immutableOf().arrayOf();
3028 e.committed = 1;
3029 break;
3030
3031 case 'w':
3032 for (u = 0; u < e.len;)
3033 {
3034 if (const p = utf_decodeChar(e.peekString(), u, c))
3035 {
3036 e.error("%.*s", cast(int)p.length, p.ptr);
3037 return setError();
3038 }
3039 else
3040 {
3041 buffer.writeUTF16(c);
3042 newlen++;
3043 if (c >= 0x10000)
3044 newlen++;
3045 }
3046 }
3047 buffer.writeUTF16(0);
3048 e.setData(buffer.extractData(), newlen, 2);
3049 if (sc && sc.flags & SCOPE.Cfile)
3050 e.type = Type.tuns16.sarrayOf(e.len + 1);
3051 else
3052 e.type = Type.twchar.immutableOf().arrayOf();
3053 e.committed = 1;
3054 break;
3055
3056 case 'c':
3057 e.committed = 1;
3058 goto default;
3059
3060 default:
3061 if (sc && sc.flags & SCOPE.Cfile)
3062 e.type = Type.tchar.sarrayOf(e.len + 1);
3063 else
3064 e.type = Type.tchar.immutableOf().arrayOf();
3065 break;
3066 }
3067 e.type = e.type.typeSemantic(e.loc, sc);
3068 //type = type.immutableOf();
3069 //printf("type = %s\n", type.toChars());
3070
3071 result = e;
3072 }
3073
3074 override void visit(TupleExp exp)
3075 {
3076 static if (LOGSEMANTIC)
3077 {
3078 printf("+TupleExp::semantic(%s)\n", exp.toChars());
3079 }
3080 if (exp.type)
3081 {
3082 result = exp;
3083 return;
3084 }
3085
3086 if (exp.e0)
3087 exp.e0 = exp.e0.expressionSemantic(sc);
3088
3089 // Run semantic() on each argument
3090 bool err = false;
3091 for (size_t i = 0; i < exp.exps.length; i++)
3092 {
3093 Expression e = (*exp.exps)[i];
3094 e = e.expressionSemantic(sc);
3095 if (!e.type)
3096 {
3097 exp.error("`%s` has no value", e.toChars());
3098 err = true;
3099 }
3100 else if (e.op == EXP.error)
3101 err = true;
3102 else
3103 (*exp.exps)[i] = e;
3104 }
3105 if (err)
3106 return setError();
3107
3108 expandTuples(exp.exps);
3109
3110 exp.type = new TypeTuple(exp.exps);
3111 exp.type = exp.type.typeSemantic(exp.loc, sc);
3112 //printf("-TupleExp::semantic(%s)\n", toChars());
3113 result = exp;
3114 }
3115
3116 override void visit(ArrayLiteralExp e)
3117 {
3118 static if (LOGSEMANTIC)
3119 {
3120 printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3121 }
3122 if (e.type)
3123 {
3124 result = e;
3125 return;
3126 }
3127
3128 /* Perhaps an empty array literal [ ] should be rewritten as null?
3129 */
3130
3131 if (e.basis)
3132 e.basis = e.basis.expressionSemantic(sc);
3133 if (arrayExpressionSemantic(e.elements.peekSlice(), sc) || (e.basis && e.basis.op == EXP.error))
3134 return setError();
3135
3136 expandTuples(e.elements);
3137
3138 if (e.basis)
3139 e.elements.push(e.basis);
3140 Type t0 = arrayExpressionToCommonType(sc, *e.elements);
3141 if (e.basis)
3142 e.basis = e.elements.pop();
3143 if (t0 is null)
3144 return setError();
3145
3146 e.type = t0.arrayOf();
3147 e.type = e.type.typeSemantic(e.loc, sc);
3148
3149 /* Disallow array literals of type void being used.
3150 */
3151 if (e.elements.length > 0 && t0.ty == Tvoid)
3152 {
3153 e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3154 return setError();
3155 }
3156
3157 if (global.params.useTypeInfo && Type.dtypeinfo)
3158 semanticTypeInfo(sc, e.type);
3159
3160 result = e;
3161 }
3162
3163 override void visit(AssocArrayLiteralExp e)
3164 {
3165 static if (LOGSEMANTIC)
3166 {
3167 printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3168 }
3169 if (e.type)
3170 {
3171 result = e;
3172 return;
3173 }
3174
3175 // Run semantic() on each element
3176 bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc);
3177 bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc);
3178 if (err_keys || err_vals)
3179 return setError();
3180
3181 expandTuples(e.keys);
3182 expandTuples(e.values);
3183 if (e.keys.length != e.values.length)
3184 {
3185 e.error("number of keys is %llu, must match number of values %llu",
3186 cast(ulong) e.keys.length, cast(ulong) e.values.length);
3187 return setError();
3188 }
3189
3190 Type tkey = arrayExpressionToCommonType(sc, *e.keys);
3191 Type tvalue = arrayExpressionToCommonType(sc, *e.values);
3192 if (tkey is null || tvalue is null)
3193 return setError();
3194
3195 e.type = new TypeAArray(tvalue, tkey);
3196 e.type = e.type.typeSemantic(e.loc, sc);
3197
3198 semanticTypeInfo(sc, e.type);
3199
3200 if (checkAssocArrayLiteralEscape(sc, e, false))
3201 return setError();
3202
3203 result = e;
3204 }
3205
3206 override void visit(StructLiteralExp e)
3207 {
3208 static if (LOGSEMANTIC)
3209 {
3210 printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3211 }
3212 if (e.type)
3213 {
3214 result = e;
3215 return;
3216 }
3217
3218 e.sd.size(e.loc);
3219 if (e.sd.sizeok != Sizeok.done)
3220 return setError();
3221
3222 // run semantic() on each element
3223 if (arrayExpressionSemantic(e.elements.peekSlice(), sc))
3224 return setError();
3225
3226 expandTuples(e.elements);
3227
3228 /* Fit elements[] to the corresponding type of field[].
3229 */
3230 if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3231 return setError();
3232
3233 /* Fill out remainder of elements[] with default initializers for fields[]
3234 */
3235 if (!e.sd.fill(e.loc, *e.elements, false))
3236 {
3237 /* An error in the initializer needs to be recorded as an error
3238 * in the enclosing function or template, since the initializer
3239 * will be part of the stuct declaration.
3240 */
3241 global.increaseErrorCount();
3242 return setError();
3243 }
3244
3245 if (checkFrameAccess(e.loc, sc, e.sd, e.elements.length))
3246 return setError();
3247
3248 e.type = e.stype ? e.stype : e.sd.type;
3249 result = e;
3250 }
3251
3252 override void visit(CompoundLiteralExp cle)
3253 {
3254 static if (LOGSEMANTIC)
3255 {
3256 printf("CompoundLiteralExp::semantic('%s')\n", cle.toChars());
3257 }
3258 Type t = cle.type.typeSemantic(cle.loc, sc);
3259 auto init = initializerSemantic(cle.initializer, sc, t, INITnointerpret);
3260 auto e = initializerToExpression(init, t, (sc.flags & SCOPE.Cfile) != 0);
3261 if (!e)
3262 {
3263 error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars());
3264 return setError();
3265 }
3266 result = e;
3267 return;
3268 }
3269
3270 override void visit(TypeExp exp)
3271 {
3272 if (exp.type.ty == Terror)
3273 return setError();
3274
3275 //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3276 Expression e;
3277 Type t;
3278 Dsymbol s;
3279
3280 dmd.typesem.resolve(exp.type, exp.loc, sc, e, t, s, true);
3281 if (e)
3282 {
3283 // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3284 // then rewrite as `(this.var)` in case it would be followed by a DotVar
3285 // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3286 VarExp ve = e.isVarExp();
3287 if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3288 sc.func && sc.func.needThis && ve.var.isMember2())
3289 {
3290 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3291 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3292 }
3293 //printf("e = %s %s\n", Token.toChars(e.op), e.toChars());
3294 e = e.expressionSemantic(sc);
3295 }
3296 else if (t)
3297 {
3298 //printf("t = %d %s\n", t.ty, t.toChars());
3299 exp.type = t.typeSemantic(exp.loc, sc);
3300 e = exp;
3301 }
3302 else if (s)
3303 {
3304 //printf("s = %s %s\n", s.kind(), s.toChars());
3305 e = symbolToExp(s, exp.loc, sc, true);
3306 }
3307 else
3308 assert(0);
3309
3310 exp.type.checkComplexTransition(exp.loc, sc);
3311
3312 result = e;
3313 }
3314
3315 override void visit(ScopeExp exp)
3316 {
3317 static if (LOGSEMANTIC)
3318 {
3319 printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3320 }
3321 if (exp.type)
3322 {
3323 result = exp;
3324 return;
3325 }
3326
3327 ScopeDsymbol sds2 = exp.sds;
3328 TemplateInstance ti = sds2.isTemplateInstance();
3329 while (ti)
3330 {
3331 WithScopeSymbol withsym;
3332 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3333 return setError();
3334 if (withsym && withsym.withstate.wthis)
3335 {
3336 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3337 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3338 result = e.expressionSemantic(sc);
3339 return;
3340 }
3341 if (ti.needsTypeInference(sc))
3342 {
3343 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3344 {
3345 Dsymbol p = td.toParentLocal();
3346 FuncDeclaration fdthis = hasThis(sc);
3347 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3348 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3349 {
3350 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3351 result = e.expressionSemantic(sc);
3352 return;
3353 }
3354 }
3355 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3356 {
3357 FuncDeclaration fdthis = hasThis(sc);
3358 AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3359 if (fdthis && ad && fdthis.isMemberLocal() == ad)
3360 {
3361 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3362 result = e.expressionSemantic(sc);
3363 return;
3364 }
3365 }
3366 // ti is an instance which requires IFTI.
3367 exp.sds = ti;
3368 exp.type = Type.tvoid;
3369 result = exp;
3370 return;
3371 }
3372 ti.dsymbolSemantic(sc);
3373 if (!ti.inst || ti.errors)
3374 return setError();
3375
3376 Dsymbol s = ti.toAlias();
3377 if (s == ti)
3378 {
3379 exp.sds = ti;
3380 exp.type = Type.tvoid;
3381 result = exp;
3382 return;
3383 }
3384 sds2 = s.isScopeDsymbol();
3385 if (sds2)
3386 {
3387 ti = sds2.isTemplateInstance();
3388 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3389 continue;
3390 }
3391
3392 if (auto v = s.isVarDeclaration())
3393 {
3394 if (!v.type)
3395 {
3396 exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3397 return setError();
3398 }
3399 if ((v.storage_class & STC.manifest) && v._init)
3400 {
3401 /* When an instance that will be converted to a constant exists,
3402 * the instance representation "foo!tiargs" is treated like a
3403 * variable name, and its recursive appearance check (note that
3404 * it's equivalent with a recursive instantiation of foo) is done
3405 * separately from the circular initialization check for the
3406 * eponymous enum variable declaration.
3407 *
3408 * template foo(T) {
3409 * enum bool foo = foo; // recursive definition check (v.inuse)
3410 * }
3411 * template bar(T) {
3412 * enum bool bar = bar!T; // recursive instantiation check (ti.inuse)
3413 * }
3414 */
3415 if (ti.inuse)
3416 {
3417 exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3418 return setError();
3419 }
3420 v.checkDeprecated(exp.loc, sc);
3421 auto e = v.expandInitializer(exp.loc);
3422 ti.inuse++;
3423 e = e.expressionSemantic(sc);
3424 ti.inuse--;
3425 result = e;
3426 return;
3427 }
3428 }
3429
3430 //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3431 auto e = symbolToExp(s, exp.loc, sc, true);
3432 //printf("-1ScopeExp::semantic()\n");
3433 result = e;
3434 return;
3435 }
3436
3437 //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3438 //printf("\tparent = '%s'\n", sds2.parent.toChars());
3439 sds2.dsymbolSemantic(sc);
3440
3441 // (Aggregate|Enum)Declaration
3442 if (auto t = sds2.getType())
3443 {
3444 result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3445 return;
3446 }
3447
3448 if (auto td = sds2.isTemplateDeclaration())
3449 {
3450 result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3451 return;
3452 }
3453
3454 exp.sds = sds2;
3455 exp.type = Type.tvoid;
3456 //printf("-2ScopeExp::semantic() %s\n", toChars());
3457 result = exp;
3458 }
3459
3460 override void visit(NewExp exp)
3461 {
3462 static if (LOGSEMANTIC)
3463 {
3464 printf("NewExp::semantic() %s\n", exp.toChars());
3465 if (exp.thisexp)
3466 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3467 printf("\tnewtype: %s\n", exp.newtype.toChars());
3468 }
3469 if (exp.type) // if semantic() already run
3470 {
3471 result = exp;
3472 return;
3473 }
3474
3475 //for error messages if the argument in [] is not convertible to size_t
3476 const originalNewtype = exp.newtype;
3477
3478 // https://issues.dlang.org/show_bug.cgi?id=11581
3479 // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3480 // T should be analyzed first and edim should go into arguments iff it's
3481 // not a tuple.
3482 Expression edim = null;
3483 if (!exp.arguments && exp.newtype.isTypeSArray())
3484 {
3485 auto ts = exp.newtype.isTypeSArray();
3486 // check `new Value[Key]`
3487 ts.dim = ts.dim.expressionSemantic(sc);
3488 if (ts.dim.op == EXP.type)
3489 {
3490 exp.newtype = new TypeAArray(ts.next, ts.dim.isTypeExp().type);
3491 }
3492 else
3493 {
3494 edim = ts.dim;
3495 exp.newtype = ts.next;
3496 }
3497 }
3498
3499 ClassDeclaration cdthis = null;
3500 if (exp.thisexp)
3501 {
3502 exp.thisexp = exp.thisexp.expressionSemantic(sc);
3503 if (exp.thisexp.op == EXP.error)
3504 return setError();
3505
3506 cdthis = exp.thisexp.type.isClassHandle();
3507 if (!cdthis)
3508 {
3509 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3510 return setError();
3511 }
3512
3513 sc = sc.push(cdthis);
3514 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3515 sc = sc.pop();
3516 }
3517 else
3518 {
3519 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3520 }
3521 if (exp.type.ty == Terror)
3522 return setError();
3523
3524 if (edim)
3525 {
3526 if (exp.type.toBasetype().ty == Ttuple)
3527 {
3528 // --> new T[edim]
3529 exp.type = new TypeSArray(exp.type, edim);
3530 exp.type = exp.type.typeSemantic(exp.loc, sc);
3531 if (exp.type.ty == Terror)
3532 return setError();
3533 }
3534 else
3535 {
3536 // --> new T[](edim)
3537 exp.arguments = new Expressions();
3538 exp.arguments.push(edim);
3539 exp.type = exp.type.arrayOf();
3540 }
3541 }
3542
3543 exp.newtype = exp.type; // in case type gets cast to something else
3544 Type tb = exp.type.toBasetype();
3545 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3546 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc))
3547 {
3548 return setError();
3549 }
3550 if (preFunctionParameters(sc, exp.arguments))
3551 {
3552 return setError();
3553 }
3554
3555 if (exp.thisexp && tb.ty != Tclass)
3556 {
3557 exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3558 return setError();
3559 }
3560
3561 const size_t nargs = exp.arguments ? exp.arguments.length : 0;
3562 Expression newprefix = null;
3563
3564 if (auto tc = tb.isTypeClass())
3565 {
3566 auto cd = tc.sym;
3567 if (cd.errors)
3568 return setError();
3569 cd.size(exp.loc);
3570 if (cd.sizeok != Sizeok.done)
3571 return setError();
3572 if (!cd.ctor)
3573 cd.ctor = cd.searchCtor();
3574 if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3575 {
3576 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3577 return setError();
3578 }
3579
3580 if (cd.isInterfaceDeclaration())
3581 {
3582 exp.error("cannot create instance of interface `%s`", cd.toChars());
3583 return setError();
3584 }
3585
3586 if (cd.isAbstract())
3587 {
3588 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3589 for (size_t i = 0; i < cd.vtbl.length; i++)
3590 {
3591 FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3592 if (fd && fd.isAbstract())
3593 {
3594 errorSupplemental(exp.loc, "function `%s` is not implemented",
3595 fd.toFullSignature());
3596 }
3597 }
3598 return setError();
3599 }
3600 // checkDeprecated() is already done in newtype.typeSemantic().
3601
3602 if (cd.isNested())
3603 {
3604 /* We need a 'this' pointer for the nested class.
3605 * Ensure we have the right one.
3606 */
3607 Dsymbol s = cd.toParentLocal();
3608
3609 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3610 if (auto cdn = s.isClassDeclaration())
3611 {
3612 if (!cdthis)
3613 {
3614 void noReferenceToOuterClass()
3615 {
3616 if (cd.isAnonymous)
3617 exp.error("cannot construct anonymous nested class because no implicit `this` reference to outer class is available");
3618 else
3619 exp.error("cannot construct nested class `%s` because no implicit `this` reference to outer class `%s` is available",
3620 cd.toChars(), cdn.toChars());
3621 return setError();
3622 }
3623
3624 if (!sc.hasThis)
3625 return noReferenceToOuterClass();
3626
3627 // Supply an implicit 'this' and try again
3628 exp.thisexp = new ThisExp(exp.loc);
3629 for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3630 {
3631 if (!sp)
3632 return noReferenceToOuterClass();
3633 ClassDeclaration cdp = sp.isClassDeclaration();
3634 if (!cdp)
3635 continue;
3636 if (cdp == cdn || cdn.isBaseOf(cdp, null))
3637 break;
3638 // Add a '.outer' and try again
3639 exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3640 }
3641
3642 exp.thisexp = exp.thisexp.expressionSemantic(sc);
3643 if (exp.thisexp.op == EXP.error)
3644 return setError();
3645 cdthis = exp.thisexp.type.isClassHandle();
3646 }
3647 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3648 {
3649 //printf("cdthis = %s\n", cdthis.toChars());
3650 exp.error("`this` for nested class must be of type `%s`, not `%s`",
3651 cdn.toChars(), exp.thisexp.type.toChars());
3652 return setError();
3653 }
3654 if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3655 {
3656 exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3657 exp.newtype.toChars(), exp.thisexp.type.toChars());
3658 return setError();
3659 }
3660 }
3661 else if (exp.thisexp)
3662 {
3663 exp.error("`.new` is only for allocating nested classes");
3664 return setError();
3665 }
3666 else if (auto fdn = s.isFuncDeclaration())
3667 {
3668 // make sure the parent context fdn of cd is reachable from sc
3669 if (!ensureStaticLinkTo(sc.parent, fdn))
3670 {
3671 exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3672 fdn.toPrettyChars(), cd.toPrettyChars());
3673 return setError();
3674 }
3675 }
3676 else
3677 assert(0);
3678 }
3679 else if (exp.thisexp)
3680 {
3681 exp.error("`.new` is only for allocating nested classes");
3682 return setError();
3683 }
3684
3685 if (cd.vthis2)
3686 {
3687 if (AggregateDeclaration ad2 = cd.isMember2())
3688 {
3689 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3690 if (te.op != EXP.error)
3691 te = getRightThis(exp.loc, sc, ad2, te, cd);
3692 if (te.op == EXP.error)
3693 {
3694 exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3695 return setError();
3696 }
3697 }
3698 }
3699
3700 if (cd.disableNew && !exp.onstack)
3701 {
3702 exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
3703 originalNewtype.toChars());
3704 return setError();
3705 }
3706
3707 if (cd.ctor)
3708 {
3709 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3710 if (!f || f.errors)
3711 return setError();
3712
3713 checkFunctionAttributes(exp, sc, f);
3714 checkAccess(cd, exp.loc, sc, f);
3715
3716 TypeFunction tf = f.type.isTypeFunction();
3717 if (!exp.arguments)
3718 exp.arguments = new Expressions();
3719 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3720 return setError();
3721
3722 exp.member = f.isCtorDeclaration();
3723 assert(exp.member);
3724 }
3725 else
3726 {
3727 if (nargs)
3728 {
3729 exp.error("no constructor for `%s`", cd.toChars());
3730 return setError();
3731 }
3732
3733 // https://issues.dlang.org/show_bug.cgi?id=19941
3734 // Run semantic on all field initializers to resolve any forward
3735 // references. This is the same as done for structs in sd.fill().
3736 for (ClassDeclaration c = cd; c; c = c.baseClass)
3737 {
3738 foreach (v; c.fields)
3739 {
3740 if (v.inuse || v._scope is null || v._init is null ||
3741 v._init.isVoidInitializer())
3742 continue;
3743 v.inuse++;
3744 v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3745 v.inuse--;
3746 }
3747 }
3748 }
3749
3750 // When using `@nogc` exception handling, lower `throw new E(args)` to
3751 // `throw (__tmp = _d_newThrowable!E(), __tmp.__ctor(args), __tmp)`.
3752 if (global.params.ehnogc && exp.thrownew &&
3753 !cd.isCOMclass() && !cd.isCPPclass())
3754 {
3755 assert(cd.ctor);
3756
3757 Expression id = new IdentifierExp(exp.loc, Id.empty);
3758 id = new DotIdExp(exp.loc, id, Id.object);
3759
3760 auto tiargs = new Objects();
3761 tiargs.push(exp.newtype);
3762 id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs);
3763 id = new CallExp(exp.loc, id).expressionSemantic(sc);
3764
3765 Expression idVal;
3766 Expression tmp = extractSideEffect(sc, "__tmpThrowable", idVal, id, true);
3767 // auto castTmp = new CastExp(exp.loc, tmp, exp.type);
3768
3769 auto ctor = new DotIdExp(exp.loc, tmp, Id.ctor).expressionSemantic(sc);
3770 auto ctorCall = new CallExp(exp.loc, ctor, exp.arguments);
3771
3772 id = Expression.combine(idVal, exp.argprefix).expressionSemantic(sc);
3773 id = Expression.combine(id, ctorCall).expressionSemantic(sc);
3774 // id = Expression.combine(id, castTmp).expressionSemantic(sc);
3775
3776 result = id.expressionSemantic(sc);
3777 return;
3778 }
3779 }
3780 else if (auto ts = tb.isTypeStruct())
3781 {
3782 auto sd = ts.sym;
3783 sd.size(exp.loc);
3784 if (sd.sizeok != Sizeok.done)
3785 return setError();
3786 if (!sd.ctor)
3787 sd.ctor = sd.searchCtor();
3788 if (sd.noDefaultCtor && !nargs)
3789 {
3790 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3791 return setError();
3792 }
3793 // checkDeprecated() is already done in newtype.typeSemantic().
3794
3795 if (sd.disableNew)
3796 {
3797 exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
3798 originalNewtype.toChars());
3799 return setError();
3800 }
3801
3802 // https://issues.dlang.org/show_bug.cgi?id=22639
3803 // If the new expression has arguments, we either should call a
3804 // regular constructor of a copy constructor if the first argument
3805 // is the same type as the struct
3806 if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf())))
3807 {
3808 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3809 if (!f || f.errors)
3810 return setError();
3811
3812 checkFunctionAttributes(exp, sc, f);
3813 checkAccess(sd, exp.loc, sc, f);
3814
3815 TypeFunction tf = f.type.isTypeFunction();
3816 if (!exp.arguments)
3817 exp.arguments = new Expressions();
3818 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3819 return setError();
3820
3821 exp.member = f.isCtorDeclaration();
3822 assert(exp.member);
3823
3824 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.length))
3825 return setError();
3826 }
3827 else
3828 {
3829 if (!exp.arguments)
3830 exp.arguments = new Expressions();
3831
3832 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3833 return setError();
3834
3835 if (!sd.fill(exp.loc, *exp.arguments, false))
3836 return setError();
3837
3838 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.length : 0))
3839 return setError();
3840
3841 /* Since a `new` allocation may escape, check each of the arguments for escaping
3842 */
3843 foreach (arg; *exp.arguments)
3844 {
3845 if (arg && checkNewEscape(sc, arg, false))
3846 return setError();
3847 }
3848 }
3849
3850 exp.type = exp.type.pointerTo();
3851 }
3852 else if (tb.ty == Tarray)
3853 {
3854 if (!nargs)
3855 {
3856 // https://issues.dlang.org/show_bug.cgi?id=20422
3857 // Without this check the compiler would give a misleading error
3858 exp.error("missing length argument for array");
3859 return setError();
3860 }
3861
3862 Type tn = tb.nextOf().baseElemOf();
3863 Dsymbol s = tn.toDsymbol(sc);
3864 AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3865 if (ad && ad.noDefaultCtor)
3866 {
3867 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3868 return setError();
3869 }
3870 for (size_t i = 0; i < nargs; i++)
3871 {
3872 if (tb.ty != Tarray)
3873 {
3874 exp.error("too many arguments for array");
3875 return setError();
3876 }
3877
3878 Expression arg = (*exp.arguments)[i];
3879 arg = resolveProperties(sc, arg);
3880 arg = arg.implicitCastTo(sc, Type.tsize_t);
3881 if (arg.op == EXP.error)
3882 return setError();
3883 arg = arg.optimize(WANTvalue);
3884 if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
3885 {
3886 exp.error("negative array index `%s`", arg.toChars());
3887 return setError();
3888 }
3889 (*exp.arguments)[i] = arg;
3890 tb = tb.isTypeDArray().next.toBasetype();
3891 }
3892 }
3893 else if (tb.isscalar())
3894 {
3895 if (!nargs)
3896 {
3897 }
3898 else if (nargs == 1)
3899 {
3900 Expression e = (*exp.arguments)[0];
3901 e = e.implicitCastTo(sc, tb);
3902 (*exp.arguments)[0] = e;
3903 }
3904 else
3905 {
3906 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3907 return setError();
3908 }
3909
3910 exp.type = exp.type.pointerTo();
3911 }
3912 else if (tb.ty == Taarray)
3913 {
3914 // e.g. `new Alias(args)`
3915 if (nargs)
3916 {
3917 exp.error("`new` cannot take arguments for an associative array");
3918 return setError();
3919 }
3920 }
3921 else
3922 {
3923 exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3924 return setError();
3925 }
3926
3927 //printf("NewExp: '%s'\n", toChars());
3928 //printf("NewExp:type '%s'\n", type.toChars());
3929 semanticTypeInfo(sc, exp.type);
3930
3931 if (newprefix)
3932 {
3933 result = Expression.combine(newprefix, exp);
3934 return;
3935 }
3936 result = exp;
3937 }
3938
3939 override void visit(NewAnonClassExp e)
3940 {
3941 static if (LOGSEMANTIC)
3942 {
3943 printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3944 //printf("thisexp = %p\n", thisexp);
3945 //printf("type: %s\n", type.toChars());
3946 }
3947
3948 Expression d = new DeclarationExp(e.loc, e.cd);
3949 sc = sc.push(); // just create new scope
3950 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3951 d = d.expressionSemantic(sc);
3952 sc = sc.pop();
3953
3954 if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3955 {
3956 ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3957 if (!sds.members)
3958 sds.members = new Dsymbols();
3959 sds.members.push(e.cd);
3960 }
3961
3962 Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
3963
3964 Expression c = new CommaExp(e.loc, d, n);
3965 result = c.expressionSemantic(sc);
3966 }
3967
3968 override void visit(SymOffExp e)
3969 {
3970 static if (LOGSEMANTIC)
3971 {
3972 printf("SymOffExp::semantic('%s')\n", e.toChars());
3973 }
3974 //var.dsymbolSemantic(sc);
3975 if (!e.type)
3976 e.type = e.var.type.pointerTo();
3977
3978 if (auto v = e.var.isVarDeclaration())
3979 {
3980 if (v.checkNestedReference(sc, e.loc))
3981 return setError();
3982 }
3983 else if (auto f = e.var.isFuncDeclaration())
3984 {
3985 if (f.checkNestedReference(sc, e.loc))
3986 return setError();
3987 }
3988
3989 result = e;
3990 }
3991
3992 override void visit(VarExp e)
3993 {
3994 static if (LOGSEMANTIC)
3995 {
3996 printf("VarExp::semantic(%s)\n", e.toChars());
3997 }
3998
3999 auto vd = e.var.isVarDeclaration();
4000 auto fd = e.var.isFuncDeclaration();
4001
4002 if (fd)
4003 {
4004 //printf("L%d fd = %s\n", __LINE__, f.toChars());
4005 if (!fd.functionSemantic())
4006 return setError();
4007 }
4008
4009 if (!e.type)
4010 e.type = e.var.type;
4011 if (e.type && !e.type.deco)
4012 {
4013 auto decl = e.var.isDeclaration();
4014 if (decl)
4015 decl.inuse++;
4016 e.type = e.type.typeSemantic(e.loc, sc);
4017 if (decl)
4018 decl.inuse--;
4019 }
4020
4021 /* Fix for 1161 doesn't work because it causes visibility
4022 * problems when instantiating imported templates passing private
4023 * variables as alias template parameters.
4024 */
4025 //checkAccess(loc, sc, NULL, var);
4026
4027 if (vd)
4028 {
4029 if (vd.checkNestedReference(sc, e.loc))
4030 return setError();
4031
4032 // https://issues.dlang.org/show_bug.cgi?id=12025
4033 // If the variable is not actually used in runtime code,
4034 // the purity violation error is redundant.
4035 //checkPurity(sc, vd);
4036 }
4037 else if (fd)
4038 {
4039 // TODO: If fd isn't yet resolved its overload, the checkNestedReference
4040 // call would cause incorrect validation.
4041 // Maybe here should be moved in CallExp, or AddrExp for functions.
4042 if (fd.checkNestedReference(sc, e.loc))
4043 return setError();
4044 }
4045 else if (auto od = e.var.isOverDeclaration())
4046 {
4047 e.type = Type.tvoid; // ambiguous type?
4048 }
4049
4050 result = e;
4051 }
4052
4053 override void visit(FuncExp exp)
4054 {
4055 static if (LOGSEMANTIC)
4056 {
4057 printf("FuncExp::semantic(%s)\n", exp.toChars());
4058 if (exp.fd.treq)
4059 printf(" treq = %s\n", exp.fd.treq.toChars());
4060 }
4061
4062 if (exp.type)
4063 {
4064 result = exp;
4065 return;
4066 }
4067
4068 Expression e = exp;
4069 uint olderrors;
4070
4071 sc = sc.push(); // just create new scope
4072 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4073 sc.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4074
4075 /* fd.treq might be incomplete type,
4076 * so should not semantic it.
4077 * void foo(T)(T delegate(int) dg){}
4078 * foo(a=>a); // in IFTI, treq == T delegate(int)
4079 */
4080 //if (fd.treq)
4081 // fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4082
4083 exp.genIdent(sc);
4084
4085 // Set target of return type inference
4086 if (exp.fd.treq && !exp.fd.type.nextOf())
4087 {
4088 TypeFunction tfv = null;
4089 if (exp.fd.treq.ty == Tdelegate || exp.fd.treq.isPtrToFunction())
4090 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4091 if (tfv)
4092 {
4093 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4094 tfl.next = tfv.nextOf();
4095 }
4096 }
4097
4098 //printf("td = %p, treq = %p\n", td, fd.treq);
4099 if (exp.td)
4100 {
4101 assert(exp.td.parameters && exp.td.parameters.length);
4102 exp.td.dsymbolSemantic(sc);
4103 exp.type = Type.tvoid; // temporary type
4104
4105 if (exp.fd.treq) // defer type determination
4106 {
4107 FuncExp fe;
4108 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4109 e = fe;
4110 else
4111 e = ErrorExp.get();
4112 }
4113 goto Ldone;
4114 }
4115
4116 olderrors = global.errors;
4117 exp.fd.dsymbolSemantic(sc);
4118 if (olderrors == global.errors)
4119 {
4120 exp.fd.semantic2(sc);
4121 if (olderrors == global.errors)
4122 exp.fd.semantic3(sc);
4123 }
4124 if (olderrors != global.errors)
4125 {
4126 if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4127 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4128 e = ErrorExp.get();
4129 goto Ldone;
4130 }
4131
4132 // Type is a "delegate to" or "pointer to" the function literal
4133 if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4134 {
4135 // https://issues.dlang.org/show_bug.cgi?id=22686
4136 // if the delegate return type is an error
4137 // abort semantic of the FuncExp and propagate
4138 // the error
4139 if (exp.fd.type.isTypeError())
4140 {
4141 e = ErrorExp.get();
4142 goto Ldone;
4143 }
4144 exp.type = new TypeDelegate(exp.fd.type.isTypeFunction());
4145 exp.type = exp.type.typeSemantic(exp.loc, sc);
4146
4147 exp.fd.tok = TOK.delegate_;
4148 }
4149 else
4150 {
4151 exp.type = new TypePointer(exp.fd.type);
4152 exp.type = exp.type.typeSemantic(exp.loc, sc);
4153 //type = fd.type.pointerTo();
4154
4155 /* A lambda expression deduced to function pointer might become
4156 * to a delegate literal implicitly.
4157 *
4158 * auto foo(void function() fp) { return 1; }
4159 * assert(foo({}) == 1);
4160 *
4161 * So, should keep fd.tok == TOK.reserve if fd.treq == NULL.
4162 */
4163 if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4164 {
4165 // change to non-nested
4166 exp.fd.tok = TOK.function_;
4167 exp.fd.vthis = null;
4168 }
4169 }
4170 exp.fd.tookAddressOf++;
4171
4172 Ldone:
4173 sc = sc.pop();
4174 result = e;
4175 }
4176
4177 /**
4178 * Perform semantic analysis on function literals
4179 *
4180 * Test the following construct:
4181 * ---
4182 * (x, y, z) { return x + y + z; }(42, 84, 1992);
4183 * ---
4184 */
4185 Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4186 {
4187 if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.length)
4188 {
4189 for (size_t k = 0; k < arguments.length; k++)
4190 {
4191 Expression checkarg = (*arguments)[k];
4192 if (checkarg.op == EXP.error)
4193 return checkarg;
4194 }
4195
4196 exp.genIdent(sc);
4197
4198 assert(exp.td.parameters && exp.td.parameters.length);
4199 exp.td.dsymbolSemantic(sc);
4200
4201 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4202 size_t dim = tfl.parameterList.length;
4203 if (arguments.length < dim)
4204 {
4205 // Default arguments are always typed, so they don't need inference.
4206 Parameter p = tfl.parameterList[arguments.length];
4207 if (p.defaultArg)
4208 dim = arguments.length;
4209 }
4210
4211 if ((tfl.parameterList.varargs == VarArg.none && arguments.length > dim) ||
4212 arguments.length < dim)
4213 {
4214 OutBuffer buf;
4215 foreach (idx, ref arg; *arguments)
4216 buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4217 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4218 exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4219 buf.peekChars());
4220 exp.errorSupplemental("too %s arguments, expected %d, got %d",
4221 arguments.length < dim ? "few".ptr : "many".ptr,
4222 cast(int)dim, cast(int)arguments.length);
4223 return ErrorExp.get();
4224 }
4225
4226 auto tiargs = new Objects();
4227 tiargs.reserve(exp.td.parameters.length);
4228
4229 for (size_t i = 0; i < exp.td.parameters.length; i++)
4230 {
4231 TemplateParameter tp = (*exp.td.parameters)[i];
4232 assert(dim <= tfl.parameterList.length);
4233 foreach (u, p; tfl.parameterList)
4234 {
4235 if (u == dim)
4236 break;
4237
4238 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4239 {
4240 Expression e = (*arguments)[u];
4241 tiargs.push(e.type);
4242 break;
4243 }
4244 }
4245 }
4246
4247 auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4248 return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4249 }
4250 return exp.expressionSemantic(sc);
4251 }
4252
4253 override void visit(CallExp exp)
4254 {
4255 static if (LOGSEMANTIC)
4256 {
4257 printf("CallExp::semantic() %s\n", exp.toChars());
4258 }
4259 if (exp.type)
4260 {
4261 result = exp;
4262 return; // semantic() already run
4263 }
4264
4265 Objects* tiargs = null; // initial list of template arguments
4266 Expression ethis = null;
4267 Type tthis = null;
4268 Expression e1org = exp.e1;
4269
4270 if (auto ce = exp.e1.isCommaExp())
4271 {
4272 /* Rewrite (a,b)(args) as (a,(b(args)))
4273 */
4274 exp.e1 = ce.e2;
4275 ce.e2 = exp;
4276 result = ce.expressionSemantic(sc);
4277 return;
4278 }
4279 if (DelegateExp de = exp.e1.isDelegateExp())
4280 {
4281 exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4282 visit(exp);
4283 return;
4284 }
4285 if (FuncExp fe = exp.e1.isFuncExp())
4286 {
4287 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
4288 preFunctionParameters(sc, exp.arguments))
4289 return setError();
4290
4291 // Run e1 semantic even if arguments have any errors
4292 exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4293 if (exp.e1.op == EXP.error)
4294 {
4295 result = exp.e1;
4296 return;
4297 }
4298 }
4299 if (sc.flags & SCOPE.Cfile)
4300 {
4301 /* See if need to rewrite the AST because of cast/call ambiguity
4302 */
4303 if (auto e = castCallAmbiguity(exp, sc))
4304 {
4305 result = expressionSemantic(e, sc);
4306 return;
4307 }
4308 }
4309
4310 if (Expression ex = resolveUFCS(sc, exp))
4311 {
4312 result = ex;
4313 return;
4314 }
4315
4316 /* This recognizes:
4317 * foo!(tiargs)(funcargs)
4318 */
4319 if (ScopeExp se = exp.e1.isScopeExp())
4320 {
4321 TemplateInstance ti = se.sds.isTemplateInstance();
4322 if (ti)
4323 {
4324 /* Attempt to instantiate ti. If that works, go with it.
4325 * If not, go with partial explicit specialization.
4326 */
4327 WithScopeSymbol withsym;
4328 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4329 return setError();
4330 if (withsym && withsym.withstate.wthis)
4331 {
4332 exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4333 exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4334 goto Ldotti;
4335 }
4336 if (ti.needsTypeInference(sc, 1))
4337 {
4338 /* Go with partial explicit specialization
4339 */
4340 tiargs = ti.tiargs;
4341 assert(ti.tempdecl);
4342 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4343 exp.e1 = new TemplateExp(exp.loc, td);
4344 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4345 exp.e1 = new VarExp(exp.loc, od);
4346 else
4347 exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4348 }
4349 else
4350 {
4351 Expression e1x = exp.e1.expressionSemantic(sc);
4352 if (e1x.op == EXP.error)
4353 {
4354 result = e1x;
4355 return;
4356 }
4357 exp.e1 = e1x;
4358 }
4359 }
4360 }
4361
4362 /* This recognizes:
4363 * expr.foo!(tiargs)(funcargs)
4364 */
4365 Ldotti:
4366 if (DotTemplateInstanceExp se = exp.e1.isDotTemplateInstanceExp())
4367 {
4368 TemplateInstance ti = se.ti;
4369 {
4370 /* Attempt to instantiate ti. If that works, go with it.
4371 * If not, go with partial explicit specialization.
4372 */
4373 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4374 return setError();
4375 if (ti.needsTypeInference(sc, 1))
4376 {
4377 /* Go with partial explicit specialization
4378 */
4379 tiargs = ti.tiargs;
4380 assert(ti.tempdecl);
4381 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4382 exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4383 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4384 {
4385 exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4386 }
4387 else
4388 exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4389 }
4390 else
4391 {
4392 Expression e1x = exp.e1.expressionSemantic(sc);
4393 if (e1x.op == EXP.error)
4394 {
4395 result = e1x;
4396 return;
4397 }
4398 exp.e1 = e1x;
4399 }
4400 }
4401 }
4402
4403 Lagain:
4404 //printf("Lagain: %s\n", toChars());
4405 exp.f = null;
4406 if (exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_)
4407 {
4408 // semantic() run later for these
4409 }
4410 else
4411 {
4412 if (DotIdExp die = exp.e1.isDotIdExp())
4413 {
4414 exp.e1 = die.expressionSemantic(sc);
4415 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4416 * We handle such earlier, so go back.
4417 * Note that in the rewrite, we carefully did not run semantic() on e1
4418 */
4419 if (exp.e1.op == EXP.dotTemplateInstance)
4420 {
4421 goto Ldotti;
4422 }
4423 }
4424 else
4425 {
4426 __gshared int nest;
4427 if (++nest > global.recursionLimit)
4428 {
4429 exp.error("recursive evaluation of `%s`", exp.toChars());
4430 --nest;
4431 return setError();
4432 }
4433 Expression ex = unaSemantic(exp, sc);
4434 --nest;
4435 if (ex)
4436 {
4437 result = ex;
4438 return;
4439 }
4440 }
4441
4442 /* Look for e1 being a lazy parameter
4443 */
4444 if (VarExp ve = exp.e1.isVarExp())
4445 {
4446 if (ve.var.storage_class & STC.lazy_)
4447 {
4448 // lazy parameters can be called without violating purity and safety
4449 Type tw = ve.var.type;
4450 Type tc = ve.var.type.substWildTo(MODFlags.const_);
4451 auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4452 (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4453 auto t = new TypeDelegate(tf);
4454 ve.type = t.typeSemantic(exp.loc, sc);
4455 }
4456 VarDeclaration v = ve.var.isVarDeclaration();
4457 if (v && ve.checkPurity(sc, v))
4458 return setError();
4459 }
4460
4461 if (exp.e1.op == EXP.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4462 {
4463 SymOffExp se = cast(SymOffExp)exp.e1;
4464 exp.e1 = new VarExp(se.loc, se.var, true);
4465 exp.e1 = exp.e1.expressionSemantic(sc);
4466 }
4467 else if (DotExp de = exp.e1.isDotExp())
4468 {
4469 if (de.e2.op == EXP.overloadSet)
4470 {
4471 ethis = de.e1;
4472 tthis = de.e1.type;
4473 exp.e1 = de.e2;
4474 }
4475 }
4476 else if (exp.e1.op == EXP.star && exp.e1.type.ty == Tfunction)
4477 {
4478 // Rewrite (*fp)(arguments) to fp(arguments)
4479 exp.e1 = (cast(PtrExp)exp.e1).e1;
4480 }
4481 else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
4482 {
4483 const numArgs = exp.arguments ? exp.arguments.length : 0;
4484
4485 /* Ambiguous cases arise from CParser where there is not enough
4486 * information to determine if we have a function call or declaration.
4487 * type-name ( identifier ) ;
4488 * identifier ( identifier ) ;
4489 * If exp.e1 is a type-name, then this is a declaration. C11 does not
4490 * have type construction syntax, so don't convert this to a cast().
4491 */
4492 if (numArgs == 1)
4493 {
4494 Expression arg = (*exp.arguments)[0];
4495 if (auto ie = (*exp.arguments)[0].isIdentifierExp())
4496 {
4497 TypeExp te = cast(TypeExp)exp.e1;
4498 auto initializer = new VoidInitializer(ie.loc);
4499 Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
4500 auto decls = new Dsymbols(1);
4501 (*decls)[0] = s;
4502 s = new LinkDeclaration(s.loc, LINK.c, decls);
4503 result = new DeclarationExp(exp.loc, s);
4504 result = result.expressionSemantic(sc);
4505 }
4506 else
4507 {
4508 arg.error("identifier or `(` expected");
4509 result = ErrorExp.get();
4510 }
4511 return;
4512 }
4513 exp.error("identifier or `(` expected before `)`");
4514 result = ErrorExp.get();
4515 return;
4516 }
4517 }
4518
4519 Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4520
4521 if (exp.e1.op == EXP.error)
4522 {
4523 result = exp.e1;
4524 return;
4525 }
4526 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
4527 preFunctionParameters(sc, exp.arguments))
4528 return setError();
4529
4530 // Check for call operator overload
4531 if (t1)
4532 {
4533 if (t1.ty == Tstruct)
4534 {
4535 auto sd = (cast(TypeStruct)t1).sym;
4536 sd.size(exp.loc); // Resolve forward references to construct object
4537 if (sd.sizeok != Sizeok.done)
4538 return setError();
4539 if (!sd.ctor)
4540 sd.ctor = sd.searchCtor();
4541 /* If `sd.ctor` is a generated copy constructor, this means that it
4542 is the single constructor that this struct has. In order to not
4543 disable default construction, the ctor is nullified. The side effect
4544 of this is that the generated copy constructor cannot be called
4545 explicitly, but that is ok, because when calling a constructor the
4546 default constructor should have priority over the generated copy
4547 constructor.
4548 */
4549 if (sd.ctor)
4550 {
4551 auto ctor = sd.ctor.isCtorDeclaration();
4552 if (ctor && ctor.isCpCtor && ctor.isGenerated())
4553 sd.ctor = null;
4554 }
4555
4556 // First look for constructor
4557 if (exp.e1.op == EXP.type && sd.ctor)
4558 {
4559 if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.length))
4560 goto Lx;
4561
4562 /* https://issues.dlang.org/show_bug.cgi?id=20695
4563 If all constructors are copy constructors, then
4564 try default construction.
4565 */
4566 if (!sd.hasRegularCtor &&
4567 // https://issues.dlang.org/show_bug.cgi?id=22639
4568 // we might still have a copy constructor that could be called
4569 (*exp.arguments)[0].type.mutableOf != sd.type.mutableOf())
4570 goto Lx;
4571
4572 auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4573 if (!sd.fill(exp.loc, *sle.elements, true))
4574 return setError();
4575 if (checkFrameAccess(exp.loc, sc, sd, sle.elements.length))
4576 return setError();
4577
4578 // https://issues.dlang.org/show_bug.cgi?id=14556
4579 // Set concrete type to avoid further redundant semantic().
4580 sle.type = exp.e1.type;
4581
4582 /* Constructor takes a mutable object, so don't use
4583 * the immutable initializer symbol.
4584 */
4585 sle.useStaticInit = false;
4586
4587 Expression e = sle;
4588 if (auto cf = sd.ctor.isCtorDeclaration())
4589 {
4590 e = new DotVarExp(exp.loc, e, cf, true);
4591 }
4592 else if (auto td = sd.ctor.isTemplateDeclaration())
4593 {
4594 e = new DotIdExp(exp.loc, e, td.ident);
4595 }
4596 else if (auto os = sd.ctor.isOverloadSet())
4597 {
4598 e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4599 }
4600 else
4601 assert(0);
4602 e = new CallExp(exp.loc, e, exp.arguments);
4603 e = e.expressionSemantic(sc);
4604 result = e;
4605 return;
4606 }
4607 // No constructor, look for overload of opCall
4608 if (search_function(sd, Id.call))
4609 goto L1;
4610 // overload of opCall, therefore it's a call
4611 if (exp.e1.op != EXP.type)
4612 {
4613 if (sd.aliasthis && !isRecursiveAliasThis(exp.att1, exp.e1.type))
4614 {
4615 exp.e1 = resolveAliasThis(sc, exp.e1);
4616 goto Lagain;
4617 }
4618 exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4619 return setError();
4620 }
4621
4622 /* It's a struct literal
4623 */
4624 Lx:
4625 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4626 e = e.expressionSemantic(sc);
4627 result = e;
4628 return;
4629 }
4630 else if (t1.ty == Tclass)
4631 {
4632 L1:
4633 // Rewrite as e1.call(arguments)
4634 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4635 e = new CallExp(exp.loc, e, exp.arguments);
4636 e = e.expressionSemantic(sc);
4637 result = e;
4638 return;
4639 }
4640 else if (exp.e1.op == EXP.type && t1.isscalar())
4641 {
4642 Expression e;
4643
4644 // Make sure to use the enum type itself rather than its
4645 // base type
4646 // https://issues.dlang.org/show_bug.cgi?id=16346
4647 if (exp.e1.type.ty == Tenum)
4648 {
4649 t1 = exp.e1.type;
4650 }
4651
4652 if (!exp.arguments || exp.arguments.length == 0)
4653 {
4654 e = t1.defaultInitLiteral(exp.loc);
4655 }
4656 else if (exp.arguments.length == 1)
4657 {
4658 e = (*exp.arguments)[0];
4659 e = e.implicitCastTo(sc, t1);
4660 e = new CastExp(exp.loc, e, t1);
4661 }
4662 else
4663 {
4664 exp.error("more than one argument for construction of `%s`", t1.toChars());
4665 return setError();
4666 }
4667 e = e.expressionSemantic(sc);
4668 result = e;
4669 return;
4670 }
4671 }
4672
4673 FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4674 OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4675 {
4676 FuncDeclaration f = null;
4677 foreach (s; os.a)
4678 {
4679 if (tiargs && s.isFuncDeclaration())
4680 continue;
4681 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4682 {
4683 if (f2.errors)
4684 return null;
4685 if (f)
4686 {
4687 /* Error if match in more than one overload set,
4688 * even if one is a 'better' match than the other.
4689 */
4690 ScopeDsymbol.multiplyDefined(loc, f, f2);
4691 }
4692 else
4693 f = f2;
4694 }
4695 }
4696 if (!f)
4697 {
4698 .error(loc, "no overload matches for `%s`", exp.toChars());
4699 errorSupplemental(loc, "Candidates are:");
4700 foreach (s; os.a)
4701 {
4702 overloadApply(s, (ds){
4703 if (auto fd = ds.isFuncDeclaration())
4704 .errorSupplemental(ds.loc, "%s%s", fd.toChars(),
4705 fd.type.toTypeFunction().parameterList.parametersTypeToChars());
4706 else
4707 .errorSupplemental(ds.loc, "%s", ds.toChars());
4708 return 0;
4709 });
4710 }
4711 }
4712 else if (f.errors)
4713 f = null;
4714 return f;
4715 }
4716
4717 bool isSuper = false;
4718 if (exp.e1.op == EXP.dotVariable && t1.ty == Tfunction || exp.e1.op == EXP.dotTemplateDeclaration)
4719 {
4720 UnaExp ue = cast(UnaExp)exp.e1;
4721
4722 Expression ue1old = ue.e1; // need for 'right this' check
4723 DotVarExp dve;
4724 DotTemplateExp dte;
4725 Dsymbol s;
4726 if (exp.e1.op == EXP.dotVariable)
4727 {
4728 dve = cast(DotVarExp)exp.e1;
4729 dte = null;
4730 s = dve.var;
4731 tiargs = null;
4732 }
4733 else
4734 {
4735 dve = null;
4736 dte = cast(DotTemplateExp)exp.e1;
4737 s = dte.td;
4738 }
4739
4740 // Do overload resolution
4741 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
4742 if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4743 return setError();
4744
4745 if (exp.f.interfaceVirtual)
4746 {
4747 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4748 */
4749 auto b = exp.f.interfaceVirtual;
4750 auto ad2 = b.sym;
4751 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4752 ue.e1 = ue.e1.expressionSemantic(sc);
4753 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.length);
4754 assert(vi >= 0);
4755 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4756 assert(exp.f);
4757 }
4758 if (exp.f.needThis())
4759 {
4760 AggregateDeclaration ad = exp.f.isMemberLocal();
4761 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4762 if (ue.e1.op == EXP.error)
4763 {
4764 result = ue.e1;
4765 return;
4766 }
4767 ethis = ue.e1;
4768 tthis = ue.e1.type;
4769 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4770 {
4771 if (checkParamArgumentEscape(sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
4772 return setError();
4773 }
4774 }
4775
4776 /* Cannot call public functions from inside invariant
4777 * (because then the invariant would have infinite recursion)
4778 */
4779 if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
4780 {
4781 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4782 return setError();
4783 }
4784
4785 if (!exp.ignoreAttributes)
4786 checkFunctionAttributes(exp, sc, exp.f);
4787 checkAccess(exp.loc, sc, ue.e1, exp.f);
4788 if (!exp.f.needThis())
4789 {
4790 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4791 }
4792 else
4793 {
4794 if (ue1old.checkRightThis(sc))
4795 return setError();
4796 if (exp.e1.op == EXP.dotVariable)
4797 {
4798 dve.var = exp.f;
4799 exp.e1.type = exp.f.type;
4800 }
4801 else
4802 {
4803 exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4804 exp.e1 = exp.e1.expressionSemantic(sc);
4805 if (exp.e1.op == EXP.error)
4806 return setError();
4807 ue = cast(UnaExp)exp.e1;
4808 }
4809 version (none)
4810 {
4811 printf("ue.e1 = %s\n", ue.e1.toChars());
4812 printf("f = %s\n", exp.f.toChars());
4813 printf("t1 = %s\n", t1.toChars());
4814 printf("e1 = %s\n", exp.e1.toChars());
4815 printf("e1.type = %s\n", exp.e1.type.toChars());
4816 }
4817
4818 // See if we need to adjust the 'this' pointer
4819 AggregateDeclaration ad = exp.f.isThis();
4820 ClassDeclaration cd = ue.e1.type.isClassHandle();
4821 if (ad && cd && ad.isClassDeclaration())
4822 {
4823 if (ue.e1.op == EXP.dotType)
4824 {
4825 ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4826 exp.directcall = true;
4827 }
4828 else if (ue.e1.op == EXP.super_)
4829 exp.directcall = true;
4830 else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4831 exp.directcall = true;
4832
4833 if (ad != cd)
4834 {
4835 ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4836 ue.e1 = ue.e1.expressionSemantic(sc);
4837 }
4838 }
4839 }
4840 // If we've got a pointer to a function then deference it
4841 // https://issues.dlang.org/show_bug.cgi?id=16483
4842 if (exp.e1.type.isPtrToFunction())
4843 {
4844 Expression e = new PtrExp(exp.loc, exp.e1);
4845 e.type = exp.e1.type.nextOf();
4846 exp.e1 = e;
4847 }
4848 t1 = exp.e1.type;
4849 }
4850 else if (exp.e1.op == EXP.super_ || exp.e1.op == EXP.this_)
4851 {
4852 auto ad = sc.func ? sc.func.isThis() : null;
4853 auto cd = ad ? ad.isClassDeclaration() : null;
4854
4855 isSuper = exp.e1.op == EXP.super_;
4856 if (isSuper)
4857 {
4858 // Base class constructor call
4859 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4860 {
4861 exp.error("super class constructor call must be in a constructor");
4862 return setError();
4863 }
4864 if (!cd.baseClass.ctor)
4865 {
4866 exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4867 return setError();
4868 }
4869 }
4870 else
4871 {
4872 // `this` call expression must be inside a
4873 // constructor
4874 if (!ad || !sc.func.isCtorDeclaration())
4875 {
4876 exp.error("constructor call must be in a constructor");
4877 return setError();
4878 }
4879
4880 // https://issues.dlang.org/show_bug.cgi?id=18719
4881 // If `exp` is a call expression to another constructor
4882 // then it means that all struct/class fields will be
4883 // initialized after this call.
4884 foreach (ref field; sc.ctorflow.fieldinit)
4885 {
4886 field.csx |= CSX.this_ctor;
4887 }
4888 }
4889
4890 if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4891 {
4892 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4893 exp.error("constructor calls not allowed in loops or after labels");
4894 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4895 exp.error("multiple constructor calls");
4896 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4897 exp.error("an earlier `return` statement skips constructor");
4898 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4899 }
4900
4901 tthis = ad.type.addMod(sc.func.type.mod);
4902 auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4903 if (auto os = ctor.isOverloadSet())
4904 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4905 else
4906 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4907
4908 if (!exp.f || exp.f.errors)
4909 return setError();
4910
4911 checkFunctionAttributes(exp, sc, exp.f);
4912 checkAccess(exp.loc, sc, null, exp.f);
4913
4914 exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4915 exp.e1 = exp.e1.expressionSemantic(sc);
4916 // https://issues.dlang.org/show_bug.cgi?id=21095
4917 if (exp.e1.op == EXP.error)
4918 return setError();
4919 t1 = exp.e1.type;
4920
4921 // BUG: this should really be done by checking the static
4922 // call graph
4923 if (exp.f == sc.func)
4924 {
4925 exp.error("cyclic constructor call");
4926 return setError();
4927 }
4928 }
4929 else if (auto oe = exp.e1.isOverExp())
4930 {
4931 exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments);
4932 if (!exp.f)
4933 return setError();
4934 if (ethis)
4935 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4936 else
4937 exp.e1 = new VarExp(exp.loc, exp.f, false);
4938 goto Lagain;
4939 }
4940 else if (!t1)
4941 {
4942 exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4943 return setError();
4944 }
4945 else if (t1.ty == Terror)
4946 {
4947 return setError();
4948 }
4949 else if (t1.ty != Tfunction)
4950 {
4951 TypeFunction tf;
4952 const(char)* p;
4953 Dsymbol s;
4954 exp.f = null;
4955 if (auto fe = exp.e1.isFuncExp())
4956 {
4957 // function literal that direct called is always inferred.
4958 assert(fe.fd);
4959 exp.f = fe.fd;
4960 tf = cast(TypeFunction)exp.f.type;
4961 p = "function literal";
4962 }
4963 else if (t1.ty == Tdelegate)
4964 {
4965 TypeDelegate td = cast(TypeDelegate)t1;
4966 assert(td.next.ty == Tfunction);
4967 tf = cast(TypeFunction)td.next;
4968 p = "delegate";
4969 }
4970 else if (auto tfx = t1.isPtrToFunction())
4971 {
4972 tf = tfx;
4973 p = "function pointer";
4974 }
4975 else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4976 {
4977 DotVarExp dve = cast(DotVarExp)exp.e1;
4978 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4979 if (!exp.f)
4980 return setError();
4981 if (exp.f.needThis())
4982 {
4983 dve.var = exp.f;
4984 dve.type = exp.f.type;
4985 dve.hasOverloads = false;
4986 goto Lagain;
4987 }
4988 exp.e1 = new VarExp(dve.loc, exp.f, false);
4989 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4990 result = e.expressionSemantic(sc);
4991 return;
4992 }
4993 else if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4994 {
4995 s = (cast(VarExp)exp.e1).var;
4996 goto L2;
4997 }
4998 else if (exp.e1.op == EXP.template_)
4999 {
5000 s = (cast(TemplateExp)exp.e1).td;
5001 L2:
5002 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5003 if (!exp.f || exp.f.errors)
5004 return setError();
5005 if (exp.f.needThis())
5006 {
5007 if (hasThis(sc))
5008 {
5009 // Supply an implicit 'this', as in
5010 // this.ident
5011 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
5012 goto Lagain;
5013 }
5014 else if (isNeedThisScope(sc, exp.f))
5015 {
5016 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5017 return setError();
5018 }
5019 }
5020 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
5021 goto Lagain;
5022 }
5023 else
5024 {
5025 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
5026 return setError();
5027 }
5028
5029 const(char)* failMessage;
5030 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5031 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5032 {
5033 OutBuffer buf;
5034 buf.writeByte('(');
5035 argExpTypesToCBuffer(&buf, exp.arguments);
5036 buf.writeByte(')');
5037 if (tthis)
5038 tthis.modToBuffer(&buf);
5039
5040 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5041 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5042 p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5043 if (failMessage)
5044 errorSupplemental(exp.loc, "%s", failMessage);
5045 return setError();
5046 }
5047 // Purity and safety check should run after testing arguments matching
5048 if (exp.f)
5049 {
5050 exp.checkPurity(sc, exp.f);
5051 exp.checkSafety(sc, exp.f);
5052 exp.checkNogc(sc, exp.f);
5053 if (exp.f.checkNestedReference(sc, exp.loc))
5054 return setError();
5055 }
5056 else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
5057 {
5058 bool err = false;
5059 if (!tf.purity && sc.func.setImpure())
5060 {
5061 exp.error("`pure` %s `%s` cannot call impure %s `%s`",
5062 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5063 err = true;
5064 }
5065 if (!tf.isnogc && sc.func.setGC())
5066 {
5067 exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
5068 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5069 err = true;
5070 }
5071 if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc,
5072 "`@safe` function `%s` cannot call `@system` `%s`", sc.func, exp.e1))
5073 {
5074 exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
5075 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5076 err = true;
5077 }
5078 if (err)
5079 return setError();
5080 }
5081
5082 if (t1.ty == Tpointer)
5083 {
5084 Expression e = new PtrExp(exp.loc, exp.e1);
5085 e.type = tf;
5086 exp.e1 = e;
5087 }
5088 t1 = tf;
5089 }
5090 else if (VarExp ve = exp.e1.isVarExp())
5091 {
5092 // Do overload resolution
5093 exp.f = ve.var.isFuncDeclaration();
5094 assert(exp.f);
5095 tiargs = null;
5096
5097 if (exp.f.overnext)
5098 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
5099 else
5100 {
5101 exp.f = exp.f.toAliasFunc();
5102 TypeFunction tf = cast(TypeFunction)exp.f.type;
5103 const(char)* failMessage;
5104 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5105 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5106 {
5107 OutBuffer buf;
5108 buf.writeByte('(');
5109 argExpTypesToCBuffer(&buf, exp.arguments);
5110 buf.writeByte(')');
5111
5112 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5113 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5114 exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5115 if (failMessage)
5116 errorSupplemental(exp.loc, "%s", failMessage);
5117 exp.f = null;
5118 }
5119 }
5120 if (!exp.f || exp.f.errors)
5121 return setError();
5122
5123 if (exp.f.needThis())
5124 {
5125 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5126 if (exp.f.checkNestedReference(sc, exp.loc))
5127 return setError();
5128
5129 if (hasThis(sc))
5130 {
5131 // Supply an implicit 'this', as in
5132 // this.ident
5133 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5134 // Note: we cannot use f directly, because further overload resolution
5135 // through the supplied 'this' may cause different result.
5136 goto Lagain;
5137 }
5138 else if (isNeedThisScope(sc, exp.f))
5139 {
5140 // At this point it is possible that `exp.f` had an ambiguity error that was
5141 // silenced because the previous call to `resolveFuncCall` was done using
5142 // `FuncResolveFlag.overloadOnly`. To make sure that a proper error message
5143 // is printed, redo the call with `FuncResolveFlag.standard`.
5144 //
5145 // https://issues.dlang.org/show_bug.cgi?id=22157
5146 if (exp.f.overnext)
5147 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5148
5149 if (!exp.f || exp.f.errors)
5150 return setError();
5151
5152 // If no error is printed, it means that `f` is the single matching overload
5153 // and it needs `this`.
5154 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5155 return setError();
5156 }
5157 }
5158
5159 checkFunctionAttributes(exp, sc, exp.f);
5160 checkAccess(exp.loc, sc, null, exp.f);
5161 if (exp.f.checkNestedReference(sc, exp.loc))
5162 return setError();
5163
5164 ethis = null;
5165 tthis = null;
5166
5167 if (ve.hasOverloads)
5168 {
5169 exp.e1 = new VarExp(ve.loc, exp.f, false);
5170 exp.e1.type = exp.f.type;
5171 }
5172 t1 = exp.f.type;
5173 }
5174 assert(t1.ty == Tfunction);
5175
5176 Expression argprefix;
5177 if (!exp.arguments)
5178 exp.arguments = new Expressions();
5179 if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5180 return setError();
5181
5182 if (!exp.type)
5183 {
5184 exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5185 // avoid recursive expression printing
5186 exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5187 return setError();
5188 }
5189
5190 if (exp.f && exp.f.tintro)
5191 {
5192 Type t = exp.type;
5193 int offset = 0;
5194 TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5195 if (tf.next.isBaseOf(t, &offset) && offset)
5196 {
5197 exp.type = tf.next;
5198 result = Expression.combine(argprefix, exp.castTo(sc, t));
5199 return;
5200 }
5201 }
5202
5203 // Handle the case of a direct lambda call
5204 if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5205 {
5206 exp.f.tookAddressOf = 0;
5207 }
5208
5209 result = Expression.combine(argprefix, exp);
5210
5211 if (isSuper)
5212 {
5213 auto ad = sc.func ? sc.func.isThis() : null;
5214 auto cd = ad ? ad.isClassDeclaration() : null;
5215 if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5216 {
5217 // if super is defined in C++, it sets the vtable pointer to the base class
5218 // so we have to restore it, but still return 'this' from super() call:
5219 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5220 Loc loc = exp.loc;
5221
5222 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5223 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5224 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5225
5226 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5227 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5228
5229 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5230
5231 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5232
5233 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5234 result = e.expressionSemantic(sc);
5235 }
5236 }
5237
5238 // declare dual-context container
5239 if (exp.f && exp.f.hasDualContext() && !sc.intypeof && sc.func)
5240 {
5241 // check access to second `this`
5242 if (AggregateDeclaration ad2 = exp.f.isMember2())
5243 {
5244 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5245 if (te.op != EXP.error)
5246 te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5247 if (te.op == EXP.error)
5248 {
5249 exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5250 return setError();
5251 }
5252 }
5253 exp.vthis2 = makeThis2Argument(exp.loc, sc, exp.f);
5254 Expression de = new DeclarationExp(exp.loc, exp.vthis2);
5255 result = Expression.combine(de, result);
5256 result = result.expressionSemantic(sc);
5257 }
5258 }
5259
5260 override void visit(DeclarationExp e)
5261 {
5262 if (e.type)
5263 {
5264 result = e;
5265 return;
5266 }
5267 static if (LOGSEMANTIC)
5268 {
5269 printf("DeclarationExp::semantic() %s\n", e.toChars());
5270 }
5271
5272 uint olderrors = global.errors;
5273
5274 /* This is here to support extern(linkage) declaration,
5275 * where the extern(linkage) winds up being an AttribDeclaration
5276 * wrapper.
5277 */
5278 Dsymbol s = e.declaration;
5279
5280 while (1)
5281 {
5282 AttribDeclaration ad = s.isAttribDeclaration();
5283 if (ad)
5284 {
5285 if (ad.decl && ad.decl.length == 1)
5286 {
5287 s = (*ad.decl)[0];
5288 continue;
5289 }
5290 }
5291 break;
5292 }
5293
5294 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5295 // Insert into both local scope and function scope.
5296 // Must be unique in both.
5297 if (s.ident)
5298 {
5299 VarDeclaration v = s.isVarDeclaration();
5300 if (v)
5301 {
5302 if (sc.flags & SCOPE.Cfile)
5303 {
5304 /* Do semantic() on the type before inserting v into the symbol table
5305 */
5306 if (!v.originalType)
5307 v.originalType = v.type.syntaxCopy();
5308 Scope* sc2 = sc.push();
5309 sc2.stc |= v.storage_class & STC.FUNCATTR;
5310 sc2.linkage = LINK.c; // account for the extern(C) in front of the declaration
5311 v.inuse++;
5312 v.type = v.type.typeSemantic(v.loc, sc2);
5313 v.inuse--;
5314 sc2.pop();
5315 }
5316 else
5317 {
5318 /* Do semantic() on initializer first so this will be illegal:
5319 * int a = a;
5320 */
5321 e.declaration.dsymbolSemantic(sc);
5322 s.parent = sc.parent;
5323 }
5324 }
5325
5326 if (!sc.insert(s))
5327 {
5328 auto conflict = sc.search(Loc.initial, s.ident, null);
5329 e.error("declaration `%s` is already defined", s.toPrettyChars());
5330 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5331 conflict.kind(), conflict.toChars());
5332 return setError();
5333 }
5334
5335 if (v && (sc.flags & SCOPE.Cfile))
5336 {
5337 /* Do semantic() on initializer last so this will be legal:
5338 * int a = a;
5339 */
5340 e.declaration.dsymbolSemantic(sc);
5341 s.parent = sc.parent;
5342 }
5343
5344 if (sc.func)
5345 {
5346 // https://issues.dlang.org/show_bug.cgi?id=11720
5347 if ((s.isFuncDeclaration() ||
5348 s.isAggregateDeclaration() ||
5349 s.isEnumDeclaration() ||
5350 s.isTemplateDeclaration() ||
5351 v
5352 ) && !sc.func.localsymtab.insert(s))
5353 {
5354 // Get the previous symbol
5355 Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5356
5357 // Perturb the name mangling so that the symbols can co-exist
5358 // instead of colliding
5359 s.localNum = cast(ushort)(originalSymbol.localNum + 1);
5360 // 65535 should be enough for anyone
5361 if (!s.localNum)
5362 {
5363 e.error("more than 65535 symbols with name `%s` generated", s.ident.toChars());
5364 return setError();
5365 }
5366
5367 // Replace originalSymbol with s, which updates the localCount
5368 sc.func.localsymtab.update(s);
5369
5370 // The mangling change only works for D mangling
5371 }
5372
5373 if (!(sc.flags & SCOPE.Cfile))
5374 {
5375 /* https://issues.dlang.org/show_bug.cgi?id=21272
5376 * If we are in a foreach body we need to extract the
5377 * function containing the foreach
5378 */
5379 FuncDeclaration fes_enclosing_func;
5380 if (sc.func && sc.func.fes)
5381 fes_enclosing_func = sc.enclosing.enclosing.func;
5382
5383 // Disallow shadowing
5384 for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5385 {
5386 Dsymbol s2;
5387 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5388 {
5389 // allow STC.local symbols to be shadowed
5390 // TODO: not really an optimal design
5391 auto decl = s2.isDeclaration();
5392 if (!decl || !(decl.storage_class & STC.local))
5393 {
5394 if (sc.func.fes)
5395 {
5396 e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5397 }
5398 else
5399 {
5400 e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5401 return setError();
5402 }
5403 }
5404 }
5405 }
5406 }
5407 }
5408 }
5409 if (!s.isVarDeclaration())
5410 {
5411 Scope* sc2 = sc;
5412 if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5413 sc2 = sc.push();
5414 sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5415 e.declaration.dsymbolSemantic(sc2);
5416 if (sc2 != sc)
5417 sc2.pop();
5418 s.parent = sc.parent;
5419 }
5420 if (global.errors == olderrors)
5421 {
5422 e.declaration.semantic2(sc);
5423 if (global.errors == olderrors)
5424 {
5425 e.declaration.semantic3(sc);
5426 }
5427 }
5428 // todo: error in declaration should be propagated.
5429
5430 e.type = Type.tvoid;
5431 result = e;
5432 }
5433
5434 override void visit(TypeidExp exp)
5435 {
5436 static if (LOGSEMANTIC)
5437 {
5438 printf("TypeidExp::semantic() %s\n", exp.toChars());
5439 }
5440 Type ta = isType(exp.obj);
5441 Expression ea = isExpression(exp.obj);
5442 Dsymbol sa = isDsymbol(exp.obj);
5443 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5444
5445 if (ta)
5446 {
5447 dmd.typesem.resolve(ta, exp.loc, sc, ea, ta, sa, true);
5448 }
5449
5450 if (ea)
5451 {
5452 if (auto sym = getDsymbol(ea))
5453 ea = symbolToExp(sym, exp.loc, sc, false);
5454 else
5455 ea = ea.expressionSemantic(sc);
5456 ea = resolveProperties(sc, ea);
5457 ta = ea.type;
5458 if (ea.op == EXP.type)
5459 ea = null;
5460 }
5461
5462 if (!ta)
5463 {
5464 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5465 exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5466 return setError();
5467 }
5468
5469 ta.checkComplexTransition(exp.loc, sc);
5470
5471 Expression e;
5472 auto tb = ta.toBasetype();
5473 if (ea && tb.ty == Tclass)
5474 {
5475 if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5476 {
5477 error(exp.loc, "runtime type information is not supported for `extern(C++)` classes");
5478 e = ErrorExp.get();
5479 }
5480 else if (!Type.typeinfoclass)
5481 {
5482 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5483 e = ErrorExp.get();
5484 }
5485 else
5486 {
5487 /* Get the dynamic type, which is .classinfo
5488 */
5489 ea = ea.expressionSemantic(sc);
5490 e = new TypeidExp(ea.loc, ea);
5491 e.type = Type.typeinfoclass.type;
5492 }
5493 }
5494 else if (ta.ty == Terror)
5495 {
5496 e = ErrorExp.get();
5497 }
5498 else
5499 {
5500 // Handle this in the glue layer
5501 e = new TypeidExp(exp.loc, ta);
5502 e.type = getTypeInfoType(exp.loc, ta, sc);
5503
5504 semanticTypeInfo(sc, ta);
5505
5506 if (ea)
5507 {
5508 e = new CommaExp(exp.loc, ea, e); // execute ea
5509 e = e.expressionSemantic(sc);
5510 }
5511 }
5512 result = e;
5513 }
5514
5515 override void visit(TraitsExp e)
5516 {
5517 result = semanticTraits(e, sc);
5518 }
5519
5520 override void visit(HaltExp e)
5521 {
5522 static if (LOGSEMANTIC)
5523 {
5524 printf("HaltExp::semantic()\n");
5525 }
5526 e.type = Type.tnoreturn;
5527 result = e;
5528 }
5529
5530 override void visit(IsExp e)
5531 {
5532 /* is(targ id tok tspec)
5533 * is(targ id : tok2)
5534 * is(targ id == tok2)
5535 */
5536 Type tded = null;
5537
5538 void yes()
5539 {
5540 //printf("yes\n");
5541 if (!e.id)
5542 {
5543 result = IntegerExp.createBool(true);
5544 return;
5545 }
5546
5547 Dsymbol s;
5548 Tuple tup = isTuple(tded);
5549 if (tup)
5550 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5551 else
5552 s = new AliasDeclaration(e.loc, e.id, tded);
5553 s.dsymbolSemantic(sc);
5554
5555 /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5556 * More investigation is needed.
5557 */
5558 if (!tup && !sc.insert(s))
5559 {
5560 auto conflict = sc.search(Loc.initial, s.ident, null);
5561 e.error("declaration `%s` is already defined", s.toPrettyChars());
5562 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5563 conflict.kind(), conflict.toChars());
5564 }
5565
5566 unSpeculative(sc, s);
5567
5568 result = IntegerExp.createBool(true);
5569 }
5570 void no()
5571 {
5572 result = IntegerExp.createBool(false);
5573 //printf("no\n");
5574 }
5575
5576 static if (LOGSEMANTIC)
5577 {
5578 printf("IsExp::semantic(%s)\n", e.toChars());
5579 }
5580 if (e.id && !(sc.flags & SCOPE.condition))
5581 {
5582 e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5583 return setError();
5584 }
5585
5586 if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5587 {
5588 const oldErrors = global.startGagging();
5589 Dsymbol sym = e.targ.toDsymbol(sc);
5590 global.endGagging(oldErrors);
5591
5592 if (sym is null)
5593 return no();
5594 Package p = resolveIsPackage(sym);
5595 if (p is null)
5596 return no();
5597 if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5598 return no();
5599 else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5600 return no();
5601 tded = e.targ;
5602 return yes();
5603 }
5604
5605 {
5606 Scope* sc2 = sc.copy(); // keep sc.flags
5607 sc2.tinst = null;
5608 sc2.minst = null;
5609 sc2.flags |= SCOPE.fullinst;
5610 Type t = e.targ.trySemantic(e.loc, sc2);
5611 sc2.pop();
5612 if (!t) // errors, so condition is false
5613 return no();
5614 e.targ = t;
5615 }
5616
5617 if (e.tok2 != TOK.reserved)
5618 {
5619 switch (e.tok2)
5620 {
5621 case TOK.struct_:
5622 if (e.targ.ty != Tstruct)
5623 return no();
5624 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5625 return no();
5626 tded = e.targ;
5627 break;
5628
5629 case TOK.union_:
5630 if (e.targ.ty != Tstruct)
5631 return no();
5632 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5633 return no();
5634 tded = e.targ;
5635 break;
5636
5637 case TOK.class_:
5638 if (e.targ.ty != Tclass)
5639 return no();
5640 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5641 return no();
5642 tded = e.targ;
5643 break;
5644
5645 case TOK.interface_:
5646 if (e.targ.ty != Tclass)
5647 return no();
5648 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5649 return no();
5650 tded = e.targ;
5651 break;
5652
5653 case TOK.const_:
5654 if (!e.targ.isConst())
5655 return no();
5656 tded = e.targ;
5657 break;
5658
5659 case TOK.immutable_:
5660 if (!e.targ.isImmutable())
5661 return no();
5662 tded = e.targ;
5663 break;
5664
5665 case TOK.shared_:
5666 if (!e.targ.isShared())
5667 return no();
5668 tded = e.targ;
5669 break;
5670
5671 case TOK.inout_:
5672 if (!e.targ.isWild())
5673 return no();
5674 tded = e.targ;
5675 break;
5676
5677 case TOK.super_:
5678 // If class or interface, get the base class and interfaces
5679 if (e.targ.ty != Tclass)
5680 return no();
5681 else
5682 {
5683 ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5684 auto args = new Parameters();
5685 args.reserve(cd.baseclasses.length);
5686 if (cd.semanticRun < PASS.semanticdone)
5687 cd.dsymbolSemantic(null);
5688 for (size_t i = 0; i < cd.baseclasses.length; i++)
5689 {
5690 BaseClass* b = (*cd.baseclasses)[i];
5691 args.push(new Parameter(STC.in_, b.type, null, null, null));
5692 }
5693 tded = new TypeTuple(args);
5694 }
5695 break;
5696
5697 case TOK.enum_:
5698 if (e.targ.ty != Tenum)
5699 return no();
5700 if (e.id)
5701 tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5702 else
5703 tded = e.targ;
5704
5705 if (tded.ty == Terror)
5706 return setError();
5707 break;
5708
5709 case TOK.delegate_:
5710 if (e.targ.ty != Tdelegate)
5711 return no();
5712 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5713 break;
5714
5715 case TOK.function_:
5716 case TOK.parameters:
5717 {
5718 if (e.targ.ty != Tfunction)
5719 return no();
5720 tded = e.targ;
5721
5722 /* Generate tuple from function parameter types.
5723 */
5724 assert(tded.ty == Tfunction);
5725 auto tdedf = tded.isTypeFunction();
5726 auto args = new Parameters();
5727 foreach (i, arg; tdedf.parameterList)
5728 {
5729 assert(arg && arg.type);
5730 /* If one of the default arguments was an error,
5731 don't return an invalid tuple
5732 */
5733 if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
5734 return setError();
5735 args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5736 }
5737 tded = new TypeTuple(args);
5738 break;
5739 }
5740 case TOK.return_:
5741 /* Get the 'return type' for the function,
5742 * delegate, or pointer to function.
5743 */
5744 if (auto tf = e.targ.isFunction_Delegate_PtrToFunction())
5745 tded = tf.next;
5746 else
5747 return no();
5748 break;
5749
5750 case TOK.argumentTypes:
5751 /* Generate a type tuple of the equivalent types used to determine if a
5752 * function argument of this type can be passed in registers.
5753 * The results of this are highly platform dependent, and intended
5754 * primarly for use in implementing va_arg().
5755 */
5756 tded = target.toArgTypes(e.targ);
5757 if (!tded)
5758 return no();
5759 // not valid for a parameter
5760 break;
5761
5762 case TOK.vector:
5763 if (e.targ.ty != Tvector)
5764 return no();
5765 tded = (cast(TypeVector)e.targ).basetype;
5766 break;
5767
5768 default:
5769 assert(0);
5770 }
5771
5772 // https://issues.dlang.org/show_bug.cgi?id=18753
5773 if (tded)
5774 return yes();
5775 return no();
5776 }
5777 else if (e.tspec && !e.id && !(e.parameters && e.parameters.length))
5778 {
5779 /* Evaluate to true if targ matches tspec
5780 * is(targ == tspec)
5781 * is(targ : tspec)
5782 */
5783 e.tspec = e.tspec.typeSemantic(e.loc, sc);
5784 //printf("targ = %s, %s\n", e.targ.toChars(), e.targ.deco);
5785 //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5786
5787 if (e.tok == TOK.colon)
5788 {
5789 // current scope is itself deprecated, or deprecations are not errors
5790 const bool deprecationAllowed = sc.isDeprecated
5791 || global.params.useDeprecated != DiagnosticReporting.error;
5792 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5793
5794 if (preventAliasThis && e.targ.ty == Tstruct)
5795 {
5796 if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5797 return yes();
5798 else
5799 return no();
5800 }
5801 else if (preventAliasThis && e.targ.ty == Tclass)
5802 {
5803 if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5804 return yes();
5805 else
5806 return no();
5807 }
5808 else if (e.targ.implicitConvTo(e.tspec))
5809 return yes();
5810 else
5811 return no();
5812 }
5813 else /* == */
5814 {
5815 if (e.targ.equals(e.tspec))
5816 return yes();
5817 else
5818 return no();
5819 }
5820 }
5821 else if (e.tspec)
5822 {
5823 /* Evaluate to true if targ matches tspec.
5824 * If true, declare id as an alias for the specialized type.
5825 * is(targ == tspec, tpl)
5826 * is(targ : tspec, tpl)
5827 * is(targ id == tspec)
5828 * is(targ id : tspec)
5829 * is(targ id == tspec, tpl)
5830 * is(targ id : tspec, tpl)
5831 */
5832 Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5833 e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5834
5835 Objects dedtypes = Objects(e.parameters.length);
5836 dedtypes.zero();
5837
5838 MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5839
5840 if (m == MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5841 {
5842 return no();
5843 }
5844 else
5845 {
5846 tded = cast(Type)dedtypes[0];
5847 if (!tded)
5848 tded = e.targ;
5849 Objects tiargs = Objects(1);
5850 tiargs[0] = e.targ;
5851
5852 /* Declare trailing parameters
5853 */
5854 for (size_t i = 1; i < e.parameters.length; i++)
5855 {
5856 TemplateParameter tp = (*e.parameters)[i];
5857 Declaration s = null;
5858
5859 m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5860 if (m == MATCH.nomatch)
5861 return no();
5862 s.dsymbolSemantic(sc);
5863 if (!sc.insert(s))
5864 {
5865 auto conflict = sc.search(Loc.initial, s.ident, null);
5866 e.error("declaration `%s` is already defined", s.toPrettyChars());
5867 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5868 conflict.kind(), conflict.toChars());
5869 }
5870
5871 unSpeculative(sc, s);
5872 }
5873 return yes();
5874 }
5875 }
5876 else if (e.id)
5877 {
5878 /* Declare id as an alias for type targ. Evaluate to true
5879 * is(targ id)
5880 */
5881 tded = e.targ;
5882 }
5883 return yes();
5884 }
5885
5886 override void visit(BinAssignExp exp)
5887 {
5888 if (exp.type)
5889 {
5890 result = exp;
5891 return;
5892 }
5893
5894 Expression e = exp.op_overload(sc);
5895 if (e)
5896 {
5897 result = e;
5898 return;
5899 }
5900
5901 if (exp.e1.op == EXP.arrayLength)
5902 {
5903 // arr.length op= e2;
5904 e = rewriteOpAssign(exp);
5905 e = e.expressionSemantic(sc);
5906 result = e;
5907 return;
5908 }
5909 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5910 {
5911 if (checkNonAssignmentArrayOp(exp.e1))
5912 return setError();
5913
5914 if (exp.e1.op == EXP.slice)
5915 (cast(SliceExp)exp.e1).arrayop = true;
5916
5917 // T[] op= ...
5918 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5919 {
5920 // T[] op= T
5921 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5922 }
5923 else if (Expression ex = typeCombine(exp, sc))
5924 {
5925 result = ex;
5926 return;
5927 }
5928 exp.type = exp.e1.type;
5929 result = arrayOp(exp, sc);
5930 return;
5931 }
5932
5933 exp.e1 = exp.e1.expressionSemantic(sc);
5934 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5935 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
5936 exp.type = exp.e1.type;
5937
5938 if (auto ad = isAggregate(exp.e1.type))
5939 {
5940 if (const s = search_function(ad, Id.opOpAssign))
5941 {
5942 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());
5943 return setError();
5944 }
5945 }
5946 if (exp.e1.checkScalar() ||
5947 exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5948 exp.e1.checkSharedAccess(sc))
5949 return setError();
5950
5951 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);
5952 int bitwise = (exp.op == EXP.andAssign || exp.op == EXP.orAssign || exp.op == EXP.xorAssign);
5953 int shift = (exp.op == EXP.leftShiftAssign || exp.op == EXP.rightShiftAssign || exp.op == EXP.unsignedRightShiftAssign);
5954
5955 if (bitwise && exp.type.toBasetype().ty == Tbool)
5956 exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5957 else if (exp.checkNoBool())
5958 return setError();
5959
5960 if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5961 {
5962 result = scaleFactor(exp, sc);
5963 return;
5964 }
5965
5966 if (Expression ex = typeCombine(exp, sc))
5967 {
5968 result = ex;
5969 return;
5970 }
5971
5972 if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5973 return setError();
5974 if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5975 return setError();
5976
5977 if (shift)
5978 {
5979 if (exp.e2.type.toBasetype().ty != Tvector)
5980 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5981 }
5982
5983 if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5984 {
5985 result = exp.incompatibleTypes();
5986 return;
5987 }
5988
5989 if (exp.e1.op == EXP.error || exp.e2.op == EXP.error)
5990 return setError();
5991
5992 e = exp.checkOpAssignTypes(sc);
5993 if (e.op == EXP.error)
5994 {
5995 result = e;
5996 return;
5997 }
5998
5999 assert(e.op == EXP.assign || e == exp);
6000 result = (cast(BinExp)e).reorderSettingAAElem(sc);
6001 }
6002
6003 private Expression compileIt(MixinExp exp)
6004 {
6005 OutBuffer buf;
6006 if (expressionsToString(buf, sc, exp.exps))
6007 return null;
6008
6009 uint errors = global.errors;
6010 const len = buf.length;
6011 const str = buf.extractChars()[0 .. len];
6012 scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
6013 p.nextToken();
6014 //printf("p.loc.linnum = %d\n", p.loc.linnum);
6015
6016 Expression e = p.parseExpression();
6017 if (global.errors != errors)
6018 return null;
6019
6020 if (p.token.value != TOK.endOfFile)
6021 {
6022 exp.error("incomplete mixin expression `%s`", str.ptr);
6023 return null;
6024 }
6025 return e;
6026 }
6027
6028 override void visit(MixinExp exp)
6029 {
6030 /* https://dlang.org/spec/expression.html#mixin_expressions
6031 */
6032
6033 static if (LOGSEMANTIC)
6034 {
6035 printf("MixinExp::semantic('%s')\n", exp.toChars());
6036 }
6037
6038 auto e = compileIt(exp);
6039 if (!e)
6040 return setError();
6041 result = e.expressionSemantic(sc);
6042 }
6043
6044 override void visit(ImportExp e)
6045 {
6046 static if (LOGSEMANTIC)
6047 {
6048 printf("ImportExp::semantic('%s')\n", e.toChars());
6049 }
6050
6051 auto se = semanticString(sc, e.e1, "file name argument");
6052 if (!se)
6053 return setError();
6054 se = se.toUTF8(sc);
6055
6056 auto namez = se.toStringz();
6057 if (!global.filePath)
6058 {
6059 e.error("need `-J` switch to import text file `%s`", namez.ptr);
6060 return setError();
6061 }
6062
6063 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
6064 * ('Path Traversal') attacks.
6065 * https://cwe.mitre.org/data/definitions/22.html
6066 */
6067
6068 if (FileName.absolute(namez))
6069 {
6070 e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
6071 return setError();
6072 }
6073
6074 auto idxReserved = FileName.findReservedChar(namez);
6075 if (idxReserved != size_t.max)
6076 {
6077 e.error("`%s` is not a valid filename on this platform", se.toChars());
6078 e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
6079 return setError();
6080 }
6081
6082 if (FileName.refersToParentDir(namez))
6083 {
6084 e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
6085 return setError();
6086 }
6087
6088 auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
6089 if (!resolvedNamez)
6090 {
6091 e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
6092 e.errorSupplemental("Path(s) searched (as provided by `-J`):");
6093 foreach (idx, path; *global.filePath)
6094 {
6095 const attr = FileName.exists(path);
6096 const(char)* err = attr == 2 ? "" :
6097 (attr == 1 ? " (not a directory)" : " (path not found)");
6098 e.errorSupplemental("[%llu]: `%s`%s", cast(ulong)idx, path, err);
6099 }
6100 return setError();
6101 }
6102
6103 sc._module.contentImportedFiles.push(resolvedNamez.ptr);
6104 if (global.params.verbose)
6105 {
6106 const slice = se.peekString();
6107 message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, resolvedNamez.ptr);
6108 }
6109 if (global.params.moduleDeps.buffer !is null)
6110 {
6111 OutBuffer* ob = global.params.moduleDeps.buffer;
6112 Module imod = sc._module;
6113
6114 if (!global.params.moduleDeps.name)
6115 ob.writestring("depsFile ");
6116 ob.writestring(imod.toPrettyChars());
6117 ob.writestring(" (");
6118 escapePath(ob, imod.srcfile.toChars());
6119 ob.writestring(") : ");
6120 if (global.params.moduleDeps.name)
6121 ob.writestring("string : ");
6122 ob.write(se.peekString());
6123 ob.writestring(" (");
6124 escapePath(ob, resolvedNamez.ptr);
6125 ob.writestring(")");
6126 ob.writenl();
6127 }
6128 if (global.params.makeDeps.doOutput)
6129 {
6130 global.params.makeDeps.files.push(resolvedNamez.ptr);
6131 }
6132
6133 {
6134 auto fileName = FileName(resolvedNamez);
6135 if (auto fmResult = global.fileManager.lookup(fileName))
6136 {
6137 se = new StringExp(e.loc, fmResult);
6138 }
6139 else
6140 {
6141 auto readResult = File.read(resolvedNamez);
6142 if (!readResult.success)
6143 {
6144 e.error("cannot read file `%s`", resolvedNamez.ptr);
6145 return setError();
6146 }
6147 else
6148 {
6149 // take ownership of buffer (probably leaking)
6150 auto data = readResult.extractSlice();
6151 se = new StringExp(e.loc, data);
6152 global.fileManager.add(fileName, data);
6153 }
6154 }
6155 }
6156 result = se.expressionSemantic(sc);
6157 }
6158
6159 override void visit(AssertExp exp)
6160 {
6161 // https://dlang.org/spec/expression.html#assert_expressions
6162 static if (LOGSEMANTIC)
6163 {
6164 printf("AssertExp::semantic('%s')\n", exp.toChars());
6165 }
6166
6167 const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context && global.params.useAssert == CHECKENABLE.on;
6168 Expression temporariesPrefix;
6169
6170 if (generateMsg)
6171 // no message - use assert expression as msg
6172 {
6173 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
6174 return setError();
6175
6176 /*
6177 {
6178 auto a = e1, b = e2;
6179 assert(a == b, _d_assert_fail!"=="(a, b));
6180 }()
6181 */
6182
6183 /*
6184 Stores the result of an operand expression into a temporary
6185 if necessary, e.g. if it is an impure fuction call containing side
6186 effects as in https://issues.dlang.org/show_bug.cgi?id=20114
6187
6188 Params:
6189 op = an expression which may require a temporary (added to
6190 `temporariesPrefix`: `auto tmp = op`) and will be replaced
6191 by `tmp` if necessary
6192
6193 Returns: (possibly replaced) `op`
6194 */
6195 Expression maybePromoteToTmp(ref Expression op)
6196 {
6197 // https://issues.dlang.org/show_bug.cgi?id=20989
6198 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6199 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6200 {
6201 auto die = op.isDotIdExp();
6202 if (die && die.ident == Id.ptr)
6203 die.noderef = true;
6204 }
6205
6206 op = op.expressionSemantic(sc);
6207 op = resolveProperties(sc, op);
6208
6209 // Detect assert's using static operator overloads (e.g. `"var" in environment`)
6210 if (auto te = op.isTypeExp())
6211 {
6212 // Replace the TypeExp with it's textual representation
6213 // Including "..." in the error message isn't quite right but
6214 // proper solutions require more drastic changes, e.g. directly
6215 // using miniFormat and combine instead of calling _d_assert_fail
6216 auto name = new StringExp(te.loc, te.toString());
6217 return name.expressionSemantic(sc);
6218 }
6219
6220 // Create a temporary for expressions with side effects
6221 // Defensively assume that function calls may have side effects even
6222 // though it's not detected by hasSideEffect (e.g. `debug puts("Hello")` )
6223 // Rewriting CallExp's also avoids some issues with the inliner/debug generation
6224 if (op.hasSideEffect(true))
6225 {
6226 // Don't create an invalid temporary for void-expressions
6227 // Further semantic will issue an appropriate error
6228 if (op.type.ty == Tvoid)
6229 return op;
6230
6231 // https://issues.dlang.org/show_bug.cgi?id=21590
6232 // Don't create unnecessary temporaries and detect `assert(a = b)`
6233 if (op.isAssignExp() || op.isBinAssignExp())
6234 {
6235 auto left = (cast(BinExp) op).e1;
6236
6237 // Find leftmost expression to handle other rewrites,
6238 // e.g. --(++a) => a += 1 -= 1
6239 while (left.isAssignExp() || left.isBinAssignExp())
6240 left = (cast(BinExp) left).e1;
6241
6242 // Only use the assignee if it's a variable and skip
6243 // other lvalues (e.g. ref's returned by functions)
6244 if (left.isVarExp())
6245 return left;
6246
6247 // Sanity check that `op` can be converted to boolean
6248 // But don't raise errors for assignments enclosed in another expression
6249 if (op is exp.e1)
6250 op.toBoolean(sc);
6251 }
6252
6253 // Tuples with side-effects already receive a temporary during semantic
6254 if (op.type.isTypeTuple())
6255 {
6256 auto te = op.isTupleExp();
6257 assert(te);
6258
6259 // Create a new tuple without the associated temporary
6260 auto res = new TupleExp(op.loc, te.exps);
6261 return res.expressionSemantic(sc);
6262 }
6263
6264 const stc = op.isLvalue() ? STC.ref_ : 0;
6265 auto tmp = copyToTemp(stc, "__assertOp", op);
6266 tmp.dsymbolSemantic(sc);
6267
6268 auto decl = new DeclarationExp(op.loc, tmp);
6269 temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6270
6271 op = new VarExp(op.loc, tmp);
6272 op = op.expressionSemantic(sc);
6273 }
6274 return op;
6275 }
6276
6277 // if the assert condition is a mixin expression, try to compile it
6278 if (auto ce = exp.e1.isMixinExp())
6279 {
6280 if (auto e1 = compileIt(ce))
6281 exp.e1 = e1;
6282 }
6283
6284 Expressions* es;
6285 Objects* tiargs;
6286 Loc loc = exp.e1.loc;
6287
6288 const op = exp.e1.op;
6289 bool isEqualsCallExpression;
6290 if (const callExp = exp.e1.isCallExp())
6291 {
6292 // https://issues.dlang.org/show_bug.cgi?id=20331
6293 // callExp.f may be null if the assert contains a call to
6294 // a function pointer or literal
6295 if (const callExpFunc = callExp.f)
6296 {
6297 const callExpIdent = callExpFunc.ident;
6298 isEqualsCallExpression = callExpIdent == Id.__equals ||
6299 callExpIdent == Id.eq;
6300 }
6301 }
6302 if (op == EXP.equal || op == EXP.notEqual ||
6303 op == EXP.lessThan || op == EXP.greaterThan ||
6304 op == EXP.lessOrEqual || op == EXP.greaterOrEqual ||
6305 op == EXP.identity || op == EXP.notIdentity ||
6306 op == EXP.in_ ||
6307 isEqualsCallExpression)
6308 {
6309 es = new Expressions(3);
6310 tiargs = new Objects(1);
6311
6312 if (isEqualsCallExpression)
6313 {
6314 auto callExp = cast(CallExp) exp.e1;
6315 auto args = callExp.arguments;
6316
6317 // structs with opEquals get rewritten to a DotVarExp:
6318 // a.opEquals(b)
6319 // https://issues.dlang.org/show_bug.cgi?id=20100
6320 if (args.length == 1)
6321 {
6322 auto dv = callExp.e1.isDotVarExp();
6323 assert(dv);
6324
6325 // runtime args
6326 (*es)[1] = maybePromoteToTmp(dv.e1);
6327 (*es)[2] = maybePromoteToTmp((*args)[0]);
6328 }
6329 else
6330 {
6331 // runtime args
6332 (*es)[1] = maybePromoteToTmp((*args)[0]);
6333 (*es)[2] = maybePromoteToTmp((*args)[1]);
6334 }
6335 }
6336 else
6337 {
6338 auto binExp = cast(EqualExp) exp.e1;
6339
6340 // runtime args
6341 (*es)[1] = maybePromoteToTmp(binExp.e1);
6342 (*es)[2] = maybePromoteToTmp(binExp.e2);
6343 }
6344
6345 // template args
6346 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : EXPtoString(exp.e1.op));
6347 comp = comp.expressionSemantic(sc);
6348 (*es)[0] = comp;
6349 (*tiargs)[0] = (*es)[1].type;
6350 }
6351
6352 // Format exp.e1 before any additional boolean conversion
6353 // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
6354 else if (op != EXP.andAnd && op != EXP.orOr)
6355 {
6356 es = new Expressions(2);
6357 tiargs = new Objects(1);
6358
6359 if (auto ne = exp.e1.isNotExp())
6360 {
6361 // Fetch the (potential non-bool) expression and fold
6362 // (n) negations into (n % 2) negations, e.g. !!a => a
6363 for (bool neg = true; ; neg = !neg)
6364 {
6365 if (auto ne2 = ne.e1.isNotExp())
6366 ne = ne2;
6367 else
6368 {
6369 (*es)[0] = new StringExp(loc, neg ? "!" : "");
6370 (*es)[1] = maybePromoteToTmp(ne.e1);
6371 break;
6372 }
6373 }
6374 }
6375 else
6376 { // Simply format exp.e1
6377 (*es)[0] = new StringExp(loc, "");
6378 (*es)[1] = maybePromoteToTmp(exp.e1);
6379 }
6380
6381 (*tiargs)[0] = (*es)[1].type;
6382
6383 // Passing __ctfe to auto ref infers ref and aborts compilation:
6384 // "cannot modify compiler-generated variable __ctfe"
6385 auto ve = (*es)[1].isVarExp();
6386 if (ve && ve.var.ident == Id.ctfe)
6387 {
6388 exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6389 goto LSkip;
6390 }
6391 }
6392 else
6393 {
6394 OutBuffer buf;
6395 buf.printf("%s failed", exp.toChars());
6396 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6397 goto LSkip;
6398 }
6399
6400 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6401 auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6402
6403 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6404 auto ec = CallExp.create(loc, dt, es);
6405 exp.msg = ec;
6406 }
6407
6408 LSkip:
6409 if (Expression ex = unaSemantic(exp, sc))
6410 {
6411 result = ex;
6412 return;
6413 }
6414
6415 exp.e1 = resolveProperties(sc, exp.e1);
6416 // BUG: see if we can do compile time elimination of the Assert
6417 exp.e1 = exp.e1.optimize(WANTvalue);
6418 exp.e1 = exp.e1.toBoolean(sc);
6419
6420 if (exp.e1.op == EXP.error)
6421 {
6422 result = exp.e1;
6423 return;
6424 }
6425
6426 if (exp.msg)
6427 {
6428 exp.msg = expressionSemantic(exp.msg, sc);
6429 exp.msg = resolveProperties(sc, exp.msg);
6430 exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6431 exp.msg = exp.msg.optimize(WANTvalue);
6432 checkParamArgumentEscape(sc, null, null, null, STC.undefined_, exp.msg, true, false);
6433 }
6434
6435 if (exp.msg && exp.msg.op == EXP.error)
6436 {
6437 result = exp.msg;
6438 return;
6439 }
6440
6441 auto f1 = checkNonAssignmentArrayOp(exp.e1);
6442 auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6443 if (f1 || f2)
6444 return setError();
6445
6446 if (exp.e1.toBool().hasValue(false))
6447 {
6448 /* This is an `assert(0)` which means halt program execution
6449 */
6450 FuncDeclaration fd = sc.parent.isFuncDeclaration();
6451 if (fd)
6452 fd.hasReturnExp |= 4;
6453 sc.ctorflow.orCSX(CSX.halt);
6454
6455 if (global.params.useAssert == CHECKENABLE.off)
6456 {
6457 Expression e = new HaltExp(exp.loc);
6458 e = e.expressionSemantic(sc);
6459 result = e;
6460 return;
6461 }
6462
6463 // Only override the type when it isn't already some flavour of noreturn,
6464 // e.g. when this assert was generated by defaultInitLiteral
6465 if (!exp.type || !exp.type.isTypeNoreturn())
6466 exp.type = Type.tnoreturn;
6467 }
6468 else
6469 exp.type = Type.tvoid;
6470
6471 result = !temporariesPrefix
6472 ? exp
6473 : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6474 }
6475
6476 override void visit(ThrowExp te)
6477 {
6478 import dmd.statementsem;
6479
6480 if (StatementSemanticVisitor.throwSemantic(te.loc, te.e1, sc))
6481 result = te;
6482 else
6483 setError();
6484 }
6485
6486 override void visit(DotIdExp exp)
6487 {
6488 static if (LOGSEMANTIC)
6489 {
6490 printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6491 //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
6492 }
6493
6494 if (sc.flags & SCOPE.Cfile)
6495 {
6496 /* See if need to rewrite the AST because of cast/call ambiguity
6497 */
6498 if (auto e = castCallAmbiguity(exp, sc))
6499 {
6500 result = expressionSemantic(e, sc);
6501 return;
6502 }
6503
6504 if (exp.arrow) // ImportC only
6505 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
6506
6507 if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
6508 {
6509 // C11 6.5.3 says _Alignof only applies to types
6510 Expression e;
6511 Type t;
6512 Dsymbol s;
6513 dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
6514 if (e)
6515 {
6516 exp.e1.error("argument to `_Alignof` must be a type");
6517 return setError();
6518 }
6519 else if (t)
6520 {
6521 // Note similarity to getProperty() implementation of __xalignof
6522 const explicitAlignment = t.alignment();
6523 const naturalAlignment = t.alignsize();
6524 const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
6525 result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
6526 }
6527 else if (s)
6528 {
6529 exp.e1.error("argument to `_Alignof` must be a type");
6530 return setError();
6531 }
6532 else
6533 assert(0);
6534 return;
6535 }
6536
6537 if (exp.ident != Id.__sizeof)
6538 {
6539 result = fieldLookup(exp.e1, sc, exp.ident);
6540 return;
6541 }
6542 }
6543
6544 Expression e = exp.dotIdSemanticProp(sc, 1);
6545
6546 if (e && isDotOpDispatch(e))
6547 {
6548 auto ode = e;
6549 uint errors = global.startGagging();
6550 e = resolvePropertiesX(sc, e);
6551 // Any error or if 'e' is not resolved, go to UFCS
6552 if (global.endGagging(errors) || e is ode)
6553 e = null; /* fall down to UFCS */
6554 else
6555 {
6556 result = e;
6557 return;
6558 }
6559 }
6560 if (!e) // if failed to find the property
6561 {
6562 /* If ident is not a valid property, rewrite:
6563 * e1.ident
6564 * as:
6565 * .ident(e1)
6566 */
6567 e = resolveUFCSProperties(sc, exp);
6568 }
6569 result = e;
6570 }
6571
6572 override void visit(DotTemplateExp e)
6573 {
6574 if (e.type)
6575 {
6576 result = e;
6577 return;
6578 }
6579 if (Expression ex = unaSemantic(e, sc))
6580 {
6581 result = ex;
6582 return;
6583 }
6584 // 'void' like TemplateExp
6585 e.type = Type.tvoid;
6586 result = e;
6587 }
6588
6589 override void visit(DotVarExp exp)
6590 {
6591 static if (LOGSEMANTIC)
6592 {
6593 printf("DotVarExp::semantic('%s')\n", exp.toChars());
6594 }
6595 if (exp.type)
6596 {
6597 result = exp;
6598 return;
6599 }
6600
6601 exp.var = exp.var.toAlias().isDeclaration();
6602
6603 exp.e1 = exp.e1.expressionSemantic(sc);
6604
6605 if (auto tup = exp.var.isTupleDeclaration())
6606 {
6607 /* Replace:
6608 * e1.tuple(a, b, c)
6609 * with:
6610 * tuple(e1.a, e1.b, e1.c)
6611 */
6612 Expression e0;
6613 Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6614
6615 auto exps = new Expressions();
6616 exps.reserve(tup.objects.length);
6617 for (size_t i = 0; i < tup.objects.length; i++)
6618 {
6619 RootObject o = (*tup.objects)[i];
6620 Expression e;
6621 Declaration var;
6622 switch (o.dyncast()) with (DYNCAST)
6623 {
6624 case expression:
6625 e = cast(Expression)o;
6626 if (auto se = e.isDsymbolExp())
6627 var = se.s.isDeclaration();
6628 else if (auto ve = e.isVarExp())
6629 if (!ve.var.isFuncDeclaration())
6630 // Exempt functions for backwards compatibility reasons.
6631 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6632 var = ve.var;
6633 break;
6634 case dsymbol:
6635 Dsymbol s = cast(Dsymbol) o;
6636 Declaration d = s.isDeclaration();
6637 if (!d || d.isFuncDeclaration())
6638 // Exempt functions for backwards compatibility reasons.
6639 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6640 e = new DsymbolExp(exp.loc, s);
6641 else
6642 var = d;
6643 break;
6644 case type:
6645 e = new TypeExp(exp.loc, cast(Type)o);
6646 break;
6647 default:
6648 exp.error("`%s` is not an expression", o.toChars());
6649 return setError();
6650 }
6651 if (var)
6652 e = new DotVarExp(exp.loc, ev, var);
6653 exps.push(e);
6654 }
6655
6656 Expression e = new TupleExp(exp.loc, e0, exps);
6657 e = e.expressionSemantic(sc);
6658 result = e;
6659 return;
6660 }
6661 else if (auto ad = exp.var.isAliasDeclaration())
6662 {
6663 if (auto t = ad.getType())
6664 {
6665 result = new TypeExp(exp.loc, t).expressionSemantic(sc);
6666 return;
6667 }
6668 }
6669
6670 exp.e1 = exp.e1.addDtorHook(sc);
6671
6672 Type t1 = exp.e1.type;
6673
6674 if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6675 {
6676 // for functions, do checks after overload resolution
6677 if (!fd.functionSemantic())
6678 return setError();
6679
6680 /* https://issues.dlang.org/show_bug.cgi?id=13843
6681 * If fd obviously has no overloads, we should
6682 * normalize AST, and it will give a chance to wrap fd with FuncExp.
6683 */
6684 if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6685 {
6686 // (e1, fd)
6687 auto e = symbolToExp(fd, exp.loc, sc, false);
6688 result = Expression.combine(exp.e1, e);
6689 return;
6690 }
6691
6692 exp.type = fd.type;
6693 assert(exp.type);
6694 }
6695 else if (OverDeclaration od = exp.var.isOverDeclaration())
6696 {
6697 exp.type = Type.tvoid; // ambiguous type?
6698 }
6699 else
6700 {
6701 exp.type = exp.var.type;
6702 if (!exp.type && global.errors) // var is goofed up, just return error.
6703 return setError();
6704 assert(exp.type);
6705
6706 if (t1.ty == Tpointer)
6707 t1 = t1.nextOf();
6708
6709 exp.type = exp.type.addMod(t1.mod);
6710
6711 // https://issues.dlang.org/show_bug.cgi?id=23109
6712 // Run semantic on the DotVarExp type
6713 if (auto handle = exp.type.isClassHandle())
6714 {
6715 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
6716 handle.dsymbolSemantic(null);
6717 }
6718
6719 Dsymbol vparent = exp.var.toParent();
6720 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6721 if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6722 exp.e1 = e1x;
6723 else
6724 {
6725 /* Later checkRightThis will report correct error for invalid field variable access.
6726 */
6727 Expression e = new VarExp(exp.loc, exp.var);
6728 e = e.expressionSemantic(sc);
6729 result = e;
6730 return;
6731 }
6732 checkAccess(exp.loc, sc, exp.e1, exp.var);
6733
6734 VarDeclaration v = exp.var.isVarDeclaration();
6735 if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6736 {
6737 Expression e = expandVar(WANTvalue, v);
6738 if (e)
6739 {
6740 result = e;
6741 return;
6742 }
6743 }
6744
6745 if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6746 (!v.needThis() && v.semanticRun > PASS.initial))) // fix https://issues.dlang.org/show_bug.cgi?id=17258
6747 {
6748 // (e1, v)
6749 checkAccess(exp.loc, sc, exp.e1, v);
6750 Expression e = new VarExp(exp.loc, v);
6751 e = new CommaExp(exp.loc, exp.e1, e);
6752 e = e.expressionSemantic(sc);
6753 result = e;
6754 return;
6755 }
6756 }
6757 //printf("-DotVarExp::semantic('%s')\n", toChars());
6758 result = exp;
6759 }
6760
6761 override void visit(DotTemplateInstanceExp exp)
6762 {
6763 static if (LOGSEMANTIC)
6764 {
6765 printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6766 }
6767 if (exp.type)
6768 {
6769 result = exp;
6770 return;
6771 }
6772 // Indicate we need to resolve by UFCS.
6773 Expression e = exp.dotTemplateSemanticProp(sc, 1);
6774 if (!e)
6775 e = resolveUFCSProperties(sc, exp);
6776 if (e is exp)
6777 e.type = Type.tvoid; // Unresolved type, because it needs inference
6778 result = e;
6779 }
6780
6781 override void visit(DelegateExp e)
6782 {
6783 static if (LOGSEMANTIC)
6784 {
6785 printf("DelegateExp::semantic('%s')\n", e.toChars());
6786 }
6787 if (e.type)
6788 {
6789 result = e;
6790 return;
6791 }
6792
6793 e.e1 = e.e1.expressionSemantic(sc);
6794
6795 e.type = new TypeDelegate(e.func.type.isTypeFunction());
6796 e.type = e.type.typeSemantic(e.loc, sc);
6797
6798 FuncDeclaration f = e.func.toAliasFunc();
6799 AggregateDeclaration ad = f.isMemberLocal();
6800 if (f.needThis())
6801 e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6802 if (e.e1.op == EXP.error)
6803 return setError();
6804
6805 if (f.type.ty == Tfunction)
6806 {
6807 TypeFunction tf = cast(TypeFunction)f.type;
6808 if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6809 {
6810 OutBuffer thisBuf, funcBuf;
6811 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6812 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6813 e.error("%smethod `%s` is not callable using a %s`%s`",
6814 funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6815 return setError();
6816 }
6817 }
6818 if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6819 {
6820 // A downcast is required for interfaces
6821 // https://issues.dlang.org/show_bug.cgi?id=3706
6822 e.e1 = new CastExp(e.loc, e.e1, ad.type);
6823 e.e1 = e.e1.expressionSemantic(sc);
6824 }
6825 result = e;
6826 // declare dual-context container
6827 if (f.hasDualContext() && !sc.intypeof && sc.func)
6828 {
6829 // check access to second `this`
6830 if (AggregateDeclaration ad2 = f.isMember2())
6831 {
6832 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6833 if (te.op != EXP.error)
6834 te = getRightThis(e.loc, sc, ad2, te, f);
6835 if (te.op == EXP.error)
6836 {
6837 e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6838 return setError();
6839 }
6840 }
6841 VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6842 e.vthis2 = vthis2;
6843 Expression de = new DeclarationExp(e.loc, vthis2);
6844 result = Expression.combine(de, result);
6845 result = result.expressionSemantic(sc);
6846 }
6847 }
6848
6849 override void visit(DotTypeExp exp)
6850 {
6851 static if (LOGSEMANTIC)
6852 {
6853 printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6854 }
6855 if (exp.type)
6856 {
6857 result = exp;
6858 return;
6859 }
6860
6861 if (auto e = unaSemantic(exp, sc))
6862 {
6863 result = e;
6864 return;
6865 }
6866
6867 exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6868 result = exp;
6869 }
6870
6871 override void visit(AddrExp exp)
6872 {
6873 static if (LOGSEMANTIC)
6874 {
6875 printf("AddrExp::semantic('%s')\n", exp.toChars());
6876 }
6877 if (exp.type)
6878 {
6879 result = exp;
6880 return;
6881 }
6882
6883 if (Expression ex = unaSemantic(exp, sc))
6884 {
6885 result = ex;
6886 return;
6887 }
6888
6889 if (sc.flags & SCOPE.Cfile)
6890 {
6891 /* Special handling for &"string"/&(T[]){0, 1}
6892 * since C regards string/array literals as lvalues
6893 */
6894 auto e = exp.e1;
6895 if(e.isStringExp() || e.isArrayLiteralExp())
6896 {
6897 e.type = typeSemantic(e.type, Loc.initial, sc);
6898 // if type is already a pointer exp is an illegal expression of the form `&(&"")`
6899 if (!e.type.isTypePointer())
6900 {
6901 e.type = e.type.pointerTo();
6902 result = e;
6903 return;
6904 }
6905 else
6906 {
6907 // `toLvalue` call further below is upon exp.e1, omitting & from the error message
6908 exp.toLvalue(sc, null);
6909 return setError();
6910 }
6911 }
6912 }
6913
6914 int wasCond = exp.e1.op == EXP.question;
6915
6916 if (exp.e1.op == EXP.dotTemplateInstance)
6917 {
6918 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6919 TemplateInstance ti = dti.ti;
6920 {
6921 //assert(ti.needsTypeInference(sc));
6922 ti.dsymbolSemantic(sc);
6923 if (!ti.inst || ti.errors) // if template failed to expand
6924 return setError();
6925
6926 Dsymbol s = ti.toAlias();
6927 FuncDeclaration f = s.isFuncDeclaration();
6928 if (f)
6929 {
6930 exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6931 exp.e1 = exp.e1.expressionSemantic(sc);
6932 }
6933 }
6934 }
6935 else if (exp.e1.op == EXP.scope_)
6936 {
6937 TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6938 if (ti)
6939 {
6940 //assert(ti.needsTypeInference(sc));
6941 ti.dsymbolSemantic(sc);
6942 if (!ti.inst || ti.errors) // if template failed to expand
6943 return setError();
6944
6945 Dsymbol s = ti.toAlias();
6946 FuncDeclaration f = s.isFuncDeclaration();
6947 if (f)
6948 {
6949 exp.e1 = new VarExp(exp.e1.loc, f);
6950 exp.e1 = exp.e1.expressionSemantic(sc);
6951 }
6952 }
6953 }
6954 /* https://issues.dlang.org/show_bug.cgi?id=809
6955 *
6956 * If the address of a lazy variable is taken,
6957 * the expression is rewritten so that the type
6958 * of it is the delegate type. This means that
6959 * the symbol is not going to represent a call
6960 * to the delegate anymore, but rather, the
6961 * actual symbol.
6962 */
6963 if (auto ve = exp.e1.isVarExp())
6964 {
6965 if (ve.var.storage_class & STC.lazy_)
6966 {
6967 exp.e1 = exp.e1.expressionSemantic(sc);
6968 exp.e1 = resolveProperties(sc, exp.e1);
6969 if (auto callExp = exp.e1.isCallExp())
6970 {
6971 if (callExp.e1.type.toBasetype().ty == Tdelegate)
6972 {
6973 /* https://issues.dlang.org/show_bug.cgi?id=20551
6974 *
6975 * Cannot take address of lazy parameter in @safe code
6976 * because it might end up being a pointer to undefined
6977 * memory.
6978 */
6979 if (1)
6980 {
6981 if (sc.setUnsafe(false, exp.loc,
6982 "cannot take address of lazy parameter `%s` in `@safe` function `%s`", ve, sc.func))
6983 {
6984 setError();
6985 return;
6986 }
6987 }
6988 VarExp ve2 = callExp.e1.isVarExp();
6989 ve2.delegateWasExtracted = true;
6990 ve2.var.storage_class |= STC.scope_;
6991 result = ve2;
6992 return;
6993 }
6994 }
6995 }
6996 }
6997
6998 exp.e1 = exp.e1.toLvalue(sc, null);
6999 if (exp.e1.op == EXP.error)
7000 {
7001 result = exp.e1;
7002 return;
7003 }
7004 if (checkNonAssignmentArrayOp(exp.e1))
7005 return setError();
7006
7007 if (!exp.e1.type)
7008 {
7009 exp.error("cannot take address of `%s`", exp.e1.toChars());
7010 return setError();
7011 }
7012 if (!checkAddressable(exp, sc))
7013 return setError();
7014
7015 bool hasOverloads;
7016 if (auto f = isFuncAddress(exp, &hasOverloads))
7017 {
7018 if (!hasOverloads && f.checkForwardRef(exp.loc))
7019 return setError();
7020 }
7021 else if (!exp.e1.type.deco)
7022 {
7023 // try to resolve the type
7024 exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null);
7025 if (!exp.e1.type.deco) // still couldn't resolve it
7026 {
7027 if (auto ve = exp.e1.isVarExp())
7028 {
7029 Declaration d = ve.var;
7030 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
7031 }
7032 else
7033 exp.error("forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
7034 return setError();
7035 }
7036 }
7037
7038 exp.type = exp.e1.type.pointerTo();
7039
7040 // See if this should really be a delegate
7041 if (exp.e1.op == EXP.dotVariable)
7042 {
7043 DotVarExp dve = cast(DotVarExp)exp.e1;
7044 FuncDeclaration f = dve.var.isFuncDeclaration();
7045 if (f)
7046 {
7047 f = f.toAliasFunc(); // FIXME, should see overloads
7048 // https://issues.dlang.org/show_bug.cgi?id=1983
7049 if (!dve.hasOverloads)
7050 f.tookAddressOf++;
7051
7052 Expression e;
7053 if (f.needThis())
7054 e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
7055 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
7056 e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
7057 e = e.expressionSemantic(sc);
7058 result = e;
7059 return;
7060 }
7061
7062 // Look for misaligned pointer in @safe mode
7063 if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
7064 return setError();
7065 }
7066 else if (exp.e1.op == EXP.variable)
7067 {
7068 VarExp ve = cast(VarExp)exp.e1;
7069 VarDeclaration v = ve.var.isVarDeclaration();
7070 if (v)
7071 {
7072 if (!checkAddressVar(sc, exp.e1, v))
7073 return setError();
7074
7075 ve.checkPurity(sc, v);
7076 }
7077 FuncDeclaration f = ve.var.isFuncDeclaration();
7078 if (f)
7079 {
7080 /* Because nested functions cannot be overloaded,
7081 * mark here that we took its address because castTo()
7082 * may not be called with an exact match.
7083 *
7084 * https://issues.dlang.org/show_bug.cgi?id=19285 :
7085 * We also need to make sure we aren't inside a typeof. Ideally the compiler
7086 * would do typeof(...) semantic analysis speculatively then collect information
7087 * about what it used rather than relying on what are effectively semantically-global
7088 * variables but it doesn't.
7089 */
7090 if (!sc.isFromSpeculativeSemanticContext() && (!ve.hasOverloads || (f.isNested() && !f.needThis())))
7091 {
7092 // TODO: Refactor to use a proper interface that can keep track of causes.
7093 f.tookAddressOf++;
7094 }
7095
7096 if (f.isNested() && !f.needThis())
7097 {
7098 if (f.isFuncLiteralDeclaration())
7099 {
7100 if (!f.FuncDeclaration.isNested())
7101 {
7102 /* Supply a 'null' for a this pointer if no this is available
7103 */
7104 Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
7105 e = e.expressionSemantic(sc);
7106 result = e;
7107 return;
7108 }
7109 }
7110 Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
7111 e = e.expressionSemantic(sc);
7112 result = e;
7113 return;
7114 }
7115 if (f.needThis())
7116 {
7117 if (hasThis(sc))
7118 {
7119 /* Should probably supply 'this' after overload resolution,
7120 * not before.
7121 */
7122 Expression ethis = new ThisExp(exp.loc);
7123 Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
7124 e = e.expressionSemantic(sc);
7125 result = e;
7126 return;
7127 }
7128 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_))
7129 {
7130 sc.setUnsafe(false, exp.loc,
7131 "`this` reference necessary to take address of member `%s` in `@safe` function `%s`",
7132 f, sc.func);
7133 }
7134 }
7135 }
7136 }
7137 else if (exp.e1.op == EXP.index)
7138 {
7139 /* For:
7140 * int[3] a;
7141 * &a[i]
7142 * check 'a' the same as for a regular variable
7143 */
7144 if (VarDeclaration v = expToVariable(exp.e1))
7145 {
7146 exp.e1.checkPurity(sc, v);
7147 }
7148 }
7149 else if (wasCond)
7150 {
7151 /* a ? b : c was transformed to *(a ? &b : &c), but we still
7152 * need to do safety checks
7153 */
7154 assert(exp.e1.op == EXP.star);
7155 PtrExp pe = cast(PtrExp)exp.e1;
7156 assert(pe.e1.op == EXP.question);
7157 CondExp ce = cast(CondExp)pe.e1;
7158 assert(ce.e1.op == EXP.address);
7159 assert(ce.e2.op == EXP.address);
7160
7161 // Re-run semantic on the address expressions only
7162 ce.e1.type = null;
7163 ce.e1 = ce.e1.expressionSemantic(sc);
7164 ce.e2.type = null;
7165 ce.e2 = ce.e2.expressionSemantic(sc);
7166 }
7167 result = exp.optimize(WANTvalue);
7168 }
7169
7170 override void visit(PtrExp exp)
7171 {
7172 static if (LOGSEMANTIC)
7173 {
7174 printf("PtrExp::semantic('%s')\n", exp.toChars());
7175 }
7176 if (exp.type)
7177 {
7178 result = exp;
7179 return;
7180 }
7181
7182 Expression e = exp.op_overload(sc);
7183 if (e)
7184 {
7185 result = e;
7186 return;
7187 }
7188
7189 exp.e1 = exp.e1.arrayFuncConv(sc);
7190
7191 Type tb = exp.e1.type.toBasetype();
7192 switch (tb.ty)
7193 {
7194 case Tpointer:
7195 exp.type = (cast(TypePointer)tb).next;
7196 break;
7197
7198 case Tsarray:
7199 case Tarray:
7200 if (isNonAssignmentArrayOp(exp.e1))
7201 goto default;
7202 exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
7203 exp.type = (cast(TypeArray)tb).next;
7204 exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
7205 break;
7206
7207 case Terror:
7208 return setError();
7209
7210 case Tnull:
7211 exp.type = Type.tnoreturn; // typeof(*null) is bottom type
7212 break;
7213
7214 default:
7215 exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
7216 goto case Terror;
7217 }
7218
7219 if (exp.checkValue())
7220 return setError();
7221
7222 result = exp;
7223 }
7224
7225 override void visit(NegExp exp)
7226 {
7227 static if (LOGSEMANTIC)
7228 {
7229 printf("NegExp::semantic('%s')\n", exp.toChars());
7230 }
7231 if (exp.type)
7232 {
7233 result = exp;
7234 return;
7235 }
7236
7237 Expression e = exp.op_overload(sc);
7238 if (e)
7239 {
7240 result = e;
7241 return;
7242 }
7243
7244 fix16997(sc, exp);
7245 exp.type = exp.e1.type;
7246 Type tb = exp.type.toBasetype();
7247 if (tb.ty == Tarray || tb.ty == Tsarray)
7248 {
7249 if (!isArrayOpValid(exp.e1))
7250 {
7251 result = arrayOpInvalidError(exp);
7252 return;
7253 }
7254 result = exp;
7255 return;
7256 }
7257 if (!target.isVectorOpSupported(tb, exp.op))
7258 {
7259 result = exp.incompatibleTypes();
7260 return;
7261 }
7262 if (exp.e1.checkNoBool())
7263 return setError();
7264 if (exp.e1.checkArithmetic() ||
7265 exp.e1.checkSharedAccess(sc))
7266 return setError();
7267
7268 result = exp;
7269 }
7270
7271 override void visit(UAddExp exp)
7272 {
7273 static if (LOGSEMANTIC)
7274 {
7275 printf("UAddExp::semantic('%s')\n", exp.toChars());
7276 }
7277 assert(!exp.type);
7278
7279 Expression e = exp.op_overload(sc);
7280 if (e)
7281 {
7282 result = e;
7283 return;
7284 }
7285
7286 fix16997(sc, exp);
7287 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
7288 {
7289 result = exp.incompatibleTypes();
7290 return;
7291 }
7292 if (exp.e1.checkNoBool())
7293 return setError();
7294 if (exp.e1.checkArithmetic())
7295 return setError();
7296 if (exp.e1.checkSharedAccess(sc))
7297 return setError();
7298
7299 result = exp.e1;
7300 }
7301
7302 override void visit(ComExp exp)
7303 {
7304 if (exp.type)
7305 {
7306 result = exp;
7307 return;
7308 }
7309
7310 Expression e = exp.op_overload(sc);
7311 if (e)
7312 {
7313 result = e;
7314 return;
7315 }
7316
7317 fix16997(sc, exp);
7318 exp.type = exp.e1.type;
7319 Type tb = exp.type.toBasetype();
7320 if (tb.ty == Tarray || tb.ty == Tsarray)
7321 {
7322 if (!isArrayOpValid(exp.e1))
7323 {
7324 result = arrayOpInvalidError(exp);
7325 return;
7326 }
7327 result = exp;
7328 return;
7329 }
7330 if (!target.isVectorOpSupported(tb, exp.op))
7331 {
7332 result = exp.incompatibleTypes();
7333 return;
7334 }
7335 if (exp.e1.checkNoBool())
7336 return setError();
7337 if (exp.e1.checkIntegral() ||
7338 exp.e1.checkSharedAccess(sc))
7339 return setError();
7340
7341 result = exp;
7342 }
7343
7344 override void visit(NotExp e)
7345 {
7346 if (e.type)
7347 {
7348 result = e;
7349 return;
7350 }
7351
7352 e.setNoderefOperand();
7353
7354 // Note there is no operator overload
7355 if (Expression ex = unaSemantic(e, sc))
7356 {
7357 result = ex;
7358 return;
7359 }
7360
7361 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7362 if (e.e1.op == EXP.type)
7363 e.e1 = resolveAliasThis(sc, e.e1);
7364
7365 e.e1 = resolveProperties(sc, e.e1);
7366 e.e1 = e.e1.toBoolean(sc);
7367 if (e.e1.type == Type.terror)
7368 {
7369 result = e.e1;
7370 return;
7371 }
7372
7373 if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7374 {
7375 result = e.incompatibleTypes();
7376 }
7377 // https://issues.dlang.org/show_bug.cgi?id=13910
7378 // Today NotExp can take an array as its operand.
7379 if (checkNonAssignmentArrayOp(e.e1))
7380 return setError();
7381
7382 e.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
7383 result = e;
7384 }
7385
7386 override void visit(DeleteExp exp)
7387 {
7388 // @@@DEPRECATED_2.109@@@
7389 // 1. Deprecated since 2.079
7390 // 2. Error since 2.099
7391 // 3. Removal of keyword, "delete" can be used for other identities
7392 if (!exp.isRAII)
7393 {
7394 error(exp.loc, "the `delete` keyword is obsolete");
7395 errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead");
7396 return setError();
7397 }
7398
7399 Expression e = exp;
7400
7401 if (Expression ex = unaSemantic(exp, sc))
7402 {
7403 result = ex;
7404 return;
7405 }
7406 exp.e1 = resolveProperties(sc, exp.e1);
7407 exp.e1 = exp.e1.modifiableLvalue(sc, null);
7408 if (exp.e1.op == EXP.error)
7409 {
7410 result = exp.e1;
7411 return;
7412 }
7413 exp.type = Type.tvoid;
7414
7415 Type tb = exp.e1.type.toBasetype();
7416
7417 /* Now that `delete` in user code is an error, we only get here when
7418 * `isRAII` has been set to true for the deletion of a `scope class`. */
7419 if (tb.ty != Tclass)
7420 {
7421 exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7422 return setError();
7423 }
7424
7425 ClassDeclaration cd = (cast(TypeClass)tb).sym;
7426 if (cd.isCOMinterface())
7427 {
7428 /* Because COM classes are deleted by IUnknown.Release()
7429 */
7430 exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7431 return setError();
7432 }
7433
7434 bool err = false;
7435 if (cd.dtor)
7436 {
7437 err |= !cd.dtor.functionSemantic();
7438 err |= exp.checkPurity(sc, cd.dtor);
7439 err |= exp.checkSafety(sc, cd.dtor);
7440 err |= exp.checkNogc(sc, cd.dtor);
7441 }
7442 if (err)
7443 return setError();
7444
7445 result = e;
7446 }
7447
7448 override void visit(CastExp exp)
7449 {
7450 static if (LOGSEMANTIC)
7451 {
7452 printf("CastExp::semantic('%s')\n", exp.toChars());
7453 }
7454 //static int x; assert(++x < 10);
7455 if (exp.type)
7456 {
7457 result = exp;
7458 return;
7459 }
7460
7461 if ((sc && sc.flags & SCOPE.Cfile) &&
7462 exp.to && (exp.to.ty == Tident || exp.to.ty == Tsarray) &&
7463 (exp.e1.op == EXP.address || exp.e1.op == EXP.star ||
7464 exp.e1.op == EXP.uadd || exp.e1.op == EXP.negate))
7465 {
7466 /* Ambiguous cases arise from CParser if type-name is just an identifier.
7467 * ( identifier ) cast-expression
7468 * ( identifier [expression]) cast-expression
7469 * If we determine that `identifier` is a variable, and cast-expression
7470 * is one of the unary operators (& * + -), then rewrite this cast
7471 * as a binary expression.
7472 */
7473 Loc loc = exp.loc;
7474 Type t;
7475 Expression e;
7476 Dsymbol s;
7477 exp.to.resolve(loc, sc, e, t, s);
7478 if (e !is null)
7479 {
7480 if (auto ex = exp.e1.isAddrExp()) // (ident) &exp -> (ident & exp)
7481 result = new AndExp(loc, e, ex.e1);
7482 else if (auto ex = exp.e1.isPtrExp()) // (ident) *exp -> (ident * exp)
7483 result = new MulExp(loc, e, ex.e1);
7484 else if (auto ex = exp.e1.isUAddExp()) // (ident) +exp -> (ident + exp)
7485 result = new AddExp(loc, e, ex.e1);
7486 else if (auto ex = exp.e1.isNegExp()) // (ident) -exp -> (ident - exp)
7487 result = new MinExp(loc, e, ex.e1);
7488
7489 assert(result);
7490 result = result.expressionSemantic(sc);
7491 return;
7492 }
7493 }
7494
7495 if (exp.to)
7496 {
7497 exp.to = exp.to.typeSemantic(exp.loc, sc);
7498 if (exp.to == Type.terror)
7499 return setError();
7500
7501 if (!exp.to.hasPointers())
7502 exp.setNoderefOperand();
7503
7504 // When e1 is a template lambda, this cast may instantiate it with
7505 // the type 'to'.
7506 exp.e1 = inferType(exp.e1, exp.to);
7507 }
7508
7509 if (auto e = unaSemantic(exp, sc))
7510 {
7511 result = e;
7512 return;
7513 }
7514
7515 if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
7516 exp.e1 = exp.e1.arrayFuncConv(sc);
7517
7518 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7519 if (exp.e1.op == EXP.type)
7520 exp.e1 = resolveAliasThis(sc, exp.e1);
7521
7522 auto e1x = resolveProperties(sc, exp.e1);
7523 if (e1x.op == EXP.error)
7524 {
7525 result = e1x;
7526 return;
7527 }
7528 if (e1x.checkType())
7529 return setError();
7530 exp.e1 = e1x;
7531
7532 if (!exp.e1.type)
7533 {
7534 exp.error("cannot cast `%s`", exp.e1.toChars());
7535 return setError();
7536 }
7537
7538 // https://issues.dlang.org/show_bug.cgi?id=19954
7539 if (exp.e1.type.ty == Ttuple)
7540 {
7541 if (exp.to)
7542 {
7543 if (TypeTuple tt = exp.to.isTypeTuple())
7544 {
7545 if (exp.e1.type.implicitConvTo(tt))
7546 {
7547 result = exp.e1.castTo(sc, tt);
7548 return;
7549 }
7550 }
7551 }
7552 TupleExp te = exp.e1.isTupleExp();
7553 if (te.exps.length == 1)
7554 exp.e1 = (*te.exps)[0];
7555 }
7556
7557 // only allow S(x) rewrite if cast specified S explicitly.
7558 // See https://issues.dlang.org/show_bug.cgi?id=18545
7559 const bool allowImplicitConstruction = exp.to !is null;
7560
7561 if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7562 {
7563 exp.to = exp.e1.type.castMod(exp.mod);
7564 exp.to = exp.to.typeSemantic(exp.loc, sc);
7565
7566 if (exp.to == Type.terror)
7567 return setError();
7568 }
7569
7570 if (exp.to.ty == Ttuple)
7571 {
7572 exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
7573 return setError();
7574 }
7575
7576 // cast(void) is used to mark e1 as unused, so it is safe
7577 if (exp.to.ty == Tvoid)
7578 {
7579 exp.type = exp.to;
7580 result = exp;
7581 return;
7582 }
7583
7584 if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7585 {
7586 if (Expression e = exp.op_overload(sc))
7587 {
7588 result = e.implicitCastTo(sc, exp.to);
7589 return;
7590 }
7591 }
7592
7593 Type t1b = exp.e1.type.toBasetype();
7594 Type tob = exp.to.toBasetype();
7595
7596 if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7597 {
7598 /* Look to replace:
7599 * cast(S)t
7600 * with:
7601 * S(t)
7602 */
7603
7604 // Rewrite as to.call(e1)
7605 Expression e = new TypeExp(exp.loc, exp.to);
7606 e = new CallExp(exp.loc, e, exp.e1);
7607 e = e.trySemantic(sc);
7608 if (e)
7609 {
7610 result = e;
7611 return;
7612 }
7613 }
7614
7615 if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7616 {
7617 if (checkNonAssignmentArrayOp(exp.e1))
7618 return setError();
7619 }
7620
7621 // Look for casting to a vector type
7622 if (tob.ty == Tvector && t1b.ty != Tvector)
7623 {
7624 result = new VectorExp(exp.loc, exp.e1, exp.to);
7625 result = result.expressionSemantic(sc);
7626 return;
7627 }
7628
7629 Expression ex = exp.e1.castTo(sc, exp.to);
7630 if (ex.op == EXP.error)
7631 {
7632 result = ex;
7633 return;
7634 }
7635
7636 // Check for unsafe casts
7637 if (!isSafeCast(ex, t1b, tob))
7638 {
7639 if (sc.setUnsafe(false, exp.loc, "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
7640 {
7641 return setError();
7642 }
7643 }
7644
7645 // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7646 // to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out.
7647 // See `e2ir.toElemCast` for other types of casts. If `object.__ArrayCast` is improved to support more
7648 // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7649 if (tob.ty == Tarray)
7650 {
7651 // https://issues.dlang.org/show_bug.cgi?id=19840
7652 if (auto ad = isAggregate(t1b))
7653 {
7654 if (ad.aliasthis)
7655 {
7656 Expression e = resolveAliasThis(sc, exp.e1);
7657 e = new CastExp(exp.loc, e, exp.to);
7658 result = e.expressionSemantic(sc);
7659 return;
7660 }
7661 }
7662
7663 if(t1b.ty == Tarray && exp.e1.op != EXP.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7664 {
7665 auto tFrom = t1b.nextOf();
7666 auto tTo = tob.nextOf();
7667
7668 // https://issues.dlang.org/show_bug.cgi?id=20130
7669 if (exp.e1.op != EXP.string_ || !ex.isStringExp)
7670 {
7671 const uint fromSize = cast(uint)tFrom.size();
7672 const uint toSize = cast(uint)tTo.size();
7673 if (fromSize == SIZE_INVALID || toSize == SIZE_INVALID)
7674 return setError();
7675
7676 // If array element sizes do not match, we must adjust the dimensions
7677 if (fromSize != toSize)
7678 {
7679 if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7680 return setError();
7681
7682 // A runtime check is needed in case arrays don't line up. That check should
7683 // be done in the implementation of `object.__ArrayCast`
7684 if (toSize == 0 || (fromSize % toSize) != 0)
7685 {
7686 // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7687
7688 // fully qualify as `object.__ArrayCast`
7689 Expression id = new IdentifierExp(exp.loc, Id.empty);
7690 auto dotid = new DotIdExp(exp.loc, id, Id.object);
7691
7692 auto tiargs = new Objects();
7693 tiargs.push(tFrom);
7694 tiargs.push(tTo);
7695 auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7696
7697 auto arguments = new Expressions();
7698 arguments.push(exp.e1);
7699 Expression ce = new CallExp(exp.loc, dt, arguments);
7700
7701 result = expressionSemantic(ce, sc);
7702 return;
7703 }
7704 }
7705 }
7706 }
7707 }
7708
7709 if (sc && sc.flags & SCOPE.Cfile)
7710 {
7711 /* C11 6.5.4-5: A cast does not yield an lvalue.
7712 * So ensure that castTo does not strip away the cast so that this
7713 * can be enforced in other semantic visitor methods.
7714 */
7715 if (!ex.isCastExp())
7716 {
7717 ex = new CastExp(exp.loc, ex, exp.to);
7718 ex.type = exp.to;
7719 }
7720 }
7721 result = ex;
7722 }
7723
7724 override void visit(VectorExp exp)
7725 {
7726 static if (LOGSEMANTIC)
7727 {
7728 printf("VectorExp::semantic('%s')\n", exp.toChars());
7729 }
7730 if (exp.type)
7731 {
7732 result = exp;
7733 return;
7734 }
7735
7736 exp.e1 = exp.e1.expressionSemantic(sc);
7737 exp.type = exp.to.typeSemantic(exp.loc, sc);
7738 if (exp.e1.op == EXP.error || exp.type.ty == Terror)
7739 {
7740 result = exp.e1;
7741 return;
7742 }
7743
7744 Type tb = exp.type.toBasetype();
7745 assert(tb.ty == Tvector);
7746 TypeVector tv = cast(TypeVector)tb;
7747 Type te = tv.elementType();
7748 exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7749
7750 bool checkElem(Expression elem)
7751 {
7752 if (elem.isConst() == 1)
7753 return false;
7754
7755 exp.error("constant expression expected, not `%s`", elem.toChars());
7756 return true;
7757 }
7758
7759 exp.e1 = exp.e1.optimize(WANTvalue);
7760 bool res;
7761 if (exp.e1.op == EXP.arrayLiteral)
7762 {
7763 foreach (i; 0 .. exp.dim)
7764 {
7765 // Do not stop on first error - check all AST nodes even if error found
7766 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7767 }
7768 }
7769 else if (exp.e1.type.ty == Tvoid)
7770 checkElem(exp.e1);
7771
7772 result = res ? ErrorExp.get() : exp;
7773 }
7774
7775 override void visit(VectorArrayExp e)
7776 {
7777 static if (LOGSEMANTIC)
7778 {
7779 printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7780 }
7781 if (!e.type)
7782 {
7783 unaSemantic(e, sc);
7784 e.e1 = resolveProperties(sc, e.e1);
7785
7786 if (e.e1.op == EXP.error)
7787 {
7788 result = e.e1;
7789 return;
7790 }
7791 assert(e.e1.type.ty == Tvector);
7792 e.type = e.e1.type.isTypeVector().basetype;
7793 }
7794 result = e;
7795 }
7796
7797 override void visit(SliceExp exp)
7798 {
7799 static if (LOGSEMANTIC)
7800 {
7801 printf("SliceExp::semantic('%s')\n", exp.toChars());
7802 }
7803 if (exp.type)
7804 {
7805 result = exp;
7806 return;
7807 }
7808
7809 // operator overloading should be handled in ArrayExp already.
7810 if (Expression ex = unaSemantic(exp, sc))
7811 {
7812 result = ex;
7813 return;
7814 }
7815 exp.e1 = resolveProperties(sc, exp.e1);
7816 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
7817 {
7818 if (exp.lwr || exp.upr)
7819 {
7820 exp.error("cannot slice type `%s`", exp.e1.toChars());
7821 return setError();
7822 }
7823 Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7824 result = e.expressionSemantic(sc);
7825 return;
7826 }
7827 if (!exp.lwr && !exp.upr)
7828 {
7829 if (exp.e1.op == EXP.arrayLiteral)
7830 {
7831 // Convert [a,b,c][] to [a,b,c]
7832 Type t1b = exp.e1.type.toBasetype();
7833 Expression e = exp.e1;
7834 if (t1b.ty == Tsarray)
7835 {
7836 e = e.copy();
7837 e.type = t1b.nextOf().arrayOf();
7838 }
7839 result = e;
7840 return;
7841 }
7842 if (exp.e1.op == EXP.slice)
7843 {
7844 // Convert e[][] to e[]
7845 SliceExp se = cast(SliceExp)exp.e1;
7846 if (!se.lwr && !se.upr)
7847 {
7848 result = se;
7849 return;
7850 }
7851 }
7852 if (isArrayOpOperand(exp.e1))
7853 {
7854 // Convert (a[]+b[])[] to a[]+b[]
7855 result = exp.e1;
7856 return;
7857 }
7858 }
7859 if (exp.e1.op == EXP.error)
7860 {
7861 result = exp.e1;
7862 return;
7863 }
7864 if (exp.e1.type.ty == Terror)
7865 return setError();
7866
7867 Type t1b = exp.e1.type.toBasetype();
7868 if (auto tp = t1b.isTypePointer())
7869 {
7870 if (t1b.isPtrToFunction())
7871 {
7872 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7873 return setError();
7874 }
7875 if (!exp.lwr || !exp.upr)
7876 {
7877 exp.error("upper and lower bounds are needed to slice a pointer");
7878 if (auto ad = isAggregate(tp.next.toBasetype()))
7879 {
7880 auto s = search_function(ad, Id.index);
7881 if (!s) s = search_function(ad, Id.slice);
7882 if (s)
7883 {
7884 auto fd = s.isFuncDeclaration();
7885 if ((fd && !fd.getParameterList().length) || s.isTemplateDeclaration())
7886 {
7887 exp.errorSupplemental(
7888 "pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`",
7889 exp.e1.toChars(),
7890 s.ident.toChars(),
7891 exp.e1.toChars()
7892 );
7893 }
7894
7895 }
7896 }
7897
7898 return setError();
7899 }
7900 if (sc.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions"))
7901 return setError();
7902 }
7903 else if (t1b.ty == Tarray)
7904 {
7905 }
7906 else if (t1b.ty == Tsarray)
7907 {
7908 }
7909 else if (t1b.ty == Ttuple)
7910 {
7911 if (!exp.lwr && !exp.upr)
7912 {
7913 result = exp.e1;
7914 return;
7915 }
7916 if (!exp.lwr || !exp.upr)
7917 {
7918 exp.error("need upper and lower bound to slice tuple");
7919 return setError();
7920 }
7921 }
7922 else if (t1b.ty == Tvector && exp.e1.isLvalue())
7923 {
7924 // Convert e1 to corresponding static array
7925 TypeVector tv1 = cast(TypeVector)t1b;
7926 t1b = tv1.basetype;
7927 t1b = t1b.castMod(tv1.mod);
7928 exp.e1.type = t1b;
7929 }
7930 else
7931 {
7932 exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7933 return setError();
7934 }
7935
7936 /* Run semantic on lwr and upr.
7937 */
7938 Scope* scx = sc;
7939 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7940 {
7941 // Create scope for 'length' variable
7942 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7943 sym.parent = sc.scopesym;
7944 sc = sc.push(sym);
7945 }
7946 if (exp.lwr)
7947 {
7948 if (t1b.ty == Ttuple)
7949 sc = sc.startCTFE();
7950 exp.lwr = exp.lwr.expressionSemantic(sc);
7951 exp.lwr = resolveProperties(sc, exp.lwr);
7952 if (t1b.ty == Ttuple)
7953 sc = sc.endCTFE();
7954 exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7955 }
7956 if (exp.upr)
7957 {
7958 if (t1b.ty == Ttuple)
7959 sc = sc.startCTFE();
7960 exp.upr = exp.upr.expressionSemantic(sc);
7961 exp.upr = resolveProperties(sc, exp.upr);
7962 if (t1b.ty == Ttuple)
7963 sc = sc.endCTFE();
7964 exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7965 }
7966 if (sc != scx)
7967 sc = sc.pop();
7968 if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7969 return setError();
7970
7971 if (t1b.ty == Ttuple)
7972 {
7973 exp.lwr = exp.lwr.ctfeInterpret();
7974 exp.upr = exp.upr.ctfeInterpret();
7975 uinteger_t i1 = exp.lwr.toUInteger();
7976 uinteger_t i2 = exp.upr.toUInteger();
7977
7978 TupleExp te;
7979 TypeTuple tup;
7980 size_t length;
7981 if (exp.e1.op == EXP.tuple) // slicing an expression tuple
7982 {
7983 te = cast(TupleExp)exp.e1;
7984 tup = null;
7985 length = te.exps.length;
7986 }
7987 else if (exp.e1.op == EXP.type) // slicing a type tuple
7988 {
7989 te = null;
7990 tup = cast(TypeTuple)t1b;
7991 length = Parameter.dim(tup.arguments);
7992 }
7993 else
7994 assert(0);
7995
7996 if (i2 < i1 || length < i2)
7997 {
7998 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7999 return setError();
8000 }
8001
8002 size_t j1 = cast(size_t)i1;
8003 size_t j2 = cast(size_t)i2;
8004 Expression e;
8005 if (exp.e1.op == EXP.tuple)
8006 {
8007 auto exps = new Expressions(j2 - j1);
8008 for (size_t i = 0; i < j2 - j1; i++)
8009 {
8010 (*exps)[i] = (*te.exps)[j1 + i];
8011 }
8012 e = new TupleExp(exp.loc, te.e0, exps);
8013 }
8014 else
8015 {
8016 auto args = new Parameters();
8017 args.reserve(j2 - j1);
8018 for (size_t i = j1; i < j2; i++)
8019 {
8020 Parameter arg = Parameter.getNth(tup.arguments, i);
8021 args.push(arg);
8022 }
8023 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
8024 }
8025 e = e.expressionSemantic(sc);
8026 result = e;
8027 return;
8028 }
8029
8030 exp.type = t1b.nextOf().arrayOf();
8031 // Allow typedef[] -> typedef[]
8032 if (exp.type.equals(t1b))
8033 exp.type = exp.e1.type;
8034
8035 // We might know $ now
8036 setLengthVarIfKnown(exp.lengthVar, t1b);
8037
8038 if (exp.lwr && exp.upr)
8039 {
8040 exp.lwr = exp.lwr.optimize(WANTvalue);
8041 exp.upr = exp.upr.optimize(WANTvalue);
8042
8043 IntRange lwrRange = getIntRange(exp.lwr);
8044 IntRange uprRange = getIntRange(exp.upr);
8045
8046 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8047 {
8048 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8049 el = el.expressionSemantic(sc);
8050 el = el.optimize(WANTvalue);
8051 if (el.op == EXP.int64)
8052 {
8053 // Array length is known at compile-time. Upper is in bounds if it fits length.
8054 dinteger_t length = el.toInteger();
8055 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
8056 exp.upperIsInBounds = bounds.contains(uprRange);
8057 }
8058 else if (exp.upr.op == EXP.int64 && exp.upr.toInteger() == 0)
8059 {
8060 // Upper slice expression is '0'. Value is always in bounds.
8061 exp.upperIsInBounds = true;
8062 }
8063 else if (exp.upr.op == EXP.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
8064 {
8065 // Upper slice expression is '$'. Value is always in bounds.
8066 exp.upperIsInBounds = true;
8067 }
8068 }
8069 else if (t1b.ty == Tpointer)
8070 {
8071 exp.upperIsInBounds = true;
8072 }
8073 else
8074 assert(0);
8075
8076 exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
8077
8078 //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
8079 }
8080
8081 result = exp;
8082 }
8083
8084 override void visit(ArrayLengthExp e)
8085 {
8086 static if (LOGSEMANTIC)
8087 {
8088 printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
8089 }
8090 if (e.type)
8091 {
8092 result = e;
8093 return;
8094 }
8095
8096 if (Expression ex = unaSemantic(e, sc))
8097 {
8098 result = ex;
8099 return;
8100 }
8101 e.e1 = resolveProperties(sc, e.e1);
8102
8103 e.type = Type.tsize_t;
8104 result = e;
8105 }
8106
8107 override void visit(ArrayExp exp)
8108 {
8109 static if (LOGSEMANTIC)
8110 {
8111 printf("ArrayExp::semantic('%s')\n", exp.toChars());
8112 }
8113 assert(!exp.type);
8114
8115 if (sc.flags & SCOPE.Cfile)
8116 {
8117 /* See if need to rewrite the AST because of cast/call ambiguity
8118 */
8119 if (auto e = castCallAmbiguity(exp, sc))
8120 {
8121 result = expressionSemantic(e, sc);
8122 return;
8123 }
8124 }
8125
8126 result = exp.carraySemantic(sc); // C semantics
8127 if (result)
8128 return;
8129
8130 Expression e = exp.op_overload(sc);
8131 if (e)
8132 {
8133 result = e;
8134 return;
8135 }
8136
8137 if (isAggregate(exp.e1.type))
8138 exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
8139 else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8140 exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
8141 else if (isIndexableNonAggregate(exp.e1.type))
8142 exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
8143 else
8144 exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
8145
8146 result = ErrorExp.get();
8147 }
8148
8149 override void visit(DotExp exp)
8150 {
8151 static if (LOGSEMANTIC)
8152 {
8153 printf("DotExp::semantic('%s')\n", exp.toChars());
8154 if (exp.type)
8155 printf("\ttype = %s\n", exp.type.toChars());
8156 }
8157 exp.e1 = exp.e1.expressionSemantic(sc);
8158 exp.e2 = exp.e2.expressionSemantic(sc);
8159
8160 if (exp.e1.op == EXP.type)
8161 {
8162 result = exp.e2;
8163 return;
8164 }
8165 if (exp.e2.op == EXP.type)
8166 {
8167 result = exp.e2;
8168 return;
8169 }
8170 if (auto te = exp.e2.isTemplateExp())
8171 {
8172 Expression e = new DotTemplateExp(exp.loc, exp.e1, te.td);
8173 result = e.expressionSemantic(sc);
8174 return;
8175 }
8176 if (!exp.type)
8177 exp.type = exp.e2.type;
8178 result = exp;
8179 }
8180
8181 override void visit(CommaExp e)
8182 {
8183 //printf("Semantic.CommaExp() %s\n", e.toChars());
8184 if (e.type)
8185 {
8186 result = e;
8187 return;
8188 }
8189
8190 // Allow `((a,b),(x,y))`
8191 if (e.allowCommaExp)
8192 {
8193 CommaExp.allow(e.e1);
8194 CommaExp.allow(e.e2);
8195 }
8196
8197 if (Expression ex = binSemanticProp(e, sc))
8198 {
8199 result = ex;
8200 return;
8201 }
8202 e.e1 = e.e1.addDtorHook(sc);
8203
8204 if (checkNonAssignmentArrayOp(e.e1))
8205 return setError();
8206
8207 // Comma expressions trigger this conversion
8208 e.e2 = e.e2.arrayFuncConv(sc);
8209
8210 e.type = e.e2.type;
8211 result = e;
8212
8213 if (sc.flags & SCOPE.Cfile)
8214 return;
8215
8216 if (e.type is Type.tvoid)
8217 {
8218 checkMustUse(e.e1, sc);
8219 discardValue(e.e1);
8220 }
8221 else if (!e.allowCommaExp && !e.isGenerated)
8222 e.error("using the result of a comma expression is not allowed");
8223 }
8224
8225 override void visit(IntervalExp e)
8226 {
8227 static if (LOGSEMANTIC)
8228 {
8229 printf("IntervalExp::semantic('%s')\n", e.toChars());
8230 }
8231 if (e.type)
8232 {
8233 result = e;
8234 return;
8235 }
8236
8237 Expression le = e.lwr;
8238 le = le.expressionSemantic(sc);
8239 le = resolveProperties(sc, le);
8240
8241 Expression ue = e.upr;
8242 ue = ue.expressionSemantic(sc);
8243 ue = resolveProperties(sc, ue);
8244
8245 if (le.op == EXP.error)
8246 {
8247 result = le;
8248 return;
8249 }
8250 if (ue.op == EXP.error)
8251 {
8252 result = ue;
8253 return;
8254 }
8255
8256 e.lwr = le;
8257 e.upr = ue;
8258
8259 e.type = Type.tvoid;
8260 result = e;
8261 }
8262
8263 override void visit(DelegatePtrExp e)
8264 {
8265 static if (LOGSEMANTIC)
8266 {
8267 printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
8268 }
8269 if (!e.type)
8270 {
8271 unaSemantic(e, sc);
8272 e.e1 = resolveProperties(sc, e.e1);
8273
8274 if (e.e1.op == EXP.error)
8275 {
8276 result = e.e1;
8277 return;
8278 }
8279 e.type = Type.tvoidptr;
8280 }
8281 result = e;
8282 }
8283
8284 override void visit(DelegateFuncptrExp e)
8285 {
8286 static if (LOGSEMANTIC)
8287 {
8288 printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
8289 }
8290 if (!e.type)
8291 {
8292 unaSemantic(e, sc);
8293 e.e1 = resolveProperties(sc, e.e1);
8294 if (e.e1.op == EXP.error)
8295 {
8296 result = e.e1;
8297 return;
8298 }
8299 e.type = e.e1.type.nextOf().pointerTo();
8300 }
8301 result = e;
8302 }
8303
8304 override void visit(IndexExp exp)
8305 {
8306 static if (LOGSEMANTIC)
8307 {
8308 printf("IndexExp::semantic('%s')\n", exp.toChars());
8309 }
8310 if (exp.type)
8311 {
8312 result = exp;
8313 return;
8314 }
8315
8316 // operator overloading should be handled in ArrayExp already.
8317 if (!exp.e1.type)
8318 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
8319 assert(exp.e1.type); // semantic() should already be run on it
8320 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8321 {
8322 exp.e2 = exp.e2.expressionSemantic(sc);
8323 exp.e2 = resolveProperties(sc, exp.e2);
8324 Type nt;
8325 if (exp.e2.op == EXP.type)
8326 nt = new TypeAArray(exp.e1.type, exp.e2.type);
8327 else
8328 nt = new TypeSArray(exp.e1.type, exp.e2);
8329 Expression e = new TypeExp(exp.loc, nt);
8330 result = e.expressionSemantic(sc);
8331 return;
8332 }
8333 if (exp.e1.op == EXP.error)
8334 {
8335 result = exp.e1;
8336 return;
8337 }
8338 if (exp.e1.type.ty == Terror)
8339 return setError();
8340
8341 // Note that unlike C we do not implement the int[ptr]
8342
8343 Type t1b = exp.e1.type.toBasetype();
8344
8345 if (t1b.ty == Tvector)
8346 {
8347 // Convert e1 to corresponding static array
8348 TypeVector tv1 = cast(TypeVector)t1b;
8349 t1b = tv1.basetype;
8350 t1b = t1b.castMod(tv1.mod);
8351 exp.e1.type = t1b;
8352 }
8353 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8354 {
8355 if (!checkAddressable(exp, sc))
8356 return setError();
8357 }
8358
8359 /* Run semantic on e2
8360 */
8361 Scope* scx = sc;
8362 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
8363 {
8364 // Create scope for 'length' variable
8365 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
8366 sym.parent = sc.scopesym;
8367 sc = sc.push(sym);
8368 }
8369 if (t1b.ty == Ttuple)
8370 sc = sc.startCTFE();
8371 exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
8372 exp.e2 = resolveProperties(sc, exp.e2);
8373 if (t1b.ty == Ttuple)
8374 sc = sc.endCTFE();
8375 if (exp.e2.op == EXP.tuple)
8376 {
8377 TupleExp te = cast(TupleExp)exp.e2;
8378 if (te.exps && te.exps.length == 1)
8379 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
8380 }
8381 if (sc != scx)
8382 sc = sc.pop();
8383 if (exp.e2.type == Type.terror)
8384 return setError();
8385
8386 if (checkNonAssignmentArrayOp(exp.e1))
8387 return setError();
8388
8389 switch (t1b.ty)
8390 {
8391 case Tpointer:
8392 if (t1b.isPtrToFunction())
8393 {
8394 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
8395 return setError();
8396 }
8397 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8398 if (exp.e2.type == Type.terror)
8399 return setError();
8400 exp.e2 = exp.e2.optimize(WANTvalue);
8401 if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
8402 {
8403 }
8404 else if (sc.setUnsafe(false, exp.loc, "`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1))
8405 {
8406 return setError();
8407 }
8408 exp.type = (cast(TypeNext)t1b).next;
8409 break;
8410
8411 case Tarray:
8412 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8413 if (exp.e2.type == Type.terror)
8414 return setError();
8415 exp.type = (cast(TypeNext)t1b).next;
8416 break;
8417
8418 case Tsarray:
8419 {
8420 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8421 if (exp.e2.type == Type.terror)
8422 return setError();
8423 exp.type = t1b.nextOf();
8424 break;
8425 }
8426 case Taarray:
8427 {
8428 TypeAArray taa = cast(TypeAArray)t1b;
8429 /* We can skip the implicit conversion if they differ only by
8430 * constness
8431 * https://issues.dlang.org/show_bug.cgi?id=2684
8432 * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8433 */
8434 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8435 {
8436 exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8437 if (exp.e2.type == Type.terror)
8438 return setError();
8439 }
8440
8441 semanticTypeInfo(sc, taa);
8442 checkNewEscape(sc, exp.e2, false);
8443
8444 exp.type = taa.next;
8445 break;
8446 }
8447 case Ttuple:
8448 {
8449 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8450 if (exp.e2.type == Type.terror)
8451 return setError();
8452
8453 exp.e2 = exp.e2.ctfeInterpret();
8454 uinteger_t index = exp.e2.toUInteger();
8455
8456 TupleExp te;
8457 TypeTuple tup;
8458 size_t length;
8459 if (exp.e1.op == EXP.tuple)
8460 {
8461 te = cast(TupleExp)exp.e1;
8462 tup = null;
8463 length = te.exps.length;
8464 }
8465 else if (exp.e1.op == EXP.type)
8466 {
8467 te = null;
8468 tup = cast(TypeTuple)t1b;
8469 length = Parameter.dim(tup.arguments);
8470 }
8471 else
8472 assert(0);
8473
8474 if (length <= index)
8475 {
8476 exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8477 return setError();
8478 }
8479 Expression e;
8480 if (exp.e1.op == EXP.tuple)
8481 {
8482 e = (*te.exps)[cast(size_t)index];
8483 e = Expression.combine(te.e0, e);
8484 }
8485 else
8486 e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8487 result = e;
8488 return;
8489 }
8490 default:
8491 exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8492 return setError();
8493 }
8494
8495 // We might know $ now
8496 setLengthVarIfKnown(exp.lengthVar, t1b);
8497
8498 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8499 {
8500 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8501 el = el.expressionSemantic(sc);
8502 el = el.optimize(WANTvalue);
8503 if (el.op == EXP.int64)
8504 {
8505 exp.e2 = exp.e2.optimize(WANTvalue);
8506 dinteger_t length = el.toInteger();
8507 if (length)
8508 {
8509 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8510 // OR it in, because it might already be set for C array indexing
8511 exp.indexIsInBounds |= bounds.contains(getIntRange(exp.e2));
8512 }
8513 else if (sc.flags & SCOPE.Cfile && t1b.ty == Tsarray)
8514 {
8515 if (auto ve = exp.e1.isVarExp())
8516 {
8517 /* Rewrite 0-length C array ve[exp.e2] as *(ve + exp.e2)
8518 */
8519 auto vp = ve.castTo(sc, t1b.isTypeSArray().next.pointerTo());
8520 auto e = new AddExp(exp.loc, vp, exp.e2);
8521 auto pe = new PtrExp(exp.loc, e);
8522 result = pe.expressionSemantic(sc).optimize(WANTvalue);
8523 return;
8524 }
8525 }
8526 }
8527 }
8528
8529 result = exp;
8530 }
8531
8532 override void visit(PostExp exp)
8533 {
8534 static if (LOGSEMANTIC)
8535 {
8536 printf("PostExp::semantic('%s')\n", exp.toChars());
8537 }
8538 if (exp.type)
8539 {
8540 result = exp;
8541 return;
8542 }
8543
8544 if (sc.flags & SCOPE.Cfile)
8545 {
8546 /* See if need to rewrite the AST because of cast/call ambiguity
8547 */
8548 if (auto e = castCallAmbiguity(exp, sc))
8549 {
8550 result = expressionSemantic(e, sc);
8551 return;
8552 }
8553 }
8554
8555 if (Expression ex = binSemantic(exp, sc))
8556 {
8557 result = ex;
8558 return;
8559 }
8560 Expression e1x = resolveProperties(sc, exp.e1);
8561 if (e1x.op == EXP.error)
8562 {
8563 result = e1x;
8564 return;
8565 }
8566 exp.e1 = e1x;
8567
8568 Expression e = exp.op_overload(sc);
8569 if (e)
8570 {
8571 result = e;
8572 return;
8573 }
8574
8575 if (exp.e1.checkReadModifyWrite(exp.op))
8576 return setError();
8577
8578 if (exp.e1.op == EXP.slice)
8579 {
8580 const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
8581 exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8582 return setError();
8583 }
8584
8585 Type t1 = exp.e1.type.toBasetype();
8586 if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == EXP.arrayLength)
8587 {
8588 /* Check for operator overloading,
8589 * but rewrite in terms of ++e instead of e++
8590 */
8591
8592 /* If e1 is not trivial, take a reference to it
8593 */
8594 Expression de = null;
8595 if (exp.e1.op != EXP.variable && exp.e1.op != EXP.arrayLength)
8596 {
8597 // ref v = e1;
8598 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8599 de = new DeclarationExp(exp.loc, v);
8600 exp.e1 = new VarExp(exp.e1.loc, v);
8601 }
8602
8603 /* Rewrite as:
8604 * auto tmp = e1; ++e1; tmp
8605 */
8606 auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8607 Expression ea = new DeclarationExp(exp.loc, tmp);
8608
8609 Expression eb = exp.e1.syntaxCopy();
8610 eb = new PreExp(exp.op == EXP.plusPlus ? EXP.prePlusPlus : EXP.preMinusMinus, exp.loc, eb);
8611
8612 Expression ec = new VarExp(exp.loc, tmp);
8613
8614 // Combine de,ea,eb,ec
8615 if (de)
8616 ea = new CommaExp(exp.loc, de, ea);
8617 e = new CommaExp(exp.loc, ea, eb);
8618 e = new CommaExp(exp.loc, e, ec);
8619 e = e.expressionSemantic(sc);
8620 result = e;
8621 return;
8622 }
8623
8624 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8625 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
8626
8627 e = exp;
8628 if (exp.e1.checkScalar() ||
8629 exp.e1.checkSharedAccess(sc))
8630 return setError();
8631 if (exp.e1.checkNoBool())
8632 return setError();
8633
8634 if (exp.e1.type.ty == Tpointer)
8635 e = scaleFactor(exp, sc);
8636 else
8637 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8638 e.type = exp.e1.type;
8639 result = e;
8640 }
8641
8642 override void visit(PreExp exp)
8643 {
8644 Expression e = exp.op_overload(sc);
8645 // printf("PreExp::semantic('%s')\n", toChars());
8646 if (e)
8647 {
8648 result = e;
8649 return;
8650 }
8651
8652 // Rewrite as e1+=1 or e1-=1
8653 if (exp.op == EXP.prePlusPlus)
8654 e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8655 else
8656 e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8657 result = e.expressionSemantic(sc);
8658 }
8659
8660 /*
8661 * Get the expression initializer for a specific struct
8662 *
8663 * Params:
8664 * sd = the struct for which the expression initializer is needed
8665 * loc = the location of the initializer
8666 * sc = the scope where the expression is located
8667 * t = the type of the expression
8668 *
8669 * Returns:
8670 * The expression initializer or error expression if any errors occured
8671 */
8672 private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8673 {
8674 if (sd.zeroInit && !sd.isNested())
8675 {
8676 // https://issues.dlang.org/show_bug.cgi?id=14606
8677 // Always use BlitExp for the special expression: (struct = 0)
8678 return IntegerExp.literal!0;
8679 }
8680
8681 if (sd.isNested())
8682 {
8683 auto sle = new StructLiteralExp(loc, sd, null, t);
8684 if (!sd.fill(loc, *sle.elements, true))
8685 return ErrorExp.get();
8686 if (checkFrameAccess(loc, sc, sd, sle.elements.length))
8687 return ErrorExp.get();
8688
8689 sle.type = t;
8690 return sle;
8691 }
8692
8693 return t.defaultInit(loc);
8694 }
8695
8696 override void visit(AssignExp exp)
8697 {
8698 static if (LOGSEMANTIC)
8699 {
8700 if (exp.op == EXP.blit) printf("BlitExp.toElem('%s')\n", exp.toChars());
8701 if (exp.op == EXP.assign) printf("AssignExp.toElem('%s')\n", exp.toChars());
8702 if (exp.op == EXP.construct) printf("ConstructExp.toElem('%s')\n", exp.toChars());
8703 }
8704
8705 void setResult(Expression e, int line = __LINE__)
8706 {
8707 //printf("line %d\n", line);
8708 result = e;
8709 }
8710
8711 if (exp.type)
8712 {
8713 return setResult(exp);
8714 }
8715
8716 Expression e1old = exp.e1;
8717
8718 if (auto e2comma = exp.e2.isCommaExp())
8719 {
8720 if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
8721 exp.error("using the result of a comma expression is not allowed");
8722
8723 /* Rewrite to get rid of the comma from rvalue
8724 * e1=(e0,e2) => e0,(e1=e2)
8725 */
8726 Expression e0;
8727 exp.e2 = Expression.extractLast(e2comma, e0);
8728 Expression e = Expression.combine(e0, exp);
8729 return setResult(e.expressionSemantic(sc));
8730 }
8731
8732 /* Look for operator overloading of a[arguments] = e2.
8733 * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8734 * converted to unary operator overloading already.
8735 */
8736 if (auto ae = exp.e1.isArrayExp())
8737 {
8738 Expression res;
8739
8740 ae.e1 = ae.e1.expressionSemantic(sc);
8741 ae.e1 = resolveProperties(sc, ae.e1);
8742 Expression ae1old = ae.e1;
8743
8744 const(bool) maybeSlice =
8745 (ae.arguments.length == 0 ||
8746 ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
8747
8748 IntervalExp ie = null;
8749 if (maybeSlice && ae.arguments.length)
8750 {
8751 assert((*ae.arguments)[0].op == EXP.interval);
8752 ie = cast(IntervalExp)(*ae.arguments)[0];
8753 }
8754 while (true)
8755 {
8756 if (ae.e1.op == EXP.error)
8757 return setResult(ae.e1);
8758
8759 Expression e0 = null;
8760 Expression ae1save = ae.e1;
8761 ae.lengthVar = null;
8762
8763 Type t1b = ae.e1.type.toBasetype();
8764 AggregateDeclaration ad = isAggregate(t1b);
8765 if (!ad)
8766 break;
8767 if (search_function(ad, Id.indexass))
8768 {
8769 // Deal with $
8770 res = resolveOpDollar(sc, ae, &e0);
8771 if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8772 goto Lfallback;
8773 if (res.op == EXP.error)
8774 return setResult(res);
8775
8776 res = exp.e2.expressionSemantic(sc);
8777 if (res.op == EXP.error)
8778 return setResult(res);
8779 exp.e2 = res;
8780
8781 /* Rewrite (a[arguments] = e2) as:
8782 * a.opIndexAssign(e2, arguments)
8783 */
8784 Expressions* a = ae.arguments.copy();
8785 a.insert(0, exp.e2);
8786 res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8787 res = new CallExp(exp.loc, res, a);
8788 if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8789 res = res.trySemantic(sc);
8790 else
8791 res = res.expressionSemantic(sc);
8792 if (res)
8793 return setResult(Expression.combine(e0, res));
8794 }
8795
8796 Lfallback:
8797 if (maybeSlice && search_function(ad, Id.sliceass))
8798 {
8799 // Deal with $
8800 res = resolveOpDollar(sc, ae, ie, &e0);
8801 if (res.op == EXP.error)
8802 return setResult(res);
8803
8804 res = exp.e2.expressionSemantic(sc);
8805 if (res.op == EXP.error)
8806 return setResult(res);
8807
8808 exp.e2 = res;
8809
8810 /* Rewrite (a[i..j] = e2) as:
8811 * a.opSliceAssign(e2, i, j)
8812 */
8813 auto a = new Expressions();
8814 a.push(exp.e2);
8815 if (ie)
8816 {
8817 a.push(ie.lwr);
8818 a.push(ie.upr);
8819 }
8820 res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8821 res = new CallExp(exp.loc, res, a);
8822 res = res.expressionSemantic(sc);
8823 return setResult(Expression.combine(e0, res));
8824 }
8825
8826 // No operator overloading member function found yet, but
8827 // there might be an alias this to try.
8828 if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
8829 {
8830 /* Rewrite (a[arguments] op e2) as:
8831 * a.aliasthis[arguments] op e2
8832 */
8833 ae.e1 = resolveAliasThis(sc, ae1save, true);
8834 if (ae.e1)
8835 continue;
8836 }
8837 break;
8838 }
8839 ae.e1 = ae1old; // recovery
8840 ae.lengthVar = null;
8841 }
8842
8843 /* Run this.e1 semantic.
8844 */
8845 {
8846 Expression e1x = exp.e1;
8847
8848 /* With UFCS, e.f = value
8849 * Could mean:
8850 * .f(e, value)
8851 * or:
8852 * .f(e) = value
8853 */
8854 if (auto dti = e1x.isDotTemplateInstanceExp())
8855 {
8856 Expression e = dti.dotTemplateSemanticProp(sc, 1);
8857 if (!e)
8858 {
8859 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8860 }
8861
8862 e1x = e;
8863 }
8864 else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
8865 {
8866 auto die = e1x.isDotIdExp();
8867 e1x = fieldLookup(die.e1, sc, die.ident);
8868 }
8869 else if (auto die = e1x.isDotIdExp())
8870 {
8871 Expression e = die.dotIdSemanticProp(sc, 1);
8872 if (e && isDotOpDispatch(e))
8873 {
8874 /* https://issues.dlang.org/show_bug.cgi?id=19687
8875 *
8876 * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8877 * but that call is done with gagged errors. That is the only time when
8878 * semantic gets ran on e2, that is why the error never gets to be printed.
8879 * In order to make sure that UFCS is tried with correct parameters, e2
8880 * needs to have semantic ran on it.
8881 */
8882 auto ode = e;
8883 exp.e2 = exp.e2.expressionSemantic(sc);
8884 uint errors = global.startGagging();
8885 e = resolvePropertiesX(sc, e, exp.e2);
8886 // Any error or if 'e' is not resolved, go to UFCS
8887 if (global.endGagging(errors) || e is ode)
8888 e = null; /* fall down to UFCS */
8889 else
8890 return setResult(e);
8891 }
8892 if (!e)
8893 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8894 e1x = e;
8895 }
8896 else
8897 {
8898 if (auto se = e1x.isSliceExp())
8899 se.arrayop = true;
8900
8901 e1x = e1x.expressionSemantic(sc);
8902 }
8903
8904 /* We have f = value.
8905 * Could mean:
8906 * f(value)
8907 * or:
8908 * f() = value
8909 */
8910 if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8911 return setResult(e);
8912
8913 if (e1x.checkRightThis(sc))
8914 {
8915 return setError();
8916 }
8917 exp.e1 = e1x;
8918 assert(exp.e1.type);
8919 }
8920 Type t1 = exp.e1.type.isTypeEnum() ? exp.e1.type : exp.e1.type.toBasetype();
8921
8922 /* Run this.e2 semantic.
8923 * Different from other binary expressions, the analysis of e2
8924 * depends on the result of e1 in assignments.
8925 */
8926 {
8927 Expression e2x = inferType(exp.e2, t1.baseElemOf());
8928 e2x = e2x.expressionSemantic(sc);
8929 if (!t1.isTypeSArray())
8930 e2x = e2x.arrayFuncConv(sc);
8931 e2x = resolveProperties(sc, e2x);
8932 if (e2x.op == EXP.type)
8933 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8934 if (e2x.op == EXP.error)
8935 return setResult(e2x);
8936 // We delay checking the value for structs/classes as these might have
8937 // an opAssign defined.
8938 if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
8939 e2x.checkSharedAccess(sc))
8940 return setError();
8941
8942 auto etmp = checkNoreturnVarAccess(e2x);
8943 if (etmp != e2x)
8944 return setResult(etmp);
8945
8946 exp.e2 = e2x;
8947 }
8948
8949 /* Rewrite tuple assignment as a tuple of assignments.
8950 */
8951 {
8952 Expression e2x = exp.e2;
8953
8954 Ltupleassign:
8955 if (exp.e1.op == EXP.tuple && e2x.op == EXP.tuple)
8956 {
8957 TupleExp tup1 = cast(TupleExp)exp.e1;
8958 TupleExp tup2 = cast(TupleExp)e2x;
8959 size_t dim = tup1.exps.length;
8960 Expression e = null;
8961 if (dim != tup2.exps.length)
8962 {
8963 exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
8964 return setError();
8965 }
8966 if (dim == 0)
8967 {
8968 e = IntegerExp.literal!0;
8969 e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8970 e = Expression.combine(tup1.e0, tup2.e0, e);
8971 }
8972 else
8973 {
8974 auto exps = new Expressions(dim);
8975 for (size_t i = 0; i < dim; i++)
8976 {
8977 Expression ex1 = (*tup1.exps)[i];
8978 Expression ex2 = (*tup2.exps)[i];
8979 (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8980 }
8981 e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8982 }
8983 return setResult(e.expressionSemantic(sc));
8984 }
8985
8986 /* Look for form: e1 = e2.aliasthis.
8987 */
8988 if (exp.e1.op == EXP.tuple)
8989 {
8990 TupleDeclaration td = isAliasThisTuple(e2x);
8991 if (!td)
8992 goto Lnomatch;
8993
8994 assert(exp.e1.type.ty == Ttuple);
8995 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8996
8997 Expression e0;
8998 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8999
9000 auto iexps = new Expressions();
9001 iexps.push(ev);
9002 for (size_t u = 0; u < iexps.length; u++)
9003 {
9004 Lexpand:
9005 Expression e = (*iexps)[u];
9006
9007 Parameter arg = Parameter.getNth(tt.arguments, u);
9008 //printf("[%d] iexps.length = %d, ", u, iexps.length);
9009 //printf("e = (%s %s, %s), ", Token.toChars[e.op], e.toChars(), e.type.toChars());
9010 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
9011
9012 if (!arg || !e.type.implicitConvTo(arg.type))
9013 {
9014 // expand initializer to tuple
9015 if (expandAliasThisTuples(iexps, u) != -1)
9016 {
9017 if (iexps.length <= u)
9018 break;
9019 goto Lexpand;
9020 }
9021 goto Lnomatch;
9022 }
9023 }
9024 e2x = new TupleExp(e2x.loc, e0, iexps);
9025 e2x = e2x.expressionSemantic(sc);
9026 if (e2x.op == EXP.error)
9027 {
9028 result = e2x;
9029 return;
9030 }
9031 // Do not need to overwrite this.e2
9032 goto Ltupleassign;
9033 }
9034 Lnomatch:
9035 }
9036
9037 /* Inside constructor, if this is the first assignment of object field,
9038 * rewrite this to initializing the field.
9039 */
9040 if (exp.op == EXP.assign
9041 && exp.e1.checkModifiable(sc) == Modifiable.initialization)
9042 {
9043 //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
9044 auto t = exp.type;
9045 exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
9046 exp.type = t;
9047
9048 // https://issues.dlang.org/show_bug.cgi?id=13515
9049 // set Index::modifiable flag for complex AA element initialization
9050 if (auto ie1 = exp.e1.isIndexExp())
9051 {
9052 Expression e1x = ie1.markSettingAAElem();
9053 if (e1x.op == EXP.error)
9054 {
9055 result = e1x;
9056 return;
9057 }
9058 }
9059 }
9060 else if (exp.op == EXP.construct && exp.e1.op == EXP.variable &&
9061 (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
9062 {
9063 exp.memset = MemorySet.referenceInit;
9064 }
9065
9066 if (exp.op == EXP.assign) // skip EXP.blit and EXP.construct, which are initializations
9067 {
9068 exp.e1.checkSharedAccess(sc);
9069 checkUnsafeAccess(sc, exp.e1, false, true);
9070 }
9071
9072 checkUnsafeAccess(sc, exp.e2, true, true); // Initializer must always be checked
9073
9074 /* If it is an assignment from a 'foreign' type,
9075 * check for operator overloading.
9076 */
9077 if (exp.memset == MemorySet.referenceInit)
9078 {
9079 // If this is an initialization of a reference,
9080 // do nothing
9081 }
9082 else if (t1.ty == Tstruct)
9083 {
9084 auto e1x = exp.e1;
9085 auto e2x = exp.e2;
9086 auto sd = (cast(TypeStruct)t1).sym;
9087
9088 if (exp.op == EXP.construct)
9089 {
9090 Type t2 = e2x.type.toBasetype();
9091 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
9092 {
9093 sd.size(exp.loc);
9094 if (sd.sizeok != Sizeok.done)
9095 return setError();
9096 if (!sd.ctor)
9097 sd.ctor = sd.searchCtor();
9098
9099 // https://issues.dlang.org/show_bug.cgi?id=15661
9100 // Look for the form from last of comma chain.
9101 auto e2y = lastComma(e2x);
9102
9103 CallExp ce = (e2y.op == EXP.call) ? cast(CallExp)e2y : null;
9104 DotVarExp dve = (ce && ce.e1.op == EXP.dotVariable)
9105 ? cast(DotVarExp)ce.e1 : null;
9106 if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
9107 // https://issues.dlang.org/show_bug.cgi?id=19389
9108 dve.e1.op != EXP.dotVariable &&
9109 e2y.type.implicitConvTo(t1))
9110 {
9111 /* Look for form of constructor call which is:
9112 * __ctmp.ctor(arguments...)
9113 */
9114
9115 /* Before calling the constructor, initialize
9116 * variable with a bit copy of the default
9117 * initializer
9118 */
9119 Expression einit = getInitExp(sd, exp.loc, sc, t1);
9120 if (einit.op == EXP.error)
9121 {
9122 result = einit;
9123 return;
9124 }
9125
9126 auto ae = new BlitExp(exp.loc, exp.e1, einit);
9127 ae.type = e1x.type;
9128
9129 /* Replace __ctmp being constructed with e1.
9130 * We need to copy constructor call expression,
9131 * because it may be used in other place.
9132 */
9133 auto dvx = cast(DotVarExp)dve.copy();
9134 dvx.e1 = e1x;
9135 auto cx = cast(CallExp)ce.copy();
9136 cx.e1 = dvx;
9137 if (checkConstructorEscape(sc, cx, false))
9138 return setError();
9139
9140 Expression e0;
9141 Expression.extractLast(e2x, e0);
9142
9143 auto e = Expression.combine(e0, ae, cx);
9144 e = e.expressionSemantic(sc);
9145 result = e;
9146 return;
9147 }
9148 // https://issues.dlang.org/show_bug.cgi?id=21586
9149 // Rewrite CondExp or e1 will miss direct construction, e.g.
9150 // e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
9151 // a temporary created and an extra destructor call.
9152 // AST will be rewritten to:
9153 // a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
9154 if (e2x.op == EXP.question)
9155 {
9156 /* Rewrite as:
9157 * a ? e1 = b : e1 = c;
9158 */
9159 CondExp econd = cast(CondExp)e2x;
9160 Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
9161 Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
9162 Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
9163 result = e.expressionSemantic(sc);
9164 return;
9165 }
9166 if (sd.postblit || sd.hasCopyCtor)
9167 {
9168 /* We have a copy constructor for this
9169 */
9170
9171 if (e2x.isLvalue())
9172 {
9173 if (sd.hasCopyCtor)
9174 {
9175 /* Rewrite as:
9176 * e1 = init, e1.copyCtor(e2);
9177 */
9178 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
9179 einit.type = e1x.type;
9180
9181 Expression e;
9182 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9183 e = new CallExp(exp.loc, e, e2x);
9184 e = new CommaExp(exp.loc, einit, e);
9185
9186 //printf("e: %s\n", e.toChars());
9187
9188 result = e.expressionSemantic(sc);
9189 return;
9190 }
9191 else
9192 {
9193 if (!e2x.type.implicitConvTo(e1x.type))
9194 {
9195 exp.error("conversion error from `%s` to `%s`",
9196 e2x.type.toChars(), e1x.type.toChars());
9197 return setError();
9198 }
9199
9200 /* Rewrite as:
9201 * (e1 = e2).postblit();
9202 *
9203 * Blit assignment e1 = e2 returns a reference to the original e1,
9204 * then call the postblit on it.
9205 */
9206 Expression e = e1x.copy();
9207 e.type = e.type.mutableOf();
9208 if (e.type.isShared && !sd.type.isShared)
9209 e.type = e.type.unSharedOf();
9210 e = new BlitExp(exp.loc, e, e2x);
9211 e = new DotVarExp(exp.loc, e, sd.postblit, false);
9212 e = new CallExp(exp.loc, e);
9213 result = e.expressionSemantic(sc);
9214 return;
9215 }
9216 }
9217 else
9218 {
9219 /* The struct value returned from the function is transferred
9220 * so should not call the destructor on it.
9221 */
9222 e2x = valueNoDtor(e2x);
9223 }
9224 }
9225
9226 // https://issues.dlang.org/show_bug.cgi?id=19251
9227 // if e2 cannot be converted to e1.type, maybe there is an alias this
9228 if (!e2x.implicitConvTo(t1))
9229 {
9230 AggregateDeclaration ad2 = isAggregate(e2x.type);
9231 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9232 {
9233 /* Rewrite (e1 op e2) as:
9234 * (e1 op e2.aliasthis)
9235 */
9236 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9237 result = exp.expressionSemantic(sc);
9238 return;
9239 }
9240 }
9241 }
9242 else if (!e2x.implicitConvTo(t1))
9243 {
9244 sd.size(exp.loc);
9245 if (sd.sizeok != Sizeok.done)
9246 return setError();
9247 if (!sd.ctor)
9248 sd.ctor = sd.searchCtor();
9249
9250 if (sd.ctor)
9251 {
9252 /* Look for implicit constructor call
9253 * Rewrite as:
9254 * e1 = init, e1.ctor(e2)
9255 */
9256
9257 /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
9258 * Using `new` to initialize a struct object is a common mistake, but
9259 * the error message from the compiler is not very helpful in that
9260 * case. If exp.e2 is a NewExp and the type of new is the same as
9261 * the type as exp.e1 (struct in this case), then we know for sure
9262 * that the user wants to instantiate a struct. This is done to avoid
9263 * issuing an error when the user actually wants to call a constructor
9264 * which receives a class object.
9265 *
9266 * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
9267 * which receives an instance of a Foo2 class
9268 */
9269 if (exp.e2.op == EXP.new_)
9270 {
9271 auto newExp = cast(NewExp)(exp.e2);
9272 if (newExp.newtype && newExp.newtype == t1)
9273 {
9274 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
9275 newExp.toChars(), newExp.type.toChars(), t1.toChars());
9276 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
9277 return setError();
9278 }
9279 }
9280
9281 Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
9282 einit.type = e1x.type;
9283
9284 Expression e;
9285 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9286 e = new CallExp(exp.loc, e, e2x);
9287 e = new CommaExp(exp.loc, einit, e);
9288 e = e.expressionSemantic(sc);
9289 result = e;
9290 return;
9291 }
9292 if (search_function(sd, Id.call))
9293 {
9294 /* Look for static opCall
9295 * https://issues.dlang.org/show_bug.cgi?id=2702
9296 * Rewrite as:
9297 * e1 = typeof(e1).opCall(arguments)
9298 */
9299 e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
9300 e2x = new CallExp(exp.loc, e2x, exp.e2);
9301
9302 e2x = e2x.expressionSemantic(sc);
9303 e2x = resolveProperties(sc, e2x);
9304 if (e2x.op == EXP.error)
9305 {
9306 result = e2x;
9307 return;
9308 }
9309 if (e2x.checkValue() || e2x.checkSharedAccess(sc))
9310 return setError();
9311 }
9312 }
9313 else // https://issues.dlang.org/show_bug.cgi?id=11355
9314 {
9315 AggregateDeclaration ad2 = isAggregate(e2x.type);
9316 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9317 {
9318 /* Rewrite (e1 op e2) as:
9319 * (e1 op e2.aliasthis)
9320 */
9321 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9322 result = exp.expressionSemantic(sc);
9323 return;
9324 }
9325 }
9326 }
9327 else if (exp.op == EXP.assign)
9328 {
9329 if (e1x.op == EXP.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
9330 {
9331 /*
9332 * Rewrite:
9333 * aa[key] = e2;
9334 * as:
9335 * ref __aatmp = aa;
9336 * ref __aakey = key;
9337 * ref __aaval = e2;
9338 * (__aakey in __aatmp
9339 * ? __aatmp[__aakey].opAssign(__aaval)
9340 * : ConstructExp(__aatmp[__aakey], __aaval));
9341 */
9342 // ensure we keep the expr modifiable
9343 Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
9344 if (esetting.op == EXP.error)
9345 {
9346 result = esetting;
9347 return;
9348 }
9349 assert(esetting.op == EXP.index);
9350 IndexExp ie = cast(IndexExp) esetting;
9351 Type t2 = e2x.type.toBasetype();
9352
9353 Expression e0 = null;
9354 Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
9355 Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
9356 Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
9357
9358 AssignExp ae = cast(AssignExp)exp.copy();
9359 ae.e1 = new IndexExp(exp.loc, ea, ek);
9360 ae.e1 = ae.e1.expressionSemantic(sc);
9361 ae.e1 = ae.e1.optimize(WANTvalue);
9362 ae.e2 = ev;
9363 Expression e = ae.op_overload(sc);
9364 if (e)
9365 {
9366 Expression ey = null;
9367 if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
9368 {
9369 ey = ev;
9370 }
9371 else if (!ev.implicitConvTo(ie.type) && sd.ctor)
9372 {
9373 // Look for implicit constructor call
9374 // Rewrite as S().ctor(e2)
9375 ey = new StructLiteralExp(exp.loc, sd, null);
9376 ey = new DotIdExp(exp.loc, ey, Id.ctor);
9377 ey = new CallExp(exp.loc, ey, ev);
9378 ey = ey.trySemantic(sc);
9379 }
9380 if (ey)
9381 {
9382 Expression ex;
9383 ex = new IndexExp(exp.loc, ea, ek);
9384 ex = ex.expressionSemantic(sc);
9385 ex = ex.modifiableLvalue(sc, ex); // allocate new slot
9386 ex = ex.optimize(WANTvalue);
9387
9388 ey = new ConstructExp(exp.loc, ex, ey);
9389 ey = ey.expressionSemantic(sc);
9390 if (ey.op == EXP.error)
9391 {
9392 result = ey;
9393 return;
9394 }
9395 ex = e;
9396
9397 // https://issues.dlang.org/show_bug.cgi?id=14144
9398 // The whole expression should have the common type
9399 // of opAssign() return and assigned AA entry.
9400 // Even if there's no common type, expression should be typed as void.
9401 if (!typeMerge(sc, EXP.question, ex, ey))
9402 {
9403 ex = new CastExp(ex.loc, ex, Type.tvoid);
9404 ey = new CastExp(ey.loc, ey, Type.tvoid);
9405 }
9406 e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
9407 }
9408 e = Expression.combine(e0, e);
9409 e = e.expressionSemantic(sc);
9410 result = e;
9411 return;
9412 }
9413 }
9414 else
9415 {
9416 Expression e = exp.op_overload(sc);
9417 if (e)
9418 {
9419 result = e;
9420 return;
9421 }
9422 }
9423 }
9424 else
9425 assert(exp.op == EXP.blit);
9426
9427 if (e2x.checkValue())
9428 return setError();
9429
9430 exp.e1 = e1x;
9431 exp.e2 = e2x;
9432 }
9433 else if (t1.ty == Tclass)
9434 {
9435 // Disallow assignment operator overloads for same type
9436 if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
9437 {
9438 Expression e = exp.op_overload(sc);
9439 if (e)
9440 {
9441 result = e;
9442 return;
9443 }
9444 }
9445 if (exp.e2.checkValue())
9446 return setError();
9447 }
9448 else if (t1.ty == Tsarray)
9449 {
9450 // SliceExp cannot have static array type without context inference.
9451 assert(exp.e1.op != EXP.slice);
9452 Expression e1x = exp.e1;
9453 Expression e2x = exp.e2;
9454
9455 /* C strings come through as static arrays. May need to adjust the size of the
9456 * string to match the size of e1.
9457 */
9458 Type t2 = e2x.type.toBasetype();
9459 if (sc.flags & SCOPE.Cfile && e2x.isStringExp() && t2.isTypeSArray())
9460 {
9461 uinteger_t dim1 = t1.isTypeSArray().dim.toInteger();
9462 uinteger_t dim2 = t2.isTypeSArray().dim.toInteger();
9463 if (dim1 + 1 == dim2 || dim2 < dim1)
9464 {
9465 auto tsa2 = t2.isTypeSArray();
9466 auto newt = tsa2.next.sarrayOf(dim1).immutableOf();
9467 e2x = castTo(e2x, sc, newt);
9468 exp.e2 = e2x;
9469 }
9470 }
9471
9472 if (e2x.implicitConvTo(e1x.type))
9473 {
9474 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()))
9475 {
9476 if (e1x.checkPostblit(sc, t1))
9477 return setError();
9478 }
9479
9480 // e2 matches to t1 because of the implicit length match, so
9481 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9482 {
9483 // convert e1 to e1[]
9484 // e.g. e1[] = a[] + b[];
9485 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9486 sle.arrayop = true;
9487 e1x = sle.expressionSemantic(sc);
9488 }
9489 else
9490 {
9491 // convert e2 to t1 later
9492 // e.g. e1 = [1, 2, 3];
9493 }
9494 }
9495 else
9496 {
9497 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9498 {
9499 uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9500 uinteger_t dim2 = dim1;
9501 if (auto ale = e2x.isArrayLiteralExp())
9502 {
9503 dim2 = ale.elements ? ale.elements.length : 0;
9504 }
9505 else if (auto se = e2x.isSliceExp())
9506 {
9507 Type tx = toStaticArrayType(se);
9508 if (tx)
9509 dim2 = (cast(TypeSArray)tx).dim.toInteger();
9510 }
9511 if (dim1 != dim2)
9512 {
9513 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9514 return setError();
9515 }
9516 }
9517
9518 // May be block or element-wise assignment, so
9519 // convert e1 to e1[]
9520 if (exp.op != EXP.assign)
9521 {
9522 // If multidimensional static array, treat as one large array
9523 //
9524 // Find the appropriate array type depending on the assignment, e.g.
9525 // int[3] = int => int[3]
9526 // int[3][2] = int => int[6]
9527 // int[3][2] = int[] => int[3][2]
9528 // int[3][2][4] + int => int[24]
9529 // int[3][2][4] + int[] => int[3][8]
9530 ulong dim = t1.isTypeSArray().dim.toUInteger();
9531 auto type = t1.nextOf();
9532
9533 for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9534 {
9535 import core.checkedint : mulu;
9536
9537 // Accumulate skipped dimensions
9538 bool overflow = false;
9539 dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9540 if (overflow || dim >= uint.max)
9541 {
9542 // dym exceeds maximum array size
9543 exp.error("static array `%s` size overflowed to %llu",
9544 e1x.type.toChars(), cast(ulong) dim);
9545 return setError();
9546 }
9547
9548 // Move to the element type
9549 type = tsa.nextOf().toBasetype();
9550
9551 // Rewrite ex1 as a static array if a matching type was found
9552 if (e2x.implicitConvTo(type) > MATCH.nomatch)
9553 {
9554 e1x.type = type.sarrayOf(dim);
9555 break;
9556 }
9557 }
9558 }
9559 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9560 sle.arrayop = true;
9561 e1x = sle.expressionSemantic(sc);
9562 }
9563 if (e1x.op == EXP.error)
9564 return setResult(e1x);
9565 if (e2x.op == EXP.error)
9566 return setResult(e2x);
9567
9568 exp.e1 = e1x;
9569 exp.e2 = e2x;
9570 t1 = e1x.type.toBasetype();
9571 }
9572 /* Check the mutability of e1.
9573 */
9574 if (auto ale = exp.e1.isArrayLengthExp())
9575 {
9576 // e1 is not an lvalue, but we let code generator handle it
9577
9578 auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9579 if (ale1x.op == EXP.error)
9580 return setResult(ale1x);
9581 ale.e1 = ale1x;
9582
9583 Type tn = ale.e1.type.toBasetype().nextOf();
9584 checkDefCtor(ale.loc, tn);
9585
9586 Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9587 if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9588 return setError();
9589
9590 exp.e2 = exp.e2.expressionSemantic(sc);
9591 auto lc = lastComma(exp.e2);
9592 lc = lc.optimize(WANTvalue);
9593 // use slice expression when arr.length = 0 to avoid runtime call
9594 if(lc.op == EXP.int64 && lc.toInteger() == 0)
9595 {
9596 Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
9597 Expression as = new AssignExp(ale.loc, ale.e1, se);
9598 as = as.expressionSemantic(sc);
9599 auto res = Expression.combine(as, exp.e2);
9600 res.type = ale.type;
9601 return setResult(res);
9602 }
9603
9604 // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9605 Expression id = new IdentifierExp(ale.loc, Id.empty);
9606 id = new DotIdExp(ale.loc, id, Id.object);
9607 auto tiargs = new Objects();
9608 tiargs.push(ale.e1.type);
9609 id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9610 id = new DotIdExp(ale.loc, id, hook);
9611 id = id.expressionSemantic(sc);
9612
9613 auto arguments = new Expressions();
9614 arguments.reserve(5);
9615 if (global.params.tracegc)
9616 {
9617 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9618 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9619 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9620 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9621 }
9622 arguments.push(ale.e1);
9623 arguments.push(exp.e2);
9624
9625 Expression ce = new CallExp(ale.loc, id, arguments);
9626 auto res = ce.expressionSemantic(sc);
9627 // if (global.params.verbose)
9628 // message("lowered %s =>\n %s", exp.toChars(), res.toChars());
9629 return setResult(res);
9630 }
9631 else if (auto se = exp.e1.isSliceExp())
9632 {
9633 Type tn = se.type.nextOf();
9634 const fun = sc.func;
9635 if (exp.op == EXP.assign && !tn.isMutable() &&
9636 // allow modifiation in module ctor, see
9637 // https://issues.dlang.org/show_bug.cgi?id=9884
9638 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9639 {
9640 exp.error("slice `%s` is not mutable", se.toChars());
9641 return setError();
9642 }
9643
9644 if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
9645 {
9646 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9647 exp.e1.toChars(), tn.baseElemOf().toChars());
9648 result = ErrorExp.get();
9649 return;
9650 }
9651
9652 // For conditional operator, both branches need conversion.
9653 while (se.e1.op == EXP.slice)
9654 se = cast(SliceExp)se.e1;
9655 if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray)
9656 {
9657 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9658 if (se.e1.op == EXP.error)
9659 return setResult(se.e1);
9660 }
9661 }
9662 else
9663 {
9664 if (t1.ty == Tsarray && exp.op == EXP.assign)
9665 {
9666 Type tn = exp.e1.type.nextOf();
9667 if (tn && !tn.baseElemOf().isAssignable())
9668 {
9669 exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9670 exp.e1.toChars(), tn.baseElemOf().toChars());
9671 result = ErrorExp.get();
9672 return;
9673 }
9674 }
9675
9676 Expression e1x = exp.e1;
9677
9678 // Try to do a decent error message with the expression
9679 // before it gets constant folded
9680 if (exp.op == EXP.assign)
9681 e1x = e1x.modifiableLvalue(sc, e1old);
9682
9683 e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
9684
9685 if (e1x.op == EXP.error)
9686 {
9687 result = e1x;
9688 return;
9689 }
9690 exp.e1 = e1x;
9691 }
9692
9693 /* Tweak e2 based on the type of e1.
9694 */
9695 Expression e2x = exp.e2;
9696 Type t2 = e2x.type.toBasetype();
9697
9698 // If it is a array, get the element type. Note that it may be
9699 // multi-dimensional.
9700 Type telem = t1;
9701 while (telem.ty == Tarray)
9702 telem = telem.nextOf();
9703
9704 if (exp.e1.op == EXP.slice && t1.nextOf() &&
9705 (telem.ty != Tvoid || e2x.op == EXP.null_) &&
9706 e2x.implicitConvTo(t1.nextOf()))
9707 {
9708 // Check for block assignment. If it is of type void[], void[][], etc,
9709 // '= null' is the only allowable block assignment (Bug 7493)
9710 exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is
9711 e2x = e2x.implicitCastTo(sc, t1.nextOf());
9712 if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9713 return setError();
9714 }
9715 else if (exp.e1.op == EXP.slice &&
9716 (t2.ty == Tarray || t2.ty == Tsarray) &&
9717 t2.nextOf().implicitConvTo(t1.nextOf()))
9718 {
9719 // Check element-wise assignment.
9720
9721 /* If assigned elements number is known at compile time,
9722 * check the mismatch.
9723 */
9724 SliceExp se1 = cast(SliceExp)exp.e1;
9725 TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9726 TypeSArray tsa2 = null;
9727 if (auto ale = e2x.isArrayLiteralExp())
9728 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.length);
9729 else if (auto se = e2x.isSliceExp())
9730 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9731 else
9732 tsa2 = t2.isTypeSArray();
9733
9734 if (tsa1 && tsa2)
9735 {
9736 uinteger_t dim1 = tsa1.dim.toInteger();
9737 uinteger_t dim2 = tsa2.dim.toInteger();
9738 if (dim1 != dim2)
9739 {
9740 exp.error("mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
9741 return setError();
9742 }
9743 }
9744
9745 if (exp.op != EXP.blit &&
9746 (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9747 e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9748 e2x.op != EXP.slice && e2x.isLvalue()))
9749 {
9750 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9751 return setError();
9752 }
9753
9754 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9755 e2x.op != EXP.slice && e2x.op != EXP.assign &&
9756 e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
9757 !(e2x.op == EXP.add || e2x.op == EXP.min ||
9758 e2x.op == EXP.mul || e2x.op == EXP.div ||
9759 e2x.op == EXP.mod || e2x.op == EXP.xor ||
9760 e2x.op == EXP.and || e2x.op == EXP.or ||
9761 e2x.op == EXP.pow ||
9762 e2x.op == EXP.tilde || e2x.op == EXP.negate))
9763 {
9764 const(char)* e1str = exp.e1.toChars();
9765 const(char)* e2str = e2x.toChars();
9766 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9767 }
9768
9769 Type t2n = t2.nextOf();
9770 Type t1n = t1.nextOf();
9771 int offset;
9772 if (t2n.equivalent(t1n) ||
9773 t1n.isBaseOf(t2n, &offset) && offset == 0)
9774 {
9775 /* Allow copy of distinct qualifier elements.
9776 * eg.
9777 * char[] dst; const(char)[] src;
9778 * dst[] = src;
9779 *
9780 * class C {} class D : C {}
9781 * C[2] ca; D[] da;
9782 * ca[] = da;
9783 */
9784 if (isArrayOpValid(e2x))
9785 {
9786 // Don't add CastExp to keep AST for array operations
9787 e2x = e2x.copy();
9788 e2x.type = exp.e1.type.constOf();
9789 }
9790 else
9791 e2x = e2x.castTo(sc, exp.e1.type.constOf());
9792 }
9793 else
9794 {
9795 /* https://issues.dlang.org/show_bug.cgi?id=15778
9796 * A string literal has an array type of immutable
9797 * elements by default, and normally it cannot be convertible to
9798 * array type of mutable elements. But for element-wise assignment,
9799 * elements need to be const at best. So we should give a chance
9800 * to change code unit size for polysemous string literal.
9801 */
9802 if (e2x.op == EXP.string_)
9803 e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9804 else
9805 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9806 }
9807 if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9808 {
9809 if (sc.setUnsafe(false, exp.loc, "cannot copy `void[]` to `void[]` in `@safe` code"))
9810 return setError();
9811 }
9812 }
9813 else
9814 {
9815 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9816 t1.ty == Tarray && t2.ty == Tsarray &&
9817 e2x.op != EXP.slice &&
9818 t2.implicitConvTo(t1))
9819 {
9820 // Disallow ar[] = sa (Converted to ar[] = sa[])
9821 // Disallow da = sa (Converted to da = sa[])
9822 const(char)* e1str = exp.e1.toChars();
9823 const(char)* e2str = e2x.toChars();
9824 const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
9825 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9826 }
9827 if (exp.op == EXP.blit)
9828 e2x = e2x.castTo(sc, exp.e1.type);
9829 else
9830 {
9831 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9832
9833 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9834
9835 // If the implicit cast has failed and the assign expression is
9836 // the initialization of a struct member field
9837 if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
9838 {
9839 scope sd = (cast(TypeStruct)t1).sym;
9840 Dsymbol opAssign = search_function(sd, Id.assign);
9841
9842 // and the struct defines an opAssign
9843 if (opAssign)
9844 {
9845 // offer more information about the cause of the problem
9846 errorSupplemental(exp.loc,
9847 "`%s` is the first assignment of `%s` therefore it represents its initialization",
9848 exp.toChars(), exp.e1.toChars());
9849 errorSupplemental(exp.loc,
9850 "`opAssign` methods are not used for initialization, but for subsequent assignments");
9851 }
9852 }
9853 }
9854 }
9855 if (e2x.op == EXP.error)
9856 {
9857 result = e2x;
9858 return;
9859 }
9860 exp.e2 = e2x;
9861 t2 = exp.e2.type.toBasetype();
9862
9863 /* Look for array operations
9864 */
9865 if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9866 {
9867 // Look for valid array operations
9868 if (exp.memset != MemorySet.blockAssign &&
9869 exp.e1.op == EXP.slice &&
9870 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9871 {
9872 exp.type = exp.e1.type;
9873 if (exp.op == EXP.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9874 // tweak mutability of e1 element
9875 exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9876 result = arrayOp(exp, sc);
9877 return;
9878 }
9879
9880 // Drop invalid array operations in e2
9881 // d = a[] + b[], d = (a[] + b[])[0..2], etc
9882 if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == EXP.assign))
9883 return setError();
9884
9885 // Remains valid array assignments
9886 // d = d[], d = [1,2,3], etc
9887 }
9888
9889 /* Don't allow assignment to classes that were allocated on the stack with:
9890 * scope Class c = new Class();
9891 */
9892 if (exp.e1.op == EXP.variable && exp.op == EXP.assign)
9893 {
9894 VarExp ve = cast(VarExp)exp.e1;
9895 VarDeclaration vd = ve.var.isVarDeclaration();
9896 if (vd && vd.onstack)
9897 {
9898 assert(t1.ty == Tclass);
9899 exp.error("cannot rebind scope variables");
9900 }
9901 }
9902
9903 if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9904 {
9905 exp.error("cannot modify compiler-generated variable `__ctfe`");
9906 }
9907
9908 exp.type = exp.e1.type;
9909 assert(exp.type);
9910 auto assignElem = exp.e2;
9911 auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
9912 /* https://issues.dlang.org/show_bug.cgi?id=22366
9913 *
9914 * `reorderSettingAAElem` creates a tree of comma expressions, however,
9915 * `checkAssignExp` expects only AssignExps.
9916 */
9917 if (res == exp) // no `AA[k] = v` rewrite was performed
9918 checkAssignEscape(sc, res, false, false);
9919 else
9920 checkNewEscape(sc, assignElem, false); // assigning to AA puts it on heap
9921
9922 if (auto ae = res.isConstructExp())
9923 {
9924 Type t1b = ae.e1.type.toBasetype();
9925 if (t1b.ty != Tsarray && t1b.ty != Tarray)
9926 return setResult(res);
9927
9928 // only non-trivial array constructions may need to be lowered (non-POD elements basically)
9929 Type t1e = t1b.nextOf();
9930 TypeStruct ts = t1e.baseElemOf().isTypeStruct();
9931 if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
9932 return setResult(res);
9933
9934 // don't lower ref-constructions etc.
9935 if (!(t1b.ty == Tsarray || ae.e1.isSliceExp) ||
9936 (ae.e1.isVarExp && ae.e1.isVarExp.var.isVarDeclaration.isReference))
9937 return setResult(res);
9938
9939 // Construction from an equivalent other array?
9940 // Only lower with lvalue RHS elements; let the glue layer move rvalue elements.
9941 Type t2b = ae.e2.type.toBasetype();
9942 // skip over a (possibly implicit) cast of a static array RHS to a slice
9943 Expression rhs = ae.e2;
9944 Type rhsType = t2b;
9945 if (t2b.ty == Tarray)
9946 {
9947 if (auto ce = rhs.isCastExp())
9948 {
9949 auto ct = ce.e1.type.toBasetype();
9950 if (ct.ty == Tsarray)
9951 {
9952 rhs = ce.e1;
9953 rhsType = ct;
9954 }
9955 }
9956 }
9957 const lowerToArrayCtor =
9958 ( (rhsType.ty == Tarray && !rhs.isArrayLiteralExp) ||
9959 (rhsType.ty == Tsarray && rhs.isLvalue) ) &&
9960 t1e.equivalent(t2b.nextOf);
9961
9962 // Construction from a single element?
9963 // If the RHS is an rvalue, then we'll need to make a temporary for it (copied multiple times).
9964 const lowerToArraySetCtor = !lowerToArrayCtor && t1e.equivalent(t2b);
9965
9966 if (lowerToArrayCtor || lowerToArraySetCtor)
9967 {
9968 auto func = lowerToArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
9969 const other = lowerToArrayCtor ? "other array" : "value";
9970 if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
9971 return setError();
9972
9973 // Lower to object._d_array{,set}ctor(e1, e2)
9974 Expression id = new IdentifierExp(exp.loc, Id.empty);
9975 id = new DotIdExp(exp.loc, id, Id.object);
9976 id = new DotIdExp(exp.loc, id, func);
9977
9978 auto arguments = new Expressions();
9979 arguments.push(new CastExp(ae.loc, ae.e1, t1e.arrayOf).expressionSemantic(sc));
9980 if (lowerToArrayCtor)
9981 {
9982 arguments.push(new CastExp(ae.loc, rhs, t2b.nextOf.arrayOf).expressionSemantic(sc));
9983 Expression ce = new CallExp(exp.loc, id, arguments);
9984 res = ce.expressionSemantic(sc);
9985 }
9986 else
9987 {
9988 Expression e0;
9989 // promote an rvalue RHS element to a temporary, it's passed by ref to _d_arraysetctor
9990 if (!ae.e2.isLvalue)
9991 {
9992 auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
9993 e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
9994 arguments.push(new VarExp(vd.loc, vd).expressionSemantic(sc));
9995 }
9996 else
9997 arguments.push(ae.e2);
9998
9999 Expression ce = new CallExp(exp.loc, id, arguments);
10000 res = Expression.combine(e0, ce).expressionSemantic(sc);
10001 }
10002
10003 if (global.params.verbose)
10004 message("lowered %s =>\n %s", exp.toChars(), res.toChars());
10005 }
10006 }
10007 else if (auto ae = res.isAssignExp())
10008 res = lowerArrayAssign(ae);
10009 else if (auto ce = res.isCommaExp())
10010 {
10011 if (auto ae1 = ce.e1.isAssignExp())
10012 ce.e1 = lowerArrayAssign(ae1, true);
10013 if (auto ae2 = ce.e2.isAssignExp())
10014 ce.e2 = lowerArrayAssign(ae2, true);
10015 }
10016
10017 return setResult(res);
10018 }
10019
10020 /***************************************
10021 * Lower AssignExp to `_d_array{setassign,assign_l,assign_r}` if needed.
10022 *
10023 * Params:
10024 * ae = the AssignExp to be lowered
10025 * fromCommaExp = indicates whether `ae` is part of a CommaExp or not,
10026 * so no unnecessary temporay variable is created.
10027 * Returns:
10028 * a CommaExp contiaining call a to `_d_array{setassign,assign_l,assign_r}`
10029 * if needed or `ae` otherwise
10030 */
10031 private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false)
10032 {
10033 Type t1b = ae.e1.type.toBasetype();
10034 if (t1b.ty != Tsarray && t1b.ty != Tarray)
10035 return ae;
10036
10037 const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
10038 (ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
10039 (ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
10040
10041 const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
10042 (ae.e1.type.nextOf() && ae.e2.type.implicitConvTo(ae.e1.type.nextOf()));
10043
10044 if (!isArrayAssign && !isArraySetAssign)
10045 return ae;
10046
10047 const ts = t1b.nextOf().baseElemOf().isTypeStruct();
10048 if (!ts || (!ts.sym.postblit && !ts.sym.dtor))
10049 return ae;
10050
10051 Expression res;
10052 Identifier func = isArraySetAssign ? Id._d_arraysetassign :
10053 ae.e2.isLvalue() || ae.e2.isSliceExp() ? Id._d_arrayassign_l : Id._d_arrayassign_r;
10054
10055 // Lower to `.object._d_array{setassign,assign_l,assign_r}(e1, e2)``
10056 Expression id = new IdentifierExp(ae.loc, Id.empty);
10057 id = new DotIdExp(ae.loc, id, Id.object);
10058 id = new DotIdExp(ae.loc, id, func);
10059
10060 auto arguments = new Expressions();
10061 arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf)
10062 .expressionSemantic(sc));
10063
10064 Expression eValue2, value2 = ae.e2;
10065 if (isArrayAssign && value2.isLvalue())
10066 value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf())
10067 .expressionSemantic(sc);
10068 else if (!fromCommaExp &&
10069 (isArrayAssign || (isArraySetAssign && !value2.isLvalue())))
10070 {
10071 // Rvalues from CommaExps were introduced in `visit(AssignExp)`
10072 // and are temporary variables themselves. Rvalues from trivial
10073 // SliceExps are simply passed by reference without any copying.
10074
10075 // `__assigntmp` will be destroyed together with the array `ae.e1`.
10076 // When `ae.e2` is a variadic arg array, it is also `scope`, so
10077 // `__assigntmp` may also be scope.
10078 StorageClass stc = STC.nodtor;
10079 if (isArrayAssign)
10080 stc |= STC.rvalue | STC.scope_;
10081
10082 auto vd = copyToTemp(stc, "__assigntmp", ae.e2);
10083 eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
10084 value2 = new VarExp(vd.loc, vd).expressionSemantic(sc);
10085 }
10086 arguments.push(value2);
10087
10088 Expression ce = new CallExp(ae.loc, id, arguments);
10089 res = Expression.combine(eValue2, ce).expressionSemantic(sc);
10090 if (isArrayAssign)
10091 res = Expression.combine(res, ae.e1).expressionSemantic(sc);
10092
10093 if (global.params.verbose)
10094 message("lowered %s =>\n %s", ae.toChars(), res.toChars());
10095
10096 return res;
10097 }
10098
10099 override void visit(PowAssignExp exp)
10100 {
10101 if (exp.type)
10102 {
10103 result = exp;
10104 return;
10105 }
10106
10107 Expression e = exp.op_overload(sc);
10108 if (e)
10109 {
10110 result = e;
10111 return;
10112 }
10113
10114 if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
10115 return setError();
10116
10117 assert(exp.e1.type && exp.e2.type);
10118 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
10119 {
10120 if (checkNonAssignmentArrayOp(exp.e1))
10121 return setError();
10122
10123 // T[] ^^= ...
10124 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
10125 {
10126 // T[] ^^= T
10127 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
10128 }
10129 else if (Expression ex = typeCombine(exp, sc))
10130 {
10131 result = ex;
10132 return;
10133 }
10134
10135 // Check element types are arithmetic
10136 Type tb1 = exp.e1.type.nextOf().toBasetype();
10137 Type tb2 = exp.e2.type.toBasetype();
10138 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10139 tb2 = tb2.nextOf().toBasetype();
10140 if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
10141 {
10142 exp.type = exp.e1.type;
10143 result = arrayOp(exp, sc);
10144 return;
10145 }
10146 }
10147 else
10148 {
10149 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10150 }
10151
10152 if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
10153 {
10154 Expression e0 = null;
10155 e = exp.reorderSettingAAElem(sc);
10156 e = Expression.extractLast(e, e0);
10157 assert(e == exp);
10158
10159 if (exp.e1.op == EXP.variable)
10160 {
10161 // Rewrite: e1 = e1 ^^ e2
10162 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
10163 e = new AssignExp(exp.loc, exp.e1, e);
10164 }
10165 else
10166 {
10167 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
10168 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
10169 auto de = new DeclarationExp(exp.e1.loc, v);
10170 auto ve = new VarExp(exp.e1.loc, v);
10171 e = new PowExp(exp.loc, ve, exp.e2);
10172 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
10173 e = new CommaExp(exp.loc, de, e);
10174 }
10175 e = Expression.combine(e0, e);
10176 e = e.expressionSemantic(sc);
10177 result = e;
10178 return;
10179 }
10180 result = exp.incompatibleTypes();
10181 }
10182
10183 override void visit(CatAssignExp exp)
10184 {
10185 if (exp.type)
10186 {
10187 result = exp;
10188 return;
10189 }
10190
10191 //printf("CatAssignExp::semantic() %s\n", exp.toChars());
10192 Expression e = exp.op_overload(sc);
10193 if (e)
10194 {
10195 result = e;
10196 return;
10197 }
10198
10199 if (SliceExp se = exp.e1.isSliceExp())
10200 {
10201 if (se.e1.type.toBasetype().ty == Tsarray)
10202 {
10203 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
10204 return setError();
10205 }
10206 }
10207
10208 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10209 if (exp.e1.op == EXP.error)
10210 {
10211 result = exp.e1;
10212 return;
10213 }
10214 if (exp.e2.op == EXP.error)
10215 {
10216 result = exp.e2;
10217 return;
10218 }
10219
10220 if (checkNonAssignmentArrayOp(exp.e2))
10221 return setError();
10222
10223 Type tb1 = exp.e1.type.toBasetype();
10224 Type tb1next = tb1.nextOf();
10225 Type tb2 = exp.e2.type.toBasetype();
10226
10227 /* Possibilities:
10228 * EXP.concatenateAssign: appending T[] to T[]
10229 * EXP.concatenateElemAssign: appending T to T[]
10230 * EXP.concatenateDcharAssign: appending dchar to T[]
10231 */
10232 if ((tb1.ty == Tarray) &&
10233 (tb2.ty == Tarray || tb2.ty == Tsarray) &&
10234 (exp.e2.implicitConvTo(exp.e1.type) ||
10235 (tb2.nextOf().implicitConvTo(tb1next) &&
10236 (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
10237 {
10238 // EXP.concatenateAssign
10239 assert(exp.op == EXP.concatenateAssign);
10240 if (exp.e1.checkPostblit(sc, tb1next))
10241 return setError();
10242
10243 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
10244 }
10245 else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
10246 {
10247 /* https://issues.dlang.org/show_bug.cgi?id=19782
10248 *
10249 * If e2 is implicitly convertible to tb1next, the conversion
10250 * might be done through alias this, in which case, e2 needs to
10251 * be modified accordingly (e2 => e2.aliasthis).
10252 */
10253 if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
10254 goto Laliasthis;
10255 if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
10256 goto Laliasthis;
10257 // Append element
10258 if (exp.e2.checkPostblit(sc, tb2))
10259 return setError();
10260
10261 if (checkNewEscape(sc, exp.e2, false))
10262 return setError();
10263
10264 exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
10265 exp.e2 = doCopyOrMove(sc, exp.e2);
10266 }
10267 else if (tb1.ty == Tarray &&
10268 (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
10269 exp.e2.type.ty != tb1next.ty &&
10270 exp.e2.implicitConvTo(Type.tdchar))
10271 {
10272 // Append dchar to char[] or wchar[]
10273 exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
10274
10275 /* Do not allow appending wchar to char[] because if wchar happens
10276 * to be a surrogate pair, nothing good can result.
10277 */
10278 }
10279 else
10280 {
10281 // Try alias this on first operand
10282 static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
10283 {
10284 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
10285 if (!ad1 || !ad1.aliasthis)
10286 return null;
10287
10288 /* Rewrite (e1 op e2) as:
10289 * (e1.aliasthis op e2)
10290 */
10291 if (isRecursiveAliasThis(exp.att1, exp.e1.type))
10292 return null;
10293 //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars());
10294 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
10295 BinExp be = cast(BinExp)exp.copy();
10296 be.e1 = e1;
10297 return be.trySemantic(sc);
10298 }
10299
10300 // Try alias this on second operand
10301 static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
10302 {
10303 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
10304 if (!ad2 || !ad2.aliasthis)
10305 return null;
10306 /* Rewrite (e1 op e2) as:
10307 * (e1 op e2.aliasthis)
10308 */
10309 if (isRecursiveAliasThis(exp.att2, exp.e2.type))
10310 return null;
10311 //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars());
10312 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
10313 BinExp be = cast(BinExp)exp.copy();
10314 be.e2 = e2;
10315 return be.trySemantic(sc);
10316 }
10317
10318 Laliasthis:
10319 result = tryAliasThisForLhs(exp, sc);
10320 if (result)
10321 return;
10322
10323 result = tryAliasThisForRhs(exp, sc);
10324 if (result)
10325 return;
10326
10327 exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
10328 return setError();
10329 }
10330
10331 if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
10332 return setError();
10333
10334 exp.type = exp.e1.type;
10335 auto assignElem = exp.e2;
10336 auto res = exp.reorderSettingAAElem(sc);
10337 if (res != exp) // `AA[k] = v` rewrite was performed
10338 checkNewEscape(sc, assignElem, false);
10339 else if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
10340 checkAssignEscape(sc, res, false, false);
10341
10342 result = res;
10343
10344 if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
10345 !(sc.flags & (SCOPE.ctfe | SCOPE.compile)))
10346 {
10347 // if aa ordering is triggered, `res` will be a CommaExp
10348 // and `.e2` will be the rewritten original expression.
10349
10350 // `output` will point to the expression that the lowering will overwrite
10351 Expression* output;
10352 if (auto comma = res.isCommaExp())
10353 {
10354 output = &comma.e2;
10355 // manual cast because it could be either CatAssignExp or CatElemAssignExp
10356 exp = cast(CatAssignExp)comma.e2;
10357 }
10358 else
10359 {
10360 output = &result;
10361 exp = cast(CatAssignExp)result;
10362 }
10363
10364 if (exp.op == EXP.concatenateAssign)
10365 {
10366 Identifier hook = global.params.tracegc ? Id._d_arrayappendTTrace : Id._d_arrayappendT;
10367
10368 if (!verifyHookExist(exp.loc, *sc, hook, "appending array to arrays", Id.object))
10369 return setError();
10370
10371 // Lower to object._d_arrayappendT{,Trace}({file, line, funcname}, e1, e2)
10372 Expression id = new IdentifierExp(exp.loc, Id.empty);
10373 id = new DotIdExp(exp.loc, id, Id.object);
10374 id = new DotIdExp(exp.loc, id, hook);
10375
10376 auto arguments = new Expressions();
10377 arguments.reserve(5);
10378 if (global.params.tracegc)
10379 {
10380 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
10381 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
10382 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
10383 arguments.push(new StringExp(exp.loc, funcname.toDString()));
10384 }
10385
10386 arguments.push(exp.e1);
10387 arguments.push(exp.e2);
10388 Expression ce = new CallExp(exp.loc, id, arguments);
10389 *output = ce.expressionSemantic(sc);
10390 }
10391 else if (exp.op == EXP.concatenateElemAssign)
10392 {
10393 /* Do not lower concats to the indices array returned by
10394 *`static foreach`, as this array is only used at compile-time.
10395 */
10396 if (auto ve = exp.e1.isVarExp)
10397 {
10398 import core.stdc.ctype : isdigit;
10399 // The name of the indices array that static foreach loops uses.
10400 // See dmd.cond.lowerNonArrayAggregate
10401 enum varName = "__res";
10402 const(char)[] id = ve.var.ident.toString;
10403 if (ve.var.storage_class & STC.temp && id.length > varName.length &&
10404 id[0 .. varName.length] == varName && id[varName.length].isdigit)
10405 return;
10406 }
10407
10408 Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX;
10409 if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object))
10410 return setError();
10411
10412 // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
10413 Expression id = new IdentifierExp(exp.loc, Id.empty);
10414 id = new DotIdExp(exp.loc, id, Id.object);
10415 auto tiargs = new Objects();
10416 tiargs.push(exp.e1.type);
10417 id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs);
10418 id = new DotIdExp(exp.loc, id, hook);
10419
10420 auto arguments = new Expressions();
10421 arguments.reserve(5);
10422 if (global.params.tracegc)
10423 {
10424 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
10425 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
10426 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
10427 arguments.push(new StringExp(exp.loc, funcname.toDString()));
10428 }
10429
10430 Expression eValue1;
10431 Expression value1 = extractSideEffect(sc, "__appendtmp", eValue1, exp.e1);
10432
10433 arguments.push(value1);
10434 arguments.push(new IntegerExp(exp.loc, 1, Type.tsize_t));
10435
10436 Expression ce = new CallExp(exp.loc, id, arguments);
10437
10438 Expression eValue2;
10439 Expression value2 = exp.e2;
10440 if (!value2.isVarExp() && !value2.isConst())
10441 {
10442 /* Before the template hook, this check was performed in e2ir.d
10443 * for expressions like `a ~= a[$-1]`. Here, $ will be modified
10444 * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in
10445 * a temporary variable.
10446 */
10447 value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true);
10448 exp.e2 = value2;
10449
10450 // `__appendtmp*` will be destroyed together with the array `exp.e1`.
10451 auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
10452 vd.storage_class |= STC.nodtor;
10453 // Be more explicit that this "declaration" is local to the expression
10454 vd.storage_class |= STC.exptemp;
10455 }
10456
10457 auto ale = new ArrayLengthExp(exp.loc, value1);
10458 auto elem = new IndexExp(exp.loc, value1, new MinExp(exp.loc, ale, IntegerExp.literal!1));
10459 auto ae = new ConstructExp(exp.loc, elem, value2);
10460
10461 auto e0 = Expression.combine(ce, ae).expressionSemantic(sc);
10462 e0 = Expression.combine(e0, value1);
10463 e0 = Expression.combine(eValue1, e0);
10464
10465 e0 = Expression.combine(eValue2, e0);
10466
10467 *output = e0.expressionSemantic(sc);
10468 }
10469 }
10470
10471 }
10472
10473 override void visit(AddExp exp)
10474 {
10475 static if (LOGSEMANTIC)
10476 {
10477 printf("AddExp::semantic('%s')\n", exp.toChars());
10478 }
10479 if (exp.type)
10480 {
10481 result = exp;
10482 return;
10483 }
10484
10485 if (Expression ex = binSemanticProp(exp, sc))
10486 {
10487 result = ex;
10488 return;
10489 }
10490 Expression e = exp.op_overload(sc);
10491 if (e)
10492 {
10493 result = e;
10494 return;
10495 }
10496
10497 /* ImportC: convert arrays to pointers, functions to pointers to functions
10498 */
10499 exp.e1 = exp.e1.arrayFuncConv(sc);
10500 exp.e2 = exp.e2.arrayFuncConv(sc);
10501
10502 Type tb1 = exp.e1.type.toBasetype();
10503 Type tb2 = exp.e2.type.toBasetype();
10504
10505 bool err = false;
10506 if (tb1.ty == Tdelegate || tb1.isPtrToFunction())
10507 {
10508 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10509 }
10510 if (tb2.ty == Tdelegate || tb2.isPtrToFunction())
10511 {
10512 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10513 }
10514 if (err)
10515 return setError();
10516
10517 if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
10518 {
10519 result = scaleFactor(exp, sc);
10520 return;
10521 }
10522
10523 if (tb1.ty == Tpointer && tb2.ty == Tpointer)
10524 {
10525 result = exp.incompatibleTypes();
10526 return;
10527 }
10528
10529 if (Expression ex = typeCombine(exp, sc))
10530 {
10531 result = ex;
10532 return;
10533 }
10534
10535 Type tb = exp.type.toBasetype();
10536 if (tb.ty == Tarray || tb.ty == Tsarray)
10537 {
10538 if (!isArrayOpValid(exp))
10539 {
10540 result = arrayOpInvalidError(exp);
10541 return;
10542 }
10543 result = exp;
10544 return;
10545 }
10546
10547 tb1 = exp.e1.type.toBasetype();
10548 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
10549 {
10550 result = exp.incompatibleTypes();
10551 return;
10552 }
10553 if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
10554 {
10555 switch (exp.type.toBasetype().ty)
10556 {
10557 case Tfloat32:
10558 case Timaginary32:
10559 exp.type = Type.tcomplex32;
10560 break;
10561
10562 case Tfloat64:
10563 case Timaginary64:
10564 exp.type = Type.tcomplex64;
10565 break;
10566
10567 case Tfloat80:
10568 case Timaginary80:
10569 exp.type = Type.tcomplex80;
10570 break;
10571
10572 default:
10573 assert(0);
10574 }
10575 }
10576 result = exp;
10577 }
10578
10579 override void visit(MinExp exp)
10580 {
10581 static if (LOGSEMANTIC)
10582 {
10583 printf("MinExp::semantic('%s')\n", exp.toChars());
10584 }
10585 if (exp.type)
10586 {
10587 result = exp;
10588 return;
10589 }
10590
10591 if (Expression ex = binSemanticProp(exp, sc))
10592 {
10593 result = ex;
10594 return;
10595 }
10596 Expression e = exp.op_overload(sc);
10597 if (e)
10598 {
10599 result = e;
10600 return;
10601 }
10602
10603 /* ImportC: convert arrays to pointers, functions to pointers to functions
10604 */
10605 exp.e1 = exp.e1.arrayFuncConv(sc);
10606 exp.e2 = exp.e2.arrayFuncConv(sc);
10607
10608 Type t1 = exp.e1.type.toBasetype();
10609 Type t2 = exp.e2.type.toBasetype();
10610
10611 bool err = false;
10612 if (t1.ty == Tdelegate || t1.isPtrToFunction())
10613 {
10614 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10615 }
10616 if (t2.ty == Tdelegate || t2.isPtrToFunction())
10617 {
10618 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10619 }
10620 if (err)
10621 return setError();
10622
10623 if (t1.ty == Tpointer)
10624 {
10625 if (t2.ty == Tpointer)
10626 {
10627 // https://dlang.org/spec/expression.html#add_expressions
10628 // "If both operands are pointers, and the operator is -, the pointers are
10629 // subtracted and the result is divided by the size of the type pointed to
10630 // by the operands. It is an error if the pointers point to different types."
10631 Type p1 = t1.nextOf();
10632 Type p2 = t2.nextOf();
10633
10634 if (!p1.equivalent(p2))
10635 {
10636 // Deprecation to remain for at least a year, after which this should be
10637 // changed to an error
10638 // See https://github.com/dlang/dmd/pull/7332
10639 deprecation(exp.loc,
10640 "cannot subtract pointers to different types: `%s` and `%s`.",
10641 t1.toChars(), t2.toChars());
10642 }
10643
10644 // Need to divide the result by the stride
10645 // Replace (ptr - ptr) with (ptr - ptr) / stride
10646 long stride;
10647
10648 // make sure pointer types are compatible
10649 if (Expression ex = typeCombine(exp, sc))
10650 {
10651 result = ex;
10652 return;
10653 }
10654
10655 exp.type = Type.tptrdiff_t;
10656 stride = t2.nextOf().size();
10657 if (stride == 0)
10658 {
10659 e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
10660 }
10661 else if (stride == cast(long)SIZE_INVALID)
10662 e = ErrorExp.get();
10663 else
10664 {
10665 e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
10666 e.type = Type.tptrdiff_t;
10667 }
10668 }
10669 else if (t2.isintegral())
10670 e = scaleFactor(exp, sc);
10671 else
10672 {
10673 exp.error("can't subtract `%s` from pointer", t2.toChars());
10674 e = ErrorExp.get();
10675 }
10676 result = e;
10677 return;
10678 }
10679 if (t2.ty == Tpointer)
10680 {
10681 exp.type = exp.e2.type;
10682 exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
10683 return setError();
10684 }
10685
10686 if (Expression ex = typeCombine(exp, sc))
10687 {
10688 result = ex;
10689 return;
10690 }
10691
10692 Type tb = exp.type.toBasetype();
10693 if (tb.ty == Tarray || tb.ty == Tsarray)
10694 {
10695 if (!isArrayOpValid(exp))
10696 {
10697 result = arrayOpInvalidError(exp);
10698 return;
10699 }
10700 result = exp;
10701 return;
10702 }
10703
10704 t1 = exp.e1.type.toBasetype();
10705 t2 = exp.e2.type.toBasetype();
10706 if (!target.isVectorOpSupported(t1, exp.op, t2))
10707 {
10708 result = exp.incompatibleTypes();
10709 return;
10710 }
10711 if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
10712 {
10713 switch (exp.type.ty)
10714 {
10715 case Tfloat32:
10716 case Timaginary32:
10717 exp.type = Type.tcomplex32;
10718 break;
10719
10720 case Tfloat64:
10721 case Timaginary64:
10722 exp.type = Type.tcomplex64;
10723 break;
10724
10725 case Tfloat80:
10726 case Timaginary80:
10727 exp.type = Type.tcomplex80;
10728 break;
10729
10730 default:
10731 assert(0);
10732 }
10733 }
10734 result = exp;
10735 return;
10736 }
10737
10738 override void visit(CatExp exp)
10739 {
10740 // https://dlang.org/spec/expression.html#cat_expressions
10741 //printf("CatExp.semantic() %s\n", toChars());
10742 if (exp.type)
10743 {
10744 result = exp;
10745 return;
10746 }
10747
10748 if (Expression ex = binSemanticProp(exp, sc))
10749 {
10750 result = ex;
10751 return;
10752 }
10753 Expression e = exp.op_overload(sc);
10754 if (e)
10755 {
10756 result = e;
10757 return;
10758 }
10759
10760 Type tb1 = exp.e1.type.toBasetype();
10761 Type tb2 = exp.e2.type.toBasetype();
10762
10763 auto f1 = checkNonAssignmentArrayOp(exp.e1);
10764 auto f2 = checkNonAssignmentArrayOp(exp.e2);
10765 if (f1 || f2)
10766 return setError();
10767
10768 Type tb1next = tb1.nextOf();
10769 Type tb2next = tb2.nextOf();
10770
10771 // Check for: array ~ array
10772 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)))
10773 {
10774 /* https://issues.dlang.org/show_bug.cgi?id=9248
10775 * Here to avoid the case of:
10776 * void*[] a = [cast(void*)1];
10777 * void*[] b = [cast(void*)2];
10778 * a ~ b;
10779 * becoming:
10780 * a ~ [cast(void*)b];
10781 */
10782
10783 /* https://issues.dlang.org/show_bug.cgi?id=14682
10784 * Also to avoid the case of:
10785 * int[][] a;
10786 * a ~ [];
10787 * becoming:
10788 * a ~ cast(int[])[];
10789 */
10790 goto Lpeer;
10791 }
10792
10793 // Check for: array ~ element
10794 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10795 {
10796 if (exp.e1.op == EXP.arrayLiteral)
10797 {
10798 exp.e2 = doCopyOrMove(sc, exp.e2);
10799 // https://issues.dlang.org/show_bug.cgi?id=14686
10800 // Postblit call appears in AST, and this is
10801 // finally translated to an ArrayLiteralExp in below optimize().
10802 }
10803 else if (exp.e1.op == EXP.string_)
10804 {
10805 // No postblit call exists on character (integer) value.
10806 }
10807 else
10808 {
10809 if (exp.e2.checkPostblit(sc, tb2))
10810 return setError();
10811 // Postblit call will be done in runtime helper function
10812 }
10813
10814 if (exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
10815 {
10816 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10817 exp.type = tb2.arrayOf();
10818 goto L2elem;
10819 }
10820 if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10821 {
10822 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10823 exp.type = tb1next.arrayOf();
10824 L2elem:
10825 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10826 {
10827 // Make e2 into [e2]
10828 exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10829 }
10830 else if (checkNewEscape(sc, exp.e2, false))
10831 return setError();
10832 result = exp.optimize(WANTvalue);
10833 return;
10834 }
10835 }
10836 // Check for: element ~ array
10837 if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10838 {
10839 if (exp.e2.op == EXP.arrayLiteral)
10840 {
10841 exp.e1 = doCopyOrMove(sc, exp.e1);
10842 }
10843 else if (exp.e2.op == EXP.string_)
10844 {
10845 }
10846 else
10847 {
10848 if (exp.e1.checkPostblit(sc, tb1))
10849 return setError();
10850 }
10851
10852 if (exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
10853 {
10854 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10855 exp.type = tb1.arrayOf();
10856 goto L1elem;
10857 }
10858 if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10859 {
10860 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10861 exp.type = tb2next.arrayOf();
10862 L1elem:
10863 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10864 {
10865 // Make e1 into [e1]
10866 exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10867 }
10868 else if (checkNewEscape(sc, exp.e1, false))
10869 return setError();
10870 result = exp.optimize(WANTvalue);
10871 return;
10872 }
10873 }
10874
10875 Lpeer:
10876 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10877 {
10878 Type t1 = tb1next.mutableOf().constOf().arrayOf();
10879 Type t2 = tb2next.mutableOf().constOf().arrayOf();
10880 if (exp.e1.op == EXP.string_ && !(cast(StringExp)exp.e1).committed)
10881 exp.e1.type = t1;
10882 else
10883 exp.e1 = exp.e1.castTo(sc, t1);
10884 if (exp.e2.op == EXP.string_ && !(cast(StringExp)exp.e2).committed)
10885 exp.e2.type = t2;
10886 else
10887 exp.e2 = exp.e2.castTo(sc, t2);
10888 }
10889
10890 if (Expression ex = typeCombine(exp, sc))
10891 {
10892 result = ex;
10893 return;
10894 }
10895 exp.type = exp.type.toHeadMutable();
10896
10897 Type tb = exp.type.toBasetype();
10898 if (tb.ty == Tsarray)
10899 exp.type = tb.nextOf().arrayOf();
10900 if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10901 {
10902 exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10903 }
10904 if (Type tbn = tb.nextOf())
10905 {
10906 if (exp.checkPostblit(sc, tbn))
10907 return setError();
10908 }
10909 Type t1 = exp.e1.type.toBasetype();
10910 Type t2 = exp.e2.type.toBasetype();
10911 if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10912 (t2.ty == Tarray || t2.ty == Tsarray))
10913 {
10914 // Normalize to ArrayLiteralExp or StringExp as far as possible
10915 e = exp.optimize(WANTvalue);
10916 }
10917 else
10918 {
10919 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10920 result = exp.incompatibleTypes();
10921 return;
10922 }
10923
10924 result = e;
10925 }
10926
10927 override void visit(MulExp exp)
10928 {
10929 version (none)
10930 {
10931 printf("MulExp::semantic() %s\n", exp.toChars());
10932 }
10933 if (exp.type)
10934 {
10935 result = exp;
10936 return;
10937 }
10938
10939 if (Expression ex = binSemanticProp(exp, sc))
10940 {
10941 result = ex;
10942 return;
10943 }
10944 Expression e = exp.op_overload(sc);
10945 if (e)
10946 {
10947 result = e;
10948 return;
10949 }
10950
10951 if (Expression ex = typeCombine(exp, sc))
10952 {
10953 result = ex;
10954 return;
10955 }
10956
10957 Type tb = exp.type.toBasetype();
10958 if (tb.ty == Tarray || tb.ty == Tsarray)
10959 {
10960 if (!isArrayOpValid(exp))
10961 {
10962 result = arrayOpInvalidError(exp);
10963 return;
10964 }
10965 result = exp;
10966 return;
10967 }
10968
10969 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10970 return setError();
10971
10972 if (exp.type.isfloating())
10973 {
10974 Type t1 = exp.e1.type;
10975 Type t2 = exp.e2.type;
10976
10977 if (t1.isreal())
10978 {
10979 exp.type = t2;
10980 }
10981 else if (t2.isreal())
10982 {
10983 exp.type = t1;
10984 }
10985 else if (t1.isimaginary())
10986 {
10987 if (t2.isimaginary())
10988 {
10989 switch (t1.toBasetype().ty)
10990 {
10991 case Timaginary32:
10992 exp.type = Type.tfloat32;
10993 break;
10994
10995 case Timaginary64:
10996 exp.type = Type.tfloat64;
10997 break;
10998
10999 case Timaginary80:
11000 exp.type = Type.tfloat80;
11001 break;
11002
11003 default:
11004 assert(0);
11005 }
11006
11007 // iy * iv = -yv
11008 exp.e1.type = exp.type;
11009 exp.e2.type = exp.type;
11010 e = new NegExp(exp.loc, exp);
11011 e = e.expressionSemantic(sc);
11012 result = e;
11013 return;
11014 }
11015 else
11016 exp.type = t2; // t2 is complex
11017 }
11018 else if (t2.isimaginary())
11019 {
11020 exp.type = t1; // t1 is complex
11021 }
11022 }
11023 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11024 {
11025 result = exp.incompatibleTypes();
11026 return;
11027 }
11028 result = exp;
11029 }
11030
11031 override void visit(DivExp exp)
11032 {
11033 if (exp.type)
11034 {
11035 result = exp;
11036 return;
11037 }
11038
11039 if (Expression ex = binSemanticProp(exp, sc))
11040 {
11041 result = ex;
11042 return;
11043 }
11044 Expression e = exp.op_overload(sc);
11045 if (e)
11046 {
11047 result = e;
11048 return;
11049 }
11050
11051 if (Expression ex = typeCombine(exp, sc))
11052 {
11053 result = ex;
11054 return;
11055 }
11056
11057 Type tb = exp.type.toBasetype();
11058 if (tb.ty == Tarray || tb.ty == Tsarray)
11059 {
11060 if (!isArrayOpValid(exp))
11061 {
11062 result = arrayOpInvalidError(exp);
11063 return;
11064 }
11065 result = exp;
11066 return;
11067 }
11068
11069 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11070 return setError();
11071
11072 if (exp.type.isfloating())
11073 {
11074 Type t1 = exp.e1.type;
11075 Type t2 = exp.e2.type;
11076
11077 if (t1.isreal())
11078 {
11079 exp.type = t2;
11080 if (t2.isimaginary())
11081 {
11082 // x/iv = i(-x/v)
11083 exp.e2.type = t1;
11084 e = new NegExp(exp.loc, exp);
11085 e = e.expressionSemantic(sc);
11086 result = e;
11087 return;
11088 }
11089 }
11090 else if (t2.isreal())
11091 {
11092 exp.type = t1;
11093 }
11094 else if (t1.isimaginary())
11095 {
11096 if (t2.isimaginary())
11097 {
11098 switch (t1.toBasetype().ty)
11099 {
11100 case Timaginary32:
11101 exp.type = Type.tfloat32;
11102 break;
11103
11104 case Timaginary64:
11105 exp.type = Type.tfloat64;
11106 break;
11107
11108 case Timaginary80:
11109 exp.type = Type.tfloat80;
11110 break;
11111
11112 default:
11113 assert(0);
11114 }
11115 }
11116 else
11117 exp.type = t2; // t2 is complex
11118 }
11119 else if (t2.isimaginary())
11120 {
11121 exp.type = t1; // t1 is complex
11122 }
11123 }
11124 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11125 {
11126 result = exp.incompatibleTypes();
11127 return;
11128 }
11129 result = exp;
11130 }
11131
11132 override void visit(ModExp exp)
11133 {
11134 if (exp.type)
11135 {
11136 result = exp;
11137 return;
11138 }
11139
11140 if (Expression ex = binSemanticProp(exp, sc))
11141 {
11142 result = ex;
11143 return;
11144 }
11145 Expression e = exp.op_overload(sc);
11146 if (e)
11147 {
11148 result = e;
11149 return;
11150 }
11151
11152 if (Expression ex = typeCombine(exp, sc))
11153 {
11154 result = ex;
11155 return;
11156 }
11157
11158 Type tb = exp.type.toBasetype();
11159 if (tb.ty == Tarray || tb.ty == Tsarray)
11160 {
11161 if (!isArrayOpValid(exp))
11162 {
11163 result = arrayOpInvalidError(exp);
11164 return;
11165 }
11166 result = exp;
11167 return;
11168 }
11169 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11170 {
11171 result = exp.incompatibleTypes();
11172 return;
11173 }
11174
11175 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11176 return setError();
11177
11178 if (exp.type.isfloating())
11179 {
11180 exp.type = exp.e1.type;
11181 if (exp.e2.type.iscomplex())
11182 {
11183 exp.error("cannot perform modulo complex arithmetic");
11184 return setError();
11185 }
11186 }
11187 result = exp;
11188 }
11189
11190 override void visit(PowExp exp)
11191 {
11192 if (exp.type)
11193 {
11194 result = exp;
11195 return;
11196 }
11197
11198 //printf("PowExp::semantic() %s\n", toChars());
11199 if (Expression ex = binSemanticProp(exp, sc))
11200 {
11201 result = ex;
11202 return;
11203 }
11204 Expression e = exp.op_overload(sc);
11205 if (e)
11206 {
11207 result = e;
11208 return;
11209 }
11210
11211 if (Expression ex = typeCombine(exp, sc))
11212 {
11213 result = ex;
11214 return;
11215 }
11216
11217 Type tb = exp.type.toBasetype();
11218 if (tb.ty == Tarray || tb.ty == Tsarray)
11219 {
11220 if (!isArrayOpValid(exp))
11221 {
11222 result = arrayOpInvalidError(exp);
11223 return;
11224 }
11225 result = exp;
11226 return;
11227 }
11228
11229 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11230 return setError();
11231
11232 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11233 {
11234 result = exp.incompatibleTypes();
11235 return;
11236 }
11237
11238 // First, attempt to fold the expression.
11239 e = exp.optimize(WANTvalue);
11240 if (e.op != EXP.pow)
11241 {
11242 e = e.expressionSemantic(sc);
11243 result = e;
11244 return;
11245 }
11246
11247 Module mmath = Module.loadStdMath();
11248 if (!mmath)
11249 {
11250 e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
11251 return setError();
11252 }
11253 e = new ScopeExp(exp.loc, mmath);
11254
11255 if (exp.e2.op == EXP.float64 && exp.e2.toReal() == CTFloat.half)
11256 {
11257 // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
11258 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
11259 }
11260 else
11261 {
11262 // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
11263 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
11264 }
11265 e = e.expressionSemantic(sc);
11266 result = e;
11267 return;
11268 }
11269
11270 override void visit(ShlExp exp)
11271 {
11272 //printf("ShlExp::semantic(), type = %p\n", type);
11273 if (exp.type)
11274 {
11275 result = exp;
11276 return;
11277 }
11278
11279 if (Expression ex = binSemanticProp(exp, sc))
11280 {
11281 result = ex;
11282 return;
11283 }
11284 Expression e = exp.op_overload(sc);
11285 if (e)
11286 {
11287 result = e;
11288 return;
11289 }
11290
11291 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11292 return setError();
11293
11294 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11295 {
11296 result = exp.incompatibleTypes();
11297 return;
11298 }
11299 exp.e1 = integralPromotions(exp.e1, sc);
11300 if (exp.e2.type.toBasetype().ty != Tvector)
11301 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11302
11303 exp.type = exp.e1.type;
11304 result = exp;
11305 }
11306
11307 override void visit(ShrExp exp)
11308 {
11309 if (exp.type)
11310 {
11311 result = exp;
11312 return;
11313 }
11314
11315 if (Expression ex = binSemanticProp(exp, sc))
11316 {
11317 result = ex;
11318 return;
11319 }
11320 Expression e = exp.op_overload(sc);
11321 if (e)
11322 {
11323 result = e;
11324 return;
11325 }
11326
11327 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11328 return setError();
11329
11330 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11331 {
11332 result = exp.incompatibleTypes();
11333 return;
11334 }
11335 exp.e1 = integralPromotions(exp.e1, sc);
11336 if (exp.e2.type.toBasetype().ty != Tvector)
11337 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11338
11339 exp.type = exp.e1.type;
11340 result = exp;
11341 }
11342
11343 override void visit(UshrExp exp)
11344 {
11345 if (exp.type)
11346 {
11347 result = exp;
11348 return;
11349 }
11350
11351 if (Expression ex = binSemanticProp(exp, sc))
11352 {
11353 result = ex;
11354 return;
11355 }
11356 Expression e = exp.op_overload(sc);
11357 if (e)
11358 {
11359 result = e;
11360 return;
11361 }
11362
11363 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11364 return setError();
11365
11366 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11367 {
11368 result = exp.incompatibleTypes();
11369 return;
11370 }
11371 exp.e1 = integralPromotions(exp.e1, sc);
11372 if (exp.e2.type.toBasetype().ty != Tvector)
11373 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11374
11375 exp.type = exp.e1.type;
11376 result = exp;
11377 }
11378
11379 override void visit(AndExp exp)
11380 {
11381 if (exp.type)
11382 {
11383 result = exp;
11384 return;
11385 }
11386
11387 if (Expression ex = binSemanticProp(exp, sc))
11388 {
11389 result = ex;
11390 return;
11391 }
11392 Expression e = exp.op_overload(sc);
11393 if (e)
11394 {
11395 result = e;
11396 return;
11397 }
11398
11399 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11400 {
11401 exp.type = exp.e1.type;
11402 result = exp;
11403 return;
11404 }
11405
11406 if (Expression ex = typeCombine(exp, sc))
11407 {
11408 result = ex;
11409 return;
11410 }
11411
11412 Type tb = exp.type.toBasetype();
11413 if (tb.ty == Tarray || tb.ty == Tsarray)
11414 {
11415 if (!isArrayOpValid(exp))
11416 {
11417 result = arrayOpInvalidError(exp);
11418 return;
11419 }
11420 result = exp;
11421 return;
11422 }
11423 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11424 {
11425 result = exp.incompatibleTypes();
11426 return;
11427 }
11428 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11429 return setError();
11430
11431 result = exp;
11432 }
11433
11434 override void visit(OrExp exp)
11435 {
11436 if (exp.type)
11437 {
11438 result = exp;
11439 return;
11440 }
11441
11442 if (Expression ex = binSemanticProp(exp, sc))
11443 {
11444 result = ex;
11445 return;
11446 }
11447 Expression e = exp.op_overload(sc);
11448 if (e)
11449 {
11450 result = e;
11451 return;
11452 }
11453
11454 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11455 {
11456 exp.type = exp.e1.type;
11457 result = exp;
11458 return;
11459 }
11460
11461 if (Expression ex = typeCombine(exp, sc))
11462 {
11463 result = ex;
11464 return;
11465 }
11466
11467 Type tb = exp.type.toBasetype();
11468 if (tb.ty == Tarray || tb.ty == Tsarray)
11469 {
11470 if (!isArrayOpValid(exp))
11471 {
11472 result = arrayOpInvalidError(exp);
11473 return;
11474 }
11475 result = exp;
11476 return;
11477 }
11478 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11479 {
11480 result = exp.incompatibleTypes();
11481 return;
11482 }
11483 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11484 return setError();
11485
11486 result = exp;
11487 }
11488
11489 override void visit(XorExp exp)
11490 {
11491 if (exp.type)
11492 {
11493 result = exp;
11494 return;
11495 }
11496
11497 if (Expression ex = binSemanticProp(exp, sc))
11498 {
11499 result = ex;
11500 return;
11501 }
11502 Expression e = exp.op_overload(sc);
11503 if (e)
11504 {
11505 result = e;
11506 return;
11507 }
11508
11509 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11510 {
11511 exp.type = exp.e1.type;
11512 result = exp;
11513 return;
11514 }
11515
11516 if (Expression ex = typeCombine(exp, sc))
11517 {
11518 result = ex;
11519 return;
11520 }
11521
11522 Type tb = exp.type.toBasetype();
11523 if (tb.ty == Tarray || tb.ty == Tsarray)
11524 {
11525 if (!isArrayOpValid(exp))
11526 {
11527 result = arrayOpInvalidError(exp);
11528 return;
11529 }
11530 result = exp;
11531 return;
11532 }
11533 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11534 {
11535 result = exp.incompatibleTypes();
11536 return;
11537 }
11538 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11539 return setError();
11540
11541 result = exp;
11542 }
11543
11544 override void visit(LogicalExp exp)
11545 {
11546 static if (LOGSEMANTIC)
11547 {
11548 printf("LogicalExp::semantic() %s\n", exp.toChars());
11549 }
11550
11551 if (exp.type)
11552 {
11553 result = exp;
11554 return;
11555 }
11556
11557 exp.setNoderefOperands();
11558
11559 Expression e1x = exp.e1.expressionSemantic(sc);
11560
11561 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11562 if (e1x.op == EXP.type)
11563 e1x = resolveAliasThis(sc, e1x);
11564
11565 e1x = resolveProperties(sc, e1x);
11566 e1x = e1x.toBoolean(sc);
11567
11568 if (sc.flags & SCOPE.condition)
11569 {
11570 /* If in static if, don't evaluate e2 if we don't have to.
11571 */
11572 e1x = e1x.optimize(WANTvalue);
11573 if (e1x.toBool().hasValue(exp.op == EXP.orOr))
11574 {
11575 if (sc.flags & SCOPE.Cfile)
11576 result = new IntegerExp(exp.op == EXP.orOr);
11577 else
11578 result = IntegerExp.createBool(exp.op == EXP.orOr);
11579 return;
11580 }
11581 }
11582
11583 CtorFlow ctorflow = sc.ctorflow.clone();
11584 Expression e2x = exp.e2.expressionSemantic(sc);
11585 sc.merge(exp.loc, ctorflow);
11586 ctorflow.freeFieldinit();
11587
11588 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11589 if (e2x.op == EXP.type)
11590 e2x = resolveAliasThis(sc, e2x);
11591
11592 e2x = resolveProperties(sc, e2x);
11593
11594 auto f1 = checkNonAssignmentArrayOp(e1x);
11595 auto f2 = checkNonAssignmentArrayOp(e2x);
11596 if (f1 || f2)
11597 return setError();
11598
11599 // Unless the right operand is 'void', the expression is converted to 'bool'.
11600 if (e2x.type.ty != Tvoid)
11601 e2x = e2x.toBoolean(sc);
11602
11603 if (e2x.op == EXP.type || e2x.op == EXP.scope_)
11604 {
11605 exp.error("`%s` is not an expression", exp.e2.toChars());
11606 return setError();
11607 }
11608 if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
11609 {
11610 result = e1x;
11611 return;
11612 }
11613 if (e2x.op == EXP.error)
11614 {
11615 result = e2x;
11616 return;
11617 }
11618
11619 // The result type is 'bool', unless the right operand has type 'void'.
11620 if (e2x.type.ty == Tvoid)
11621 exp.type = Type.tvoid;
11622 else
11623 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11624
11625 exp.e1 = e1x;
11626 exp.e2 = e2x;
11627 result = exp;
11628 }
11629
11630
11631 override void visit(CmpExp exp)
11632 {
11633 static if (LOGSEMANTIC)
11634 {
11635 printf("CmpExp::semantic('%s')\n", exp.toChars());
11636 }
11637 if (exp.type)
11638 {
11639 result = exp;
11640 return;
11641 }
11642
11643 exp.setNoderefOperands();
11644
11645 if (Expression ex = binSemanticProp(exp, sc))
11646 {
11647 result = ex;
11648 return;
11649 }
11650 Type t1 = exp.e1.type.toBasetype();
11651 Type t2 = exp.e2.type.toBasetype();
11652 if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
11653 {
11654 exp.error("do not use `null` when comparing class types");
11655 return setError();
11656 }
11657
11658
11659 EXP cmpop = exp.op;
11660 if (auto e = exp.op_overload(sc, &cmpop))
11661 {
11662 if (!e.type.isscalar() && e.type.equals(exp.e1.type))
11663 {
11664 exp.error("recursive `opCmp` expansion");
11665 return setError();
11666 }
11667 if (e.op == EXP.call)
11668 {
11669
11670 if (t1.ty == Tclass && t2.ty == Tclass)
11671 {
11672 // Lower to object.__cmp(e1, e2)
11673 Expression cl = new IdentifierExp(exp.loc, Id.empty);
11674 cl = new DotIdExp(exp.loc, cl, Id.object);
11675 cl = new DotIdExp(exp.loc, cl, Id.__cmp);
11676 cl = cl.expressionSemantic(sc);
11677
11678 auto arguments = new Expressions();
11679 // Check if op_overload found a better match by calling e2.opCmp(e1)
11680 // If the operands were swapped, then the result must be reversed
11681 // e1.opCmp(e2) == -e2.opCmp(e1)
11682 // cmpop takes care of this
11683 if (exp.op == cmpop)
11684 {
11685 arguments.push(exp.e1);
11686 arguments.push(exp.e2);
11687 }
11688 else
11689 {
11690 // Use better match found by op_overload
11691 arguments.push(exp.e2);
11692 arguments.push(exp.e1);
11693 }
11694
11695 cl = new CallExp(exp.loc, cl, arguments);
11696 cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
11697 result = cl.expressionSemantic(sc);
11698 return;
11699 }
11700
11701 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
11702 e = e.expressionSemantic(sc);
11703 }
11704 result = e;
11705 return;
11706 }
11707
11708
11709 if (Expression ex = typeCombine(exp, sc))
11710 {
11711 result = ex;
11712 return;
11713 }
11714
11715 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11716 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11717 if (f1 || f2)
11718 return setError();
11719
11720 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11721
11722 // Special handling for array comparisons
11723 Expression arrayLowering = null;
11724 t1 = exp.e1.type.toBasetype();
11725 t2 = exp.e2.type.toBasetype();
11726 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
11727 {
11728 Type t1next = t1.nextOf();
11729 Type t2next = t2.nextOf();
11730 if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
11731 {
11732 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
11733 return setError();
11734 }
11735 if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
11736 {
11737 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
11738 return setError();
11739
11740 // Lower to object.__cmp(e1, e2)
11741 Expression al = new IdentifierExp(exp.loc, Id.empty);
11742 al = new DotIdExp(exp.loc, al, Id.object);
11743 al = new DotIdExp(exp.loc, al, Id.__cmp);
11744 al = al.expressionSemantic(sc);
11745
11746 auto arguments = new Expressions(2);
11747 (*arguments)[0] = exp.e1;
11748 (*arguments)[1] = exp.e2;
11749
11750 al = new CallExp(exp.loc, al, arguments);
11751 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
11752
11753 arrayLowering = al;
11754 }
11755 }
11756 else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
11757 {
11758 if (t2.ty == Tstruct)
11759 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
11760 else
11761 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
11762 return setError();
11763 }
11764 else if (t1.iscomplex() || t2.iscomplex())
11765 {
11766 exp.error("compare not defined for complex operands");
11767 return setError();
11768 }
11769 else if (t1.ty == Taarray || t2.ty == Taarray)
11770 {
11771 exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
11772 return setError();
11773 }
11774 else if (!target.isVectorOpSupported(t1, exp.op, t2))
11775 {
11776 result = exp.incompatibleTypes();
11777 return;
11778 }
11779 else
11780 {
11781 bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
11782 bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
11783 if (r1 || r2)
11784 return setError();
11785 }
11786
11787 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
11788 if (arrayLowering)
11789 {
11790 arrayLowering = arrayLowering.expressionSemantic(sc);
11791 result = arrayLowering;
11792 return;
11793 }
11794
11795 if (auto tv = t1.isTypeVector())
11796 exp.type = tv.toBooleanVector();
11797
11798 result = exp;
11799 return;
11800 }
11801
11802 override void visit(InExp exp)
11803 {
11804 if (exp.type)
11805 {
11806 result = exp;
11807 return;
11808 }
11809
11810 if (Expression ex = binSemanticProp(exp, sc))
11811 {
11812 result = ex;
11813 return;
11814 }
11815 Expression e = exp.op_overload(sc);
11816 if (e)
11817 {
11818 result = e;
11819 return;
11820 }
11821
11822 Type t2b = exp.e2.type.toBasetype();
11823 switch (t2b.ty)
11824 {
11825 case Taarray:
11826 {
11827 TypeAArray ta = cast(TypeAArray)t2b;
11828
11829 // Special handling for array keys
11830 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11831 {
11832 // Convert key to type of key
11833 exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11834 }
11835
11836 semanticTypeInfo(sc, ta.index);
11837
11838 // Return type is pointer to value
11839 exp.type = ta.nextOf().pointerTo();
11840 break;
11841 }
11842
11843 case Terror:
11844 return setError();
11845
11846 case Tarray, Tsarray:
11847 result = exp.incompatibleTypes();
11848 exp.errorSupplemental("`in` is only allowed on associative arrays");
11849 const(char)* slice = (t2b.ty == Tsarray) ? "[]" : "";
11850 exp.errorSupplemental("perhaps use `std.algorithm.find(%s, %s%s)` instead",
11851 exp.e1.toChars(), exp.e2.toChars(), slice);
11852 return;
11853
11854 default:
11855 result = exp.incompatibleTypes();
11856 return;
11857 }
11858 result = exp;
11859 }
11860
11861 override void visit(RemoveExp e)
11862 {
11863 if (Expression ex = binSemantic(e, sc))
11864 {
11865 result = ex;
11866 return;
11867 }
11868 result = e;
11869 }
11870
11871 override void visit(EqualExp exp)
11872 {
11873 //printf("EqualExp::semantic('%s')\n", exp.toChars());
11874 if (exp.type)
11875 {
11876 result = exp;
11877 return;
11878 }
11879
11880 exp.setNoderefOperands();
11881
11882 if (auto e = binSemanticProp(exp, sc))
11883 {
11884 result = e;
11885 return;
11886 }
11887 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
11888 {
11889 /* https://issues.dlang.org/show_bug.cgi?id=12520
11890 * empty tuples are represented as types so special cases are added
11891 * so that they can be compared for equality with tuples of values.
11892 */
11893 static auto extractTypeTupAndExpTup(Expression e)
11894 {
11895 static struct Result { bool ttEmpty; bool te; }
11896 auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
11897 return Result(tt && (!tt.arguments || !tt.arguments.length), e.isTupleExp() !is null);
11898 }
11899 auto tups1 = extractTypeTupAndExpTup(exp.e1);
11900 auto tups2 = extractTypeTupAndExpTup(exp.e2);
11901 // AliasSeq!() == AliasSeq!(<at least a value>)
11902 if (tups1.ttEmpty && tups2.te)
11903 {
11904 result = IntegerExp.createBool(exp.op != EXP.equal);
11905 return;
11906 }
11907 // AliasSeq!(<at least a value>) == AliasSeq!()
11908 else if (tups1.te && tups2.ttEmpty)
11909 {
11910 result = IntegerExp.createBool(exp.op != EXP.equal);
11911 return;
11912 }
11913 // AliasSeq!() == AliasSeq!()
11914 else if (tups1.ttEmpty && tups2.ttEmpty)
11915 {
11916 result = IntegerExp.createBool(exp.op == EXP.equal);
11917 return;
11918 }
11919 // otherwise, two types are really not comparable
11920 result = exp.incompatibleTypes();
11921 return;
11922 }
11923
11924 {
11925 auto t1 = exp.e1.type;
11926 auto t2 = exp.e2.type;
11927 if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11928 exp.error("comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11929 t1.toChars(), t2.toChars());
11930 }
11931
11932 /* Before checking for operator overloading, check to see if we're
11933 * comparing the addresses of two statics. If so, we can just see
11934 * if they are the same symbol.
11935 */
11936 if (exp.e1.op == EXP.address && exp.e2.op == EXP.address)
11937 {
11938 AddrExp ae1 = cast(AddrExp)exp.e1;
11939 AddrExp ae2 = cast(AddrExp)exp.e2;
11940 if (ae1.e1.op == EXP.variable && ae2.e1.op == EXP.variable)
11941 {
11942 VarExp ve1 = cast(VarExp)ae1.e1;
11943 VarExp ve2 = cast(VarExp)ae2.e1;
11944 if (ve1.var == ve2.var)
11945 {
11946 // They are the same, result is 'true' for ==, 'false' for !=
11947 result = IntegerExp.createBool(exp.op == EXP.equal);
11948 return;
11949 }
11950 }
11951 }
11952
11953 Type t1 = exp.e1.type.toBasetype();
11954 Type t2 = exp.e2.type.toBasetype();
11955
11956 // Indicates whether the comparison of the 2 specified array types
11957 // requires an object.__equals() lowering.
11958 static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11959 {
11960 Type t1n = t1.nextOf().toBasetype();
11961 Type t2n = t2.nextOf().toBasetype();
11962 if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11963 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11964 {
11965 return false;
11966 }
11967 if (t1n.constOf() != t2n.constOf())
11968 return true;
11969
11970 Type t = t1n;
11971 while (t.toBasetype().nextOf())
11972 t = t.nextOf().toBasetype();
11973 if (auto ts = t.isTypeStruct())
11974 {
11975 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11976 if (global.params.useTypeInfo && Type.dtypeinfo)
11977 semanticTypeInfo(sc, ts);
11978
11979 return ts.sym.hasIdentityEquals; // has custom opEquals
11980 }
11981
11982 return false;
11983 }
11984
11985 if (auto e = exp.op_overload(sc))
11986 {
11987 result = e;
11988 return;
11989 }
11990
11991
11992 const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11993 (t2.ty == Tarray || t2.ty == Tsarray);
11994 const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11995
11996 if (!needsArrayLowering)
11997 {
11998 if (auto e = typeCombine(exp, sc))
11999 {
12000 result = e;
12001 return;
12002 }
12003 }
12004
12005 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12006 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12007 if (f1 || f2)
12008 return setError();
12009
12010 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
12011
12012 if (!isArrayComparison)
12013 {
12014 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
12015 {
12016 // Cast both to complex
12017 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
12018 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
12019 }
12020 }
12021
12022 // lower some array comparisons to object.__equals(e1, e2)
12023 if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
12024 {
12025 //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
12026
12027 // https://issues.dlang.org/show_bug.cgi?id=22390
12028 // Equality comparison between array of noreturns simply lowers to length equality comparison
12029 if (t1.nextOf.isTypeNoreturn() && t2.nextOf.isTypeNoreturn())
12030 {
12031 Expression exp_l1 = new DotIdExp(exp.e1.loc, exp.e1, Id.length);
12032 Expression exp_l2 = new DotIdExp(exp.e2.loc, exp.e2, Id.length);
12033 auto e = new EqualExp(EXP.equal, exp.loc, exp_l1, exp_l2);
12034 result = e.expressionSemantic(sc);
12035 return;
12036 }
12037
12038 if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
12039 return setError();
12040
12041 Expression __equals = new IdentifierExp(exp.loc, Id.empty);
12042 Identifier id = Identifier.idPool("__equals");
12043 __equals = new DotIdExp(exp.loc, __equals, Id.object);
12044 __equals = new DotIdExp(exp.loc, __equals, id);
12045
12046 auto arguments = new Expressions(2);
12047 (*arguments)[0] = exp.e1;
12048 (*arguments)[1] = exp.e2;
12049
12050 __equals = new CallExp(exp.loc, __equals, arguments);
12051 if (exp.op == EXP.notEqual)
12052 {
12053 __equals = new NotExp(exp.loc, __equals);
12054 }
12055 __equals = __equals.trySemantic(sc); // for better error message
12056 if (!__equals)
12057 {
12058 exp.error("incompatible types for array comparison: `%s` and `%s`",
12059 exp.e1.type.toChars(), exp.e2.type.toChars());
12060 __equals = ErrorExp.get();
12061 }
12062
12063 result = __equals;
12064 return;
12065 }
12066
12067 if (exp.e1.type.toBasetype().ty == Taarray)
12068 semanticTypeInfo(sc, exp.e1.type.toBasetype());
12069
12070
12071 if (!target.isVectorOpSupported(t1, exp.op, t2))
12072 {
12073 result = exp.incompatibleTypes();
12074 return;
12075 }
12076
12077 if (auto tv = t1.isTypeVector())
12078 exp.type = tv.toBooleanVector();
12079
12080 result = exp;
12081 }
12082
12083 override void visit(IdentityExp exp)
12084 {
12085 if (exp.type)
12086 {
12087 result = exp;
12088 return;
12089 }
12090
12091 exp.setNoderefOperands();
12092
12093 if (auto e = binSemanticProp(exp, sc))
12094 {
12095 result = e;
12096 return;
12097 }
12098
12099 if (auto e = typeCombine(exp, sc))
12100 {
12101 result = e;
12102 return;
12103 }
12104
12105 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12106 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12107 if (f1 || f2)
12108 return setError();
12109
12110 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
12111 {
12112 result = exp.incompatibleTypes();
12113 return;
12114 }
12115
12116 exp.type = Type.tbool;
12117
12118 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
12119 {
12120 // Cast both to complex
12121 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
12122 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
12123 }
12124
12125 auto tb1 = exp.e1.type.toBasetype();
12126 auto tb2 = exp.e2.type.toBasetype();
12127 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
12128 {
12129 result = exp.incompatibleTypes();
12130 return;
12131 }
12132
12133 if (exp.e1.op == EXP.call)
12134 exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
12135 if (exp.e2.op == EXP.call)
12136 exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
12137
12138 if (exp.e1.type.toBasetype().ty == Tsarray ||
12139 exp.e2.type.toBasetype().ty == Tsarray)
12140 exp.deprecation("identity comparison of static arrays "
12141 ~ "implicitly coerces them to slices, "
12142 ~ "which are compared by reference");
12143
12144 result = exp;
12145 }
12146
12147 override void visit(CondExp exp)
12148 {
12149 static if (LOGSEMANTIC)
12150 {
12151 printf("CondExp::semantic('%s')\n", exp.toChars());
12152 }
12153 if (exp.type)
12154 {
12155 result = exp;
12156 return;
12157 }
12158
12159 if (auto die = exp.econd.isDotIdExp())
12160 die.noderef = true;
12161
12162 Expression ec = exp.econd.expressionSemantic(sc);
12163 ec = resolveProperties(sc, ec);
12164 ec = ec.toBoolean(sc);
12165
12166 CtorFlow ctorflow_root = sc.ctorflow.clone();
12167 Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
12168 e1x = resolveProperties(sc, e1x);
12169
12170 CtorFlow ctorflow1 = sc.ctorflow;
12171 sc.ctorflow = ctorflow_root;
12172 Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
12173 e2x = resolveProperties(sc, e2x);
12174
12175 sc.merge(exp.loc, ctorflow1);
12176 ctorflow1.freeFieldinit();
12177
12178 if (ec.op == EXP.error)
12179 {
12180 result = ec;
12181 return;
12182 }
12183 if (ec.type == Type.terror)
12184 return setError();
12185 exp.econd = ec;
12186
12187 if (e1x.op == EXP.error)
12188 {
12189 result = e1x;
12190 return;
12191 }
12192 if (e1x.type == Type.terror)
12193 return setError();
12194 exp.e1 = e1x;
12195
12196 if (e2x.op == EXP.error)
12197 {
12198 result = e2x;
12199 return;
12200 }
12201 if (e2x.type == Type.terror)
12202 return setError();
12203 exp.e2 = e2x;
12204
12205 auto f0 = checkNonAssignmentArrayOp(exp.econd);
12206 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12207 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12208 if (f0 || f1 || f2)
12209 return setError();
12210
12211 Type t1 = exp.e1.type;
12212 Type t2 = exp.e2.type;
12213 if (t1.ty == Tnoreturn)
12214 {
12215 exp.type = t2;
12216 exp.e1 = specialNoreturnCast(exp.e1, exp.type);
12217 }
12218 else if (t2.ty == Tnoreturn)
12219 {
12220 exp.type = t1;
12221 exp.e2 = specialNoreturnCast(exp.e2, exp.type);
12222 }
12223 // If either operand is void the result is void, we have to cast both
12224 // the expression to void so that we explicitly discard the expression
12225 // value if any
12226 // https://issues.dlang.org/show_bug.cgi?id=16598
12227 else if (t1.ty == Tvoid || t2.ty == Tvoid)
12228 {
12229 exp.type = Type.tvoid;
12230 exp.e1 = exp.e1.castTo(sc, exp.type);
12231 exp.e2 = exp.e2.castTo(sc, exp.type);
12232 }
12233 else if (t1 == t2)
12234 exp.type = t1;
12235 else
12236 {
12237 if (Expression ex = typeCombine(exp, sc))
12238 {
12239 result = ex;
12240 return;
12241 }
12242
12243 switch (exp.e1.type.toBasetype().ty)
12244 {
12245 case Tcomplex32:
12246 case Tcomplex64:
12247 case Tcomplex80:
12248 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
12249 break;
12250 default:
12251 break;
12252 }
12253 switch (exp.e2.type.toBasetype().ty)
12254 {
12255 case Tcomplex32:
12256 case Tcomplex64:
12257 case Tcomplex80:
12258 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
12259 break;
12260 default:
12261 break;
12262 }
12263 if (exp.type.toBasetype().ty == Tarray)
12264 {
12265 exp.e1 = exp.e1.castTo(sc, exp.type);
12266 exp.e2 = exp.e2.castTo(sc, exp.type);
12267 }
12268 }
12269 exp.type = exp.type.merge2();
12270 version (none)
12271 {
12272 printf("res: %s\n", exp.type.toChars());
12273 printf("e1 : %s\n", exp.e1.type.toChars());
12274 printf("e2 : %s\n", exp.e2.type.toChars());
12275 }
12276
12277 /* https://issues.dlang.org/show_bug.cgi?id=14696
12278 * If either e1 or e2 contain temporaries which need dtor,
12279 * make them conditional.
12280 * Rewrite:
12281 * cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
12282 * to:
12283 * (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
12284 * and replace edtors of __tmp1 and __tmp2 with:
12285 * __tmp1.edtor --> __cond && __tmp1.dtor()
12286 * __tmp2.edtor --> __cond || __tmp2.dtor()
12287 */
12288 exp.hookDtors(sc);
12289
12290 result = exp;
12291 }
12292
12293 override void visit(GenericExp exp)
12294 {
12295 static if (LOGSEMANTIC)
12296 {
12297 printf("GenericExp::semantic('%s')\n", exp.toChars());
12298 }
12299 // C11 6.5.1.1 Generic Selection
12300
12301 auto ec = exp.cntlExp.expressionSemantic(sc).arrayFuncConv(sc);
12302 bool errors = ec.isErrorExp() !is null;
12303 auto tc = ec.type;
12304
12305 auto types = (*exp.types)[];
12306 foreach (i, ref t; types)
12307 {
12308 if (!t)
12309 continue; // `default:` case
12310 t = t.typeSemantic(ec.loc, sc);
12311 if (t.isTypeError())
12312 {
12313 errors = true;
12314 continue;
12315 }
12316
12317 /* C11 6.5.1-2 duplicate check
12318 */
12319 /* C11 distinguishes int, long, and long long. But D doesn't, so depending on the
12320 * C target, a long may have the same type as `int` in the D type system.
12321 * So, skip checks when this may be the case. Later pick the first match
12322 */
12323 if (
12324 (t.ty == Tint32 || t.ty == Tuns32) && target.c.longsize == 4 ||
12325 (t.ty == Tint64 || t.ty == Tuns64) && target.c.longsize == 8 ||
12326 (t.ty == Tfloat64 || t.ty == Timaginary64 || t.ty == Tcomplex64) && target.c.long_doublesize == 8
12327 )
12328 continue;
12329
12330 foreach (t2; types[0 .. i])
12331 {
12332 if (t2 && t2.equals(t))
12333 {
12334 error(ec.loc, "generic association type `%s` can only appear once", t.toChars());
12335 errors = true;
12336 break;
12337 }
12338 }
12339 }
12340
12341 auto exps = (*exp.exps)[];
12342 foreach (ref e; exps)
12343 {
12344 e = e.expressionSemantic(sc);
12345 if (e.isErrorExp())
12346 errors = true;
12347 }
12348
12349 if (errors)
12350 return setError();
12351
12352 enum size_t None = ~0;
12353 size_t imatch = None;
12354 size_t idefault = None;
12355 foreach (const i, t; types)
12356 {
12357 if (t)
12358 {
12359 /* if tc is compatible with t, it's a match
12360 * C11 6.2.7 defines a compatible type as being the same type, including qualifiers
12361 */
12362 if (tc.equals(t))
12363 {
12364 assert(imatch == None);
12365 imatch = i;
12366 break; // pick first match
12367 }
12368 }
12369 else
12370 idefault = i; // multiple defaults are not allowed, and are caught by cparse
12371 }
12372
12373 if (imatch == None)
12374 imatch = idefault;
12375 if (imatch == None)
12376 {
12377 error(exp.loc, "no compatible generic association type for controlling expression type `%s`", tc.toChars());
12378 return setError();
12379 }
12380
12381 result = exps[imatch];
12382 }
12383
12384 override void visit(FileInitExp e)
12385 {
12386 //printf("FileInitExp::semantic()\n");
12387 e.type = Type.tstring;
12388 result = e;
12389 }
12390
12391 override void visit(LineInitExp e)
12392 {
12393 e.type = Type.tint32;
12394 result = e;
12395 }
12396
12397 override void visit(ModuleInitExp e)
12398 {
12399 //printf("ModuleInitExp::semantic()\n");
12400 e.type = Type.tstring;
12401 result = e;
12402 }
12403
12404 override void visit(FuncInitExp e)
12405 {
12406 //printf("FuncInitExp::semantic()\n");
12407 e.type = Type.tstring;
12408 if (sc.func)
12409 {
12410 result = e.resolveLoc(Loc.initial, sc);
12411 return;
12412 }
12413 result = e;
12414 }
12415
12416 override void visit(PrettyFuncInitExp e)
12417 {
12418 //printf("PrettyFuncInitExp::semantic()\n");
12419 e.type = Type.tstring;
12420 if (sc.func)
12421 {
12422 result = e.resolveLoc(Loc.initial, sc);
12423 return;
12424 }
12425
12426 result = e;
12427 }
12428 }
12429
12430 /**********************************
12431 * Try to run semantic routines.
12432 * If they fail, return NULL.
12433 */
12434 Expression trySemantic(Expression exp, Scope* sc)
12435 {
12436 //printf("+trySemantic(%s)\n", exp.toChars());
12437 uint errors = global.startGagging();
12438 Expression e = expressionSemantic(exp, sc);
12439 if (global.endGagging(errors))
12440 {
12441 e = null;
12442 }
12443 //printf("-trySemantic(%s)\n", exp.toChars());
12444 return e;
12445 }
12446
12447 /**************************
12448 * Helper function for easy error propagation.
12449 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12450 */
12451 Expression unaSemantic(UnaExp e, Scope* sc)
12452 {
12453 static if (LOGSEMANTIC)
12454 {
12455 printf("UnaExp::semantic('%s')\n", e.toChars());
12456 }
12457 Expression e1x = e.e1.expressionSemantic(sc);
12458 if (e1x.op == EXP.error)
12459 return e1x;
12460 e.e1 = e1x;
12461 return null;
12462 }
12463
12464 /**************************
12465 * Helper function for easy error propagation.
12466 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12467 */
12468 Expression binSemantic(BinExp e, Scope* sc)
12469 {
12470 static if (LOGSEMANTIC)
12471 {
12472 printf("BinExp::semantic('%s')\n", e.toChars());
12473 }
12474 Expression e1x = e.e1.expressionSemantic(sc);
12475 Expression e2x = e.e2.expressionSemantic(sc);
12476
12477 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
12478 if (e1x.op == EXP.type)
12479 e1x = resolveAliasThis(sc, e1x);
12480 if (e2x.op == EXP.type)
12481 e2x = resolveAliasThis(sc, e2x);
12482
12483 if (e1x.op == EXP.error)
12484 return e1x;
12485 if (e2x.op == EXP.error)
12486 return e2x;
12487 e.e1 = e1x;
12488 e.e2 = e2x;
12489 return null;
12490 }
12491
12492 Expression binSemanticProp(BinExp e, Scope* sc)
12493 {
12494 if (Expression ex = binSemantic(e, sc))
12495 return ex;
12496 Expression e1x = resolveProperties(sc, e.e1);
12497 Expression e2x = resolveProperties(sc, e.e2);
12498 if (e1x.op == EXP.error)
12499 return e1x;
12500 if (e2x.op == EXP.error)
12501 return e2x;
12502 e.e1 = e1x;
12503 e.e2 = e2x;
12504 return null;
12505 }
12506
12507 // entrypoint for semantic ExpressionSemanticVisitor
12508 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
12509 {
12510 scope v = new ExpressionSemanticVisitor(sc);
12511 e.accept(v);
12512 return v.result;
12513 }
12514
12515 private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
12516 {
12517 //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
12518 if (Expression ex = unaSemantic(exp, sc))
12519 return ex;
12520
12521 if (!(sc.flags & SCOPE.Cfile) && exp.ident == Id._mangleof)
12522 {
12523 // symbol.mangleof
12524
12525 // return mangleof as an Expression
12526 static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
12527 {
12528 assert(ds);
12529 if (auto f = ds.isFuncDeclaration())
12530 {
12531 if (f.checkForwardRef(loc))
12532 return ErrorExp.get();
12533
12534 if (f.purityInprocess || f.safetyInprocess || f.nothrowInprocess || f.nogcInprocess)
12535 {
12536 f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
12537 return ErrorExp.get();
12538 }
12539 }
12540 OutBuffer buf;
12541 mangleToBuffer(ds, &buf);
12542 Expression e = new StringExp(loc, buf.extractSlice());
12543 return e.expressionSemantic(sc);
12544 }
12545
12546 Dsymbol ds;
12547 switch (exp.e1.op)
12548 {
12549 case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
12550 case EXP.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
12551 case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
12552 case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
12553 case EXP.template_:
12554 {
12555 TemplateExp te = exp.e1.isTemplateExp();
12556 return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
12557 }
12558
12559 default:
12560 break;
12561 }
12562 }
12563
12564 if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
12565 {
12566 // bypass checkPurity
12567 return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
12568 }
12569
12570 if (!exp.e1.isDotExp())
12571 {
12572 exp.e1 = resolvePropertiesX(sc, exp.e1);
12573 }
12574
12575 if (auto te = exp.e1.isTupleExp())
12576 {
12577 if (exp.ident == Id.offsetof)
12578 {
12579 /* 'distribute' the .offsetof to each of the tuple elements.
12580 */
12581 auto exps = new Expressions(te.exps.length);
12582 foreach (i, e; (*te.exps)[])
12583 {
12584 (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
12585 }
12586 // Don't evaluate te.e0 in runtime
12587 Expression e = new TupleExp(exp.loc, null, exps);
12588 e = e.expressionSemantic(sc);
12589 return e;
12590 }
12591 if (exp.ident == Id.length)
12592 {
12593 // Don't evaluate te.e0 in runtime
12594 return new IntegerExp(exp.loc, te.exps.length, Type.tsize_t);
12595 }
12596 }
12597
12598 // https://issues.dlang.org/show_bug.cgi?id=14416
12599 // Template has no built-in properties except for 'stringof'.
12600 if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
12601 {
12602 exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12603 return ErrorExp.get();
12604 }
12605 if (!exp.e1.type)
12606 {
12607 exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12608 return ErrorExp.get();
12609 }
12610
12611 return exp;
12612 }
12613
12614 /******************************
12615 * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
12616 * Params:
12617 * exp = expression to resolve
12618 * sc = context
12619 * flag = if 1 then do not emit error messages, just return null
12620 * Returns:
12621 * resolved expression, null if error
12622 */
12623 Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, int flag)
12624 {
12625 //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
12626
12627 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
12628
12629 const cfile = (sc.flags & SCOPE.Cfile) != 0;
12630
12631 /* Special case: rewrite this.id and super.id
12632 * to be classtype.id and baseclasstype.id
12633 * if we have no this pointer.
12634 */
12635 if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
12636 {
12637 if (AggregateDeclaration ad = sc.getStructClassScope())
12638 {
12639 if (exp.e1.isThisExp())
12640 {
12641 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
12642 }
12643 else
12644 {
12645 if (auto cd = ad.isClassDeclaration())
12646 {
12647 if (cd.baseClass)
12648 exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
12649 }
12650 }
12651 }
12652 }
12653
12654 {
12655 Expression e = dotIdSemanticPropX(exp, sc);
12656 if (e != exp)
12657 return e;
12658 }
12659
12660 Expression eleft;
12661 Expression eright;
12662 if (auto de = exp.e1.isDotExp())
12663 {
12664 eleft = de.e1;
12665 eright = de.e2;
12666 }
12667 else
12668 {
12669 eleft = null;
12670 eright = exp.e1;
12671 }
12672
12673 Type t1b = exp.e1.type.toBasetype();
12674
12675 if (auto ie = eright.isScopeExp()) // also used for template alias's
12676 {
12677 auto flags = SearchLocalsOnly;
12678 /* Disable access to another module's private imports.
12679 * The check for 'is sds our current module' is because
12680 * the current module should have access to its own imports.
12681 */
12682 if (ie.sds.isModule() && ie.sds != sc._module)
12683 flags |= IgnorePrivateImports;
12684 if (sc.flags & SCOPE.ignoresymbolvisibility)
12685 flags |= IgnoreSymbolVisibility;
12686 Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
12687 /* Check for visibility before resolving aliases because public
12688 * aliases to private symbols are public.
12689 */
12690 if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
12691 {
12692 s = null;
12693 }
12694 if (s)
12695 {
12696 auto p = s.isPackage();
12697 if (p && checkAccess(sc, p))
12698 {
12699 s = null;
12700 }
12701 }
12702 if (s)
12703 {
12704 // if 's' is a tuple variable, the tuple is returned.
12705 s = s.toAlias();
12706
12707 exp.checkDeprecated(sc, s);
12708 exp.checkDisabled(sc, s);
12709
12710 if (auto em = s.isEnumMember())
12711 {
12712 return em.getVarExp(exp.loc, sc);
12713 }
12714 if (auto v = s.isVarDeclaration())
12715 {
12716 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
12717 if (!v.type ||
12718 !v.type.deco && v.inuse)
12719 {
12720 if (v.inuse)
12721 exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
12722 else
12723 exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
12724 return ErrorExp.get();
12725 }
12726 if (v.type.isTypeError())
12727 return ErrorExp.get();
12728
12729 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
12730 {
12731 /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
12732 * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
12733 * be reverted. `wantsym` is the hack to work around the problem.
12734 */
12735 if (v.inuse)
12736 {
12737 error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
12738 return ErrorExp.get();
12739 }
12740 auto e = v.expandInitializer(exp.loc);
12741 v.inuse++;
12742 e = e.expressionSemantic(sc);
12743 v.inuse--;
12744 return e;
12745 }
12746
12747 Expression e;
12748 if (v.needThis())
12749 {
12750 if (!eleft)
12751 eleft = new ThisExp(exp.loc);
12752 e = new DotVarExp(exp.loc, eleft, v);
12753 e = e.expressionSemantic(sc);
12754 }
12755 else
12756 {
12757 e = new VarExp(exp.loc, v);
12758 if (eleft)
12759 {
12760 e = new CommaExp(exp.loc, eleft, e);
12761 e.type = v.type;
12762 }
12763 }
12764 e = e.deref();
12765 return e.expressionSemantic(sc);
12766 }
12767
12768 if (auto f = s.isFuncDeclaration())
12769 {
12770 //printf("it's a function\n");
12771 if (!f.functionSemantic())
12772 return ErrorExp.get();
12773 Expression e;
12774 if (f.needThis())
12775 {
12776 if (!eleft)
12777 eleft = new ThisExp(exp.loc);
12778 e = new DotVarExp(exp.loc, eleft, f, true);
12779 e = e.expressionSemantic(sc);
12780 }
12781 else
12782 {
12783 e = new VarExp(exp.loc, f, true);
12784 if (eleft)
12785 {
12786 e = new CommaExp(exp.loc, eleft, e);
12787 e.type = f.type;
12788 }
12789 }
12790 return e;
12791 }
12792 if (auto td = s.isTemplateDeclaration())
12793 {
12794 Expression e;
12795 if (eleft)
12796 e = new DotTemplateExp(exp.loc, eleft, td);
12797 else
12798 e = new TemplateExp(exp.loc, td);
12799 e = e.expressionSemantic(sc);
12800 return e;
12801 }
12802 if (OverDeclaration od = s.isOverDeclaration())
12803 {
12804 Expression e = new VarExp(exp.loc, od, true);
12805 if (eleft)
12806 {
12807 e = new CommaExp(exp.loc, eleft, e);
12808 e.type = Type.tvoid; // ambiguous type?
12809 }
12810 return e.expressionSemantic(sc);
12811 }
12812 if (auto o = s.isOverloadSet())
12813 {
12814 //printf("'%s' is an overload set\n", o.toChars());
12815 return new OverExp(exp.loc, o);
12816 }
12817
12818 if (auto t = s.getType())
12819 {
12820 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
12821 }
12822
12823 if (auto tup = s.isTupleDeclaration())
12824 {
12825 if (eleft)
12826 {
12827 Expression e = new DotVarExp(exp.loc, eleft, tup);
12828 e = e.expressionSemantic(sc);
12829 return e;
12830 }
12831 Expression e = new TupleExp(exp.loc, tup);
12832 e = e.expressionSemantic(sc);
12833 return e;
12834 }
12835
12836 if (auto sds = s.isScopeDsymbol())
12837 {
12838 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
12839 Expression e = new ScopeExp(exp.loc, sds);
12840 e = e.expressionSemantic(sc);
12841 if (eleft)
12842 e = new DotExp(exp.loc, eleft, e);
12843 return e;
12844 }
12845
12846 if (auto imp = s.isImport())
12847 {
12848 Expression se = new ScopeExp(exp.loc, imp.pkg);
12849 return se.expressionSemantic(sc);
12850 }
12851 // BUG: handle other cases like in IdentifierExp::semantic()
12852 debug
12853 {
12854 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
12855 }
12856 assert(0);
12857 }
12858 else if (exp.ident == Id.stringof)
12859 {
12860 Expression e = new StringExp(exp.loc, ie.toString());
12861 e = e.expressionSemantic(sc);
12862 return e;
12863 }
12864 if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
12865 {
12866 flag = 0;
12867 }
12868 if (flag)
12869 return null;
12870 s = ie.sds.search_correct(exp.ident);
12871 if (s && symbolIsVisible(sc, s))
12872 {
12873 if (s.isPackage())
12874 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
12875 else
12876 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());
12877 }
12878 else
12879 exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
12880 return ErrorExp.get();
12881 }
12882 else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum &&
12883 !(
12884 exp.ident == Id.__sizeof ||
12885 exp.ident == Id.__xalignof ||
12886 !cfile &&
12887 (exp.ident == Id._mangleof ||
12888 exp.ident == Id.offsetof ||
12889 exp.ident == Id._init ||
12890 exp.ident == Id.stringof)
12891 ))
12892 {
12893 Type t1bn = t1b.nextOf();
12894 if (flag)
12895 {
12896 if (AggregateDeclaration ad = isAggregate(t1bn))
12897 {
12898 if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
12899 return null;
12900 }
12901 }
12902
12903 /* Rewrite:
12904 * p.ident
12905 * as:
12906 * (*p).ident
12907 */
12908 if (flag && t1bn.ty == Tvoid)
12909 return null;
12910 Expression e = new PtrExp(exp.loc, exp.e1);
12911 e = e.expressionSemantic(sc);
12912 return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12913 }
12914 else if (exp.ident == Id.__xalignof &&
12915 exp.e1.isVarExp() &&
12916 exp.e1.isVarExp().var.isVarDeclaration() &&
12917 !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
12918 {
12919 // For `x.alignof` get the alignment of the variable, not the alignment of its type
12920 const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
12921 const naturalAlignment = exp.e1.type.alignsize();
12922 const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
12923 Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
12924 return e;
12925 }
12926 else if ((exp.ident == Id.max || exp.ident == Id.min) &&
12927 exp.e1.isVarExp() &&
12928 exp.e1.isVarExp().var.isBitFieldDeclaration())
12929 {
12930 // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
12931 auto bf = exp.e1.isVarExp().var.isBitFieldDeclaration();
12932 return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
12933 }
12934 else if ((exp.ident == Id.max || exp.ident == Id.min) &&
12935 exp.e1.isDotVarExp() &&
12936 exp.e1.isDotVarExp().var.isBitFieldDeclaration())
12937 {
12938 // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
12939 auto bf = exp.e1.isDotVarExp().var.isBitFieldDeclaration();
12940 return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
12941 }
12942 else
12943 {
12944 if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
12945 flag = 0;
12946 Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12947 if (e)
12948 {
12949 e = e.expressionSemantic(sc);
12950 }
12951 return e;
12952 }
12953 }
12954
12955 // Resolve e1.ident!tiargs without seeing UFCS.
12956 // If flag == 1, stop "not a property" error and return NULL.
12957 Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, int flag)
12958 {
12959 static if (LOGSEMANTIC)
12960 {
12961 printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
12962 }
12963
12964 static Expression errorExp()
12965 {
12966 return ErrorExp.get();
12967 }
12968
12969 Expression e1 = exp.e1;
12970
12971 if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
12972 {
12973 // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
12974 // and do the symbol search in that context (Issue: 19476)
12975 auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
12976 e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12977 }
12978
12979 auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12980
12981 Expression e = die.dotIdSemanticPropX(sc);
12982 if (e == die)
12983 {
12984 exp.e1 = die.e1; // take back
12985 Type t1b = exp.e1.type.toBasetype();
12986 if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12987 {
12988 /* No built-in type has templatized properties, so do shortcut.
12989 * It is necessary in: 1024.max!"a < b"
12990 */
12991 if (flag)
12992 return null;
12993 }
12994 e = die.dotIdSemanticProp(sc, flag);
12995 if (flag)
12996 {
12997 if (!e ||
12998 isDotOpDispatch(e))
12999 {
13000 /* opDispatch!tiargs would be a function template that needs IFTI,
13001 * so it's not a template
13002 */
13003 return null;
13004 }
13005 }
13006 }
13007 assert(e);
13008
13009 if (e.op == EXP.error)
13010 return e;
13011 if (DotVarExp dve = e.isDotVarExp())
13012 {
13013 if (FuncDeclaration fd = dve.var.isFuncDeclaration())
13014 {
13015 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
13016 {
13017 e = new DotTemplateExp(dve.loc, dve.e1, td);
13018 e = e.expressionSemantic(sc);
13019 }
13020 }
13021 else if (OverDeclaration od = dve.var.isOverDeclaration())
13022 {
13023 exp.e1 = dve.e1; // pull semantic() result
13024
13025 if (!exp.findTempDecl(sc))
13026 goto Lerr;
13027 if (exp.ti.needsTypeInference(sc))
13028 return exp;
13029 exp.ti.dsymbolSemantic(sc);
13030 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13031 return errorExp();
13032
13033 if (Declaration v = exp.ti.toAlias().isDeclaration())
13034 {
13035 if (v.type && !v.type.deco)
13036 v.type = v.type.typeSemantic(v.loc, sc);
13037 return new DotVarExp(exp.loc, exp.e1, v)
13038 .expressionSemantic(sc);
13039 }
13040 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13041 .expressionSemantic(sc);
13042 }
13043 }
13044 else if (e.op == EXP.variable)
13045 {
13046 VarExp ve = cast(VarExp)e;
13047 if (FuncDeclaration fd = ve.var.isFuncDeclaration())
13048 {
13049 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
13050 {
13051 e = new TemplateExp(ve.loc, td)
13052 .expressionSemantic(sc);
13053 }
13054 }
13055 else if (OverDeclaration od = ve.var.isOverDeclaration())
13056 {
13057 exp.ti.tempdecl = od;
13058 return new ScopeExp(exp.loc, exp.ti)
13059 .expressionSemantic(sc);
13060 }
13061 }
13062
13063 if (DotTemplateExp dte = e.isDotTemplateExp())
13064 {
13065 exp.e1 = dte.e1; // pull semantic() result
13066
13067 exp.ti.tempdecl = dte.td;
13068 if (!exp.ti.semanticTiargs(sc))
13069 return errorExp();
13070 if (exp.ti.needsTypeInference(sc))
13071 return exp;
13072 exp.ti.dsymbolSemantic(sc);
13073 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13074 return errorExp();
13075
13076 if (Declaration v = exp.ti.toAlias().isDeclaration())
13077 {
13078 return new DotVarExp(exp.loc, exp.e1, v)
13079 .expressionSemantic(sc);
13080 }
13081 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13082 .expressionSemantic(sc);
13083 }
13084 else if (e.op == EXP.template_)
13085 {
13086 exp.ti.tempdecl = (cast(TemplateExp)e).td;
13087 return new ScopeExp(exp.loc, exp.ti)
13088 .expressionSemantic(sc);
13089 }
13090 else if (DotExp de = e.isDotExp())
13091 {
13092 if (de.e2.op == EXP.overloadSet)
13093 {
13094 if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
13095 {
13096 return errorExp();
13097 }
13098 if (exp.ti.needsTypeInference(sc))
13099 return exp;
13100 exp.ti.dsymbolSemantic(sc);
13101 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13102 return errorExp();
13103
13104 if (Declaration v = exp.ti.toAlias().isDeclaration())
13105 {
13106 if (v.type && !v.type.deco)
13107 v.type = v.type.typeSemantic(v.loc, sc);
13108 return new DotVarExp(exp.loc, exp.e1, v)
13109 .expressionSemantic(sc);
13110 }
13111 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13112 .expressionSemantic(sc);
13113 }
13114 }
13115 else if (OverExp oe = e.isOverExp())
13116 {
13117 exp.ti.tempdecl = oe.vars;
13118 return new ScopeExp(exp.loc, exp.ti)
13119 .expressionSemantic(sc);
13120 }
13121
13122 Lerr:
13123 exp.error("`%s` isn't a template", e.toChars());
13124 return errorExp();
13125 }
13126
13127 /***************************************
13128 * If expression is shared, check that we can access it.
13129 * Give error message if not.
13130 *
13131 * Params:
13132 * e = expression to check
13133 * sc = context
13134 * returnRef = Whether this expression is for a `return` statement
13135 * off a `ref` function, in which case a single level
13136 * of dereference is allowed (e.g. `shared(int)*`).
13137 * Returns:
13138 * true on error
13139 */
13140 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
13141 {
13142 if (global.params.noSharedAccess != FeatureState.enabled ||
13143 !sc ||
13144 sc.intypeof ||
13145 sc.flags & SCOPE.ctfe)
13146 {
13147 return false;
13148 }
13149
13150 //printf("checkSharedAccess() `%s` returnRef: %d\n", e.toChars(), returnRef);
13151
13152 /* In case we don't know which expression triggered it,
13153 * e.g. for `visit(Type)` overload
13154 */
13155 Expression original = e;
13156
13157 bool check(Expression e, bool allowRef)
13158 {
13159 bool sharedError(Expression e)
13160 {
13161 // https://dlang.org/phobos/core_atomic.html
13162 e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
13163 return true;
13164 }
13165
13166 // Error by default
13167 bool visit(Expression e)
13168 {
13169 if (e.type.isShared())
13170 return sharedError(e);
13171 return false;
13172 }
13173
13174 bool visitNew(NewExp e)
13175 {
13176 if (e.thisexp)
13177 check(e.thisexp, false);
13178 // Note: This handles things like `new shared(Throwable).msg`,
13179 // where accessing `msg` would violate `shared`.
13180 if (e.newtype.isShared())
13181 return sharedError(original);
13182 return false;
13183 }
13184
13185 bool visitVar(VarExp e)
13186 {
13187 // https://issues.dlang.org/show_bug.cgi?id=22626
13188 // Synchronized functions don't need to use core.atomic
13189 // when accessing `this`.
13190 if (sc.func && sc.func.isSynchronized())
13191 {
13192 if (e.var.isThisDeclaration())
13193 return false;
13194 else
13195 return sharedError(e);
13196 }
13197 else if (!allowRef && e.var.type.isShared())
13198 return sharedError(e);
13199
13200 return false;
13201 }
13202
13203 bool visitAddr(AddrExp e)
13204 {
13205 return check(e.e1, true);
13206 }
13207
13208 bool visitPtr(PtrExp e)
13209 {
13210 if (!allowRef && e.type.isShared())
13211 return sharedError(e);
13212
13213 if (e.e1.type.isShared())
13214 return sharedError(e);
13215
13216 return check(e.e1, false);
13217 }
13218
13219 bool visitThis(ThisExp e)
13220 {
13221 if (sc.func && sc.func.isSynchronized())
13222 return false;
13223
13224 if (!allowRef && e.type.isShared())
13225 return sharedError(e);
13226
13227 return false;
13228 }
13229
13230 bool visitDotVar(DotVarExp e)
13231 {
13232 //printf("dotvarexp = %s\n", e.toChars());
13233 auto fd = e.var.isFuncDeclaration();
13234 const sharedFunc = fd && fd.type.isShared;
13235 // Allow using `DotVarExp` within value types
13236 if (!allowRef && e.type.isShared() && !sharedFunc && !(sc.func && sc.func.isSynchronized()))
13237 return sharedError(e);
13238 if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
13239 return check(e.e1, allowRef);
13240
13241 // If we end up with a single `VarExp`, it might be a `ref` param
13242 // `shared ref T` param == `shared(T)*`.
13243 if (auto ve = e.e1.isVarExp())
13244 {
13245 return check(e.e1, allowRef && (ve.var.storage_class & STC.ref_));
13246 }
13247
13248 return check(e.e1, false);
13249 }
13250
13251 bool visitIndex(IndexExp e)
13252 {
13253 if (!allowRef && e.type.isShared())
13254 return sharedError(e);
13255
13256 if (e.e1.type.isShared())
13257 return sharedError(e);
13258
13259 return check(e.e1, false);
13260 }
13261
13262 bool visitComma(CommaExp e)
13263 {
13264 // Cannot be `return ref` since we can't use the return,
13265 // but it's better to show that error than an unrelated `shared` one
13266 return check(e.e2, true);
13267 }
13268
13269 switch (e.op)
13270 {
13271 default: return visit(e);
13272
13273 // Those have no indirections / can be ignored
13274 case EXP.call:
13275 case EXP.error:
13276 case EXP.complex80:
13277 case EXP.int64:
13278 case EXP.null_: return false;
13279
13280 case EXP.variable: return visitVar(e.isVarExp());
13281 case EXP.new_: return visitNew(e.isNewExp());
13282 case EXP.address: return visitAddr(e.isAddrExp());
13283 case EXP.star: return visitPtr(e.isPtrExp());
13284 case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
13285 case EXP.index: return visitIndex(e.isIndexExp());
13286 case EXP.this_: return visitThis(e.isThisExp());
13287 }
13288 }
13289
13290 return check(e, returnRef);
13291 }
13292
13293
13294
13295 /****************************************************
13296 * Determine if `exp`, which gets its address taken, can do so safely.
13297 * Params:
13298 * sc = context
13299 * exp = expression having its address taken
13300 * v = the variable getting its address taken
13301 * Returns:
13302 * `true` if ok, `false` for error
13303 */
13304 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
13305 {
13306 //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
13307 if (v is null)
13308 return true;
13309
13310 if (!v.canTakeAddressOf())
13311 {
13312 exp.error("cannot take address of `%s`", exp.toChars());
13313 return false;
13314 }
13315 if (sc.func && !sc.intypeof && !v.isDataseg())
13316 {
13317 if (global.params.useDIP1000 != FeatureState.enabled &&
13318 !(v.storage_class & STC.temp) &&
13319 sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func))
13320 {
13321 return false;
13322 }
13323 }
13324 return true;
13325 }
13326
13327 /**************************************
13328 * This check ensures that the object in `exp` can have its address taken, or
13329 * issue a diagnostic error.
13330 * Params:
13331 * e = expression to check
13332 * sc = context
13333 * Returns:
13334 * true if the expression is addressable
13335 */
13336 bool checkAddressable(Expression e, Scope* sc)
13337 {
13338 Expression ex = e;
13339 while (true)
13340 {
13341 switch (ex.op)
13342 {
13343 case EXP.dotVariable:
13344 // https://issues.dlang.org/show_bug.cgi?id=22749
13345 // Error about taking address of any bit-field, regardless of
13346 // whether SCOPE.Cfile is set.
13347 if (auto bf = ex.isDotVarExp().var.isBitFieldDeclaration())
13348 {
13349 e.error("cannot take address of bit-field `%s`", bf.toChars());
13350 return false;
13351 }
13352 goto case EXP.cast_;
13353
13354 case EXP.index:
13355 ex = ex.isBinExp().e1;
13356 continue;
13357
13358 case EXP.address:
13359 case EXP.array:
13360 case EXP.cast_:
13361 ex = ex.isUnaExp().e1;
13362 continue;
13363
13364 case EXP.variable:
13365 if (sc.flags & SCOPE.Cfile)
13366 {
13367 // C11 6.5.3.2: A variable that has its address taken cannot be
13368 // stored in a register.
13369 // C11 6.3.2.1: An array that has its address computed with `[]`
13370 // or cast to an lvalue pointer cannot be stored in a register.
13371 if (ex.isVarExp().var.storage_class & STC.register)
13372 {
13373 if (e.isIndexExp())
13374 e.error("cannot index through register variable `%s`", ex.toChars());
13375 else
13376 e.error("cannot take address of register variable `%s`", ex.toChars());
13377 return false;
13378 }
13379 }
13380 break;
13381
13382 default:
13383 break;
13384 }
13385 break;
13386 }
13387 return true;
13388 }
13389
13390
13391 /*******************************
13392 * Checks the attributes of a function.
13393 * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
13394 * and usage of `deprecated` and `@disabled`-ed symbols are checked.
13395 *
13396 * Params:
13397 * exp = expression to check attributes for
13398 * sc = scope of the function
13399 * f = function to be checked
13400 * Returns: `true` if error occur.
13401 */
13402 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
13403 {
13404 with(exp)
13405 {
13406 bool error = checkDisabled(sc, f);
13407 error |= checkDeprecated(sc, f);
13408 error |= checkPurity(sc, f);
13409 error |= checkSafety(sc, f);
13410 error |= checkNogc(sc, f);
13411 return error;
13412 }
13413 }
13414
13415 /*******************************
13416 * Helper function for `getRightThis()`.
13417 * Gets `this` of the next outer aggregate.
13418 * Params:
13419 * loc = location to use for error messages
13420 * sc = context
13421 * s = the parent symbol of the existing `this`
13422 * ad = struct or class we need the correct `this` for
13423 * e1 = existing `this`
13424 * t = type of the existing `this`
13425 * var = the specific member of ad we're accessing
13426 * flag = if true, return `null` instead of throwing an error
13427 * Returns:
13428 * Expression representing the `this` for the var
13429 */
13430 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
13431 {
13432 int n = 0;
13433 while (s && s.isFuncDeclaration())
13434 {
13435 FuncDeclaration f = s.isFuncDeclaration();
13436 if (f.vthis)
13437 {
13438 n++;
13439 e1 = new VarExp(loc, f.vthis);
13440 if (f.hasDualContext())
13441 {
13442 // (*__this)[i]
13443 if (n > 1)
13444 e1 = e1.expressionSemantic(sc);
13445 e1 = new PtrExp(loc, e1);
13446 uint i = f.followInstantiationContext(ad);
13447 e1 = new IndexExp(loc, e1, new IntegerExp(i));
13448 s = f.toParentP(ad);
13449 continue;
13450 }
13451 }
13452 else
13453 {
13454 if (flag)
13455 return null;
13456 e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
13457 e1 = ErrorExp.get();
13458 return e1;
13459 }
13460 s = s.toParent2();
13461 }
13462 if (n > 1 || e1.op == EXP.index)
13463 e1 = e1.expressionSemantic(sc);
13464 if (s && e1.type.equivalent(Type.tvoidptr))
13465 {
13466 if (auto sad = s.isAggregateDeclaration())
13467 {
13468 Type ta = sad.handleType();
13469 if (ta.ty == Tstruct)
13470 ta = ta.pointerTo();
13471 e1.type = ta;
13472 }
13473 }
13474 e1.type = e1.type.addMod(t.mod);
13475 return e1;
13476 }
13477
13478 /*******************************
13479 * Make a dual-context container for use as a `this` argument.
13480 * Params:
13481 * loc = location to use for error messages
13482 * sc = current scope
13483 * fd = target function that will take the `this` argument
13484 * Returns:
13485 * Temporary closure variable.
13486 * Note:
13487 * The function `fd` is added to the nested references of the
13488 * newly created variable such that a closure is made for the variable when
13489 * the address of `fd` is taken.
13490 */
13491 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
13492 {
13493 Type tthis2 = Type.tvoidptr.sarrayOf(2);
13494 VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
13495 vthis2.storage_class |= STC.temp;
13496 vthis2.dsymbolSemantic(sc);
13497 vthis2.parent = sc.parent;
13498 // make it a closure var
13499 assert(sc.func);
13500 sc.func.closureVars.push(vthis2);
13501 // add `fd` to the nested refs
13502 vthis2.nestedrefs.push(fd);
13503 return vthis2;
13504 }
13505
13506 /*******************************
13507 * Make sure that the runtime hook `id` exists.
13508 * Params:
13509 * loc = location to use for error messages
13510 * sc = current scope
13511 * id = the hook identifier
13512 * description = what the hook does
13513 * module_ = what module the hook is located in
13514 * Returns:
13515 * a `bool` indicating if the hook is present.
13516 */
13517 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
13518 {
13519 auto rootSymbol = sc.search(loc, Id.empty, null);
13520 if (auto moduleSymbol = rootSymbol.search(loc, module_))
13521 if (moduleSymbol.search(loc, id))
13522 return true;
13523 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);
13524 return false;
13525 }
13526
13527 /***************************************
13528 * Fit elements[] to the corresponding types of the `sd`'s fields.
13529 *
13530 * Params:
13531 * sd = the struct declaration
13532 * loc = location to use for error messages
13533 * sc = context
13534 * elements = explicit arguments used to construct object
13535 * stype = the constructed object type.
13536 * Returns:
13537 * false if any errors occur,
13538 * otherwise true and elements[] are rewritten for the output.
13539 */
13540 private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
13541 {
13542 if (!elements)
13543 return true;
13544
13545 const nfields = sd.nonHiddenFields();
13546 size_t offset = 0;
13547 for (size_t i = 0; i < elements.length; i++)
13548 {
13549 Expression e = (*elements)[i];
13550 if (!e)
13551 continue;
13552
13553 e = resolveProperties(sc, e);
13554 if (i >= nfields)
13555 {
13556 if (i < sd.fields.length && e.op == EXP.null_)
13557 {
13558 // CTFE sometimes creates null as hidden pointer; we'll allow this.
13559 continue;
13560 }
13561 .error(loc, "more initializers than fields (%llu) of `%s`", cast(ulong)nfields, sd.toChars());
13562 return false;
13563 }
13564 VarDeclaration v = sd.fields[i];
13565 if (v.offset < offset)
13566 {
13567 .error(loc, "overlapping initialization for `%s`", v.toChars());
13568 if (!sd.isUnionDeclaration())
13569 {
13570 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
13571 " must initialize only the first member of a `union`. All subsequent" ~
13572 " non-overlapping fields are default initialized";
13573 .errorSupplemental(loc, errorMsg);
13574 }
13575 return false;
13576 }
13577 const vsize = v.type.size();
13578 if (vsize == SIZE_INVALID)
13579 return false;
13580 offset = cast(uint)(v.offset + vsize);
13581
13582 Type t = v.type;
13583 if (stype)
13584 t = t.addMod(stype.mod);
13585 Type origType = t;
13586 Type tb = t.toBasetype();
13587
13588 const hasPointers = tb.hasPointers();
13589 if (hasPointers)
13590 {
13591 if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
13592 (v.offset & (target.ptrsize - 1))) &&
13593 (sc.setUnsafe(false, loc,
13594 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, v)))
13595 {
13596 return false;
13597 }
13598 }
13599
13600 /* Look for case of initializing a static array with a too-short
13601 * string literal, such as:
13602 * char[5] foo = "abc";
13603 * Allow this by doing an explicit cast, which will lengthen the string
13604 * literal.
13605 */
13606 if (e.op == EXP.string_ && tb.ty == Tsarray)
13607 {
13608 StringExp se = cast(StringExp)e;
13609 Type typeb = se.type.toBasetype();
13610 TY tynto = tb.nextOf().ty;
13611 if (!se.committed &&
13612 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
13613 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
13614 {
13615 e = se.castTo(sc, t);
13616 goto L1;
13617 }
13618 }
13619
13620 while (!e.implicitConvTo(t) && tb.ty == Tsarray)
13621 {
13622 /* Static array initialization, as in:
13623 * T[3][5] = e;
13624 */
13625 t = tb.nextOf();
13626 tb = t.toBasetype();
13627 }
13628 if (!e.implicitConvTo(t))
13629 t = origType; // restore type for better diagnostic
13630
13631 e = e.implicitCastTo(sc, t);
13632 L1:
13633 if (e.op == EXP.error)
13634 return false;
13635
13636 (*elements)[i] = doCopyOrMove(sc, e);
13637 }
13638 return true;
13639 }
13640
13641
13642 /**
13643 * Returns `em` as a VariableExp
13644 * Params:
13645 * em = the EnumMember to wrap
13646 * loc = location of use of em
13647 * sc = scope of use of em
13648 * Returns:
13649 * VarExp referenceing `em` or ErrorExp if `em` if disabled/deprecated
13650 */
13651 Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
13652 {
13653 dsymbolSemantic(em, sc);
13654 if (em.errors)
13655 return ErrorExp.get();
13656 em.checkDisabled(loc, sc);
13657
13658 if (em.depdecl && !em.depdecl._scope)
13659 em.depdecl._scope = sc;
13660 em.checkDeprecated(loc, sc);
13661
13662 if (em.errors)
13663 return ErrorExp.get();
13664 Expression e = new VarExp(loc, em);
13665 e = e.expressionSemantic(sc);
13666 if (!(sc.flags & SCOPE.Cfile) && em.isCsymbol())
13667 {
13668 /* C11 types them as int. But if in D file,
13669 * type qualified names as the enum
13670 */
13671 e.type = em.parent.isEnumDeclaration().type;
13672 assert(e.type);
13673 }
13674 return e;
13675 }
13676
13677
13678 /*****************************
13679 * Try to treat `exp` as a boolean,
13680 * Params:
13681 * exp = the expression
13682 * sc = scope to evalute `exp` in
13683 * Returns:
13684 * Modified expression on success, ErrorExp on error
13685 */
13686 Expression toBoolean(Expression exp, Scope* sc)
13687 {
13688 switch(exp.op)
13689 {
13690 case EXP.delete_:
13691 exp.error("`delete` does not give a boolean result");
13692 return ErrorExp.get();
13693
13694 case EXP.comma:
13695 auto ce = exp.isCommaExp();
13696 auto ex2 = ce.e2.toBoolean(sc);
13697 if (ex2.op == EXP.error)
13698 return ex2;
13699 ce.e2 = ex2;
13700 ce.type = ce.e2.type;
13701 return ce;
13702
13703 case EXP.assign:
13704 case EXP.construct:
13705 case EXP.blit:
13706 if (sc.flags & SCOPE.Cfile)
13707 return exp;
13708 // Things like:
13709 // if (a = b) ...
13710 // are usually mistakes.
13711 exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
13712 return ErrorExp.get();
13713
13714 //LogicalExp
13715 case EXP.andAnd:
13716 case EXP.orOr:
13717 auto le = exp.isLogicalExp();
13718 auto ex2 = le.e2.toBoolean(sc);
13719 if (ex2.op == EXP.error)
13720 return ex2;
13721 le.e2 = ex2;
13722 return le;
13723
13724 case EXP.question:
13725 auto ce = exp.isCondExp();
13726 auto ex1 = ce.e1.toBoolean(sc);
13727 auto ex2 = ce.e2.toBoolean(sc);
13728 if (ex1.op == EXP.error)
13729 return ex1;
13730 if (ex2.op == EXP.error)
13731 return ex2;
13732 ce.e1 = ex1;
13733 ce.e2 = ex2;
13734 return ce;
13735
13736
13737 default:
13738 // Default is 'yes' - do nothing
13739 Expression e = arrayFuncConv(exp, sc);
13740 Type t = e.type;
13741 Type tb = t.toBasetype();
13742 Type att = null;
13743
13744 while (1)
13745 {
13746 // Structs can be converted to bool using opCast(bool)()
13747 if (auto ts = tb.isTypeStruct())
13748 {
13749 AggregateDeclaration ad = ts.sym;
13750 /* Don't really need to check for opCast first, but by doing so we
13751 * get better error messages if it isn't there.
13752 */
13753 if (Dsymbol fd = search_function(ad, Id._cast))
13754 {
13755 e = new CastExp(exp.loc, e, Type.tbool);
13756 e = e.expressionSemantic(sc);
13757 return e;
13758 }
13759
13760 // Forward to aliasthis.
13761 if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
13762 {
13763 e = resolveAliasThis(sc, e);
13764 t = e.type;
13765 tb = e.type.toBasetype();
13766 continue;
13767 }
13768 }
13769 break;
13770 }
13771
13772 if (!t.isBoolean())
13773 {
13774 if (tb != Type.terror)
13775 exp.error("expression `%s` of type `%s` does not have a boolean value",
13776 exp.toChars(), t.toChars());
13777 return ErrorExp.get();
13778 }
13779 return e;
13780 }
13781 }