]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/expressionsem.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / gcc / d / dmd / expressionsem.d
CommitLineData
5fee5ec3
IB
1/**
2 * Semantic analysis of expressions.
3 *
4 * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
5 *
6 * Copyright: Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d)
10 * Documentation: https://dlang.org/phobos/dmd_expressionsem.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d
12 */
13
14module dmd.expressionsem;
15
16import core.stdc.stdio;
17
18import dmd.access;
19import dmd.aggregate;
20import dmd.aliasthis;
21import dmd.arrayop;
22import dmd.arraytypes;
23import dmd.attrib;
24import dmd.astcodegen;
25import dmd.astenums;
26import dmd.canthrow;
27import dmd.chkformat;
28import dmd.ctorflow;
29import dmd.dscope;
30import dmd.dsymbol;
31import dmd.declaration;
32import dmd.dclass;
33import dmd.dcast;
34import dmd.delegatize;
35import dmd.denum;
36import dmd.dimport;
37import dmd.dinterpret;
38import dmd.dmangle;
39import dmd.dmodule;
40import dmd.dstruct;
41import dmd.dsymbolsem;
42import dmd.dtemplate;
43import dmd.errors;
44import dmd.escape;
45import dmd.expression;
0fb57034 46import dmd.file_manager;
5fee5ec3
IB
47import dmd.func;
48import dmd.globals;
49import dmd.hdrgen;
50import dmd.id;
51import dmd.identifier;
52import dmd.imphint;
0fb57034 53import dmd.importc;
5fee5ec3
IB
54import dmd.init;
55import dmd.initsem;
56import dmd.inline;
57import dmd.intrange;
58import dmd.mtype;
59import dmd.nspace;
60import dmd.opover;
61import dmd.optimize;
62import dmd.parse;
63import dmd.printast;
64import dmd.root.ctfloat;
65import dmd.root.file;
66import dmd.root.filename;
0fb57034 67import dmd.common.outbuffer;
5fee5ec3
IB
68import dmd.root.rootobject;
69import dmd.root.string;
70import dmd.semantic2;
71import dmd.semantic3;
72import dmd.sideeffect;
73import dmd.safe;
74import dmd.target;
75import dmd.tokens;
76import dmd.traits;
77import dmd.typesem;
78import dmd.typinf;
79import dmd.utf;
80import dmd.utils;
81import dmd.visitor;
82
83enum LOGSEMANTIC = false;
84
85/********************************************************
86 * Perform semantic analysis and CTFE on expressions to produce
87 * a string.
88 * Params:
89 * buf = append generated string to buffer
90 * sc = context
91 * exps = array of Expressions
92 * Returns:
93 * true on error
94 */
95bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
96{
97 if (!exps)
98 return false;
99
100 foreach (ex; *exps)
101 {
102 if (!ex)
103 continue;
104 auto sc2 = sc.startCTFE();
105 auto e2 = ex.expressionSemantic(sc2);
106 auto e3 = resolveProperties(sc2, e2);
107 sc2.endCTFE();
108
109 // allowed to contain types as well as expressions
110 auto e4 = ctfeInterpretForPragmaMsg(e3);
9c7d5e88 111 if (!e4 || e4.op == EXP.error)
5fee5ec3
IB
112 return true;
113
114 // expand tuple
115 if (auto te = e4.isTupleExp())
116 {
117 if (expressionsToString(buf, sc, te.exps))
118 return true;
119 continue;
120 }
121 // char literals exp `.toStringExp` return `null` but we cant override it
122 // because in most contexts we don't want the conversion to succeed.
123 IntegerExp ie = e4.isIntegerExp();
124 const ty = (ie && ie.type) ? ie.type.ty : Terror;
125 if (ty.isSomeChar)
126 {
127 auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
128 e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
129 }
130
131 if (StringExp se = e4.toStringExp())
132 buf.writestring(se.toUTF8(sc).peekString());
133 else
134 buf.writestring(e4.toString());
135 }
136 return false;
137}
138
139
140/***********************************************************
141 * Resolve `exp` as a compile-time known string.
142 * Params:
143 * sc = scope
144 * exp = Expression which expected as a string
145 * s = What the string is expected for, will be used in error diagnostic.
146 * Returns:
147 * String literal, or `null` if error happens.
148 */
149StringExp semanticString(Scope *sc, Expression exp, const char* s)
150{
151 sc = sc.startCTFE();
152 exp = exp.expressionSemantic(sc);
153 exp = resolveProperties(sc, exp);
154 sc = sc.endCTFE();
155
9c7d5e88 156 if (exp.op == EXP.error)
5fee5ec3
IB
157 return null;
158
159 auto e = exp;
160 if (exp.type.isString())
161 {
162 e = e.ctfeInterpret();
9c7d5e88 163 if (e.op == EXP.error)
5fee5ec3
IB
164 return null;
165 }
166
167 auto se = e.toStringExp();
168 if (!se)
169 {
170 exp.error("`string` expected for %s, not `(%s)` of type `%s`",
171 s, exp.toChars(), exp.type.toChars());
172 return null;
173 }
174 return se;
175}
176
177private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
178{
179 Expression e0;
180 Expression e1 = Expression.extractLast(ue.e1, e0);
181 // https://issues.dlang.org/show_bug.cgi?id=12585
182 // Extract the side effect part if ue.e1 is comma.
183
184 if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
185 {
186 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
187 * Rewrite:
188 * e1.opIndex( ... use of $ ... )
189 * e1.opSlice( ... use of $ ... )
190 * as:
191 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
192 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
193 */
194 e1 = extractSideEffect(sc, "__dop", e0, e1, false);
195 assert(e1.isVarExp());
196 e1.isVarExp().var.storage_class |= STC.exptemp; // lifetime limited to expression
197 }
198 ue.e1 = e1;
199 return e0;
200}
201
202/**************************************
203 * Runs semantic on ae.arguments. Declares temporary variables
204 * if '$' was used.
205 */
206Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
207{
208 assert(!ae.lengthVar);
209 *pe0 = null;
210 AggregateDeclaration ad = isAggregate(ae.e1.type);
211 Dsymbol slice = search_function(ad, Id.slice);
212 //printf("slice = %s %s\n", slice.kind(), slice.toChars());
213 foreach (i, e; *ae.arguments)
214 {
215 if (i == 0)
216 *pe0 = extractOpDollarSideEffect(sc, ae);
217
9c7d5e88 218 if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
5fee5ec3
IB
219 {
220 Lfallback:
221 if (ae.arguments.dim == 1)
222 return null;
223 ae.error("multi-dimensional slicing requires template `opSlice`");
224 return ErrorExp.get();
225 }
226 //printf("[%d] e = %s\n", i, e.toChars());
227
228 // Create scope for '$' variable for this dimension
229 auto sym = new ArrayScopeSymbol(sc, ae);
230 sym.parent = sc.scopesym;
231 sc = sc.push(sym);
232 ae.lengthVar = null; // Create it only if required
233 ae.currentDimension = i; // Dimension for $, if required
234
235 e = e.expressionSemantic(sc);
236 e = resolveProperties(sc, e);
237
238 if (ae.lengthVar && sc.func)
239 {
240 // If $ was used, declare it now
241 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
242 de = de.expressionSemantic(sc);
243 *pe0 = Expression.combine(*pe0, de);
244 }
245 sc = sc.pop();
246
247 if (auto ie = e.isIntervalExp())
248 {
249 auto tiargs = new Objects();
250 Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
251 edim = edim.expressionSemantic(sc);
252 tiargs.push(edim);
253
254 auto fargs = new Expressions(2);
255 (*fargs)[0] = ie.lwr;
256 (*fargs)[1] = ie.upr;
257
258 uint xerrors = global.startGagging();
259 sc = sc.push();
260 FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
261 sc = sc.pop();
262 global.endGagging(xerrors);
263 if (!fslice)
264 goto Lfallback;
265
266 e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
267 e = new CallExp(ae.loc, e, fargs);
268 e = e.expressionSemantic(sc);
269 }
270
271 if (!e.type)
272 {
273 ae.error("`%s` has no value", e.toChars());
274 e = ErrorExp.get();
275 }
9c7d5e88 276 if (e.op == EXP.error)
5fee5ec3
IB
277 return e;
278
279 (*ae.arguments)[i] = e;
280 }
281 return ae;
282}
283
284/**************************************
285 * Runs semantic on se.lwr and se.upr. Declares a temporary variable
286 * if '$' was used.
287 * Returns:
288 * ae, or ErrorExp if errors occurred
289 */
290Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
291{
292 //assert(!ae.lengthVar);
293 if (!ie)
294 return ae;
295
296 VarDeclaration lengthVar = ae.lengthVar;
297 bool errors = false;
298
299 // create scope for '$'
300 auto sym = new ArrayScopeSymbol(sc, ae);
301 sym.parent = sc.scopesym;
302 sc = sc.push(sym);
303
304 Expression sem(Expression e)
305 {
306 e = e.expressionSemantic(sc);
307 e = resolveProperties(sc, e);
308 if (!e.type)
309 {
310 ae.error("`%s` has no value", e.toChars());
311 errors = true;
312 }
313 return e;
314 }
315
316 ie.lwr = sem(ie.lwr);
317 ie.upr = sem(ie.upr);
318
319 if (lengthVar != ae.lengthVar && sc.func)
320 {
321 // If $ was used, declare it now
322 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
323 de = de.expressionSemantic(sc);
324 *pe0 = Expression.combine(*pe0, de);
325 }
326
327 sc = sc.pop();
328
329 return errors ? ErrorExp.get() : ae;
330}
331
332/******************************
333 * Perform semantic() on an array of Expressions.
334 */
335bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
336{
337 bool err = false;
338 if (exps)
339 {
340 foreach (ref e; *exps)
341 {
342 if (e)
343 {
344 auto e2 = e.expressionSemantic(sc);
9c7d5e88 345 if (e2.op == EXP.error)
5fee5ec3 346 err = true;
9c7d5e88 347 if (preserveErrors || e2.op != EXP.error)
5fee5ec3
IB
348 e = e2;
349 }
350 }
351 }
352 return err;
353}
354
355/******************************
356 * Check the tail CallExp is really property function call.
357 * Bugs:
358 * This doesn't appear to do anything.
359 */
360private bool checkPropertyCall(Expression e)
361{
362 e = lastComma(e);
363
364 if (auto ce = e.isCallExp())
365 {
366 if (ce.f)
367 {
368 auto tf = ce.f.type.isTypeFunction();
369 /* If a forward reference to ce.f, try to resolve it
370 */
371 if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
372 {
373 ce.f.dsymbolSemantic(null);
374 tf = ce.f.type.isTypeFunction();
375 }
376 }
377 else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
378 assert(0);
379 }
380 return false;
381}
382
383/******************************
384 * Find symbol in accordance with the UFCS name look up rule
385 */
386private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
387{
388 //printf("searchUFCS(ident = %s)\n", ident.toChars());
389 Loc loc = ue.loc;
390
391 // TODO: merge with Scope.search.searchScopes()
392 Dsymbol searchScopes(int flags)
393 {
394 Dsymbol s = null;
395 for (Scope* scx = sc; scx; scx = scx.enclosing)
396 {
397 if (!scx.scopesym)
398 continue;
399 if (scx.scopesym.isModule())
400 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
401 s = scx.scopesym.search(loc, ident, flags);
402 if (s)
403 {
404 // overload set contains only module scope symbols.
405 if (s.isOverloadSet())
406 break;
407 // selective/renamed imports also be picked up
408 if (AliasDeclaration ad = s.isAliasDeclaration())
409 {
410 if (ad._import)
411 break;
412 }
413 // See only module scope symbols for UFCS target.
414 Dsymbol p = s.toParent2();
415 if (p && p.isModule())
416 break;
417 }
418 s = null;
419
420 // Stop when we hit a module, but keep going if that is not just under the global scope
421 if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
422 break;
423 }
424 return s;
425 }
426
427 int flags = 0;
428 Dsymbol s;
429
430 if (sc.flags & SCOPE.ignoresymbolvisibility)
431 flags |= IgnoreSymbolVisibility;
432
433 // First look in local scopes
434 s = searchScopes(flags | SearchLocalsOnly);
435 if (!s)
436 {
437 // Second look in imported modules
438 s = searchScopes(flags | SearchImportsOnly);
439 }
440
441 if (!s)
442 return ue.e1.type.Type.getProperty(sc, loc, ident, 0);
443
444 FuncDeclaration f = s.isFuncDeclaration();
445 if (f)
446 {
447 TemplateDeclaration td = getFuncTemplateDecl(f);
448 if (td)
449 {
450 if (td.overroot)
451 td = td.overroot;
452 s = td;
453 }
454 }
455
456 if (auto dti = ue.isDotTemplateInstanceExp())
457 {
458 auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
459 if (!ti.updateTempDecl(sc, s))
460 return ErrorExp.get();
461 return new ScopeExp(loc, ti);
462 }
463 else
464 {
465 //printf("-searchUFCS() %s\n", s.toChars());
466 return new DsymbolExp(loc, s);
467 }
468}
469
470/******************************
471 * Pull out callable entity with UFCS.
472 */
473private Expression resolveUFCS(Scope* sc, CallExp ce)
474{
475 Loc loc = ce.loc;
476 Expression eleft;
477 Expression e;
478
479 if (auto die = ce.e1.isDotIdExp())
480 {
481 Identifier ident = die.ident;
482
483 Expression ex = die.semanticX(sc);
484 if (ex != die)
485 {
486 ce.e1 = ex;
487 return null;
488 }
489 eleft = die.e1;
490
491 Type t = eleft.type.toBasetype();
492 if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
493 {
494 /* Built-in types and arrays have no callable properties, so do shortcut.
495 * It is necessary in: e.init()
496 */
497 }
498 else if (t.ty == Taarray)
499 {
500 if (ident == Id.remove)
501 {
502 /* Transform:
503 * aa.remove(arg) into delete aa[arg]
504 */
505 if (!ce.arguments || ce.arguments.dim != 1)
506 {
507 ce.error("expected key as argument to `aa.remove()`");
508 return ErrorExp.get();
509 }
510 if (!eleft.type.isMutable())
511 {
512 ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
513 return ErrorExp.get();
514 }
515 Expression key = (*ce.arguments)[0];
516 key = key.expressionSemantic(sc);
517 key = resolveProperties(sc, key);
518
519 TypeAArray taa = t.isTypeAArray();
520 key = key.implicitCastTo(sc, taa.index);
521
522 if (key.checkValue() || key.checkSharedAccess(sc))
523 return ErrorExp.get();
524
525 semanticTypeInfo(sc, taa.index);
526
527 return new RemoveExp(loc, eleft, key);
528 }
529 }
530 else
531 {
532 if (Expression ey = die.semanticY(sc, 1))
533 {
9c7d5e88 534 if (ey.op == EXP.error)
5fee5ec3
IB
535 return ey;
536 ce.e1 = ey;
537 if (isDotOpDispatch(ey))
538 {
539 uint errors = global.startGagging();
540 e = ce.syntaxCopy().expressionSemantic(sc);
541 if (!global.endGagging(errors))
542 return e;
543
544 // even opDispatch and UFCS must have valid arguments,
545 // so now that we've seen indication of a problem,
546 // check them for issues.
547 Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
548
549 if (arrayExpressionSemantic(originalArguments, sc))
550 return ErrorExp.get();
551
552 /* fall down to UFCS */
553 }
554 else
555 return null;
556 }
557 }
558
559 /* https://issues.dlang.org/show_bug.cgi?id=13953
560 *
561 * If a struct has an alias this to an associative array
562 * and remove is used on a struct instance, we have to
563 * check first if there is a remove function that can be called
564 * on the struct. If not we must check the alias this.
565 *
566 * struct A
567 * {
568 * string[string] a;
569 * alias a this;
570 * }
571 *
572 * void fun()
573 * {
574 * A s;
575 * s.remove("foo");
576 * }
577 */
578 const errors = global.startGagging();
579 e = searchUFCS(sc, die, ident);
580 // if there were any errors and the identifier was remove
581 if (global.endGagging(errors))
582 {
583 if (ident == Id.remove)
584 {
585 // check alias this
586 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
587 if (alias_e && alias_e != die.e1)
588 {
589 die.e1 = alias_e;
590 CallExp ce2 = ce.syntaxCopy();
591 ce2.e1 = die;
592 e = ce2.isCallExp().trySemantic(sc);
593 if (e)
594 return e;
595 }
596 }
597 // if alias this did not work out, print the initial errors
598 searchUFCS(sc, die, ident);
599 }
600 }
601 else if (auto dti = ce.e1.isDotTemplateInstanceExp())
602 {
603 if (Expression ey = dti.semanticY(sc, 1))
604 {
605 ce.e1 = ey;
606 return null;
607 }
608 eleft = dti.e1;
609 e = searchUFCS(sc, dti, dti.ti.name);
610 }
611 else
612 return null;
613
614 // Rewrite
615 ce.e1 = e;
616 if (!ce.arguments)
617 ce.arguments = new Expressions();
618 ce.arguments.shift(eleft);
619
620 return null;
621}
622
623/******************************
624 * Pull out property with UFCS.
625 */
626private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
627{
628 Loc loc = e1.loc;
629 Expression eleft;
630 Expression e;
631
632 if (auto die = e1.isDotIdExp())
633 {
634 eleft = die.e1;
635 e = searchUFCS(sc, die, die.ident);
636 }
637 else if (auto dti = e1.isDotTemplateInstanceExp())
638 {
639 eleft = dti.e1;
640 e = searchUFCS(sc, dti, dti.ti.name);
641 }
642 else
643 return null;
644
645 if (e is null)
646 return null;
647
648 // Rewrite
649 if (e2)
650 {
651 // run semantic without gagging
652 e2 = e2.expressionSemantic(sc);
653
654 /* f(e1) = e2
655 */
656 Expression ex = e.copy();
657 auto a1 = new Expressions(1);
658 (*a1)[0] = eleft;
659 ex = new CallExp(loc, ex, a1);
660 auto e1PassSemantic = ex.trySemantic(sc);
661
662 /* f(e1, e2)
663 */
664 auto a2 = new Expressions(2);
665 (*a2)[0] = eleft;
666 (*a2)[1] = e2;
667 e = new CallExp(loc, e, a2);
668 e = e.trySemantic(sc);
669 if (!e1PassSemantic && !e)
670 {
671 /* https://issues.dlang.org/show_bug.cgi?id=20448
672 *
673 * If both versions have failed to pass semantic,
674 * f(e1) = e2 gets priority in error printing
675 * because f might be a templated function that
676 * failed to instantiate and we have to print
677 * the instantiation errors.
678 */
679 return e1.expressionSemantic(sc);
680 }
681 else if (ex && !e)
682 {
683 checkPropertyCall(ex);
684 ex = new AssignExp(loc, ex, e2);
685 return ex.expressionSemantic(sc);
686 }
687 else
688 {
689 // strict setter prints errors if fails
690 e = e.expressionSemantic(sc);
691 }
692 checkPropertyCall(e);
693 return e;
694 }
695 else
696 {
697 /* f(e1)
698 */
699 auto arguments = new Expressions(1);
700 (*arguments)[0] = eleft;
701 e = new CallExp(loc, e, arguments);
702 e = e.expressionSemantic(sc);
703 checkPropertyCall(e);
704 return e.expressionSemantic(sc);
705 }
706}
707
708/******************************
709 * If e1 is a property function (template), resolve it.
710 */
711Expression resolvePropertiesOnly(Scope* sc, Expression e1)
712{
713 //printf("e1 = %s %s\n", Token::toChars(e1.op), e1.toChars());
714
715 Expression handleOverloadSet(OverloadSet os)
716 {
717 assert(os);
718 foreach (s; os.a)
719 {
720 auto fd = s.isFuncDeclaration();
721 auto td = s.isTemplateDeclaration();
722 if (fd)
723 {
724 if (fd.type.isTypeFunction().isproperty)
725 return resolveProperties(sc, e1);
726 }
727 else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
728 {
729 if (fd.type.isTypeFunction().isproperty ||
730 (fd.storage_class2 & STC.property) ||
731 (td._scope.stc & STC.property))
732 return resolveProperties(sc, e1);
733 }
734 }
735 return e1;
736 }
737
738 Expression handleTemplateDecl(TemplateDeclaration td)
739 {
740 assert(td);
741 if (td.onemember)
742 {
743 if (auto fd = td.onemember.isFuncDeclaration())
744 {
745 if (fd.type.isTypeFunction().isproperty ||
746 (fd.storage_class2 & STC.property) ||
747 (td._scope.stc & STC.property))
748 return resolveProperties(sc, e1);
749 }
750 }
751 return e1;
752 }
753
754 Expression handleFuncDecl(FuncDeclaration fd)
755 {
756 assert(fd);
757 if (fd.type.isTypeFunction().isproperty)
758 return resolveProperties(sc, e1);
759 return e1;
760 }
761
762 if (auto de = e1.isDotExp())
763 {
764 if (auto os = de.e2.isOverExp())
765 return handleOverloadSet(os.vars);
766 }
767 else if (auto oe = e1.isOverExp())
768 return handleOverloadSet(oe.vars);
769 else if (auto dti = e1.isDotTemplateInstanceExp())
770 {
771 if (dti.ti.tempdecl)
772 if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
773 return handleTemplateDecl(td);
774 }
775 else if (auto dte = e1.isDotTemplateExp())
776 return handleTemplateDecl(dte.td);
777 else if (auto se = e1.isScopeExp())
778 {
779 Dsymbol s = se.sds;
780 TemplateInstance ti = s.isTemplateInstance();
781 if (ti && !ti.semanticRun && ti.tempdecl)
782 if (auto td = ti.tempdecl.isTemplateDeclaration())
783 return handleTemplateDecl(td);
784 }
785 else if (auto et = e1.isTemplateExp())
786 return handleTemplateDecl(et.td);
787 else if (e1.isDotVarExp() && e1.type.isTypeFunction())
788 {
789 DotVarExp dve = e1.isDotVarExp();
790 return handleFuncDecl(dve.var.isFuncDeclaration());
791 }
792 else if (e1.isVarExp() && e1.type && e1.type.isTypeFunction() && (sc.intypeof || !e1.isVarExp().var.needThis()))
793 return handleFuncDecl(e1.isVarExp().var.isFuncDeclaration());
794 return e1;
795}
796
797/****************************************
798 * Turn symbol `s` into the expression it represents.
799 *
800 * Params:
801 * s = symbol to resolve
802 * loc = location of use of `s`
803 * sc = context
804 * hasOverloads = applies if `s` represents a function.
805 * true means it's overloaded and will be resolved later,
806 * false means it's the exact function symbol.
807 * Returns:
808 * `s` turned into an expression, `ErrorExp` if an error occurred
809 */
810Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
811{
812 static if (LOGSEMANTIC)
813 {
814 printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
815 }
816
817Lagain:
818 Expression e;
819
820 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
821 //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
822 Dsymbol olds = s;
823 Declaration d = s.isDeclaration();
824 if (d && (d.storage_class & STC.templateparameter))
825 {
826 s = s.toAlias();
827 }
828 else
829 {
830 // functions are checked after overloading
831 // templates are checked after matching constraints
832 if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
833 {
834 s.checkDeprecated(loc, sc);
835 if (d)
836 d.checkDisabled(loc, sc);
837 }
838
839 // https://issues.dlang.org/show_bug.cgi?id=12023
840 // if 's' is a tuple variable, the tuple is returned.
841 s = s.toAlias();
842
843 //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
844 if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration())
845 {
846 s.checkDeprecated(loc, sc);
847 if (d)
848 d.checkDisabled(loc, sc);
849 }
850 }
851
852 if (auto em = s.isEnumMember())
853 {
854 return em.getVarExp(loc, sc);
855 }
856 if (auto v = s.isVarDeclaration())
857 {
858 //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
859 if (sc.intypeof == 1 && !v.inuse)
860 v.dsymbolSemantic(sc);
861 if (!v.type || // during variable type inference
862 !v.type.deco && v.inuse) // during variable type semantic
863 {
864 if (v.inuse) // variable type depends on the variable itself
865 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
866 else // variable type cannot be determined
867 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
868 return ErrorExp.get();
869 }
870 if (v.type.ty == Terror)
871 return ErrorExp.get();
872
873 if ((v.storage_class & STC.manifest) && v._init)
874 {
875 if (v.inuse)
876 {
877 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
878 return ErrorExp.get();
879 }
880 e = v.expandInitializer(loc);
881 v.inuse++;
882 e = e.expressionSemantic(sc);
883 v.inuse--;
884 return e;
885 }
886
887 // We need to run semantics to correctly set 'STC.field' if it is a member variable
888 // that could be forward referenced. This is needed for 'v.needThis()' to work
889 if (v.isThis())
890 v.dsymbolSemantic(sc);
891
892 // Change the ancestor lambdas to delegate before hasThis(sc) call.
893 if (v.checkNestedReference(sc, loc))
894 return ErrorExp.get();
895
896 if (v.needThis() && hasThis(sc))
897 e = new DotVarExp(loc, new ThisExp(loc), v);
898 else
899 e = new VarExp(loc, v);
900 e = e.expressionSemantic(sc);
901 return e;
902 }
903 if (auto fld = s.isFuncLiteralDeclaration())
904 {
905 //printf("'%s' is a function literal\n", fld.toChars());
906 e = new FuncExp(loc, fld);
907 return e.expressionSemantic(sc);
908 }
909 if (auto f = s.isFuncDeclaration())
910 {
911 f = f.toAliasFunc();
912 if (!f.functionSemantic())
913 return ErrorExp.get();
914
915 if (!hasOverloads && f.checkForwardRef(loc))
916 return ErrorExp.get();
917
918 auto fd = s.isFuncDeclaration();
919 fd.type = f.type;
920 return new VarExp(loc, fd, hasOverloads);
921 }
922 if (OverDeclaration od = s.isOverDeclaration())
923 {
924 e = new VarExp(loc, od, true);
925 e.type = Type.tvoid;
926 return e;
927 }
928 if (OverloadSet o = s.isOverloadSet())
929 {
930 //printf("'%s' is an overload set\n", o.toChars());
931 return new OverExp(loc, o);
932 }
933
934 if (Import imp = s.isImport())
935 {
936 if (!imp.pkg)
937 {
938 .error(loc, "forward reference of import `%s`", imp.toChars());
939 return ErrorExp.get();
940 }
941 auto ie = new ScopeExp(loc, imp.pkg);
942 return ie.expressionSemantic(sc);
943 }
944 if (Package pkg = s.isPackage())
945 {
946 auto ie = new ScopeExp(loc, pkg);
947 return ie.expressionSemantic(sc);
948 }
949 if (Module mod = s.isModule())
950 {
951 auto ie = new ScopeExp(loc, mod);
952 return ie.expressionSemantic(sc);
953 }
954 if (Nspace ns = s.isNspace())
955 {
956 auto ie = new ScopeExp(loc, ns);
957 return ie.expressionSemantic(sc);
958 }
959
960 if (Type t = s.getType())
961 {
962 return (new TypeExp(loc, t)).expressionSemantic(sc);
963 }
964
965 if (TupleDeclaration tup = s.isTupleDeclaration())
966 {
967 if (tup.needThis() && hasThis(sc))
968 e = new DotVarExp(loc, new ThisExp(loc), tup);
969 else
970 e = new TupleExp(loc, tup);
971 e = e.expressionSemantic(sc);
972 return e;
973 }
974
975 if (TemplateInstance ti = s.isTemplateInstance())
976 {
977 ti.dsymbolSemantic(sc);
978 if (!ti.inst || ti.errors)
979 return ErrorExp.get();
980 s = ti.toAlias();
981 if (!s.isTemplateInstance())
982 goto Lagain;
983 e = new ScopeExp(loc, ti);
984 e = e.expressionSemantic(sc);
985 return e;
986 }
987 if (TemplateDeclaration td = s.isTemplateDeclaration())
988 {
989 Dsymbol p = td.toParentLocal();
990 FuncDeclaration fdthis = hasThis(sc);
991 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
992 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
993 {
994 e = new DotTemplateExp(loc, new ThisExp(loc), td);
995 }
996 else
997 e = new TemplateExp(loc, td);
998 e = e.expressionSemantic(sc);
999 return e;
1000 }
1001
1002 .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1003 return ErrorExp.get();
1004}
1005
1006/*************************************************************
1007 * Given var, get the
1008 * right `this` pointer if var is in an outer class, but our
1009 * existing `this` pointer is in an inner class.
1010 * Params:
1011 * loc = location to use for error messages
1012 * sc = context
1013 * ad = struct or class we need the correct `this` for
1014 * e1 = existing `this`
1015 * var = the specific member of ad we're accessing
1016 * flag = if true, return `null` instead of throwing an error
1017 * Returns:
1018 * Expression representing the `this` for the var
1019 */
1020private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1021{
1022 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1023L1:
1024 Type t = e1.type.toBasetype();
1025 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1026
9c7d5e88 1027 if (e1.op == EXP.objcClassReference)
5fee5ec3
IB
1028 {
1029 // We already have an Objective-C class reference, just use that as 'this'.
1030 return e1;
1031 }
1032 else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1033 var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1034 var.isFuncDeclaration.objc.selector)
1035 {
1036 return new ObjcClassReferenceExp(e1.loc, ad.isClassDeclaration());
1037 }
1038
1039 /* Access of a member which is a template parameter in dual-scope scenario
1040 * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1041 * class B {int m; inc() { new A().inc!m(); } }
1042 */
9c7d5e88 1043 if (e1.op == EXP.this_)
5fee5ec3
IB
1044 {
1045 FuncDeclaration f = hasThis(sc);
1046 if (f && f.isThis2)
1047 {
1048 if (f.followInstantiationContext(ad))
1049 {
1050 e1 = new VarExp(loc, f.vthis);
1051 e1 = new PtrExp(loc, e1);
1052 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1053 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
9c7d5e88 1054 if (e1.op == EXP.error)
5fee5ec3
IB
1055 return e1;
1056 goto L1;
1057 }
1058 }
1059 }
1060
1061 /* If e1 is not the 'this' pointer for ad
1062 */
1063 if (ad &&
1064 !(t.isTypePointer() && t.nextOf().isTypeStruct() && t.nextOf().isTypeStruct().sym == ad) &&
1065 !(t.isTypeStruct() && t.isTypeStruct().sym == ad))
1066 {
1067 ClassDeclaration cd = ad.isClassDeclaration();
1068 ClassDeclaration tcd = t.isClassHandle();
1069
1070 /* e1 is the right this if ad is a base class of e1
1071 */
1072 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1073 {
1074 /* Only classes can be inner classes with an 'outer'
1075 * member pointing to the enclosing class instance
1076 */
1077 if (tcd && tcd.isNested())
1078 {
1079 /* e1 is the 'this' pointer for an inner class: tcd.
1080 * Rewrite it as the 'this' pointer for the outer class.
1081 */
1082 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1083 e1 = new DotVarExp(loc, e1, vthis);
1084 e1.type = vthis.type;
1085 e1.type = e1.type.addMod(t.mod);
1086 // Do not call ensureStaticLinkTo()
1087 //e1 = e1.semantic(sc);
1088
1089 // Skip up over nested functions, and get the enclosing
1090 // class type.
1091 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
9c7d5e88 1092 if (e1.op == EXP.error)
5fee5ec3
IB
1093 return e1;
1094 goto L1;
1095 }
1096
1097 /* Can't find a path from e1 to ad
1098 */
1099 if (flag)
1100 return null;
1101 e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1102 return ErrorExp.get();
1103 }
1104 }
1105 return e1;
1106}
1107
1108/***************************************
1109 * Pull out any properties.
1110 */
1111private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1112{
9c7d5e88 1113 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
5fee5ec3
IB
1114 Loc loc = e1.loc;
1115
1116 OverloadSet os;
1117 Dsymbol s;
1118 Objects* tiargs;
1119 Type tthis;
1120 if (auto de = e1.isDotExp())
1121 {
1122 if (auto oe = de.e2.isOverExp())
1123 {
1124 tiargs = null;
1125 tthis = de.e1.type;
1126 os = oe.vars;
1127 goto Los;
1128 }
1129 }
1130 else if (e1.isOverExp())
1131 {
1132 tiargs = null;
1133 tthis = null;
1134 os = e1.isOverExp().vars;
1135 Los:
1136 assert(os);
1137 FuncDeclaration fd = null;
1138 if (e2)
1139 {
1140 e2 = e2.expressionSemantic(sc);
9c7d5e88 1141 if (e2.op == EXP.error)
5fee5ec3
IB
1142 return ErrorExp.get();
1143 e2 = resolveProperties(sc, e2);
1144
1145 Expressions a;
1146 a.push(e2);
1147
1148 for (size_t i = 0; i < os.a.dim; i++)
1149 {
1150 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1151 {
1152 if (f.errors)
1153 return ErrorExp.get();
1154 fd = f;
1155 assert(fd.type.ty == Tfunction);
1156 }
1157 }
1158 if (fd)
1159 {
1160 Expression e = new CallExp(loc, e1, e2);
1161 return e.expressionSemantic(sc);
1162 }
1163 }
1164 {
1165 for (size_t i = 0; i < os.a.dim; i++)
1166 {
1167 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1168 {
1169 if (f.errors)
1170 return ErrorExp.get();
1171 fd = f;
1172 assert(fd.type.ty == Tfunction);
1173 auto tf = fd.type.isTypeFunction();
1174 if (!tf.isref && e2)
1175 {
1176 error(loc, "%s is not an lvalue", e1.toChars());
1177 return ErrorExp.get();
1178 }
1179 }
1180 }
1181 if (fd)
1182 {
1183 Expression e = new CallExp(loc, e1);
1184 if (e2)
1185 e = new AssignExp(loc, e, e2);
1186 return e.expressionSemantic(sc);
1187 }
1188 }
1189 if (e2)
1190 goto Leprop;
1191 }
1192 else if (auto dti = e1.isDotTemplateInstanceExp())
1193 {
1194 if (!dti.findTempDecl(sc))
1195 goto Leprop;
1196 if (!dti.ti.semanticTiargs(sc))
1197 goto Leprop;
1198 tiargs = dti.ti.tiargs;
1199 tthis = dti.e1.type;
1200 if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1201 goto Los;
1202 if ((s = dti.ti.tempdecl) !is null)
1203 goto Lfd;
1204 }
1205 else if (auto dte = e1.isDotTemplateExp())
1206 {
1207 s = dte.td;
1208 tiargs = null;
1209 tthis = dte.e1.type;
1210 goto Lfd;
1211 }
1212 else if (auto se = e1.isScopeExp())
1213 {
1214 s = se.sds;
1215 TemplateInstance ti = s.isTemplateInstance();
1216 if (ti && !ti.semanticRun && ti.tempdecl)
1217 {
1218 //assert(ti.needsTypeInference(sc));
1219 if (!ti.semanticTiargs(sc))
1220 goto Leprop;
1221 tiargs = ti.tiargs;
1222 tthis = null;
1223 if ((os = ti.tempdecl.isOverloadSet()) !is null)
1224 goto Los;
1225 if ((s = ti.tempdecl) !is null)
1226 goto Lfd;
1227 }
1228 }
1229 else if (auto te = e1.isTemplateExp())
1230 {
1231 s = te.td;
1232 tiargs = null;
1233 tthis = null;
1234 goto Lfd;
1235 }
9c7d5e88 1236 else if (e1.op == EXP.dotVariable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(DotVarExp)e1).var.isOverDeclaration()))
5fee5ec3
IB
1237 {
1238 DotVarExp dve = cast(DotVarExp)e1;
1239 s = dve.var;
1240 tiargs = null;
1241 tthis = dve.e1.type;
1242 goto Lfd;
1243 }
9c7d5e88 1244 else if (sc && sc.flags & SCOPE.Cfile && e1.op == EXP.variable && !e2)
0fb57034
IB
1245 {
1246 // ImportC: do not implicitly call function if no ( ) are present
1247 }
9c7d5e88 1248 else if (e1.op == EXP.variable && e1.type && (e1.type.toBasetype().ty == Tfunction || (cast(VarExp)e1).var.isOverDeclaration()))
5fee5ec3
IB
1249 {
1250 s = (cast(VarExp)e1).var;
1251 tiargs = null;
1252 tthis = null;
1253 Lfd:
1254 assert(s);
1255 if (e2)
1256 {
1257 e2 = e2.expressionSemantic(sc);
9c7d5e88 1258 if (e2.op == EXP.error)
5fee5ec3
IB
1259 return ErrorExp.get();
1260 e2 = resolveProperties(sc, e2);
1261
1262 Expressions a;
1263 a.push(e2);
1264
1265 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1266 if (fd && fd.type)
1267 {
1268 if (fd.errors)
1269 return ErrorExp.get();
1270 if (!checkSymbolAccess(sc, fd))
1271 {
1272 // @@@DEPRECATED_2020-10@@@
1273 // When turning into error, uncomment the return statement
1274 TypeFunction tf = cast(TypeFunction)fd.type;
1275 deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1276 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1277 //return ErrorExp.get();
1278 }
1279 assert(fd.type.ty == Tfunction);
1280 Expression e = new CallExp(loc, e1, e2);
1281 return e.expressionSemantic(sc);
1282 }
1283 }
1284 {
1285 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1286 if (fd && fd.type)
1287 {
1288 if (fd.errors)
1289 return ErrorExp.get();
1290 assert(fd.type.ty == Tfunction);
1291 TypeFunction tf = cast(TypeFunction)fd.type;
1292 if (!e2 || tf.isref)
1293 {
1294 if (!checkSymbolAccess(sc, fd))
1295 {
1296 // @@@DEPRECATED_2020-10@@@
1297 // When turning into error, uncomment the return statement
1298 deprecation(loc, "Function `%s` of type `%s` is not accessible from module `%s`",
1299 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1300 //return ErrorExp.get();
1301 }
1302 Expression e = new CallExp(loc, e1);
1303 if (e2)
1304 e = new AssignExp(loc, e, e2);
1305 return e.expressionSemantic(sc);
1306 }
1307 }
1308 }
1309 if (FuncDeclaration fd = s.isFuncDeclaration())
1310 {
1311 // Keep better diagnostic message for invalid property usage of functions
1312 assert(fd.type.ty == Tfunction);
1313 Expression e = new CallExp(loc, e1, e2);
1314 return e.expressionSemantic(sc);
1315 }
1316 if (e2)
1317 goto Leprop;
1318 }
9c7d5e88 1319 if (e1.op == EXP.variable)
5fee5ec3
IB
1320 {
1321 VarExp ve = cast(VarExp)e1;
1322 VarDeclaration v = ve.var.isVarDeclaration();
1323 if (v && ve.checkPurity(sc, v))
1324 return ErrorExp.get();
1325 }
1326 if (e2)
1327 return null;
1328
9c7d5e88 1329 if (e1.type && e1.op != EXP.type) // function type is not a property
5fee5ec3
IB
1330 {
1331 /* Look for e1 being a lazy parameter; rewrite as delegate call
1332 * only if the symbol wasn't already treated as a delegate
1333 */
1334 auto ve = e1.isVarExp();
1335 if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1336 {
1337 Expression e = new CallExp(loc, e1);
1338 return e.expressionSemantic(sc);
1339 }
9c7d5e88 1340 else if (e1.op == EXP.dotVariable)
5fee5ec3
IB
1341 {
1342 // Check for reading overlapped pointer field in @safe code.
1343 if (checkUnsafeAccess(sc, e1, true, true))
1344 return ErrorExp.get();
1345 }
9c7d5e88 1346 else if (e1.op == EXP.call)
5fee5ec3
IB
1347 {
1348 CallExp ce = cast(CallExp)e1;
1349 // Check for reading overlapped pointer field in @safe code.
1350 if (checkUnsafeAccess(sc, ce.e1, true, true))
1351 return ErrorExp.get();
1352 }
1353 }
1354
1355 if (!e1.type)
1356 {
1357 error(loc, "cannot resolve type for %s", e1.toChars());
1358 e1 = ErrorExp.get();
1359 }
1360 return e1;
1361
1362Leprop:
1363 error(loc, "not a property %s", e1.toChars());
1364 return ErrorExp.get();
1365}
1366
1367extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1368{
1369 //printf("resolveProperties(%s)\n", e.toChars());
1370 e = resolvePropertiesX(sc, e);
1371 if (e.checkRightThis(sc))
1372 return ErrorExp.get();
1373 return e;
1374}
1375
1376/****************************************
1377 * The common type is determined by applying ?: to each pair.
1378 * Output:
1379 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1380 * Returns:
1381 * The common type, or `null` if an error has occured
1382 */
1383private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
1384{
1385 /* Still have a problem with:
1386 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1387 * which works if the array literal is initialized top down with the ubyte[][]
1388 * type, but fails with this function doing bottom up typing.
1389 */
1390
1391 //printf("arrayExpressionToCommonType()\n");
1392 scope IntegerExp integerexp = IntegerExp.literal!0;
1393 scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1394
1395 Type t0 = null;
1396 Expression e0 = null;
5fee5ec3
IB
1397 bool foundType;
1398
1399 for (size_t i = 0; i < exps.dim; i++)
1400 {
1401 Expression e = exps[i];
1402 if (!e)
1403 continue;
1404
1405 e = resolveProperties(sc, e);
1406 if (!e.type)
1407 {
1408 e.error("`%s` has no value", e.toChars());
1409 t0 = Type.terror;
1410 continue;
1411 }
9c7d5e88 1412 if (e.op == EXP.type)
5fee5ec3
IB
1413 {
1414 foundType = true; // do not break immediately, there might be more errors
1415 e.checkValue(); // report an error "type T has no value"
1416 t0 = Type.terror;
1417 continue;
1418 }
1419 if (e.type.ty == Tvoid)
1420 {
1421 // void expressions do not concur to the determination of the common
1422 // type.
1423 continue;
1424 }
1425 if (checkNonAssignmentArrayOp(e))
1426 {
1427 t0 = Type.terror;
1428 continue;
1429 }
1430
1431 e = doCopyOrMove(sc, e);
1432
1433 if (!foundType && t0 && !t0.equals(e.type))
1434 {
1435 /* This applies ?: to merge the types. It's backwards;
1436 * ?: should call this function to merge types.
1437 */
1438 condexp.type = null;
1439 condexp.e1 = e0;
1440 condexp.e2 = e;
1441 condexp.loc = e.loc;
1442 Expression ex = condexp.expressionSemantic(sc);
9c7d5e88 1443 if (ex.op == EXP.error)
5fee5ec3 1444 e = ex;
9c7d5e88 1445 else if (e.op == EXP.function_ || e.op == EXP.delegate_)
5fee5ec3
IB
1446 {
1447 // https://issues.dlang.org/show_bug.cgi?id=21285
1448 // Functions and delegates don't convert correctly with castTo below
0fb57034 1449 exps[i] = condexp.e1;
5fee5ec3
IB
1450 e = condexp.e2;
1451 }
1452 else
1453 {
1454 // Convert to common type
0fb57034 1455 exps[i] = condexp.e1.castTo(sc, condexp.type);
5fee5ec3
IB
1456 e = condexp.e2.castTo(sc, condexp.type);
1457 }
1458 }
5fee5ec3
IB
1459 e0 = e;
1460 t0 = e.type;
9c7d5e88 1461 if (e.op != EXP.error)
5fee5ec3
IB
1462 exps[i] = e;
1463 }
1464
1465 // [] is typed as void[]
1466 if (!t0)
1467 return Type.tvoid;
1468
1469 // It's an error, don't do the cast
1470 if (t0.ty == Terror)
1471 return null;
1472
1473 for (size_t i = 0; i < exps.dim; i++)
1474 {
1475 Expression e = exps[i];
1476 if (!e)
1477 continue;
1478
1479 e = e.implicitCastTo(sc, t0);
9c7d5e88 1480 if (e.op == EXP.error)
5fee5ec3
IB
1481 {
1482 /* https://issues.dlang.org/show_bug.cgi?id=13024
1483 * a workaround for the bug in typeMerge -
1484 * it should paint e1 and e2 by deduced common type,
1485 * but doesn't in this particular case.
1486 */
1487 return null;
1488 }
1489 exps[i] = e;
1490 }
1491 return t0;
1492}
1493
9c7d5e88 1494private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expression e2)
5fee5ec3
IB
1495{
1496 Expression e;
1497 switch (op)
1498 {
9c7d5e88 1499 case EXP.addAssign:
5fee5ec3
IB
1500 e = new AddExp(loc, e1, e2);
1501 break;
1502
9c7d5e88 1503 case EXP.minAssign:
5fee5ec3
IB
1504 e = new MinExp(loc, e1, e2);
1505 break;
1506
9c7d5e88 1507 case EXP.mulAssign:
5fee5ec3
IB
1508 e = new MulExp(loc, e1, e2);
1509 break;
1510
9c7d5e88 1511 case EXP.divAssign:
5fee5ec3
IB
1512 e = new DivExp(loc, e1, e2);
1513 break;
1514
9c7d5e88 1515 case EXP.modAssign:
5fee5ec3
IB
1516 e = new ModExp(loc, e1, e2);
1517 break;
1518
9c7d5e88 1519 case EXP.andAssign:
5fee5ec3
IB
1520 e = new AndExp(loc, e1, e2);
1521 break;
1522
9c7d5e88 1523 case EXP.orAssign:
5fee5ec3
IB
1524 e = new OrExp(loc, e1, e2);
1525 break;
1526
9c7d5e88 1527 case EXP.xorAssign:
5fee5ec3
IB
1528 e = new XorExp(loc, e1, e2);
1529 break;
1530
9c7d5e88 1531 case EXP.leftShiftAssign:
5fee5ec3
IB
1532 e = new ShlExp(loc, e1, e2);
1533 break;
1534
9c7d5e88 1535 case EXP.rightShiftAssign:
5fee5ec3
IB
1536 e = new ShrExp(loc, e1, e2);
1537 break;
1538
9c7d5e88 1539 case EXP.unsignedRightShiftAssign:
5fee5ec3
IB
1540 e = new UshrExp(loc, e1, e2);
1541 break;
1542
1543 default:
1544 assert(0);
1545 }
1546 return e;
1547}
1548
1549/*********************
1550 * Rewrite:
1551 * array.length op= e2
1552 * as:
1553 * array.length = array.length op e2
1554 * or:
1555 * auto tmp = &array;
1556 * (*tmp).length = (*tmp).length op e2
1557 */
1558private Expression rewriteOpAssign(BinExp exp)
1559{
1560 Expression e;
1561
9c7d5e88 1562 assert(exp.e1.op == EXP.arrayLength);
5fee5ec3 1563 ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
9c7d5e88 1564 if (ale.e1.op == EXP.variable)
5fee5ec3
IB
1565 {
1566 e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1567 e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1568 }
1569 else
1570 {
1571 /* auto tmp = &array;
1572 * (*tmp).length = (*tmp).length op e2
1573 */
1574 auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1575
1576 Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1577 Expression elvalue = e1.syntaxCopy();
1578 e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1579 e = new AssignExp(exp.loc, elvalue, e);
1580 e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1581 }
1582 return e;
1583}
1584
1585/****************************************
1586 * Preprocess arguments to function.
1587 * Input:
1588 * reportErrors whether or not to report errors here. Some callers are not
1589 * checking actual function params, so they'll do their own error reporting
1590 * Output:
1591 * exps[] tuples expanded, properties resolved, rewritten in place
1592 * Returns:
1593 * true a semantic error occurred
1594 */
1595private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1596{
1597 bool err = false;
1598 if (exps)
1599 {
1600 expandTuples(exps);
1601
1602 for (size_t i = 0; i < exps.dim; i++)
1603 {
1604 Expression arg = (*exps)[i];
1605 arg = resolveProperties(sc, arg);
0fb57034 1606 arg = arg.arrayFuncConv(sc);
9c7d5e88 1607 if (arg.op == EXP.type)
5fee5ec3
IB
1608 {
1609 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1610 arg = resolveAliasThis(sc, arg);
1611
9c7d5e88 1612 if (arg.op == EXP.type)
5fee5ec3
IB
1613 {
1614 if (reportErrors)
1615 {
1616 arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1617 arg = ErrorExp.get();
1618 }
1619 err = true;
1620 }
1621 }
1622 else if (arg.type.toBasetype().ty == Tfunction)
1623 {
1624 if (reportErrors)
1625 {
1626 arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1627 arg = ErrorExp.get();
1628 }
1629 err = true;
1630 }
1631 else if (checkNonAssignmentArrayOp(arg))
1632 {
1633 arg = ErrorExp.get();
1634 err = true;
1635 }
1636 (*exps)[i] = arg;
1637 }
1638 }
1639 return err;
1640}
1641
1642/********************************************
1643 * Issue an error if default construction is disabled for type t.
1644 * Default construction is required for arrays and 'out' parameters.
1645 * Returns:
1646 * true an error was issued
1647 */
1648private bool checkDefCtor(Loc loc, Type t)
1649{
1650 t = t.baseElemOf();
1651 if (t.ty == Tstruct)
1652 {
1653 StructDeclaration sd = (cast(TypeStruct)t).sym;
1654 if (sd.noDefaultCtor)
1655 {
1656 sd.error(loc, "default construction is disabled");
1657 return true;
1658 }
1659 }
1660 return false;
1661}
1662
1663/****************************************
1664 * Now that we know the exact type of the function we're calling,
1665 * the arguments[] need to be adjusted:
1666 * 1. implicitly convert argument to the corresponding parameter type
1667 * 2. add default arguments for any missing arguments
1668 * 3. do default promotions on arguments corresponding to ...
1669 * 4. add hidden _arguments[] argument
1670 * 5. call copy constructor for struct value arguments
1671 * Params:
1672 * loc = location of function call
1673 * sc = context
1674 * tf = type of the function
1675 * ethis = `this` argument, `null` if none or not known
1676 * tthis = type of `this` argument, `null` if no `this` argument
1677 * arguments = array of actual arguments to function call
1678 * fd = the function being called, `null` if called indirectly
1679 * prettype = set to return type of function
1680 * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none
1681 * Returns:
1682 * true errors happened
1683 */
1684private bool functionParameters(const ref Loc loc, Scope* sc,
1685 TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1686 Type* prettype, Expression* peprefix)
1687{
1688 //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1689 assert(arguments);
1690 assert(fd || tf.next);
1691 size_t nargs = arguments ? arguments.dim : 0;
1692 const size_t nparams = tf.parameterList.length;
1693 const olderrors = global.errors;
1694 bool err = false;
1695 *prettype = Type.terror;
1696 Expression eprefix = null;
1697 *peprefix = null;
1698
1699 if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1700 {
1701 error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1702 return true;
1703 }
1704
1705 // If inferring return type, and semantic3() needs to be run if not already run
1706 if (!tf.next && fd.inferRetType)
1707 {
1708 fd.functionSemantic();
1709 }
1710 else if (fd && fd.parent)
1711 {
1712 TemplateInstance ti = fd.parent.isTemplateInstance();
1713 if (ti && ti.tempdecl)
1714 {
1715 fd.functionSemantic3();
1716 }
1717 }
1718
1719 /* If calling a pragma(inline, true) function,
1720 * set flag to later scan for inlines.
1721 */
1722 if (fd && fd.inlining == PINLINE.always)
1723 {
1724 if (sc._module)
1725 sc._module.hasAlwaysInlines = true;
1726 if (sc.func)
1727 sc.func.hasAlwaysInlines = true;
1728 }
1729
1730 const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1731
1732 const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1733
1734 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1735 * based on the actual argument types.
1736 * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1737 * of the arguments.
1738 */
1739 MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1740
1741 bool done = false;
1742 foreach (const i; 0 .. n)
1743 {
1744 Expression arg = (i < nargs) ? (*arguments)[i] : null;
1745
1746 if (i < nparams)
1747 {
1748 bool errorArgs()
1749 {
1750 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1751 return true;
1752 }
1753
1754 Parameter p = tf.parameterList[i];
1755
1756 if (!arg)
1757 {
1758 if (!p.defaultArg)
1759 {
1760 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1761 goto L2;
1762 return errorArgs();
1763 }
1764 arg = p.defaultArg;
1765 arg = inlineCopy(arg, sc);
1766 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1767 arg = arg.resolveLoc(loc, sc);
1768 arguments.push(arg);
1769 nargs++;
1770 }
1771 else
1772 {
1773 if (isDefaultInitOp(arg.op))
1774 {
1775 arg = arg.resolveLoc(loc, sc);
1776 (*arguments)[i] = arg;
1777 }
1778 }
1779
1780
1781 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1782 {
1783 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1784 {
1785 MATCH m;
1786 if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1787 {
1788 if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1789 goto L2;
1790 else if (nargs != nparams)
1791 return errorArgs();
1792 goto L1;
1793 }
1794 }
1795 L2:
1796 Type tb = p.type.toBasetype();
1797 switch (tb.ty)
1798 {
1799 case Tsarray:
1800 case Tarray:
1801 {
1802 /* Create a static array variable v of type arg.type:
1803 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1804 *
1805 * The array literal in the initializer of the hidden variable
1806 * is now optimized.
1807 * https://issues.dlang.org/show_bug.cgi?id=2356
1808 */
1809 Type tbn = (cast(TypeArray)tb).next; // array element type
1810 Type tret = p.isLazyArray();
1811
1812 auto elements = new Expressions(nargs - i);
1813 foreach (u; 0 .. elements.dim)
1814 {
1815 Expression a = (*arguments)[i + u];
1816 if (tret && a.implicitConvTo(tret))
1817 {
1818 // p is a lazy array of delegates, tret is return type of the delegates
1819 a = a.implicitCastTo(sc, tret)
1820 .optimize(WANTvalue)
1821 .toDelegate(tret, sc);
1822 }
1823 else
1824 a = a.implicitCastTo(sc, tbn);
1825 a = a.addDtorHook(sc);
1826 (*elements)[u] = a;
1827 }
1828 // https://issues.dlang.org/show_bug.cgi?id=14395
1829 // Convert to a static array literal, or its slice.
1830 arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1831 if (tb.ty == Tarray)
1832 {
1833 arg = new SliceExp(loc, arg, null, null);
1834 arg.type = p.type;
1835 }
1836 break;
1837 }
1838 case Tclass:
1839 {
1840 /* Set arg to be:
1841 * new Tclass(arg0, arg1, ..., argn)
1842 */
1843 auto args = new Expressions(nargs - i);
1844 foreach (u; i .. nargs)
1845 (*args)[u - i] = (*arguments)[u];
1846 arg = new NewExp(loc, null, null, p.type, args);
1847 break;
1848 }
1849 default:
1850 if (!arg)
1851 {
1852 error(loc, "not enough arguments");
1853 return true;
1854 }
1855 break;
1856 }
1857 arg = arg.expressionSemantic(sc);
1858 //printf("\targ = '%s'\n", arg.toChars());
1859 arguments.setDim(i + 1);
1860 (*arguments)[i] = arg;
1861 nargs = i + 1;
1862 done = true;
1863 }
1864
1865 L1:
1866 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1867 {
1868 if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
1869 {
1870 wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1871 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1872 }
1873 }
1874 }
1875 if (done)
1876 break;
1877 }
1878 if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1879 tf.next && tf.next.hasWild() &&
1880 (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1881 {
1882 bool errorInout(MOD wildmatch)
1883 {
1884 const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1885 error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1886 return true;
1887 }
1888
1889 if (fd)
1890 {
1891 /* If the called function may return the reference to
1892 * outer inout data, it should be rejected.
1893 *
1894 * void foo(ref inout(int) x) {
1895 * ref inout(int) bar(inout(int)) { return x; }
1896 * struct S {
1897 * ref inout(int) bar() inout { return x; }
1898 * ref inout(int) baz(alias a)() inout { return x; }
1899 * }
1900 * bar(int.init) = 1; // bad!
1901 * S().bar() = 1; // bad!
1902 * }
1903 * void test() {
1904 * int a;
1905 * auto s = foo(a);
1906 * s.baz!a() = 1; // bad!
1907 * }
1908 *
1909 */
1910 bool checkEnclosingWild(Dsymbol s)
1911 {
1912 bool checkWild(Dsymbol s)
1913 {
1914 if (!s)
1915 return false;
1916 if (auto ad = s.isAggregateDeclaration())
1917 {
1918 if (ad.isNested())
1919 return checkEnclosingWild(s);
1920 }
1921 else if (auto ff = s.isFuncDeclaration())
1922 {
1923 if ((cast(TypeFunction)ff.type).iswild)
1924 return errorInout(wildmatch);
1925
1926 if (ff.isNested() || ff.isThis())
1927 return checkEnclosingWild(s);
1928 }
1929 return false;
1930 }
1931
1932 Dsymbol ctx0 = s.toParent2();
1933 Dsymbol ctx1 = s.toParentLocal();
1934 if (checkWild(ctx0))
1935 return true;
1936 if (ctx0 != ctx1)
1937 return checkWild(ctx1);
1938 return false;
1939 }
1940 if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1941 return true;
1942 }
1943 else if (tf.isWild())
1944 return errorInout(wildmatch);
1945 }
1946
1947 Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1948 tthis &&
1949 tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1950 tthis.hasPointers())
1951 ? ethis : null;
1952
1953 assert(nargs >= nparams);
1954 foreach (const i, arg; (*arguments)[0 .. nargs])
1955 {
1956 assert(arg);
1957 if (i < nparams)
1958 {
1959 Parameter p = tf.parameterList[i];
1960 Type targ = arg.type; // keep original type for isCopyable() because alias this
1961 // resolution may hide an uncopyable type
1962
1963 if (!(p.storageClass & STC.lazy_ && p.type.ty == Tvoid))
1964 {
1965 Type tprm = p.type.hasWild()
1966 ? p.type.substWildTo(wildmatch)
1967 : p.type;
1968
1969 const hasCopyCtor = (arg.type.ty == Tstruct) && (cast(TypeStruct)arg.type).sym.hasCopyCtor;
1970 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
1971 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
1972 {
1973 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
1974 arg = arg.implicitCastTo(sc, tprm);
1975 arg = arg.optimize(WANTvalue, p.isReference());
1976 }
1977 }
1978
1979 // Support passing rvalue to `in` parameters
1980 if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
1981 {
1982 if (!arg.isLvalue())
1983 {
1984 auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
1985 Expression ev = new DeclarationExp(arg.loc, v);
1986 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
1987 arg = ev.expressionSemantic(sc);
1988 }
1989 arg = arg.toLvalue(sc, arg);
1990
1991 // Look for mutable misaligned pointer, etc., in @safe mode
1992 err |= checkUnsafeAccess(sc, arg, false, true);
1993 }
1994 else if (p.storageClass & STC.ref_)
1995 {
1996 if (global.params.rvalueRefParam &&
1997 !arg.isLvalue() &&
1998 targ.isCopyable())
1999 { /* allow rvalues to be passed to ref parameters by copying
2000 * them to a temp, then pass the temp as the argument
2001 */
2002 auto v = copyToTemp(0, "__rvalue", arg);
2003 Expression ev = new DeclarationExp(arg.loc, v);
2004 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2005 arg = ev.expressionSemantic(sc);
2006 }
2007 arg = arg.toLvalue(sc, arg);
2008
2009 // Look for mutable misaligned pointer, etc., in @safe mode
2010 err |= checkUnsafeAccess(sc, arg, false, true);
2011 }
2012 else if (p.storageClass & STC.out_)
2013 {
2014 Type t = arg.type;
2015 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2016 {
2017 arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2018 err = true;
2019 }
2020 else
2021 {
2022 // Look for misaligned pointer, etc., in @safe mode
2023 err |= checkUnsafeAccess(sc, arg, false, true);
2024 err |= checkDefCtor(arg.loc, t); // t must be default constructible
2025 }
2026 arg = arg.toLvalue(sc, arg);
2027 }
2028 else if (p.storageClass & STC.lazy_)
2029 {
2030 // Convert lazy argument to a delegate
2031 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2032 arg = toDelegate(arg, t, sc);
2033 }
2034 //printf("arg: %s\n", arg.toChars());
2035 //printf("type: %s\n", arg.type.toChars());
2036 //printf("param: %s\n", p.toChars());
2037
2038 if (firstArg && p.storageClass & STC.return_)
2039 {
2040 /* Argument value can be assigned to firstArg.
2041 * Check arg to see if it matters.
2042 */
2043 if (global.params.useDIP1000 == FeatureState.enabled)
2044 err |= checkParamArgumentReturn(sc, firstArg, arg, false);
2045 }
2046 else if (tf.parameterEscapes(tthis, p))
2047 {
2048 /* Argument value can escape from the called function.
2049 * Check arg to see if it matters.
2050 */
2051 if (global.params.useDIP1000 == FeatureState.enabled)
2052 err |= checkParamArgumentEscape(sc, fd, p, arg, false, false);
2053 }
2054 else if (!(p.storageClass & STC.return_))
2055 {
2056 /* Argument value cannot escape from the called function.
2057 */
2058 Expression a = arg;
9c7d5e88 2059 if (a.op == EXP.cast_)
5fee5ec3
IB
2060 a = (cast(CastExp)a).e1;
2061
2062 ArrayLiteralExp ale;
2063 if (p.type.toBasetype().ty == Tarray &&
2064 (ale = a.isArrayLiteralExp()) !is null)
2065 {
2066 // allocate the array literal as temporary static array on the stack
2067 ale.type = ale.type.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0);
2068 auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2069 auto declareTmp = new DeclarationExp(ale.loc, tmp);
2070 auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp), p.type);
2071 arg = CommaExp.combine(declareTmp, castToSlice);
2072 arg = arg.expressionSemantic(sc);
2073 }
9c7d5e88 2074 else if (a.op == EXP.function_)
5fee5ec3
IB
2075 {
2076 /* Function literals can only appear once, so if this
2077 * appearance was scoped, there cannot be any others.
2078 */
2079 FuncExp fe = cast(FuncExp)a;
2080 fe.fd.tookAddressOf = 0;
2081 }
9c7d5e88 2082 else if (a.op == EXP.delegate_)
5fee5ec3
IB
2083 {
2084 /* For passing a delegate to a scoped parameter,
2085 * this doesn't count as taking the address of it.
2086 * We only worry about 'escaping' references to the function.
2087 */
2088 DelegateExp de = cast(DelegateExp)a;
9c7d5e88 2089 if (de.e1.op == EXP.variable)
5fee5ec3
IB
2090 {
2091 VarExp ve = cast(VarExp)de.e1;
2092 FuncDeclaration f = ve.var.isFuncDeclaration();
2093 if (f)
2094 {
2095 if (f.tookAddressOf)
2096 --f.tookAddressOf;
2097 //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2098 }
2099 }
2100 }
2101 }
2102 if (!p.isReference())
2103 err |= arg.checkSharedAccess(sc);
2104
2105 arg = arg.optimize(WANTvalue, p.isReference());
2106
2107 /* Determine if this parameter is the "first reference" parameter through which
2108 * later "return" arguments can be stored.
2109 */
2110 if (i == 0 && !tthis && p.isReference() && p.type &&
2111 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2112 {
2113 Type tb = p.type.baseElemOf();
2114 if (tb.isMutable() && tb.hasPointers())
2115 {
2116 firstArg = arg;
2117 }
2118 }
2119 }
2120 else
2121 {
2122 // These will be the trailing ... arguments
2123 // If not D linkage, do promotions
2124 if (tf.linkage != LINK.d)
2125 {
2126 // Promote bytes, words, etc., to ints
2127 arg = integralPromotions(arg, sc);
2128
2129 // Promote floats to doubles
2130 switch (arg.type.ty)
2131 {
2132 case Tfloat32:
2133 arg = arg.castTo(sc, Type.tfloat64);
2134 break;
2135
2136 case Timaginary32:
2137 arg = arg.castTo(sc, Type.timaginary64);
2138 break;
2139
2140 default:
2141 break;
2142 }
2143 if (tf.parameterList.varargs == VarArg.variadic)
2144 {
2145 const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2146 if (arg.type.ty == Tarray)
2147 {
2148 arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2149 err = true;
2150 }
2151 if (arg.type.ty == Tsarray)
2152 {
2153 arg.error("cannot pass static arrays to `%s` vararg functions", p);
2154 err = true;
2155 }
2156 }
2157 }
2158
2159 // Do not allow types that need destructors or copy constructors.
2160 if (arg.type.needsDestruction())
2161 {
2162 arg.error("cannot pass types that need destruction as variadic arguments");
2163 err = true;
2164 }
2165 if (arg.type.needsCopyOrPostblit())
2166 {
2167 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2168 err = true;
2169 }
2170
2171 // Convert static arrays to dynamic arrays
2172 // BUG: I don't think this is right for D2
2173 Type tb = arg.type.toBasetype();
2174 if (tb.ty == Tsarray)
2175 {
2176 TypeSArray ts = cast(TypeSArray)tb;
2177 Type ta = ts.next.arrayOf();
2178 if (ts.size(arg.loc) == 0)
2179 arg = new NullExp(arg.loc, ta);
2180 else
2181 arg = arg.castTo(sc, ta);
2182 }
2183 if (tb.ty == Tstruct)
2184 {
2185 //arg = callCpCtor(sc, arg);
2186 }
2187 // Give error for overloaded function addresses
9c7d5e88 2188 if (arg.op == EXP.symbolOffset)
5fee5ec3
IB
2189 {
2190 SymOffExp se = cast(SymOffExp)arg;
2191 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2192 {
2193 arg.error("function `%s` is overloaded", arg.toChars());
2194 err = true;
2195 }
2196 }
2197 err |= arg.checkValue();
2198 err |= arg.checkSharedAccess(sc);
2199 arg = arg.optimize(WANTvalue);
2200 }
2201 (*arguments)[i] = arg;
2202 }
2203
2204 /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2205 */
2206 const isVa_list = tf.parameterList.varargs == VarArg.none;
2207 if (fd && fd.flags & FUNCFLAG.printf)
2208 {
2209 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2210 {
2211 checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2212 }
2213 }
2214 else if (fd && fd.flags & FUNCFLAG.scanf)
2215 {
2216 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2217 {
2218 checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2219 }
2220 }
2221 else
2222 {
2223 // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2224 }
2225
2226 /* Remaining problems:
2227 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2228 * implemented by calling a function) we'll defer this for now.
2229 * 2. value structs (or static arrays of them) that need to be copy constructed
2230 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2231 * function gets called.
2232 * 4. value structs need to be destructed after the function call for platforms where the caller destroys the arguments.
2233 * 2, 3 and 4 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2234 * up properly. Pushing arguments on the stack then cannot fail.
2235 */
2236 {
2237 /* TODO: tackle problem 1)
2238 */
2239 const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2240 if (!leftToRight)
2241 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2242
2243 /* Does Problem (4) apply?
2244 */
2245 const bool callerDestroysArgs = !target.isCalleeDestroyingArgs(tf);
2246
2247 const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2248 const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2249 const ptrdiff_t step = (leftToRight ? 1 : -1);
2250
2251 /* Compute indices of last throwing argument and first arg needing destruction.
2252 * Used to not set up destructors unless an arg needs destruction on a throw
2253 * in a later argument.
2254 */
2255 ptrdiff_t lastthrow = -1; // last argument that may throw
2256 ptrdiff_t firstdtor = -1; // first argument that needs destruction
2257 ptrdiff_t lastdtor = -1; // last argument that needs destruction
2258 for (ptrdiff_t i = start; i != end; i += step)
2259 {
2260 Expression arg = (*arguments)[i];
2261 if (canThrow(arg, sc.func, false))
2262 lastthrow = i;
2263 if (arg.type.needsDestruction())
2264 {
2265 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2266 if (!(p && (p.storageClass & (STC.lazy_ | STC.ref_ | STC.out_))))
2267 {
2268 if (firstdtor == -1)
2269 firstdtor = i;
2270 lastdtor = i;
2271 }
2272 }
2273 }
2274
2275 /* Do we need 'eprefix' for problems 3 or 4?
2276 */
2277 const bool needsPrefix = callerDestroysArgs
2278 ? firstdtor >= 0 // true if any argument needs destruction
2279 : firstdtor >= 0 && lastthrow >= 0 &&
2280 (lastthrow - firstdtor) * step > 0; // last throw after first destruction
2281 const ptrdiff_t lastPrefix = callerDestroysArgs
2282 ? lastdtor // up to last argument requiring destruction
2283 : lastthrow; // up to last potentially throwing argument
2284
2285 /* Problem 3: initialize 'eprefix' by declaring the gate
2286 */
2287 VarDeclaration gate;
2288 if (needsPrefix && !callerDestroysArgs)
2289 {
2290 // eprefix => bool __gate [= false]
2291 Identifier idtmp = Identifier.generateId("__gate");
2292 gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2293 gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2294 gate.dsymbolSemantic(sc);
2295
2296 auto ae = new DeclarationExp(loc, gate);
2297 eprefix = ae.expressionSemantic(sc);
2298 }
2299
2300 for (ptrdiff_t i = start; i != end; i += step)
2301 {
2302 Expression arg = (*arguments)[i];
2303 //printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
2304
2305 Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2306 const bool isRef = parameter && parameter.isReference();
2307 const bool isLazy = (parameter && (parameter.storageClass & STC.lazy_));
2308
2309 /* Skip lazy parameters
2310 */
2311 if (isLazy)
2312 continue;
2313
2314 /* Do we have 'eprefix' and aren't past 'lastPrefix' yet?
2315 * Then declare a temporary variable for this arg and append that declaration
2316 * to 'eprefix', which will implicitly take care of potential problem 2) for
2317 * this arg.
2318 * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
2319 * excluding all lazy parameters.
2320 */
2321 if (needsPrefix && (lastPrefix - i) * step >= 0)
2322 {
2323 const bool needsDtor = !isRef && arg.type.needsDestruction() &&
2324 // Problem 3: last throwing arg doesn't require dtor patching
2325 (callerDestroysArgs || i != lastPrefix);
2326
2327 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2328 */
2329 auto tmp = copyToTemp(
2330 (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_),
2331 needsDtor ? "__pfx" : "__pfy",
2332 !isRef ? arg : arg.addressOf());
2333 tmp.dsymbolSemantic(sc);
2334
2335 if (callerDestroysArgs)
2336 {
2337 /* Problem 4: Normal temporary, destructed after the call
2338 */
2339 if (needsDtor)
2340 tmp.isArgDtorVar = true; // mark it so that the backend passes it by ref to the function being called
2341 }
2342 else
2343 {
2344 /* Problem 3: Modify the destructor so it only runs if gate==false,
2345 * i.e., only if there was a throw while constructing the args
2346 */
2347 if (!needsDtor)
2348 {
2349 if (tmp.edtor)
2350 {
2351 assert(i == lastPrefix);
2352 tmp.edtor = null;
2353 }
2354 }
2355 else
2356 {
2357 // edtor => (__gate || edtor)
2358 assert(tmp.edtor);
2359 Expression e = tmp.edtor;
9c7d5e88 2360 e = new LogicalExp(e.loc, EXP.orOr, new VarExp(e.loc, gate), e);
5fee5ec3
IB
2361 tmp.edtor = e.expressionSemantic(sc);
2362 //printf("edtor: %s\n", tmp.edtor.toChars());
2363 }
2364 }
2365
2366 // eprefix => (eprefix, auto __pfx/y = arg)
2367 auto ae = new DeclarationExp(loc, tmp);
2368 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2369
2370 // arg => __pfx/y
2371 arg = new VarExp(loc, tmp);
2372 arg = arg.expressionSemantic(sc);
2373 if (isRef)
2374 {
2375 arg = new PtrExp(loc, arg);
2376 arg = arg.expressionSemantic(sc);
2377 }
2378
2379 /* Problem 3: Last throwing arg?
2380 * Then finalize eprefix => (eprefix, gate = true), i.e., disable the
2381 * dtors right after constructing the last throwing arg.
2382 * From now on, the callee will take care of destructing the args because
2383 * the args are implicitly moved into function parameters.
2384 */
2385 if (!callerDestroysArgs && i == lastPrefix)
2386 {
2387 auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2388 eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2389 }
2390 }
2391 else // not part of 'eprefix'
2392 {
2393 /* Handle problem 2) by calling the copy constructor for value structs
2394 * (or static arrays of them) if appropriate.
2395 */
2396 Type tv = arg.type.baseElemOf();
2397 if (!isRef && tv.ty == Tstruct)
2398 arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2399 }
2400
2401 (*arguments)[i] = arg;
2402 }
2403 }
2404 //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2405
2406 /* Test compliance with DIP1021
2407 */
2408 if (global.params.useDIP1021 &&
2409 tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2410 err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2411
2412 // If D linkage and variadic, add _arguments[] as first argument
2413 if (tf.isDstyleVariadic())
2414 {
2415 assert(arguments.dim >= nparams);
2416
2417 auto args = new Parameters(arguments.dim - nparams);
2418 for (size_t i = 0; i < arguments.dim - nparams; i++)
2419 {
2420 auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2421 (*args)[i] = arg;
2422 }
2423 auto tup = new TypeTuple(args);
2424 Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2425 arguments.insert(0, e);
2426 }
2427
2428 /* Determine function return type: tret
2429 */
2430 Type tret = tf.next;
2431 if (isCtorCall)
2432 {
2433 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2434 // wildmatch, tf.isWild(), fd.isReturnIsolated());
2435 if (!tthis)
2436 {
2437 assert(sc.intypeof || global.errors);
2438 tthis = fd.isThis().type.addMod(fd.type.mod);
2439 }
2440 if (tf.isWild() && !fd.isReturnIsolated())
2441 {
2442 if (wildmatch)
2443 tret = tret.substWildTo(wildmatch);
2444 int offset;
2445 if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2446 {
2447 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2448 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2449 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2450 err = true;
2451 }
2452 }
2453 tret = tthis;
2454 }
2455 else if (wildmatch && tret)
2456 {
2457 /* Adjust function return type based on wildmatch
2458 */
2459 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2460 tret = tret.substWildTo(wildmatch);
2461 }
2462
2463 *prettype = tret;
2464 *peprefix = eprefix;
2465 return (err || olderrors != global.errors);
2466}
2467
2468/**
2469 * Determines whether a symbol represents a module or package
2470 * (Used as a helper for is(type == module) and is(type == package))
2471 *
2472 * Params:
2473 * sym = the symbol to be checked
2474 *
2475 * Returns:
2476 * the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2477 */
2478Package resolveIsPackage(Dsymbol sym)
2479{
2480 Package pkg;
2481 if (Import imp = sym.isImport())
2482 {
2483 if (imp.pkg is null)
2484 {
2485 .error(sym.loc, "Internal Compiler Error: unable to process forward-referenced import `%s`",
2486 imp.toChars());
2487 assert(0);
2488 }
2489 pkg = imp.pkg;
2490 }
2491 else if (auto mod = sym.isModule())
2492 pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2493 else
2494 pkg = sym.isPackage();
2495 if (pkg)
2496 pkg.resolvePKGunknown();
2497 return pkg;
2498}
2499
2500private Module loadStdMath()
2501{
2502 __gshared Import impStdMath = null;
2503 __gshared Identifier[1] stdID;
2504 if (!impStdMath)
2505 {
2506 stdID[0] = Id.std;
2507 auto s = new Import(Loc.initial, stdID[], Id.math, null, false);
2508 // Module.load will call fatal() if there's no std.math available.
2509 // Gag the error here, pushing the error handling to the caller.
2510 uint errors = global.startGagging();
2511 s.load(null);
2512 if (s.mod)
2513 {
2514 s.mod.importAll(null);
2515 s.mod.dsymbolSemantic(null);
2516 }
2517 global.endGagging(errors);
2518 impStdMath = s;
2519 }
2520 return impStdMath.mod;
2521}
2522
2523private extern (C++) final class ExpressionSemanticVisitor : Visitor
2524{
2525 alias visit = Visitor.visit;
2526
2527 Scope* sc;
2528 Expression result;
2529
2530 this(Scope* sc)
2531 {
2532 this.sc = sc;
2533 }
2534
2535 private void setError()
2536 {
2537 result = ErrorExp.get();
2538 }
2539
2540 /**************************
2541 * Semantically analyze Expression.
2542 * Determine types, fold constants, etc.
2543 */
2544 override void visit(Expression e)
2545 {
2546 static if (LOGSEMANTIC)
2547 {
2548 printf("Expression::semantic() %s\n", e.toChars());
2549 }
2550 if (e.type)
2551 e.type = e.type.typeSemantic(e.loc, sc);
2552 else
2553 e.type = Type.tvoid;
2554 result = e;
2555 }
2556
2557 override void visit(IntegerExp e)
2558 {
2559 assert(e.type);
2560 if (e.type.ty == Terror)
2561 return setError();
2562
2563 assert(e.type.deco);
2564 e.setInteger(e.getInteger());
2565 result = e;
2566 }
2567
2568 override void visit(RealExp e)
2569 {
2570 if (!e.type)
2571 e.type = Type.tfloat64;
2572 else
2573 e.type = e.type.typeSemantic(e.loc, sc);
2574 result = e;
2575 }
2576
2577 override void visit(ComplexExp e)
2578 {
2579 if (!e.type)
2580 e.type = Type.tcomplex80;
2581 else
2582 e.type = e.type.typeSemantic(e.loc, sc);
2583 result = e;
2584 }
2585
2586 override void visit(IdentifierExp exp)
2587 {
2588 static if (LOGSEMANTIC)
2589 {
2590 printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2591 }
2592 if (exp.type) // This is used as the dummy expression
2593 {
2594 result = exp;
2595 return;
2596 }
2597
2598 Dsymbol scopesym;
2599 Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2600 if (s)
2601 {
2602 if (s.errors)
2603 return setError();
2604
2605 Expression e;
2606
2607 /* See if the symbol was a member of an enclosing 'with'
2608 */
2609 WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2610 if (withsym && withsym.withstate.wthis && symbolIsVisible(sc, s))
2611 {
2612 /* Disallow shadowing
2613 */
2614 // First find the scope of the with
2615 Scope* scwith = sc;
2616 while (scwith.scopesym != scopesym)
2617 {
2618 scwith = scwith.enclosing;
2619 assert(scwith);
2620 }
2621 // Look at enclosing scopes for symbols with the same name,
2622 // in the same function
2623 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2624 {
2625 Dsymbol s2;
2626 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2627 {
2628 exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2629 return setError();
2630 }
2631 }
2632 s = s.toAlias();
2633
2634 // Same as wthis.ident
2635 // TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2636 // The redudancy should be removed.
2637 e = new VarExp(exp.loc, withsym.withstate.wthis);
2638 e = new DotIdExp(exp.loc, e, exp.ident);
2639 e = e.expressionSemantic(sc);
2640 }
2641 else
2642 {
2643 if (withsym)
2644 {
2645 if (withsym.withstate.exp.type.ty != Tvoid)
2646 {
2647 // 'with (exp)' is a type expression
2648 // or 's' is not visible there (for error message)
2649 e = new TypeExp(exp.loc, withsym.withstate.exp.type);
2650 }
2651 else
2652 {
2653 // 'with (exp)' is a Package/Module
2654 e = withsym.withstate.exp;
2655 }
2656 e = new DotIdExp(exp.loc, e, exp.ident);
2657 result = e.expressionSemantic(sc);
2658 return;
2659 }
2660
2661 /* If f is really a function template,
2662 * then replace f with the function template declaration.
2663 */
2664 FuncDeclaration f = s.isFuncDeclaration();
2665 if (f)
2666 {
2667 TemplateDeclaration td = getFuncTemplateDecl(f);
2668 if (td)
2669 {
2670 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2671 td = td.overroot; // then get the start
2672 e = new TemplateExp(exp.loc, td, f);
2673 e = e.expressionSemantic(sc);
2674 result = e;
2675 return;
2676 }
2677 }
2678
2679 if (global.params.fixAliasThis)
2680 {
2681 ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2682 if (expDsym)
2683 {
2684 //printf("expDsym = %s\n", expDsym.exp.toChars());
2685 result = expDsym.exp.expressionSemantic(sc);
2686 return;
2687 }
2688 }
2689 // Haven't done overload resolution yet, so pass 1
2690 e = symbolToExp(s, exp.loc, sc, true);
2691 }
2692 result = e;
2693 return;
2694 }
2695
2696 if (!global.params.fixAliasThis && hasThis(sc))
2697 {
2698 for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2699 {
2700 if (ad.aliasthis)
2701 {
2702 Expression e;
2703 e = new ThisExp(exp.loc);
2704 e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2705 e = new DotIdExp(exp.loc, e, exp.ident);
2706 e = e.trySemantic(sc);
2707 if (e)
2708 {
2709 result = e;
2710 return;
2711 }
2712 }
2713
2714 auto cd = ad.isClassDeclaration();
2715 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2716 {
2717 ad = cd.baseClass;
2718 continue;
2719 }
2720 break;
2721 }
2722 }
2723
2724 if (exp.ident == Id.ctfe)
2725 {
2726 if (sc.flags & SCOPE.ctfe)
2727 {
2728 exp.error("variable `__ctfe` cannot be read at compile time");
2729 return setError();
2730 }
2731
2732 // Create the magic __ctfe bool variable
2733 auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2734 vd.storage_class |= STC.temp;
2735 vd.semanticRun = PASS.semanticdone;
2736 Expression e = new VarExp(exp.loc, vd);
2737 e = e.expressionSemantic(sc);
2738 result = e;
2739 return;
2740 }
2741
2742 // If we've reached this point and are inside a with() scope then we may
2743 // try one last attempt by checking whether the 'wthis' object supports
2744 // dynamic dispatching via opDispatch.
2745 // This is done by rewriting this expression as wthis.ident.
2746 // The innermost with() scope of the hierarchy to satisfy the condition
2747 // above wins.
2748 // https://issues.dlang.org/show_bug.cgi?id=6400
2749 for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2750 {
2751 if (!sc2.scopesym)
2752 continue;
2753
2754 if (auto ss = sc2.scopesym.isWithScopeSymbol())
2755 {
2756 if (ss.withstate.wthis)
2757 {
2758 Expression e;
2759 e = new VarExp(exp.loc, ss.withstate.wthis);
2760 e = new DotIdExp(exp.loc, e, exp.ident);
2761 e = e.trySemantic(sc);
2762 if (e)
2763 {
2764 result = e;
2765 return;
2766 }
2767 }
2768 // Try Type.opDispatch (so the static version)
9c7d5e88 2769 else if (ss.withstate.exp && ss.withstate.exp.op == EXP.type)
5fee5ec3
IB
2770 {
2771 if (Type t = ss.withstate.exp.isTypeExp().type)
2772 {
2773 Expression e;
2774 e = new TypeExp(exp.loc, t);
2775 e = new DotIdExp(exp.loc, e, exp.ident);
2776 e = e.trySemantic(sc);
2777 if (e)
2778 {
2779 result = e;
2780 return;
2781 }
2782 }
2783 }
2784 }
2785 }
2786
2787 /* Look for what user might have meant
2788 */
2789 if (const n = importHint(exp.ident.toString()))
2790 exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2791 else if (auto s2 = sc.search_correct(exp.ident))
2792 exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2793 else if (const p = Scope.search_correct_C(exp.ident))
2794 exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2795 else
2796 exp.error("undefined identifier `%s`", exp.ident.toChars());
2797
2798 result = ErrorExp.get();
2799 }
2800
2801 override void visit(DsymbolExp e)
2802 {
2803 result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2804 }
2805
2806 override void visit(ThisExp e)
2807 {
2808 static if (LOGSEMANTIC)
2809 {
2810 printf("ThisExp::semantic()\n");
2811 }
2812 if (e.type)
2813 {
2814 result = e;
2815 return;
2816 }
2817
2818 FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2819 AggregateDeclaration ad;
2820
2821 /* Special case for typeof(this) and typeof(super) since both
2822 * should work even if they are not inside a non-static member function
2823 */
2824 if (!fd && sc.intypeof == 1)
2825 {
2826 // Find enclosing struct or class
2827 for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2828 {
2829 if (!s)
2830 {
2831 e.error("`%s` is not in a class or struct scope", e.toChars());
2832 goto Lerr;
2833 }
2834 ClassDeclaration cd = s.isClassDeclaration();
2835 if (cd)
2836 {
2837 e.type = cd.type;
2838 result = e;
2839 return;
2840 }
2841 StructDeclaration sd = s.isStructDeclaration();
2842 if (sd)
2843 {
2844 e.type = sd.type;
2845 result = e;
2846 return;
2847 }
2848 }
2849 }
2850 if (!fd)
2851 goto Lerr;
2852
2853 assert(fd.vthis);
2854 e.var = fd.vthis;
2855 assert(e.var.parent);
2856 ad = fd.isMemberLocal();
2857 if (!ad)
2858 ad = fd.isMember2();
2859 assert(ad);
2860 e.type = ad.type.addMod(e.var.type.mod);
2861
2862 if (e.var.checkNestedReference(sc, e.loc))
2863 return setError();
2864
2865 result = e;
2866 return;
2867
2868 Lerr:
2869 e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2870 result = ErrorExp.get();
2871 }
2872
2873 override void visit(SuperExp e)
2874 {
2875 static if (LOGSEMANTIC)
2876 {
2877 printf("SuperExp::semantic('%s')\n", e.toChars());
2878 }
2879 if (e.type)
2880 {
2881 result = e;
2882 return;
2883 }
2884
2885 FuncDeclaration fd = hasThis(sc);
2886 ClassDeclaration cd;
2887 Dsymbol s;
2888
2889 /* Special case for typeof(this) and typeof(super) since both
2890 * should work even if they are not inside a non-static member function
2891 */
2892 if (!fd && sc.intypeof == 1)
2893 {
2894 // Find enclosing class
2895 for (s = sc.getStructClassScope(); 1; s = s.parent)
2896 {
2897 if (!s)
2898 {
2899 e.error("`%s` is not in a class scope", e.toChars());
2900 goto Lerr;
2901 }
2902 cd = s.isClassDeclaration();
2903 if (cd)
2904 {
2905 cd = cd.baseClass;
2906 if (!cd)
2907 {
2908 e.error("class `%s` has no `super`", s.toChars());
2909 goto Lerr;
2910 }
2911 e.type = cd.type;
2912 result = e;
2913 return;
2914 }
2915 }
2916 }
2917 if (!fd)
2918 goto Lerr;
2919
2920 e.var = fd.vthis;
2921 assert(e.var && e.var.parent);
2922
2923 s = fd.toParentDecl();
2924 if (s.isTemplateDeclaration()) // allow inside template constraint
2925 s = s.toParent();
2926 assert(s);
2927 cd = s.isClassDeclaration();
2928 //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2929 if (!cd)
2930 goto Lerr;
2931 if (!cd.baseClass)
2932 {
2933 e.error("no base class for `%s`", cd.toChars());
2934 e.type = cd.type.addMod(e.var.type.mod);
2935 }
2936 else
2937 {
2938 e.type = cd.baseClass.type;
2939 e.type = e.type.castMod(e.var.type.mod);
2940 }
2941
2942 if (e.var.checkNestedReference(sc, e.loc))
2943 return setError();
2944
2945 result = e;
2946 return;
2947
2948 Lerr:
2949 e.error("`super` is only allowed in non-static class member functions");
2950 result = ErrorExp.get();
2951 }
2952
2953 override void visit(NullExp e)
2954 {
2955 static if (LOGSEMANTIC)
2956 {
2957 printf("NullExp::semantic('%s')\n", e.toChars());
2958 }
2959 // NULL is the same as (void *)0
2960 if (e.type)
2961 {
2962 result = e;
2963 return;
2964 }
2965 e.type = Type.tnull;
2966 result = e;
2967 }
2968
2969 override void visit(StringExp e)
2970 {
2971 static if (LOGSEMANTIC)
2972 {
2973 printf("StringExp::semantic() %s\n", e.toChars());
2974 }
2975 if (e.type)
2976 {
2977 result = e;
2978 return;
2979 }
2980
2981 OutBuffer buffer;
2982 size_t newlen = 0;
2983 size_t u;
2984 dchar c;
2985
2986 switch (e.postfix)
2987 {
2988 case 'd':
2989 for (u = 0; u < e.len;)
2990 {
2991 if (const p = utf_decodeChar(e.peekString(), u, c))
2992 {
2993 e.error("%.*s", cast(int)p.length, p.ptr);
2994 return setError();
2995 }
2996 else
2997 {
2998 buffer.write4(c);
2999 newlen++;
3000 }
3001 }
3002 buffer.write4(0);
3003 e.setData(buffer.extractData(), newlen, 4);
3004 if (sc && sc.flags & SCOPE.Cfile)
3005 e.type = Type.tuns32.pointerTo();
3006 else
3007 e.type = Type.tdchar.immutableOf().arrayOf();
3008 e.committed = 1;
3009 break;
3010
3011 case 'w':
3012 for (u = 0; u < e.len;)
3013 {
3014 if (const p = utf_decodeChar(e.peekString(), u, c))
3015 {
3016 e.error("%.*s", cast(int)p.length, p.ptr);
3017 return setError();
3018 }
3019 else
3020 {
3021 buffer.writeUTF16(c);
3022 newlen++;
3023 if (c >= 0x10000)
3024 newlen++;
3025 }
3026 }
3027 buffer.writeUTF16(0);
3028 e.setData(buffer.extractData(), newlen, 2);
3029 if (sc && sc.flags & SCOPE.Cfile)
3030 e.type = Type.tuns16.pointerTo();
3031 else
3032 e.type = Type.twchar.immutableOf().arrayOf();
3033 e.committed = 1;
3034 break;
3035
3036 case 'c':
3037 e.committed = 1;
3038 goto default;
3039
3040 default:
3041 if (sc && sc.flags & SCOPE.Cfile)
3042 e.type = Type.tchar.pointerTo();
3043 else
3044 e.type = Type.tchar.immutableOf().arrayOf();
3045 break;
3046 }
3047 e.type = e.type.typeSemantic(e.loc, sc);
3048 //type = type.immutableOf();
3049 //printf("type = %s\n", type.toChars());
3050
3051 result = e;
3052 }
3053
3054 override void visit(TupleExp exp)
3055 {
3056 static if (LOGSEMANTIC)
3057 {
3058 printf("+TupleExp::semantic(%s)\n", exp.toChars());
3059 }
3060 if (exp.type)
3061 {
3062 result = exp;
3063 return;
3064 }
3065
3066 if (exp.e0)
3067 exp.e0 = exp.e0.expressionSemantic(sc);
3068
3069 // Run semantic() on each argument
3070 bool err = false;
3071 for (size_t i = 0; i < exp.exps.dim; i++)
3072 {
3073 Expression e = (*exp.exps)[i];
3074 e = e.expressionSemantic(sc);
3075 if (!e.type)
3076 {
3077 exp.error("`%s` has no value", e.toChars());
3078 err = true;
3079 }
9c7d5e88 3080 else if (e.op == EXP.error)
5fee5ec3
IB
3081 err = true;
3082 else
3083 (*exp.exps)[i] = e;
3084 }
3085 if (err)
3086 return setError();
3087
3088 expandTuples(exp.exps);
3089
3090 exp.type = new TypeTuple(exp.exps);
3091 exp.type = exp.type.typeSemantic(exp.loc, sc);
3092 //printf("-TupleExp::semantic(%s)\n", toChars());
3093 result = exp;
3094 }
3095
3096 override void visit(ArrayLiteralExp e)
3097 {
3098 static if (LOGSEMANTIC)
3099 {
3100 printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3101 }
3102 if (e.type)
3103 {
3104 result = e;
3105 return;
3106 }
3107
3108 /* Perhaps an empty array literal [ ] should be rewritten as null?
3109 */
3110
3111 if (e.basis)
3112 e.basis = e.basis.expressionSemantic(sc);
9c7d5e88 3113 if (arrayExpressionSemantic(e.elements, sc) || (e.basis && e.basis.op == EXP.error))
5fee5ec3
IB
3114 return setError();
3115
3116 expandTuples(e.elements);
3117
3118 if (e.basis)
3119 e.elements.push(e.basis);
3120 Type t0 = arrayExpressionToCommonType(sc, *e.elements);
3121 if (e.basis)
3122 e.basis = e.elements.pop();
3123 if (t0 is null)
3124 return setError();
3125
3126 e.type = t0.arrayOf();
3127 e.type = e.type.typeSemantic(e.loc, sc);
3128
3129 /* Disallow array literals of type void being used.
3130 */
3131 if (e.elements.dim > 0 && t0.ty == Tvoid)
3132 {
3133 e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3134 return setError();
3135 }
3136
3137 if (global.params.useTypeInfo && Type.dtypeinfo)
3138 semanticTypeInfo(sc, e.type);
3139
3140 result = e;
3141 }
3142
3143 override void visit(AssocArrayLiteralExp e)
3144 {
3145 static if (LOGSEMANTIC)
3146 {
3147 printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3148 }
3149 if (e.type)
3150 {
3151 result = e;
3152 return;
3153 }
3154
3155 // Run semantic() on each element
3156 bool err_keys = arrayExpressionSemantic(e.keys, sc);
3157 bool err_vals = arrayExpressionSemantic(e.values, sc);
3158 if (err_keys || err_vals)
3159 return setError();
3160
3161 expandTuples(e.keys);
3162 expandTuples(e.values);
3163 if (e.keys.dim != e.values.dim)
3164 {
3165 e.error("number of keys is %llu, must match number of values %llu",
3166 cast(ulong) e.keys.dim, cast(ulong) e.values.dim);
3167 return setError();
3168 }
3169
3170 Type tkey = arrayExpressionToCommonType(sc, *e.keys);
3171 Type tvalue = arrayExpressionToCommonType(sc, *e.values);
3172 if (tkey is null || tvalue is null)
3173 return setError();
3174
3175 e.type = new TypeAArray(tvalue, tkey);
3176 e.type = e.type.typeSemantic(e.loc, sc);
3177
3178 semanticTypeInfo(sc, e.type);
3179
3180 if (global.params.useDIP1000 == FeatureState.enabled)
3181 {
3182 if (checkAssocArrayLiteralEscape(sc, e, false))
3183 return setError();
3184 }
3185
3186 result = e;
3187 }
3188
3189 override void visit(StructLiteralExp e)
3190 {
3191 static if (LOGSEMANTIC)
3192 {
3193 printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3194 }
3195 if (e.type)
3196 {
3197 result = e;
3198 return;
3199 }
3200
3201 e.sd.size(e.loc);
3202 if (e.sd.sizeok != Sizeok.done)
3203 return setError();
3204
3205 // run semantic() on each element
3206 if (arrayExpressionSemantic(e.elements, sc))
3207 return setError();
3208
3209 expandTuples(e.elements);
3210
3211 /* Fit elements[] to the corresponding type of field[].
3212 */
3213 if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3214 return setError();
3215
3216 /* Fill out remainder of elements[] with default initializers for fields[]
3217 */
3218 if (!e.sd.fill(e.loc, e.elements, false))
3219 {
3220 /* An error in the initializer needs to be recorded as an error
3221 * in the enclosing function or template, since the initializer
3222 * will be part of the stuct declaration.
3223 */
3224 global.increaseErrorCount();
3225 return setError();
3226 }
3227
3228 if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
3229 return setError();
3230
3231 e.type = e.stype ? e.stype : e.sd.type;
3232 result = e;
3233 }
3234
3235 override void visit(CompoundLiteralExp cle)
3236 {
3237 static if (LOGSEMANTIC)
3238 {
3239 printf("CompoundLiteralExp::semantic('%s')\n", cle.toChars());
3240 }
3241 Type t = cle.type.typeSemantic(cle.loc, sc);
3242 auto init = initializerSemantic(cle.initializer, sc, t, INITnointerpret);
3243 auto e = initializerToExpression(init, t);
3244 if (!e)
3245 {
3246 error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars());
3247 return setError();
3248 }
3249 result = e;
3250 return;
3251 }
3252
3253 override void visit(TypeExp exp)
3254 {
3255 if (exp.type.ty == Terror)
3256 return setError();
3257
3258 //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3259 Expression e;
3260 Type t;
3261 Dsymbol s;
3262
3263 dmd.typesem.resolve(exp.type, exp.loc, sc, e, t, s, true);
3264 if (e)
3265 {
3266 // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3267 // then rewrite as `(this.var)` in case it would be followed by a DotVar
3268 // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3269 VarExp ve = e.isVarExp();
3270 if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3271 sc.func && sc.func.needThis && ve.var.toParent2().isAggregateDeclaration())
3272 {
3273 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3274 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3275 }
3276 //printf("e = %s %s\n", Token::toChars(e.op), e.toChars());
3277 e = e.expressionSemantic(sc);
3278 }
3279 else if (t)
3280 {
3281 //printf("t = %d %s\n", t.ty, t.toChars());
3282 exp.type = t.typeSemantic(exp.loc, sc);
3283 e = exp;
3284 }
3285 else if (s)
3286 {
3287 //printf("s = %s %s\n", s.kind(), s.toChars());
3288 e = symbolToExp(s, exp.loc, sc, true);
3289 }
3290 else
3291 assert(0);
3292
3293 if (global.params.vcomplex)
3294 exp.type.checkComplexTransition(exp.loc, sc);
3295
3296 result = e;
3297 }
3298
3299 override void visit(ScopeExp exp)
3300 {
3301 static if (LOGSEMANTIC)
3302 {
3303 printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3304 }
3305 if (exp.type)
3306 {
3307 result = exp;
3308 return;
3309 }
3310
3311 ScopeDsymbol sds2 = exp.sds;
3312 TemplateInstance ti = sds2.isTemplateInstance();
3313 while (ti)
3314 {
3315 WithScopeSymbol withsym;
3316 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3317 return setError();
3318 if (withsym && withsym.withstate.wthis)
3319 {
3320 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3321 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3322 result = e.expressionSemantic(sc);
3323 return;
3324 }
3325 if (ti.needsTypeInference(sc))
3326 {
3327 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3328 {
3329 Dsymbol p = td.toParentLocal();
3330 FuncDeclaration fdthis = hasThis(sc);
3331 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3332 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3333 {
3334 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3335 result = e.expressionSemantic(sc);
3336 return;
3337 }
3338 }
3339 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3340 {
3341 FuncDeclaration fdthis = hasThis(sc);
3342 AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3343 if (fdthis && ad && fdthis.isMemberLocal() == ad)
3344 {
3345 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3346 result = e.expressionSemantic(sc);
3347 return;
3348 }
3349 }
3350 // ti is an instance which requires IFTI.
3351 exp.sds = ti;
3352 exp.type = Type.tvoid;
3353 result = exp;
3354 return;
3355 }
3356 ti.dsymbolSemantic(sc);
3357 if (!ti.inst || ti.errors)
3358 return setError();
3359
3360 Dsymbol s = ti.toAlias();
3361 if (s == ti)
3362 {
3363 exp.sds = ti;
3364 exp.type = Type.tvoid;
3365 result = exp;
3366 return;
3367 }
3368 sds2 = s.isScopeDsymbol();
3369 if (sds2)
3370 {
3371 ti = sds2.isTemplateInstance();
3372 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3373 continue;
3374 }
3375
3376 if (auto v = s.isVarDeclaration())
3377 {
3378 if (!v.type)
3379 {
3380 exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3381 return setError();
3382 }
3383 if ((v.storage_class & STC.manifest) && v._init)
3384 {
3385 /* When an instance that will be converted to a constant exists,
3386 * the instance representation "foo!tiargs" is treated like a
3387 * variable name, and its recursive appearance check (note that
3388 * it's equivalent with a recursive instantiation of foo) is done
3389 * separately from the circular initialization check for the
3390 * eponymous enum variable declaration.
3391 *
3392 * template foo(T) {
3393 * enum bool foo = foo; // recursive definition check (v.inuse)
3394 * }
3395 * template bar(T) {
3396 * enum bool bar = bar!T; // recursive instantiation check (ti.inuse)
3397 * }
3398 */
3399 if (ti.inuse)
3400 {
3401 exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3402 return setError();
3403 }
3404 v.checkDeprecated(exp.loc, sc);
3405 auto e = v.expandInitializer(exp.loc);
3406 ti.inuse++;
3407 e = e.expressionSemantic(sc);
3408 ti.inuse--;
3409 result = e;
3410 return;
3411 }
3412 }
3413
3414 //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3415 auto e = symbolToExp(s, exp.loc, sc, true);
3416 //printf("-1ScopeExp::semantic()\n");
3417 result = e;
3418 return;
3419 }
3420
3421 //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3422 //printf("\tparent = '%s'\n", sds2.parent.toChars());
3423 sds2.dsymbolSemantic(sc);
3424
3425 // (Aggregate|Enum)Declaration
3426 if (auto t = sds2.getType())
3427 {
3428 result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3429 return;
3430 }
3431
3432 if (auto td = sds2.isTemplateDeclaration())
3433 {
3434 result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3435 return;
3436 }
3437
3438 exp.sds = sds2;
3439 exp.type = Type.tvoid;
3440 //printf("-2ScopeExp::semantic() %s\n", toChars());
3441 result = exp;
3442 }
3443
3444 override void visit(NewExp exp)
3445 {
3446 static if (LOGSEMANTIC)
3447 {
3448 printf("NewExp::semantic() %s\n", exp.toChars());
3449 if (exp.thisexp)
3450 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3451 printf("\tnewtype: %s\n", exp.newtype.toChars());
3452 }
3453 if (exp.type) // if semantic() already run
3454 {
3455 result = exp;
3456 return;
3457 }
3458
3459 //for error messages if the argument in [] is not convertible to size_t
3460 const originalNewtype = exp.newtype;
3461
3462 // https://issues.dlang.org/show_bug.cgi?id=11581
3463 // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3464 // T should be analyzed first and edim should go into arguments iff it's
3465 // not a tuple.
3466 Expression edim = null;
3467 if (!exp.arguments && exp.newtype.ty == Tsarray)
3468 {
3469 edim = (cast(TypeSArray)exp.newtype).dim;
3470 exp.newtype = (cast(TypeNext)exp.newtype).next;
3471 }
3472
3473 ClassDeclaration cdthis = null;
3474 if (exp.thisexp)
3475 {
3476 exp.thisexp = exp.thisexp.expressionSemantic(sc);
9c7d5e88 3477 if (exp.thisexp.op == EXP.error)
5fee5ec3
IB
3478 return setError();
3479
3480 cdthis = exp.thisexp.type.isClassHandle();
3481 if (!cdthis)
3482 {
3483 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3484 return setError();
3485 }
3486
3487 sc = sc.push(cdthis);
3488 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3489 sc = sc.pop();
3490 }
3491 else
3492 {
3493 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3494 }
3495 if (exp.type.ty == Terror)
3496 return setError();
3497
3498 if (edim)
3499 {
3500 if (exp.type.toBasetype().ty == Ttuple)
3501 {
3502 // --> new T[edim]
3503 exp.type = new TypeSArray(exp.type, edim);
3504 exp.type = exp.type.typeSemantic(exp.loc, sc);
3505 if (exp.type.ty == Terror)
3506 return setError();
3507 }
3508 else
3509 {
3510 // --> new T[](edim)
3511 exp.arguments = new Expressions();
3512 exp.arguments.push(edim);
3513 exp.type = exp.type.arrayOf();
3514 }
3515 }
3516
3517 exp.newtype = exp.type; // in case type gets cast to something else
3518 Type tb = exp.type.toBasetype();
3519 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3520 if (arrayExpressionSemantic(exp.newargs, sc) ||
3521 preFunctionParameters(sc, exp.newargs))
3522 {
3523 return setError();
3524 }
3525 if (arrayExpressionSemantic(exp.arguments, sc))
3526 {
3527 return setError();
3528 }
3529 //https://issues.dlang.org/show_bug.cgi?id=20547
3530 //exp.arguments are the "parameters" to [], not to a real function
3531 //so the errors that come from preFunctionParameters are misleading
3532 if (originalNewtype.ty == Tsarray)
3533 {
3534 if (preFunctionParameters(sc, exp.arguments, false))
3535 {
3536 exp.error("cannot create a `%s` with `new`", originalNewtype.toChars());
3537 return setError();
3538 }
3539 }
3540 else if (preFunctionParameters(sc, exp.arguments))
3541 {
3542 return setError();
3543 }
3544
3545 if (exp.thisexp && tb.ty != Tclass)
3546 {
3547 exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3548 return setError();
3549 }
3550
3551 const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
3552 Expression newprefix = null;
3553
3554 if (tb.ty == Tclass)
3555 {
3556 auto cd = (cast(TypeClass)tb).sym;
3557 cd.size(exp.loc);
3558 if (cd.sizeok != Sizeok.done)
3559 return setError();
3560 if (!cd.ctor)
3561 cd.ctor = cd.searchCtor();
3562 if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3563 {
3564 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3565 return setError();
3566 }
3567
3568 if (cd.isInterfaceDeclaration())
3569 {
3570 exp.error("cannot create instance of interface `%s`", cd.toChars());
3571 return setError();
3572 }
3573
3574 if (cd.isAbstract())
3575 {
3576 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3577 for (size_t i = 0; i < cd.vtbl.dim; i++)
3578 {
3579 FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3580 if (fd && fd.isAbstract())
3581 {
3582 errorSupplemental(exp.loc, "function `%s` is not implemented",
3583 fd.toFullSignature());
3584 }
3585 }
3586 return setError();
3587 }
3588 // checkDeprecated() is already done in newtype.typeSemantic().
3589
3590 if (cd.isNested())
3591 {
3592 /* We need a 'this' pointer for the nested class.
3593 * Ensure we have the right one.
3594 */
3595 Dsymbol s = cd.toParentLocal();
3596
3597 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3598 if (auto cdn = s.isClassDeclaration())
3599 {
3600 if (!cdthis)
3601 {
3602 // Supply an implicit 'this' and try again
3603 exp.thisexp = new ThisExp(exp.loc);
3604 for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3605 {
3606 if (!sp)
3607 {
3608 exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
3609 cdn.toChars(), cd.toChars());
3610 return setError();
3611 }
3612 ClassDeclaration cdp = sp.isClassDeclaration();
3613 if (!cdp)
3614 continue;
3615 if (cdp == cdn || cdn.isBaseOf(cdp, null))
3616 break;
3617 // Add a '.outer' and try again
3618 exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3619 }
3620
3621 exp.thisexp = exp.thisexp.expressionSemantic(sc);
9c7d5e88 3622 if (exp.thisexp.op == EXP.error)
5fee5ec3
IB
3623 return setError();
3624 cdthis = exp.thisexp.type.isClassHandle();
3625 }
3626 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3627 {
3628 //printf("cdthis = %s\n", cdthis.toChars());
3629 exp.error("`this` for nested class must be of type `%s`, not `%s`",
3630 cdn.toChars(), exp.thisexp.type.toChars());
3631 return setError();
3632 }
3633 if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3634 {
3635 exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3636 exp.newtype.toChars(), exp.thisexp.type.toChars());
3637 return setError();
3638 }
3639 }
3640 else if (exp.thisexp)
3641 {
3642 exp.error("`.new` is only for allocating nested classes");
3643 return setError();
3644 }
3645 else if (auto fdn = s.isFuncDeclaration())
3646 {
3647 // make sure the parent context fdn of cd is reachable from sc
3648 if (!ensureStaticLinkTo(sc.parent, fdn))
3649 {
3650 exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3651 fdn.toPrettyChars(), cd.toPrettyChars());
3652 return setError();
3653 }
3654 }
3655 else
3656 assert(0);
3657 }
3658 else if (exp.thisexp)
3659 {
3660 exp.error("`.new` is only for allocating nested classes");
3661 return setError();
3662 }
3663
3664 if (cd.vthis2)
3665 {
3666 if (AggregateDeclaration ad2 = cd.isMember2())
3667 {
3668 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
9c7d5e88 3669 if (te.op != EXP.error)
5fee5ec3 3670 te = getRightThis(exp.loc, sc, ad2, te, cd);
9c7d5e88 3671 if (te.op == EXP.error)
5fee5ec3
IB
3672 {
3673 exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3674 return setError();
3675 }
3676 }
3677 }
3678
3679 if (cd.disableNew)
3680 {
3681 exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
3682 originalNewtype.toChars());
3683 return setError();
3684 }
3685 else
3686 {
3687 if (exp.newargs && exp.newargs.dim)
3688 {
3689 exp.error("no allocator for `%s`", cd.toChars());
3690 return setError();
3691 }
3692 }
3693
3694 if (cd.ctor)
3695 {
3696 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3697 if (!f || f.errors)
3698 return setError();
3699
3700 checkFunctionAttributes(exp, sc, f);
3701 checkAccess(cd, exp.loc, sc, f);
3702
3703 TypeFunction tf = cast(TypeFunction)f.type;
3704 if (!exp.arguments)
3705 exp.arguments = new Expressions();
3706 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3707 return setError();
3708
3709 exp.member = f.isCtorDeclaration();
3710 assert(exp.member);
3711 }
3712 else
3713 {
3714 if (nargs)
3715 {
3716 exp.error("no constructor for `%s`", cd.toChars());
3717 return setError();
3718 }
3719
3720 // https://issues.dlang.org/show_bug.cgi?id=19941
3721 // Run semantic on all field initializers to resolve any forward
3722 // references. This is the same as done for structs in sd.fill().
3723 for (ClassDeclaration c = cd; c; c = c.baseClass)
3724 {
3725 foreach (v; c.fields)
3726 {
3727 if (v.inuse || v._scope is null || v._init is null ||
3728 v._init.isVoidInitializer())
3729 continue;
3730 v.inuse++;
3731 v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3732 v.inuse--;
3733 }
3734 }
3735 }
3736 }
3737 else if (tb.ty == Tstruct)
3738 {
3739 auto sd = (cast(TypeStruct)tb).sym;
3740 sd.size(exp.loc);
3741 if (sd.sizeok != Sizeok.done)
3742 return setError();
3743 if (!sd.ctor)
3744 sd.ctor = sd.searchCtor();
3745 if (sd.noDefaultCtor && !nargs)
3746 {
3747 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3748 return setError();
3749 }
3750 // checkDeprecated() is already done in newtype.typeSemantic().
3751
3752 if (sd.disableNew)
3753 {
3754 exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
3755 originalNewtype.toChars());
3756 return setError();
3757 }
3758 else
3759 {
3760 if (exp.newargs && exp.newargs.dim)
3761 {
3762 exp.error("no allocator for `%s`", sd.toChars());
3763 return setError();
3764 }
3765 }
3766
9c7d5e88 3767 if (sd.hasRegularCtor() && nargs)
5fee5ec3
IB
3768 {
3769 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3770 if (!f || f.errors)
3771 return setError();
3772
3773 checkFunctionAttributes(exp, sc, f);
3774 checkAccess(sd, exp.loc, sc, f);
3775
3776 TypeFunction tf = cast(TypeFunction)f.type;
3777 if (!exp.arguments)
3778 exp.arguments = new Expressions();
3779 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3780 return setError();
3781
3782 exp.member = f.isCtorDeclaration();
3783 assert(exp.member);
3784
3785 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
3786 return setError();
3787 }
3788 else
3789 {
3790 if (!exp.arguments)
3791 exp.arguments = new Expressions();
3792
3793 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3794 return setError();
3795
3796 if (!sd.fill(exp.loc, exp.arguments, false))
3797 return setError();
3798
3799 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
3800 return setError();
3801
3802 /* Since a `new` allocation may escape, check each of the arguments for escaping
3803 */
3804 if (global.params.useDIP1000 == FeatureState.enabled)
3805 {
3806 foreach (arg; *exp.arguments)
3807 {
3808 if (arg && checkNewEscape(sc, arg, false))
3809 return setError();
3810 }
3811 }
3812 }
3813
3814 exp.type = exp.type.pointerTo();
3815 }
3816 else if (tb.ty == Tarray)
3817 {
3818 if (!nargs)
3819 {
3820 // https://issues.dlang.org/show_bug.cgi?id=20422
3821 // Without this check the compiler would give a misleading error
3822 exp.error("missing length argument for array");
3823 return setError();
3824 }
3825
3826 Type tn = tb.nextOf().baseElemOf();
3827 Dsymbol s = tn.toDsymbol(sc);
3828 AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3829 if (ad && ad.noDefaultCtor)
3830 {
3831 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3832 return setError();
3833 }
3834 for (size_t i = 0; i < nargs; i++)
3835 {
3836 if (tb.ty != Tarray)
3837 {
3838 exp.error("too many arguments for array");
3839 return setError();
3840 }
3841
3842 Expression arg = (*exp.arguments)[i];
3843 arg = resolveProperties(sc, arg);
3844 arg = arg.implicitCastTo(sc, Type.tsize_t);
9c7d5e88 3845 if (arg.op == EXP.error)
5fee5ec3
IB
3846 return setError();
3847 arg = arg.optimize(WANTvalue);
9c7d5e88 3848 if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
5fee5ec3
IB
3849 {
3850 exp.error("negative array index `%s`", arg.toChars());
3851 return setError();
3852 }
3853 (*exp.arguments)[i] = arg;
3854 tb = (cast(TypeDArray)tb).next.toBasetype();
3855 }
3856 }
3857 else if (tb.isscalar())
3858 {
3859 if (!nargs)
3860 {
3861 }
3862 else if (nargs == 1)
3863 {
3864 Expression e = (*exp.arguments)[0];
3865 e = e.implicitCastTo(sc, tb);
3866 (*exp.arguments)[0] = e;
3867 }
3868 else
3869 {
3870 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3871 return setError();
3872 }
3873
3874 exp.type = exp.type.pointerTo();
3875 }
3876 else
3877 {
3878 exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3879 return setError();
3880 }
3881
3882 //printf("NewExp: '%s'\n", toChars());
3883 //printf("NewExp:type '%s'\n", type.toChars());
3884 semanticTypeInfo(sc, exp.type);
3885
3886 if (newprefix)
3887 {
3888 result = Expression.combine(newprefix, exp);
3889 return;
3890 }
3891 result = exp;
3892 }
3893
3894 override void visit(NewAnonClassExp e)
3895 {
3896 static if (LOGSEMANTIC)
3897 {
3898 printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3899 //printf("thisexp = %p\n", thisexp);
3900 //printf("type: %s\n", type.toChars());
3901 }
3902
3903 Expression d = new DeclarationExp(e.loc, e.cd);
3904 sc = sc.push(); // just create new scope
3905 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3906 d = d.expressionSemantic(sc);
3907 sc = sc.pop();
3908
3909 if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3910 {
3911 ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3912 if (!sds.members)
3913 sds.members = new Dsymbols();
3914 sds.members.push(e.cd);
3915 }
3916
3917 Expression n = new NewExp(e.loc, e.thisexp, e.newargs, e.cd.type, e.arguments);
3918
3919 Expression c = new CommaExp(e.loc, d, n);
3920 result = c.expressionSemantic(sc);
3921 }
3922
3923 override void visit(SymOffExp e)
3924 {
3925 static if (LOGSEMANTIC)
3926 {
3927 printf("SymOffExp::semantic('%s')\n", e.toChars());
3928 }
3929 //var.dsymbolSemantic(sc);
3930 if (!e.type)
3931 e.type = e.var.type.pointerTo();
3932
3933 if (auto v = e.var.isVarDeclaration())
3934 {
3935 if (v.checkNestedReference(sc, e.loc))
3936 return setError();
3937 }
3938 else if (auto f = e.var.isFuncDeclaration())
3939 {
3940 if (f.checkNestedReference(sc, e.loc))
3941 return setError();
3942 }
3943
3944 result = e;
3945 }
3946
3947 override void visit(VarExp e)
3948 {
3949 static if (LOGSEMANTIC)
3950 {
3951 printf("VarExp::semantic(%s)\n", e.toChars());
3952 }
3953
3954 auto vd = e.var.isVarDeclaration();
3955 auto fd = e.var.isFuncDeclaration();
3956
3957 if (fd)
3958 {
3959 //printf("L%d fd = %s\n", __LINE__, f.toChars());
3960 if (!fd.functionSemantic())
3961 return setError();
3962 }
3963
3964 if (!e.type)
3965 e.type = e.var.type;
3966 if (e.type && !e.type.deco)
3967 {
3968 auto decl = e.var.isDeclaration();
3969 if (decl)
3970 decl.inuse++;
3971 e.type = e.type.typeSemantic(e.loc, sc);
3972 if (decl)
3973 decl.inuse--;
3974 }
3975
3976 /* Fix for 1161 doesn't work because it causes visibility
3977 * problems when instantiating imported templates passing private
3978 * variables as alias template parameters.
3979 */
3980 //checkAccess(loc, sc, NULL, var);
3981
3982 if (vd)
3983 {
3984 if (vd.checkNestedReference(sc, e.loc))
3985 return setError();
3986
3987 // https://issues.dlang.org/show_bug.cgi?id=12025
3988 // If the variable is not actually used in runtime code,
3989 // the purity violation error is redundant.
3990 //checkPurity(sc, vd);
3991 }
3992 else if (fd)
3993 {
3994 // TODO: If fd isn't yet resolved its overload, the checkNestedReference
3995 // call would cause incorrect validation.
3996 // Maybe here should be moved in CallExp, or AddrExp for functions.
3997 if (fd.checkNestedReference(sc, e.loc))
3998 return setError();
3999 }
4000 else if (auto od = e.var.isOverDeclaration())
4001 {
4002 e.type = Type.tvoid; // ambiguous type?
4003 }
4004
4005 result = e;
4006 }
4007
4008 override void visit(FuncExp exp)
4009 {
4010 static if (LOGSEMANTIC)
4011 {
4012 printf("FuncExp::semantic(%s)\n", exp.toChars());
4013 if (exp.fd.treq)
4014 printf(" treq = %s\n", exp.fd.treq.toChars());
4015 }
4016
4017 if (exp.type)
4018 {
4019 result = exp;
4020 return;
4021 }
4022
4023 Expression e = exp;
4024 uint olderrors;
4025
4026 sc = sc.push(); // just create new scope
4027 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4028 sc.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4029
4030 /* fd.treq might be incomplete type,
4031 * so should not semantic it.
4032 * void foo(T)(T delegate(int) dg){}
4033 * foo(a=>a); // in IFTI, treq == T delegate(int)
4034 */
4035 //if (fd.treq)
4036 // fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4037
4038 exp.genIdent(sc);
4039
4040 // Set target of return type inference
4041 if (exp.fd.treq && !exp.fd.type.nextOf())
4042 {
4043 TypeFunction tfv = null;
4044 if (exp.fd.treq.ty == Tdelegate || exp.fd.treq.isPtrToFunction())
4045 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4046 if (tfv)
4047 {
4048 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4049 tfl.next = tfv.nextOf();
4050 }
4051 }
4052
4053 //printf("td = %p, treq = %p\n", td, fd.treq);
4054 if (exp.td)
4055 {
4056 assert(exp.td.parameters && exp.td.parameters.dim);
4057 exp.td.dsymbolSemantic(sc);
4058 exp.type = Type.tvoid; // temporary type
4059
4060 if (exp.fd.treq) // defer type determination
4061 {
4062 FuncExp fe;
4063 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4064 e = fe;
4065 else
4066 e = ErrorExp.get();
4067 }
4068 goto Ldone;
4069 }
4070
4071 olderrors = global.errors;
4072 exp.fd.dsymbolSemantic(sc);
4073 if (olderrors == global.errors)
4074 {
4075 exp.fd.semantic2(sc);
4076 if (olderrors == global.errors)
4077 exp.fd.semantic3(sc);
4078 }
4079 if (olderrors != global.errors)
4080 {
4081 if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4082 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4083 e = ErrorExp.get();
4084 goto Ldone;
4085 }
4086
4087 // Type is a "delegate to" or "pointer to" the function literal
4088 if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4089 {
4090 exp.type = new TypeDelegate(exp.fd.type.isTypeFunction());
4091 exp.type = exp.type.typeSemantic(exp.loc, sc);
4092
4093 exp.fd.tok = TOK.delegate_;
4094 }
4095 else
4096 {
4097 exp.type = new TypePointer(exp.fd.type);
4098 exp.type = exp.type.typeSemantic(exp.loc, sc);
4099 //type = fd.type.pointerTo();
4100
4101 /* A lambda expression deduced to function pointer might become
4102 * to a delegate literal implicitly.
4103 *
4104 * auto foo(void function() fp) { return 1; }
4105 * assert(foo({}) == 1);
4106 *
9c7d5e88 4107 * So, should keep fd.tok == TOK.reserve if fd.treq == NULL.
5fee5ec3
IB
4108 */
4109 if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4110 {
4111 // change to non-nested
4112 exp.fd.tok = TOK.function_;
4113 exp.fd.vthis = null;
4114 }
4115 }
4116 exp.fd.tookAddressOf++;
4117
4118 Ldone:
4119 sc = sc.pop();
4120 result = e;
4121 }
4122
4123 /**
4124 * Perform semantic analysis on function literals
4125 *
4126 * Test the following construct:
4127 * ---
4128 * (x, y, z) { return x + y + z; }(42, 84, 1992);
4129 * ---
4130 */
4131 Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4132 {
4133 if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
4134 {
4135 for (size_t k = 0; k < arguments.dim; k++)
4136 {
4137 Expression checkarg = (*arguments)[k];
9c7d5e88 4138 if (checkarg.op == EXP.error)
5fee5ec3
IB
4139 return checkarg;
4140 }
4141
4142 exp.genIdent(sc);
4143
4144 assert(exp.td.parameters && exp.td.parameters.dim);
4145 exp.td.dsymbolSemantic(sc);
4146
4147 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4148 size_t dim = tfl.parameterList.length;
4149 if (arguments.dim < dim)
4150 {
4151 // Default arguments are always typed, so they don't need inference.
4152 Parameter p = tfl.parameterList[arguments.dim];
4153 if (p.defaultArg)
4154 dim = arguments.dim;
4155 }
4156
4157 if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
4158 arguments.dim < dim)
4159 {
4160 OutBuffer buf;
4161 foreach (idx, ref arg; *arguments)
4162 buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4163 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4164 exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4165 buf.peekChars());
4166 exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
4167 arguments.dim < dim ? "few".ptr : "many".ptr,
4168 cast(int)dim, cast(int)arguments.dim);
4169 return ErrorExp.get();
4170 }
4171
4172 auto tiargs = new Objects();
4173 tiargs.reserve(exp.td.parameters.dim);
4174
4175 for (size_t i = 0; i < exp.td.parameters.dim; i++)
4176 {
4177 TemplateParameter tp = (*exp.td.parameters)[i];
4178 assert(dim <= tfl.parameterList.length);
4179 foreach (u, p; tfl.parameterList)
4180 {
4181 if (u == dim)
4182 break;
4183
4184 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4185 {
4186 Expression e = (*arguments)[u];
4187 tiargs.push(e.type);
4188 break;
4189 }
4190 }
4191 }
4192
4193 auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4194 return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4195 }
4196 return exp.expressionSemantic(sc);
4197 }
4198
4199 override void visit(CallExp exp)
4200 {
4201 static if (LOGSEMANTIC)
4202 {
4203 printf("CallExp::semantic() %s\n", exp.toChars());
4204 }
4205 if (exp.type)
4206 {
4207 result = exp;
4208 return; // semantic() already run
4209 }
4210
4211 Objects* tiargs = null; // initial list of template arguments
4212 Expression ethis = null;
4213 Type tthis = null;
4214 Expression e1org = exp.e1;
4215
9c7d5e88 4216 if (exp.e1.op == EXP.comma)
5fee5ec3
IB
4217 {
4218 /* Rewrite (a,b)(args) as (a,(b(args)))
4219 */
4220 auto ce = cast(CommaExp)exp.e1;
4221 exp.e1 = ce.e2;
4222 ce.e2 = exp;
4223 result = ce.expressionSemantic(sc);
4224 return;
4225 }
9c7d5e88 4226 if (exp.e1.op == EXP.delegate_)
5fee5ec3
IB
4227 {
4228 DelegateExp de = cast(DelegateExp)exp.e1;
4229 exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4230 visit(exp);
4231 return;
4232 }
9c7d5e88 4233 if (exp.e1.op == EXP.function_)
5fee5ec3
IB
4234 {
4235 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4236 return setError();
4237
4238 // Run e1 semantic even if arguments have any errors
4239 FuncExp fe = cast(FuncExp)exp.e1;
4240 exp.e1 = callExpSemantic(fe, sc, exp.arguments);
9c7d5e88 4241 if (exp.e1.op == EXP.error)
5fee5ec3
IB
4242 {
4243 result = exp.e1;
4244 return;
4245 }
4246 }
4247
4248 if (Expression ex = resolveUFCS(sc, exp))
4249 {
4250 result = ex;
4251 return;
4252 }
4253
4254 /* This recognizes:
4255 * foo!(tiargs)(funcargs)
4256 */
9c7d5e88 4257 if (exp.e1.op == EXP.scope_)
5fee5ec3
IB
4258 {
4259 ScopeExp se = cast(ScopeExp)exp.e1;
4260 TemplateInstance ti = se.sds.isTemplateInstance();
4261 if (ti)
4262 {
4263 /* Attempt to instantiate ti. If that works, go with it.
4264 * If not, go with partial explicit specialization.
4265 */
4266 WithScopeSymbol withsym;
4267 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4268 return setError();
4269 if (withsym && withsym.withstate.wthis)
4270 {
4271 exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4272 exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4273 goto Ldotti;
4274 }
4275 if (ti.needsTypeInference(sc, 1))
4276 {
4277 /* Go with partial explicit specialization
4278 */
4279 tiargs = ti.tiargs;
4280 assert(ti.tempdecl);
4281 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4282 exp.e1 = new TemplateExp(exp.loc, td);
4283 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4284 exp.e1 = new VarExp(exp.loc, od);
4285 else
4286 exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4287 }
4288 else
4289 {
4290 Expression e1x = exp.e1.expressionSemantic(sc);
9c7d5e88 4291 if (e1x.op == EXP.error)
5fee5ec3
IB
4292 {
4293 result = e1x;
4294 return;
4295 }
4296 exp.e1 = e1x;
4297 }
4298 }
4299 }
4300
4301 /* This recognizes:
4302 * expr.foo!(tiargs)(funcargs)
4303 */
4304 Ldotti:
9c7d5e88 4305 if (exp.e1.op == EXP.dotTemplateInstance)
5fee5ec3
IB
4306 {
4307 DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)exp.e1;
4308 TemplateInstance ti = se.ti;
4309 {
4310 /* Attempt to instantiate ti. If that works, go with it.
4311 * If not, go with partial explicit specialization.
4312 */
4313 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4314 return setError();
4315 if (ti.needsTypeInference(sc, 1))
4316 {
4317 /* Go with partial explicit specialization
4318 */
4319 tiargs = ti.tiargs;
4320 assert(ti.tempdecl);
4321 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4322 exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4323 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4324 {
4325 exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4326 }
4327 else
4328 exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4329 }
4330 else
4331 {
4332 Expression e1x = exp.e1.expressionSemantic(sc);
9c7d5e88 4333 if (e1x.op == EXP.error)
5fee5ec3
IB
4334 {
4335 result = e1x;
4336 return;
4337 }
4338 exp.e1 = e1x;
4339 }
4340 }
4341 }
4342
4343 Lagain:
4344 //printf("Lagain: %s\n", toChars());
4345 exp.f = null;
9c7d5e88 4346 if (exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_)
5fee5ec3
IB
4347 {
4348 // semantic() run later for these
4349 }
4350 else
4351 {
9c7d5e88 4352 if (exp.e1.op == EXP.dotIdentifier)
5fee5ec3
IB
4353 {
4354 DotIdExp die = cast(DotIdExp)exp.e1;
4355 exp.e1 = die.expressionSemantic(sc);
4356 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4357 * We handle such earlier, so go back.
4358 * Note that in the rewrite, we carefully did not run semantic() on e1
4359 */
9c7d5e88 4360 if (exp.e1.op == EXP.dotTemplateInstance)
5fee5ec3
IB
4361 {
4362 goto Ldotti;
4363 }
4364 }
4365 else
4366 {
4367 __gshared int nest;
4368 if (++nest > global.recursionLimit)
4369 {
4370 exp.error("recursive evaluation of `%s`", exp.toChars());
4371 --nest;
4372 return setError();
4373 }
4374 Expression ex = unaSemantic(exp, sc);
4375 --nest;
4376 if (ex)
4377 {
4378 result = ex;
4379 return;
4380 }
4381 }
4382
4383 /* Look for e1 being a lazy parameter
4384 */
9c7d5e88 4385 if (exp.e1.op == EXP.variable)
5fee5ec3
IB
4386 {
4387 VarExp ve = cast(VarExp)exp.e1;
4388 if (ve.var.storage_class & STC.lazy_)
4389 {
4390 // lazy parameters can be called without violating purity and safety
4391 Type tw = ve.var.type;
4392 Type tc = ve.var.type.substWildTo(MODFlags.const_);
4393 auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4394 (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4395 auto t = new TypeDelegate(tf);
4396 ve.type = t.typeSemantic(exp.loc, sc);
4397 }
4398 VarDeclaration v = ve.var.isVarDeclaration();
4399 if (v && ve.checkPurity(sc, v))
4400 return setError();
4401 }
4402
9c7d5e88 4403 if (exp.e1.op == EXP.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
5fee5ec3
IB
4404 {
4405 SymOffExp se = cast(SymOffExp)exp.e1;
4406 exp.e1 = new VarExp(se.loc, se.var, true);
4407 exp.e1 = exp.e1.expressionSemantic(sc);
4408 }
9c7d5e88 4409 else if (exp.e1.op == EXP.dot)
5fee5ec3
IB
4410 {
4411 DotExp de = cast(DotExp)exp.e1;
4412
9c7d5e88 4413 if (de.e2.op == EXP.overloadSet)
5fee5ec3
IB
4414 {
4415 ethis = de.e1;
4416 tthis = de.e1.type;
4417 exp.e1 = de.e2;
4418 }
4419 }
9c7d5e88 4420 else if (exp.e1.op == EXP.star && exp.e1.type.ty == Tfunction)
5fee5ec3
IB
4421 {
4422 // Rewrite (*fp)(arguments) to fp(arguments)
4423 exp.e1 = (cast(PtrExp)exp.e1).e1;
4424 }
9c7d5e88 4425 else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
5fee5ec3 4426 {
0fb57034
IB
4427 const numArgs = exp.arguments ? exp.arguments.length : 0;
4428 if (e1org.parens && numArgs >= 1)
4429 {
4430 /* Ambiguous cases arise from CParser where there is not enough
4431 * information to determine if we have a function call or a cast.
4432 * ( type-name ) ( identifier ) ;
4433 * ( identifier ) ( identifier ) ;
4434 * If exp.e1 is a type-name, then this is a cast.
4435 */
4436 Expression arg;
4437 foreach (a; (*exp.arguments)[])
4438 {
4439 arg = arg ? new CommaExp(a.loc, arg, a) : a;
4440 }
4441 auto t = exp.e1.isTypeExp().type;
4442 auto e = new CastExp(exp.loc, arg, t);
4443 result = e.expressionSemantic(sc);
4444 return;
4445 }
4446
5fee5ec3
IB
4447 /* Ambiguous cases arise from CParser where there is not enough
4448 * information to determine if we have a function call or declaration.
4449 * type-name ( identifier ) ;
4450 * identifier ( identifier ) ;
4451 * If exp.e1 is a type-name, then this is a declaration. C11 does not
4452 * have type construction syntax, so don't convert this to a cast().
4453 */
0fb57034 4454 if (numArgs == 1)
5fee5ec3
IB
4455 {
4456 Expression arg = (*exp.arguments)[0];
4457 if (auto ie = (*exp.arguments)[0].isIdentifierExp())
4458 {
4459 TypeExp te = cast(TypeExp)exp.e1;
4460 auto initializer = new VoidInitializer(ie.loc);
4461 Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
4462 auto decls = new Dsymbols(1);
4463 (*decls)[0] = s;
4464 s = new LinkDeclaration(s.loc, LINK.c, decls);
4465 result = new DeclarationExp(exp.loc, s);
4466 result = result.expressionSemantic(sc);
4467 }
4468 else
4469 {
4470 arg.error("identifier or `(` expected");
4471 result = ErrorExp.get();
4472 }
4473 return;
4474 }
4475 exp.error("identifier or `(` expected before `)`");
4476 result = ErrorExp.get();
4477 return;
4478 }
4479 }
4480
4481 Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4482
9c7d5e88 4483 if (exp.e1.op == EXP.error)
5fee5ec3
IB
4484 {
4485 result = exp.e1;
4486 return;
4487 }
4488 if (arrayExpressionSemantic(exp.arguments, sc) || preFunctionParameters(sc, exp.arguments))
4489 return setError();
4490
4491 // Check for call operator overload
4492 if (t1)
4493 {
4494 if (t1.ty == Tstruct)
4495 {
4496 auto sd = (cast(TypeStruct)t1).sym;
4497 sd.size(exp.loc); // Resolve forward references to construct object
4498 if (sd.sizeok != Sizeok.done)
4499 return setError();
4500 if (!sd.ctor)
4501 sd.ctor = sd.searchCtor();
4502 /* If `sd.ctor` is a generated copy constructor, this means that it
4503 is the single constructor that this struct has. In order to not
4504 disable default construction, the ctor is nullified. The side effect
4505 of this is that the generated copy constructor cannot be called
4506 explicitly, but that is ok, because when calling a constructor the
4507 default constructor should have priority over the generated copy
4508 constructor.
4509 */
4510 if (sd.ctor)
4511 {
4512 auto ctor = sd.ctor.isCtorDeclaration();
4513 if (ctor && ctor.isCpCtor && ctor.generated)
4514 sd.ctor = null;
4515 }
4516
4517 // First look for constructor
9c7d5e88 4518 if (exp.e1.op == EXP.type && sd.ctor)
5fee5ec3
IB
4519 {
4520 if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
4521 goto Lx;
4522
4523 /* https://issues.dlang.org/show_bug.cgi?id=20695
4524 If all constructors are copy constructors, then
4525 try default construction.
4526 */
4527 if (!sd.hasRegularCtor)
4528 goto Lx;
4529
4530 auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4531 if (!sd.fill(exp.loc, sle.elements, true))
4532 return setError();
4533 if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
4534 return setError();
4535
4536 // https://issues.dlang.org/show_bug.cgi?id=14556
4537 // Set concrete type to avoid further redundant semantic().
4538 sle.type = exp.e1.type;
4539
4540 /* Constructor takes a mutable object, so don't use
4541 * the immutable initializer symbol.
4542 */
4543 sle.useStaticInit = false;
4544
4545 Expression e = sle;
4546 if (auto cf = sd.ctor.isCtorDeclaration())
4547 {
4548 e = new DotVarExp(exp.loc, e, cf, true);
4549 }
4550 else if (auto td = sd.ctor.isTemplateDeclaration())
4551 {
4552 e = new DotIdExp(exp.loc, e, td.ident);
4553 }
4554 else if (auto os = sd.ctor.isOverloadSet())
4555 {
4556 e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4557 }
4558 else
4559 assert(0);
4560 e = new CallExp(exp.loc, e, exp.arguments);
4561 e = e.expressionSemantic(sc);
4562 result = e;
4563 return;
4564 }
4565 // No constructor, look for overload of opCall
4566 if (search_function(sd, Id.call))
4567 goto L1;
4568 // overload of opCall, therefore it's a call
9c7d5e88 4569 if (exp.e1.op != EXP.type)
5fee5ec3
IB
4570 {
4571 if (sd.aliasthis && !isRecursiveAliasThis(exp.att1, exp.e1.type))
4572 {
4573 exp.e1 = resolveAliasThis(sc, exp.e1);
4574 goto Lagain;
4575 }
4576 exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4577 return setError();
4578 }
4579
4580 /* It's a struct literal
4581 */
4582 Lx:
4583 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4584 e = e.expressionSemantic(sc);
4585 result = e;
4586 return;
4587 }
4588 else if (t1.ty == Tclass)
4589 {
4590 L1:
4591 // Rewrite as e1.call(arguments)
4592 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4593 e = new CallExp(exp.loc, e, exp.arguments);
4594 e = e.expressionSemantic(sc);
4595 result = e;
4596 return;
4597 }
9c7d5e88 4598 else if (exp.e1.op == EXP.type && t1.isscalar())
5fee5ec3
IB
4599 {
4600 Expression e;
4601
4602 // Make sure to use the the enum type itself rather than its
4603 // base type
4604 // https://issues.dlang.org/show_bug.cgi?id=16346
4605 if (exp.e1.type.ty == Tenum)
4606 {
4607 t1 = exp.e1.type;
4608 }
4609
4610 if (!exp.arguments || exp.arguments.dim == 0)
4611 {
4612 e = t1.defaultInitLiteral(exp.loc);
4613 }
4614 else if (exp.arguments.dim == 1)
4615 {
4616 e = (*exp.arguments)[0];
4617 e = e.implicitCastTo(sc, t1);
4618 e = new CastExp(exp.loc, e, t1);
4619 }
4620 else
4621 {
4622 exp.error("more than one argument for construction of `%s`", t1.toChars());
4623 return setError();
4624 }
4625 e = e.expressionSemantic(sc);
4626 result = e;
4627 return;
4628 }
4629 }
4630
4631 static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4632 OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4633 {
4634 FuncDeclaration f = null;
4635 foreach (s; os.a)
4636 {
4637 if (tiargs && s.isFuncDeclaration())
4638 continue;
4639 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4640 {
4641 if (f2.errors)
4642 return null;
4643 if (f)
4644 {
4645 /* Error if match in more than one overload set,
4646 * even if one is a 'better' match than the other.
4647 */
4648 ScopeDsymbol.multiplyDefined(loc, f, f2);
4649 }
4650 else
4651 f = f2;
4652 }
4653 }
4654 if (!f)
4655 .error(loc, "no overload matches for `%s`", os.toChars());
4656 else if (f.errors)
4657 f = null;
4658 return f;
4659 }
4660
4661 bool isSuper = false;
9c7d5e88 4662 if (exp.e1.op == EXP.dotVariable && t1.ty == Tfunction || exp.e1.op == EXP.dotTemplateDeclaration)
5fee5ec3
IB
4663 {
4664 UnaExp ue = cast(UnaExp)exp.e1;
4665
0fb57034 4666 Expression ue1old = ue.e1; // need for 'right this' check
5fee5ec3
IB
4667 DotVarExp dve;
4668 DotTemplateExp dte;
4669 Dsymbol s;
9c7d5e88 4670 if (exp.e1.op == EXP.dotVariable)
5fee5ec3
IB
4671 {
4672 dve = cast(DotVarExp)exp.e1;
4673 dte = null;
4674 s = dve.var;
4675 tiargs = null;
4676 }
4677 else
4678 {
4679 dve = null;
4680 dte = cast(DotTemplateExp)exp.e1;
4681 s = dte.td;
4682 }
4683
4684 // Do overload resolution
0fb57034 4685 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
5fee5ec3
IB
4686 if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4687 return setError();
4688
4689 if (exp.f.interfaceVirtual)
4690 {
4691 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4692 */
4693 auto b = exp.f.interfaceVirtual;
4694 auto ad2 = b.sym;
4695 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4696 ue.e1 = ue.e1.expressionSemantic(sc);
5fee5ec3
IB
4697 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
4698 assert(vi >= 0);
4699 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4700 assert(exp.f);
4701 }
4702 if (exp.f.needThis())
4703 {
4704 AggregateDeclaration ad = exp.f.toParentLocal().isAggregateDeclaration();
4705 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
9c7d5e88 4706 if (ue.e1.op == EXP.error)
5fee5ec3
IB
4707 {
4708 result = ue.e1;
4709 return;
4710 }
4711 ethis = ue.e1;
4712 tthis = ue.e1.type;
4713 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4714 {
4715 if (global.params.useDIP1000 == FeatureState.enabled && checkParamArgumentEscape(sc, exp.f, null, ethis, false, false))
4716 return setError();
4717 }
4718 }
4719
4720 /* Cannot call public functions from inside invariant
4721 * (because then the invariant would have infinite recursion)
4722 */
9c7d5e88 4723 if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
5fee5ec3
IB
4724 {
4725 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4726 return setError();
4727 }
4728
4729 if (!exp.ignoreAttributes)
4730 checkFunctionAttributes(exp, sc, exp.f);
4731 checkAccess(exp.loc, sc, ue.e1, exp.f);
4732 if (!exp.f.needThis())
4733 {
4734 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4735 }
4736 else
4737 {
4738 if (ue1old.checkRightThis(sc))
4739 return setError();
9c7d5e88 4740 if (exp.e1.op == EXP.dotVariable)
5fee5ec3
IB
4741 {
4742 dve.var = exp.f;
4743 exp.e1.type = exp.f.type;
4744 }
4745 else
4746 {
4747 exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4748 exp.e1 = exp.e1.expressionSemantic(sc);
9c7d5e88 4749 if (exp.e1.op == EXP.error)
5fee5ec3
IB
4750 return setError();
4751 ue = cast(UnaExp)exp.e1;
4752 }
4753 version (none)
4754 {
4755 printf("ue.e1 = %s\n", ue.e1.toChars());
4756 printf("f = %s\n", exp.f.toChars());
4757 printf("t1 = %s\n", t1.toChars());
4758 printf("e1 = %s\n", exp.e1.toChars());
4759 printf("e1.type = %s\n", exp.e1.type.toChars());
4760 }
4761
4762 // See if we need to adjust the 'this' pointer
4763 AggregateDeclaration ad = exp.f.isThis();
4764 ClassDeclaration cd = ue.e1.type.isClassHandle();
4765 if (ad && cd && ad.isClassDeclaration())
4766 {
9c7d5e88 4767 if (ue.e1.op == EXP.dotType)
5fee5ec3
IB
4768 {
4769 ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4770 exp.directcall = true;
4771 }
9c7d5e88 4772 else if (ue.e1.op == EXP.super_)
5fee5ec3
IB
4773 exp.directcall = true;
4774 else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4775 exp.directcall = true;
4776
4777 if (ad != cd)
4778 {
4779 ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4780 ue.e1 = ue.e1.expressionSemantic(sc);
4781 }
4782 }
4783 }
4784 // If we've got a pointer to a function then deference it
4785 // https://issues.dlang.org/show_bug.cgi?id=16483
4786 if (exp.e1.type.isPtrToFunction())
4787 {
4788 Expression e = new PtrExp(exp.loc, exp.e1);
4789 e.type = exp.e1.type.nextOf();
4790 exp.e1 = e;
4791 }
4792 t1 = exp.e1.type;
4793 }
9c7d5e88 4794 else if (exp.e1.op == EXP.super_ || exp.e1.op == EXP.this_)
5fee5ec3
IB
4795 {
4796 auto ad = sc.func ? sc.func.isThis() : null;
4797 auto cd = ad ? ad.isClassDeclaration() : null;
4798
9c7d5e88 4799 isSuper = exp.e1.op == EXP.super_;
5fee5ec3
IB
4800 if (isSuper)
4801 {
4802 // Base class constructor call
4803 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4804 {
4805 exp.error("super class constructor call must be in a constructor");
4806 return setError();
4807 }
4808 if (!cd.baseClass.ctor)
4809 {
4810 exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4811 return setError();
4812 }
4813 }
4814 else
4815 {
4816 // `this` call expression must be inside a
4817 // constructor
4818 if (!ad || !sc.func.isCtorDeclaration())
4819 {
4820 exp.error("constructor call must be in a constructor");
4821 return setError();
4822 }
4823
4824 // https://issues.dlang.org/show_bug.cgi?id=18719
4825 // If `exp` is a call expression to another constructor
4826 // then it means that all struct/class fields will be
4827 // initialized after this call.
4828 foreach (ref field; sc.ctorflow.fieldinit)
4829 {
4830 field.csx |= CSX.this_ctor;
4831 }
4832 }
4833
4834 if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4835 {
4836 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4837 exp.error("constructor calls not allowed in loops or after labels");
4838 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4839 exp.error("multiple constructor calls");
4840 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4841 exp.error("an earlier `return` statement skips constructor");
4842 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4843 }
4844
4845 tthis = ad.type.addMod(sc.func.type.mod);
4846 auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4847 if (auto os = ctor.isOverloadSet())
4848 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4849 else
4850 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4851
4852 if (!exp.f || exp.f.errors)
4853 return setError();
4854
4855 checkFunctionAttributes(exp, sc, exp.f);
4856 checkAccess(exp.loc, sc, null, exp.f);
4857
4858 exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4859 exp.e1 = exp.e1.expressionSemantic(sc);
4860 // https://issues.dlang.org/show_bug.cgi?id=21095
9c7d5e88 4861 if (exp.e1.op == EXP.error)
5fee5ec3
IB
4862 return setError();
4863 t1 = exp.e1.type;
4864
4865 // BUG: this should really be done by checking the static
4866 // call graph
4867 if (exp.f == sc.func)
4868 {
4869 exp.error("cyclic constructor call");
4870 return setError();
4871 }
4872 }
9c7d5e88 4873 else if (exp.e1.op == EXP.overloadSet)
5fee5ec3
IB
4874 {
4875 auto os = (cast(OverExp)exp.e1).vars;
4876 exp.f = resolveOverloadSet(exp.loc, sc, os, tiargs, tthis, exp.arguments);
4877 if (!exp.f)
4878 return setError();
4879 if (ethis)
4880 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4881 else
4882 exp.e1 = new VarExp(exp.loc, exp.f, false);
4883 goto Lagain;
4884 }
4885 else if (!t1)
4886 {
4887 exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4888 return setError();
4889 }
4890 else if (t1.ty == Terror)
4891 {
4892 return setError();
4893 }
4894 else if (t1.ty != Tfunction)
4895 {
4896 TypeFunction tf;
4897 const(char)* p;
4898 Dsymbol s;
4899 exp.f = null;
9c7d5e88 4900 if (exp.e1.op == EXP.function_)
5fee5ec3
IB
4901 {
4902 // function literal that direct called is always inferred.
4903 assert((cast(FuncExp)exp.e1).fd);
4904 exp.f = (cast(FuncExp)exp.e1).fd;
4905 tf = cast(TypeFunction)exp.f.type;
4906 p = "function literal";
4907 }
4908 else if (t1.ty == Tdelegate)
4909 {
4910 TypeDelegate td = cast(TypeDelegate)t1;
4911 assert(td.next.ty == Tfunction);
4912 tf = cast(TypeFunction)td.next;
4913 p = "delegate";
4914 }
4915 else if (auto tfx = t1.isPtrToFunction())
4916 {
4917 tf = tfx;
4918 p = "function pointer";
4919 }
9c7d5e88 4920 else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
5fee5ec3
IB
4921 {
4922 DotVarExp dve = cast(DotVarExp)exp.e1;
4923 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4924 if (!exp.f)
4925 return setError();
4926 if (exp.f.needThis())
4927 {
4928 dve.var = exp.f;
4929 dve.type = exp.f.type;
4930 dve.hasOverloads = false;
4931 goto Lagain;
4932 }
4933 exp.e1 = new VarExp(dve.loc, exp.f, false);
4934 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4935 result = e.expressionSemantic(sc);
4936 return;
4937 }
9c7d5e88 4938 else if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
5fee5ec3
IB
4939 {
4940 s = (cast(VarExp)exp.e1).var;
4941 goto L2;
4942 }
9c7d5e88 4943 else if (exp.e1.op == EXP.template_)
5fee5ec3
IB
4944 {
4945 s = (cast(TemplateExp)exp.e1).td;
4946 L2:
4947 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
4948 if (!exp.f || exp.f.errors)
4949 return setError();
4950 if (exp.f.needThis())
4951 {
4952 if (hasThis(sc))
4953 {
4954 // Supply an implicit 'this', as in
4955 // this.ident
4956 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
4957 goto Lagain;
4958 }
4959 else if (isNeedThisScope(sc, exp.f))
4960 {
4961 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
4962 return setError();
4963 }
4964 }
4965 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
4966 goto Lagain;
4967 }
4968 else
4969 {
4970 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
4971 return setError();
4972 }
4973
4974 const(char)* failMessage;
4975 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
4976 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
4977 {
4978 OutBuffer buf;
4979 buf.writeByte('(');
4980 argExpTypesToCBuffer(&buf, exp.arguments);
4981 buf.writeByte(')');
4982 if (tthis)
4983 tthis.modToBuffer(&buf);
4984
4985 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
4986 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
4987 p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
4988 if (failMessage)
4989 errorSupplemental(exp.loc, "%s", failMessage);
4990 return setError();
4991 }
4992 // Purity and safety check should run after testing arguments matching
4993 if (exp.f)
4994 {
4995 exp.checkPurity(sc, exp.f);
4996 exp.checkSafety(sc, exp.f);
4997 exp.checkNogc(sc, exp.f);
4998 if (exp.f.checkNestedReference(sc, exp.loc))
4999 return setError();
5000 }
5001 else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
5002 {
5003 bool err = false;
5004 if (!tf.purity && sc.func.setImpure())
5005 {
5006 exp.error("`pure` %s `%s` cannot call impure %s `%s`",
5007 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5008 err = true;
5009 }
5010 if (!tf.isnogc && sc.func.setGC())
5011 {
5012 exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
5013 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5014 err = true;
5015 }
5016 if (tf.trust <= TRUST.system && sc.func.setUnsafe())
5017 {
5018 exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
5019 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5020 err = true;
5021 }
5022 if (err)
5023 return setError();
5024 }
5025
5026 if (t1.ty == Tpointer)
5027 {
5028 Expression e = new PtrExp(exp.loc, exp.e1);
5029 e.type = tf;
5030 exp.e1 = e;
5031 }
5032 t1 = tf;
5033 }
9c7d5e88 5034 else if (exp.e1.op == EXP.variable)
5fee5ec3
IB
5035 {
5036 // Do overload resolution
5037 VarExp ve = cast(VarExp)exp.e1;
5038
5039 exp.f = ve.var.isFuncDeclaration();
5040 assert(exp.f);
5041 tiargs = null;
5042
5043 if (exp.f.overnext)
5044 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
5045 else
5046 {
5047 exp.f = exp.f.toAliasFunc();
5048 TypeFunction tf = cast(TypeFunction)exp.f.type;
5049 const(char)* failMessage;
5050 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5051 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5052 {
5053 OutBuffer buf;
5054 buf.writeByte('(');
5055 argExpTypesToCBuffer(&buf, exp.arguments);
5056 buf.writeByte(')');
5057
5058 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5059 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5060 exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5061 if (failMessage)
5062 errorSupplemental(exp.loc, "%s", failMessage);
5063 exp.f = null;
5064 }
5065 }
5066 if (!exp.f || exp.f.errors)
5067 return setError();
5068
5069 if (exp.f.needThis())
5070 {
5071 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5072 if (exp.f.checkNestedReference(sc, exp.loc))
5073 return setError();
5074
5075 if (hasThis(sc))
5076 {
5077 // Supply an implicit 'this', as in
5078 // this.ident
5079 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5080 // Note: we cannot use f directly, because further overload resolution
5081 // through the supplied 'this' may cause different result.
5082 goto Lagain;
5083 }
5084 else if (isNeedThisScope(sc, exp.f))
5085 {
5086 // At this point it is possible that `exp.f` had an ambiguity error that was
5087 // silenced because the previous call to `resolveFuncCall` was done using
5088 // `FuncResolveFlag.overloadOnly`. To make sure that a proper error message
5089 // is printed, redo the call with `FuncResolveFlag.standard`.
5090 //
5091 // https://issues.dlang.org/show_bug.cgi?id=22157
5092 if (exp.f.overnext)
5093 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5094
5095 if (!exp.f || exp.f.errors)
5096 return setError();
5097
5098 // If no error is printed, it means that `f` is the single matching overload
5099 // and it needs `this`.
5100 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5101 return setError();
5102 }
5103 }
5104
5105 checkFunctionAttributes(exp, sc, exp.f);
5106 checkAccess(exp.loc, sc, null, exp.f);
5107 if (exp.f.checkNestedReference(sc, exp.loc))
5108 return setError();
5109
5110 ethis = null;
5111 tthis = null;
5112
5113 if (ve.hasOverloads)
5114 {
5115 exp.e1 = new VarExp(ve.loc, exp.f, false);
5116 exp.e1.type = exp.f.type;
5117 }
5118 t1 = exp.f.type;
5119 }
5120 assert(t1.ty == Tfunction);
5121
5122 Expression argprefix;
5123 if (!exp.arguments)
5124 exp.arguments = new Expressions();
5125 if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5126 return setError();
5127
5128 if (!exp.type)
5129 {
5130 exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5131 // avoid recursive expression printing
5132 exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5133 return setError();
5134 }
5135
5136 if (exp.f && exp.f.tintro)
5137 {
5138 Type t = exp.type;
5139 int offset = 0;
5140 TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5141 if (tf.next.isBaseOf(t, &offset) && offset)
5142 {
5143 exp.type = tf.next;
5144 result = Expression.combine(argprefix, exp.castTo(sc, t));
5145 return;
5146 }
5147 }
5148
5149 // Handle the case of a direct lambda call
5150 if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5151 {
5152 exp.f.tookAddressOf = 0;
5153 }
5154
5155 result = Expression.combine(argprefix, exp);
5156
5157 if (isSuper)
5158 {
5159 auto ad = sc.func ? sc.func.isThis() : null;
5160 auto cd = ad ? ad.isClassDeclaration() : null;
5161 if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5162 {
5163 // if super is defined in C++, it sets the vtable pointer to the base class
5164 // so we have to restore it, but still return 'this' from super() call:
5165 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5166 Loc loc = exp.loc;
5167
5168 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5169 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5170 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5171
5172 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5173 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5174
5175 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5176
5177 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5178
5179 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5180 result = e.expressionSemantic(sc);
5181 }
5182 }
5183
5184 // declare dual-context container
5185 if (exp.f && exp.f.isThis2 && !sc.intypeof && sc.func)
5186 {
5187 // check access to second `this`
5188 if (AggregateDeclaration ad2 = exp.f.isMember2())
5189 {
5190 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
9c7d5e88 5191 if (te.op != EXP.error)
5fee5ec3 5192 te = getRightThis(exp.loc, sc, ad2, te, exp.f);
9c7d5e88 5193 if (te.op == EXP.error)
5fee5ec3
IB
5194 {
5195 exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5196 return setError();
5197 }
5198 }
5199 exp.vthis2 = makeThis2Argument(exp.loc, sc, exp.f);
5200 Expression de = new DeclarationExp(exp.loc, exp.vthis2);
5201 result = Expression.combine(de, result);
5202 result = result.expressionSemantic(sc);
5203 }
5204 }
5205
5206 override void visit(DeclarationExp e)
5207 {
5208 if (e.type)
5209 {
5210 result = e;
5211 return;
5212 }
5213 static if (LOGSEMANTIC)
5214 {
5215 printf("DeclarationExp::semantic() %s\n", e.toChars());
5216 }
5217
5218 uint olderrors = global.errors;
5219
5220 /* This is here to support extern(linkage) declaration,
5221 * where the extern(linkage) winds up being an AttribDeclaration
5222 * wrapper.
5223 */
5224 Dsymbol s = e.declaration;
5225
5226 while (1)
5227 {
5228 AttribDeclaration ad = s.isAttribDeclaration();
5229 if (ad)
5230 {
5231 if (ad.decl && ad.decl.dim == 1)
5232 {
5233 s = (*ad.decl)[0];
5234 continue;
5235 }
5236 }
5237 break;
5238 }
5239
5240 VarDeclaration v = s.isVarDeclaration();
5241 if (v)
5242 {
5243 // Do semantic() on initializer first, so:
5244 // int a = a;
5245 // will be illegal.
5246 e.declaration.dsymbolSemantic(sc);
5247 s.parent = sc.parent;
5248 }
5249
5250 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5251 // Insert into both local scope and function scope.
5252 // Must be unique in both.
5253 if (s.ident)
5254 {
5255 if (!sc.insert(s))
5256 {
5257 auto conflict = sc.search(Loc.initial, s.ident, null);
5258 e.error("declaration `%s` is already defined", s.toPrettyChars());
5259 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5260 conflict.kind(), conflict.toChars());
5261 return setError();
5262 }
5263 else if (sc.func)
5264 {
5265 // https://issues.dlang.org/show_bug.cgi?id=11720
5266 if ((s.isFuncDeclaration() ||
5267 s.isAggregateDeclaration() ||
5268 s.isEnumDeclaration() ||
5269 s.isTemplateDeclaration() ||
5270 v
5271 ) && !sc.func.localsymtab.insert(s))
5272 {
5273 // Get the previous symbol
5274 Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5275
5276 // Perturb the name mangling so that the symbols can co-exist
5277 // instead of colliding
5278 s.localNum = cast(ushort)(originalSymbol.localNum + 1);
5279 assert(s.localNum); // 65535 should be enough for anyone
5280
5281 // Replace originalSymbol with s, which updates the localCount
5282 sc.func.localsymtab.update(s);
5283
5284 // The mangling change only works for D mangling
5285 }
5286// else
5287 {
5288 /* https://issues.dlang.org/show_bug.cgi?id=21272
5289 * If we are in a foreach body we need to extract the
5290 * function containing the foreach
5291 */
5292 FuncDeclaration fes_enclosing_func;
5293 if (sc.func && sc.func.fes)
5294 fes_enclosing_func = sc.enclosing.enclosing.func;
5295
5296 // Disallow shadowing
5297 for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5298 {
5299 Dsymbol s2;
5300 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5301 {
5302 // allow STC.local symbols to be shadowed
5303 // TODO: not really an optimal design
5304 auto decl = s2.isDeclaration();
5305 if (!decl || !(decl.storage_class & STC.local))
5306 {
5307 if (sc.func.fes)
5308 {
5309 e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5310 }
5311 else
5312 {
5313 e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5314 return setError();
5315 }
5316 }
5317 }
5318 }
5319 }
5320 }
5321 }
5322 if (!s.isVarDeclaration())
5323 {
5324 Scope* sc2 = sc;
5325 if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5326 sc2 = sc.push();
5327 sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5328 e.declaration.dsymbolSemantic(sc2);
5329 if (sc2 != sc)
5330 sc2.pop();
5331 s.parent = sc.parent;
5332 }
5333 if (global.errors == olderrors)
5334 {
5335 e.declaration.semantic2(sc);
5336 if (global.errors == olderrors)
5337 {
5338 e.declaration.semantic3(sc);
5339 }
5340 }
5341 // todo: error in declaration should be propagated.
5342
5343 e.type = Type.tvoid;
5344 result = e;
5345 }
5346
5347 override void visit(TypeidExp exp)
5348 {
5349 static if (LOGSEMANTIC)
5350 {
5351 printf("TypeidExp::semantic() %s\n", exp.toChars());
5352 }
5353 Type ta = isType(exp.obj);
5354 Expression ea = isExpression(exp.obj);
5355 Dsymbol sa = isDsymbol(exp.obj);
5356 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5357
5358 if (ta)
5359 {
5360 dmd.typesem.resolve(ta, exp.loc, sc, ea, ta, sa, true);
5361 }
5362
5363 if (ea)
5364 {
5365 if (auto sym = getDsymbol(ea))
5366 ea = symbolToExp(sym, exp.loc, sc, false);
5367 else
5368 ea = ea.expressionSemantic(sc);
5369 ea = resolveProperties(sc, ea);
5370 ta = ea.type;
9c7d5e88 5371 if (ea.op == EXP.type)
5fee5ec3
IB
5372 ea = null;
5373 }
5374
5375 if (!ta)
5376 {
5377 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5378 exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5379 return setError();
5380 }
5381
5382 if (global.params.vcomplex)
5383 ta.checkComplexTransition(exp.loc, sc);
5384
5385 Expression e;
5386 auto tb = ta.toBasetype();
5387 if (ea && tb.ty == Tclass)
5388 {
5389 if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5390 {
5391 error(exp.loc, "Runtime type information is not supported for `extern(C++)` classes");
5392 e = ErrorExp.get();
5393 }
5394 else if (!Type.typeinfoclass)
5395 {
5396 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5397 e = ErrorExp.get();
5398 }
5399 else
5400 {
5401 /* Get the dynamic type, which is .classinfo
5402 */
5403 ea = ea.expressionSemantic(sc);
5404 e = new TypeidExp(ea.loc, ea);
5405 e.type = Type.typeinfoclass.type;
5406 }
5407 }
5408 else if (ta.ty == Terror)
5409 {
5410 e = ErrorExp.get();
5411 }
5412 else
5413 {
5414 // Handle this in the glue layer
5415 e = new TypeidExp(exp.loc, ta);
5416 e.type = getTypeInfoType(exp.loc, ta, sc);
5417
5418 semanticTypeInfo(sc, ta);
5419
5420 if (ea)
5421 {
5422 e = new CommaExp(exp.loc, ea, e); // execute ea
5423 e = e.expressionSemantic(sc);
5424 }
5425 }
5426 result = e;
5427 }
5428
5429 override void visit(TraitsExp e)
5430 {
5431 result = semanticTraits(e, sc);
5432 }
5433
5434 override void visit(HaltExp e)
5435 {
5436 static if (LOGSEMANTIC)
5437 {
5438 printf("HaltExp::semantic()\n");
5439 }
5440 e.type = Type.tnoreturn;
5441 result = e;
5442 }
5443
5444 override void visit(IsExp e)
5445 {
5446 /* is(targ id tok tspec)
5447 * is(targ id : tok2)
5448 * is(targ id == tok2)
5449 */
5450 Type tded = null;
5451
5452 void yes()
5453 {
5454 //printf("yes\n");
5455 if (!e.id)
5456 {
5457 result = IntegerExp.createBool(true);
5458 return;
5459 }
5460
5461 Dsymbol s;
5462 Tuple tup = isTuple(tded);
5463 if (tup)
5464 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5465 else
5466 s = new AliasDeclaration(e.loc, e.id, tded);
5467 s.dsymbolSemantic(sc);
5468
5469 /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5470 * More investigation is needed.
5471 */
5472 if (!tup && !sc.insert(s))
5473 {
5474 auto conflict = sc.search(Loc.initial, s.ident, null);
5475 e.error("declaration `%s` is already defined", s.toPrettyChars());
5476 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5477 conflict.kind(), conflict.toChars());
5478 }
5479
5480 unSpeculative(sc, s);
5481
5482 result = IntegerExp.createBool(true);
5483 }
5484 void no()
5485 {
5486 result = IntegerExp.createBool(false);
5487 //printf("no\n");
5488 }
5489
5490 static if (LOGSEMANTIC)
5491 {
5492 printf("IsExp::semantic(%s)\n", e.toChars());
5493 }
5494 if (e.id && !(sc.flags & SCOPE.condition))
5495 {
5496 e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5497 return setError();
5498 }
5499
5500 if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5501 {
5502 const oldErrors = global.startGagging();
5503 Dsymbol sym = e.targ.toDsymbol(sc);
5504 global.endGagging(oldErrors);
5505
5506 if (sym is null)
5507 return no();
5508 Package p = resolveIsPackage(sym);
5509 if (p is null)
5510 return no();
5511 if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5512 return no();
5513 else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5514 return no();
5515 tded = e.targ;
5516 return yes();
5517 }
5518
5519 {
5520 Scope* sc2 = sc.copy(); // keep sc.flags
5521 sc2.tinst = null;
5522 sc2.minst = null;
5523 sc2.flags |= SCOPE.fullinst;
5524 Type t = e.targ.trySemantic(e.loc, sc2);
5525 sc2.pop();
5526 if (!t) // errors, so condition is false
5527 return no();
5528 e.targ = t;
5529 }
5530
5531 if (e.tok2 != TOK.reserved)
5532 {
5533 switch (e.tok2)
5534 {
5535 case TOK.struct_:
5536 if (e.targ.ty != Tstruct)
5537 return no();
5538 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5539 return no();
5540 tded = e.targ;
5541 break;
5542
5543 case TOK.union_:
5544 if (e.targ.ty != Tstruct)
5545 return no();
5546 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5547 return no();
5548 tded = e.targ;
5549 break;
5550
5551 case TOK.class_:
5552 if (e.targ.ty != Tclass)
5553 return no();
5554 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5555 return no();
5556 tded = e.targ;
5557 break;
5558
5559 case TOK.interface_:
5560 if (e.targ.ty != Tclass)
5561 return no();
5562 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5563 return no();
5564 tded = e.targ;
5565 break;
5566
5567 case TOK.const_:
5568 if (!e.targ.isConst())
5569 return no();
5570 tded = e.targ;
5571 break;
5572
5573 case TOK.immutable_:
5574 if (!e.targ.isImmutable())
5575 return no();
5576 tded = e.targ;
5577 break;
5578
5579 case TOK.shared_:
5580 if (!e.targ.isShared())
5581 return no();
5582 tded = e.targ;
5583 break;
5584
5585 case TOK.inout_:
5586 if (!e.targ.isWild())
5587 return no();
5588 tded = e.targ;
5589 break;
5590
5591 case TOK.super_:
5592 // If class or interface, get the base class and interfaces
5593 if (e.targ.ty != Tclass)
5594 return no();
5595 else
5596 {
5597 ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5598 auto args = new Parameters();
5599 args.reserve(cd.baseclasses.dim);
5600 if (cd.semanticRun < PASS.semanticdone)
5601 cd.dsymbolSemantic(null);
5602 for (size_t i = 0; i < cd.baseclasses.dim; i++)
5603 {
5604 BaseClass* b = (*cd.baseclasses)[i];
5605 args.push(new Parameter(STC.in_, b.type, null, null, null));
5606 }
5607 tded = new TypeTuple(args);
5608 }
5609 break;
5610
5611 case TOK.enum_:
5612 if (e.targ.ty != Tenum)
5613 return no();
5614 if (e.id)
5615 tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5616 else
5617 tded = e.targ;
5618
5619 if (tded.ty == Terror)
5620 return setError();
5621 break;
5622
5623 case TOK.delegate_:
5624 if (e.targ.ty != Tdelegate)
5625 return no();
5626 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5627 break;
5628
5629 case TOK.function_:
5630 case TOK.parameters:
5631 {
5632 if (e.targ.ty != Tfunction)
5633 return no();
5634 tded = e.targ;
5635
5636 /* Generate tuple from function parameter types.
5637 */
5638 assert(tded.ty == Tfunction);
5639 auto tdedf = tded.isTypeFunction();
5640 auto args = new Parameters();
5641 foreach (i, arg; tdedf.parameterList)
5642 {
5643 assert(arg && arg.type);
5644 /* If one of the default arguments was an error,
5645 don't return an invalid tuple
5646 */
9c7d5e88 5647 if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
5fee5ec3
IB
5648 return setError();
5649 args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5650 }
5651 tded = new TypeTuple(args);
5652 break;
5653 }
5654 case TOK.return_:
5655 /* Get the 'return type' for the function,
5656 * delegate, or pointer to function.
5657 */
5658 if (auto tf = e.targ.isFunction_Delegate_PtrToFunction())
5659 tded = tf.next;
5660 else
5661 return no();
5662 break;
5663
5664 case TOK.argumentTypes:
5665 /* Generate a type tuple of the equivalent types used to determine if a
5666 * function argument of this type can be passed in registers.
5667 * The results of this are highly platform dependent, and intended
5668 * primarly for use in implementing va_arg().
5669 */
5670 tded = target.toArgTypes(e.targ);
5671 if (!tded)
5672 return no();
5673 // not valid for a parameter
5674 break;
5675
5676 case TOK.vector:
5677 if (e.targ.ty != Tvector)
5678 return no();
5679 tded = (cast(TypeVector)e.targ).basetype;
5680 break;
5681
5682 default:
5683 assert(0);
5684 }
5685
5686 // https://issues.dlang.org/show_bug.cgi?id=18753
5687 if (tded)
5688 return yes();
5689 return no();
5690 }
5691 else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
5692 {
5693 /* Evaluate to true if targ matches tspec
5694 * is(targ == tspec)
5695 * is(targ : tspec)
5696 */
5697 e.tspec = e.tspec.typeSemantic(e.loc, sc);
5698 //printf("targ = %s, %s\n", e.targ.toChars(), e.targ.deco);
5699 //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5700
5701 if (e.tok == TOK.colon)
5702 {
5703 // current scope is itself deprecated, or deprecations are not errors
5704 const bool deprecationAllowed = sc.isDeprecated
5705 || global.params.useDeprecated != DiagnosticReporting.error;
5706 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5707
5708 // baseClass might not be set if either targ or tspec is forward referenced.
5709 if (auto tc = e.targ.isTypeClass())
5710 tc.sym.dsymbolSemantic(null);
5711 if (auto tc = e.tspec.isTypeClass())
5712 tc.sym.dsymbolSemantic(null);
5713
5714 if (preventAliasThis && e.targ.ty == Tstruct)
5715 {
5716 if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5717 return yes();
5718 else
5719 return no();
5720 }
5721 else if (preventAliasThis && e.targ.ty == Tclass)
5722 {
5723 if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5724 return yes();
5725 else
5726 return no();
5727 }
5728 else if (e.targ.implicitConvTo(e.tspec))
5729 return yes();
5730 else
5731 return no();
5732 }
5733 else /* == */
5734 {
5735 if (e.targ.equals(e.tspec))
5736 return yes();
5737 else
5738 return no();
5739 }
5740 }
5741 else if (e.tspec)
5742 {
5743 /* Evaluate to true if targ matches tspec.
5744 * If true, declare id as an alias for the specialized type.
5745 * is(targ == tspec, tpl)
5746 * is(targ : tspec, tpl)
5747 * is(targ id == tspec)
5748 * is(targ id : tspec)
5749 * is(targ id == tspec, tpl)
5750 * is(targ id : tspec, tpl)
5751 */
5752 Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5753 e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5754
5755 Objects dedtypes = Objects(e.parameters.dim);
5756 dedtypes.zero();
5757
5758 MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5759 //printf("targ: %s\n", targ.toChars());
5760 //printf("tspec: %s\n", tspec.toChars());
5761 if (m == MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5762 {
5763 return no();
5764 }
5765 else
5766 {
5767 tded = cast(Type)dedtypes[0];
5768 if (!tded)
5769 tded = e.targ;
5770 Objects tiargs = Objects(1);
5771 tiargs[0] = e.targ;
5772
5773 /* Declare trailing parameters
5774 */
5775 for (size_t i = 1; i < e.parameters.dim; i++)
5776 {
5777 TemplateParameter tp = (*e.parameters)[i];
5778 Declaration s = null;
5779
5780 m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5781 if (m == MATCH.nomatch)
5782 return no();
5783 s.dsymbolSemantic(sc);
5784 if (!sc.insert(s))
5785 {
5786 auto conflict = sc.search(Loc.initial, s.ident, null);
5787 e.error("declaration `%s` is already defined", s.toPrettyChars());
5788 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5789 conflict.kind(), conflict.toChars());
5790 }
5791
5792 unSpeculative(sc, s);
5793 }
5794 return yes();
5795 }
5796 }
5797 else if (e.id)
5798 {
5799 /* Declare id as an alias for type targ. Evaluate to true
5800 * is(targ id)
5801 */
5802 tded = e.targ;
5803 }
5804 return yes();
5805 }
5806
5807 override void visit(BinAssignExp exp)
5808 {
5809 if (exp.type)
5810 {
5811 result = exp;
5812 return;
5813 }
5814
5815 Expression e = exp.op_overload(sc);
5816 if (e)
5817 {
5818 result = e;
5819 return;
5820 }
5821
9c7d5e88 5822 if (exp.e1.op == EXP.arrayLength)
5fee5ec3
IB
5823 {
5824 // arr.length op= e2;
5825 e = rewriteOpAssign(exp);
5826 e = e.expressionSemantic(sc);
5827 result = e;
5828 return;
5829 }
9c7d5e88 5830 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5fee5ec3
IB
5831 {
5832 if (checkNonAssignmentArrayOp(exp.e1))
5833 return setError();
5834
9c7d5e88 5835 if (exp.e1.op == EXP.slice)
5fee5ec3
IB
5836 (cast(SliceExp)exp.e1).arrayop = true;
5837
5838 // T[] op= ...
5839 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5840 {
5841 // T[] op= T
5842 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5843 }
5844 else if (Expression ex = typeCombine(exp, sc))
5845 {
5846 result = ex;
5847 return;
5848 }
5849 exp.type = exp.e1.type;
5850 result = arrayOp(exp, sc);
5851 return;
5852 }
5853
5854 exp.e1 = exp.e1.expressionSemantic(sc);
5855 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5856 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
5857 exp.type = exp.e1.type;
5858
5859 if (auto ad = isAggregate(exp.e1.type))
5860 {
5861 if (const s = search_function(ad, Id.opOpAssign))
5862 {
5863 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());
5864 return setError();
5865 }
5866 }
5867 if (exp.e1.checkScalar() ||
5868 exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5869 exp.e1.checkSharedAccess(sc))
5870 return setError();
5871
9c7d5e88
IB
5872 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);
5873 int bitwise = (exp.op == EXP.andAssign || exp.op == EXP.orAssign || exp.op == EXP.xorAssign);
5874 int shift = (exp.op == EXP.leftShiftAssign || exp.op == EXP.rightShiftAssign || exp.op == EXP.unsignedRightShiftAssign);
5fee5ec3
IB
5875
5876 if (bitwise && exp.type.toBasetype().ty == Tbool)
5877 exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5878 else if (exp.checkNoBool())
5879 return setError();
5880
9c7d5e88 5881 if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5fee5ec3
IB
5882 {
5883 result = scaleFactor(exp, sc);
5884 return;
5885 }
5886
5887 if (Expression ex = typeCombine(exp, sc))
5888 {
5889 result = ex;
5890 return;
5891 }
5892
5893 if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5894 return setError();
5895 if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5896 return setError();
5897
5898 if (shift)
5899 {
5900 if (exp.e2.type.toBasetype().ty != Tvector)
5901 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5902 }
5903
5904 if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5905 {
5906 result = exp.incompatibleTypes();
5907 return;
5908 }
5909
9c7d5e88 5910 if (exp.e1.op == EXP.error || exp.e2.op == EXP.error)
5fee5ec3
IB
5911 return setError();
5912
5913 e = exp.checkOpAssignTypes(sc);
9c7d5e88 5914 if (e.op == EXP.error)
5fee5ec3
IB
5915 {
5916 result = e;
5917 return;
5918 }
5919
9c7d5e88 5920 assert(e.op == EXP.assign || e == exp);
5fee5ec3
IB
5921 result = (cast(BinExp)e).reorderSettingAAElem(sc);
5922 }
5923
5924 private Expression compileIt(MixinExp exp)
5925 {
5926 OutBuffer buf;
5927 if (expressionsToString(buf, sc, exp.exps))
5928 return null;
5929
5930 uint errors = global.errors;
5931 const len = buf.length;
5932 const str = buf.extractChars()[0 .. len];
5933 scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
5934 p.nextToken();
5935 //printf("p.loc.linnum = %d\n", p.loc.linnum);
5936
5937 Expression e = p.parseExpression();
5938 if (global.errors != errors)
5939 return null;
5940
5941 if (p.token.value != TOK.endOfFile)
5942 {
5943 exp.error("incomplete mixin expression `%s`", str.ptr);
5944 return null;
5945 }
5946 return e;
5947 }
5948
5949 override void visit(MixinExp exp)
5950 {
5951 /* https://dlang.org/spec/expression.html#mixin_expressions
5952 */
5953
5954 static if (LOGSEMANTIC)
5955 {
5956 printf("MixinExp::semantic('%s')\n", exp.toChars());
5957 }
5958
5959 auto e = compileIt(exp);
5960 if (!e)
5961 return setError();
5962 result = e.expressionSemantic(sc);
5963 }
5964
5965 override void visit(ImportExp e)
5966 {
5967 static if (LOGSEMANTIC)
5968 {
5969 printf("ImportExp::semantic('%s')\n", e.toChars());
5970 }
5971
5972 auto se = semanticString(sc, e.e1, "file name argument");
5973 if (!se)
5974 return setError();
5975 se = se.toUTF8(sc);
5976
5977 auto namez = se.toStringz().ptr;
5978 if (!global.filePath)
5979 {
5980 e.error("need `-J` switch to import text file `%s`", namez);
5981 return setError();
5982 }
5983
5984 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5985 * ('Path Traversal') attacks.
5986 * http://cwe.mitre.org/data/definitions/22.html
5987 */
5988
5989 if (FileName.absolute(namez))
5990 {
5991 e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
5992 return setError();
5993 }
5994
5995 auto idxReserved = FileName.findReservedChar(namez);
5996 if (idxReserved != size_t.max)
5997 {
5998 e.error("`%s` is not a valid filename on this platform", se.toChars());
5999 e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
6000 return setError();
6001 }
6002
6003 if (FileName.refersToParentDir(namez))
6004 {
6005 e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
6006 return setError();
6007 }
6008
6009 auto name = FileName.searchPath(global.filePath, namez, false);
6010 if (!name)
6011 {
6012 e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
6013 e.errorSupplemental("Path(s) searched (as provided by `-J`):");
6014 foreach (idx, path; *global.filePath)
6015 {
6016 const attr = FileName.exists(path);
6017 const(char)* err = attr == 2 ? "" :
6018 (attr == 1 ? " (not a directory)" : " (path not found)");
6019 e.errorSupplemental("[%zu]: `%s`%s", idx, path, err);
6020 }
6021 return setError();
6022 }
6023
6024 sc._module.contentImportedFiles.push(name);
6025 if (global.params.verbose)
6026 {
6027 const slice = se.peekString();
6028 message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, name);
6029 }
6030 if (global.params.moduleDeps !is null)
6031 {
6032 OutBuffer* ob = global.params.moduleDeps;
6033 Module imod = sc._module;
6034
6035 if (!global.params.moduleDepsFile)
6036 ob.writestring("depsFile ");
6037 ob.writestring(imod.toPrettyChars());
6038 ob.writestring(" (");
6039 escapePath(ob, imod.srcfile.toChars());
6040 ob.writestring(") : ");
6041 if (global.params.moduleDepsFile)
6042 ob.writestring("string : ");
6043 ob.write(se.peekString());
6044 ob.writestring(" (");
6045 escapePath(ob, name);
6046 ob.writestring(")");
6047 ob.writenl();
6048 }
6049 if (global.params.emitMakeDeps)
6050 {
6051 global.params.makeDeps.push(name);
6052 }
6053
6054 {
0fb57034
IB
6055 auto fileName = FileName(name.toDString);
6056 if (auto fmResult = FileManager.fileManager.lookup(fileName))
5fee5ec3 6057 {
0fb57034 6058 se = new StringExp(e.loc, fmResult.data);
5fee5ec3
IB
6059 }
6060 else
6061 {
0fb57034
IB
6062 auto readResult = File.read(name);
6063 if (!readResult.success)
6064 {
6065 e.error("cannot read file `%s`", name);
6066 return setError();
6067 }
6068 else
6069 {
6070 // take ownership of buffer (probably leaking)
6071 auto data = readResult.extractSlice();
6072 se = new StringExp(e.loc, data);
6073
6074 FileBuffer* fileBuffer = FileBuffer.create();
6075 fileBuffer.data = data;
6076 FileManager.fileManager.add(fileName, fileBuffer);
6077 }
5fee5ec3
IB
6078 }
6079 }
6080 result = se.expressionSemantic(sc);
6081 }
6082
6083 override void visit(AssertExp exp)
6084 {
6085 // https://dlang.org/spec/expression.html#assert_expressions
6086 static if (LOGSEMANTIC)
6087 {
6088 printf("AssertExp::semantic('%s')\n", exp.toChars());
6089 }
6090
6091 const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context && global.params.useAssert == CHECKENABLE.on;
6092 Expression temporariesPrefix;
6093
6094 if (generateMsg)
6095 // no message - use assert expression as msg
6096 {
6097 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
6098 return setError();
6099
6100 /*
6101 {
6102 auto a = e1, b = e2;
6103 assert(a == b, _d_assert_fail!"=="(a, b));
6104 }()
6105 */
6106
6107 /*
6108 Stores the result of an operand expression into a temporary
6109 if necessary, e.g. if it is an impure fuction call containing side
6110 effects as in https://issues.dlang.org/show_bug.cgi?id=20114
6111
6112 Params:
6113 op = an expression which may require a temporary (added to
6114 `temporariesPrefix`: `auto tmp = op`) and will be replaced
6115 by `tmp` if necessary
6116
6117 Returns: (possibly replaced) `op`
6118 */
6119 Expression maybePromoteToTmp(ref Expression op)
6120 {
6121 // https://issues.dlang.org/show_bug.cgi?id=20989
6122 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6123 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6124 {
6125 auto die = op.isDotIdExp();
6126 if (die && die.ident == Id.ptr)
6127 die.noderef = true;
6128 }
6129
6130 op = op.expressionSemantic(sc);
6131 op = resolveProperties(sc, op);
6132
6133 // Detect assert's using static operator overloads (e.g. `"var" in environment`)
6134 if (auto te = op.isTypeExp())
6135 {
6136 // Replace the TypeExp with it's textual representation
6137 // Including "..." in the error message isn't quite right but
6138 // proper solutions require more drastic changes, e.g. directly
6139 // using miniFormat and combine instead of calling _d_assert_fail
6140 auto name = new StringExp(te.loc, te.toString());
6141 return name.expressionSemantic(sc);
6142 }
6143
6144 // Create a temporary for expressions with side effects
6145 // Defensively assume that function calls may have side effects even
6146 // though it's not detected by hasSideEffect (e.g. `debug puts("Hello")` )
6147 // Rewriting CallExp's also avoids some issues with the inliner/debug generation
6148 if (op.hasSideEffect(true))
6149 {
6150 // Don't create an invalid temporary for void-expressions
6151 // Further semantic will issue an appropriate error
6152 if (op.type.ty == Tvoid)
6153 return op;
6154
6155 // https://issues.dlang.org/show_bug.cgi?id=21590
6156 // Don't create unnecessary temporaries and detect `assert(a = b)`
6157 if (op.isAssignExp() || op.isBinAssignExp())
6158 {
6159 auto left = (cast(BinExp) op).e1;
6160
6161 // Find leftmost expression to handle other rewrites,
6162 // e.g. --(++a) => a += 1 -= 1
6163 while (left.isAssignExp() || left.isBinAssignExp())
6164 left = (cast(BinExp) left).e1;
6165
6166 // Only use the assignee if it's a variable and skip
6167 // other lvalues (e.g. ref's returned by functions)
6168 if (left.isVarExp())
6169 return left;
6170
6171 // Sanity check that `op` can be converted to boolean
6172 // But don't raise errors for assignments enclosed in another expression
6173 if (op is exp.e1)
6174 op.toBoolean(sc);
6175 }
6176
6177 // Tuples with side-effects already receive a temporary during semantic
6178 if (op.type.isTypeTuple())
6179 {
6180 auto te = op.isTupleExp();
6181 assert(te);
6182
6183 // Create a new tuple without the associated temporary
6184 auto res = new TupleExp(op.loc, te.exps);
6185 return res.expressionSemantic(sc);
6186 }
6187
6188 const stc = op.isLvalue() ? STC.ref_ : 0;
6189 auto tmp = copyToTemp(stc, "__assertOp", op);
6190 tmp.dsymbolSemantic(sc);
6191
6192 auto decl = new DeclarationExp(op.loc, tmp);
6193 temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6194
6195 op = new VarExp(op.loc, tmp);
6196 op = op.expressionSemantic(sc);
6197 }
6198 return op;
6199 }
6200
6201 // if the assert condition is a mixin expression, try to compile it
6202 if (auto ce = exp.e1.isMixinExp())
6203 {
6204 if (auto e1 = compileIt(ce))
6205 exp.e1 = e1;
6206 }
6207
6208 Expressions* es;
6209 Objects* tiargs;
6210 Loc loc = exp.e1.loc;
6211
9c7d5e88 6212 const op = exp.e1.op;
5fee5ec3 6213 bool isEqualsCallExpression;
9c7d5e88 6214 if (op == EXP.call)
5fee5ec3
IB
6215 {
6216 const callExp = cast(CallExp) exp.e1;
6217
6218 // https://issues.dlang.org/show_bug.cgi?id=20331
6219 // callExp.f may be null if the assert contains a call to
6220 // a function pointer or literal
6221 if (const callExpFunc = callExp.f)
6222 {
6223 const callExpIdent = callExpFunc.ident;
6224 isEqualsCallExpression = callExpIdent == Id.__equals ||
6225 callExpIdent == Id.eq;
6226 }
6227 }
9c7d5e88
IB
6228 if (op == EXP.equal || op == EXP.notEqual ||
6229 op == EXP.lessThan || op == EXP.greaterThan ||
6230 op == EXP.lessOrEqual || op == EXP.greaterOrEqual ||
6231 op == EXP.identity || op == EXP.notIdentity ||
6232 op == EXP.in_ ||
5fee5ec3
IB
6233 isEqualsCallExpression)
6234 {
6235 es = new Expressions(3);
6236 tiargs = new Objects(1);
6237
6238 if (isEqualsCallExpression)
6239 {
6240 auto callExp = cast(CallExp) exp.e1;
6241 auto args = callExp.arguments;
6242
6243 // structs with opEquals get rewritten to a DotVarExp:
6244 // a.opEquals(b)
6245 // https://issues.dlang.org/show_bug.cgi?id=20100
6246 if (args.length == 1)
6247 {
6248 auto dv = callExp.e1.isDotVarExp();
6249 assert(dv);
6250
6251 // runtime args
6252 (*es)[1] = maybePromoteToTmp(dv.e1);
6253 (*es)[2] = maybePromoteToTmp((*args)[0]);
6254 }
6255 else
6256 {
6257 // runtime args
6258 (*es)[1] = maybePromoteToTmp((*args)[0]);
6259 (*es)[2] = maybePromoteToTmp((*args)[1]);
6260 }
6261 }
6262 else
6263 {
6264 auto binExp = cast(EqualExp) exp.e1;
6265
6266 // runtime args
6267 (*es)[1] = maybePromoteToTmp(binExp.e1);
6268 (*es)[2] = maybePromoteToTmp(binExp.e2);
6269 }
6270
6271 // template args
9c7d5e88 6272 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : EXPtoString(exp.e1.op));
5fee5ec3
IB
6273 comp = comp.expressionSemantic(sc);
6274 (*es)[0] = comp;
6275 (*tiargs)[0] = (*es)[1].type;
6276 }
6277
6278 // Format exp.e1 before any additional boolean conversion
6279 // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
9c7d5e88 6280 else if (op != EXP.andAnd && op != EXP.orOr)
5fee5ec3
IB
6281 {
6282 es = new Expressions(2);
6283 tiargs = new Objects(1);
6284
6285 if (auto ne = exp.e1.isNotExp())
6286 {
6287 // Fetch the (potential non-bool) expression and fold
6288 // (n) negations into (n % 2) negations, e.g. !!a => a
6289 for (bool neg = true; ; neg = !neg)
6290 {
6291 if (auto ne2 = ne.e1.isNotExp())
6292 ne = ne2;
6293 else
6294 {
6295 (*es)[0] = new StringExp(loc, neg ? "!" : "");
6296 (*es)[1] = maybePromoteToTmp(ne.e1);
6297 break;
6298 }
6299 }
6300 }
6301 else
6302 { // Simply format exp.e1
6303 (*es)[0] = new StringExp(loc, "");
6304 (*es)[1] = maybePromoteToTmp(exp.e1);
6305 }
6306
6307 (*tiargs)[0] = (*es)[1].type;
6308
6309 // Passing __ctfe to auto ref infers ref and aborts compilation:
6310 // "cannot modify compiler-generated variable __ctfe"
6311 auto ve = (*es)[1].isVarExp();
6312 if (ve && ve.var.ident == Id.ctfe)
6313 {
6314 exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6315 goto LSkip;
6316 }
6317 }
6318 else
6319 {
6320 OutBuffer buf;
6321 buf.printf("%s failed", exp.toChars());
6322 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6323 goto LSkip;
6324 }
6325
6326 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6327 auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6328
6329 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6330 auto ec = CallExp.create(loc, dt, es);
6331 exp.msg = ec;
6332 }
6333
6334 LSkip:
6335 if (Expression ex = unaSemantic(exp, sc))
6336 {
6337 result = ex;
6338 return;
6339 }
6340
6341 exp.e1 = resolveProperties(sc, exp.e1);
6342 // BUG: see if we can do compile time elimination of the Assert
6343 exp.e1 = exp.e1.optimize(WANTvalue);
6344 exp.e1 = exp.e1.toBoolean(sc);
6345
9c7d5e88 6346 if (exp.e1.op == EXP.error)
5fee5ec3
IB
6347 {
6348 result = exp.e1;
6349 return;
6350 }
6351
6352 if (exp.msg)
6353 {
6354 exp.msg = expressionSemantic(exp.msg, sc);
6355 exp.msg = resolveProperties(sc, exp.msg);
6356 exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6357 exp.msg = exp.msg.optimize(WANTvalue);
6358 checkParamArgumentEscape(sc, null, null, exp.msg, true, false);
6359 }
6360
9c7d5e88 6361 if (exp.msg && exp.msg.op == EXP.error)
5fee5ec3
IB
6362 {
6363 result = exp.msg;
6364 return;
6365 }
6366
6367 auto f1 = checkNonAssignmentArrayOp(exp.e1);
6368 auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6369 if (f1 || f2)
6370 return setError();
6371
9c7d5e88 6372 if (exp.e1.toBool().hasValue(false))
5fee5ec3
IB
6373 {
6374 /* This is an `assert(0)` which means halt program execution
6375 */
6376 FuncDeclaration fd = sc.parent.isFuncDeclaration();
6377 if (fd)
6378 fd.hasReturnExp |= 4;
6379 sc.ctorflow.orCSX(CSX.halt);
6380
6381 if (global.params.useAssert == CHECKENABLE.off)
6382 {
6383 Expression e = new HaltExp(exp.loc);
6384 e = e.expressionSemantic(sc);
6385 result = e;
6386 return;
6387 }
0fb57034
IB
6388
6389 // Only override the type when it isn't already some flavour of noreturn,
6390 // e.g. when this assert was generated by defaultInitLiteral
6391 if (!exp.type || !exp.type.isTypeNoreturn())
6392 exp.type = Type.tnoreturn;
5fee5ec3
IB
6393 }
6394 else
6395 exp.type = Type.tvoid;
6396
6397 result = !temporariesPrefix
6398 ? exp
6399 : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6400 }
6401
6402 override void visit(DotIdExp exp)
6403 {
6404 static if (LOGSEMANTIC)
6405 {
6406 printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6407 //printf("e1.op = %d, '%s'\n", e1.op, Token::toChars(e1.op));
6408 }
0fb57034
IB
6409 if (exp.arrow) // ImportC only
6410 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
6411
6412 if (sc.flags & SCOPE.Cfile)
6413 {
6414 if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
6415 {
6416 // C11 6.5.3 says _Alignof only applies to types
6417 Expression e;
6418 Type t;
6419 Dsymbol s;
6420 dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
6421 if (e)
6422 {
6423 exp.e1.error("argument to `_Alignof` must be a type");
6424 return setError();
6425 }
6426 else if (t)
6427 {
6428 result = new IntegerExp(exp.loc, t.alignsize, Type.tsize_t);
6429 }
6430 else if (s)
6431 {
6432 exp.e1.error("argument to `_Alignof` must be a type");
6433 return setError();
6434 }
6435 else
6436 assert(0);
6437 return;
6438 }
6439 }
6440
6441 if (sc.flags & SCOPE.Cfile && exp.ident != Id.__sizeof)
6442 {
6443 result = fieldLookup(exp.e1, sc, exp.ident);
6444 return;
6445 }
6446
5fee5ec3 6447 Expression e = exp.semanticY(sc, 1);
0fb57034 6448
5fee5ec3
IB
6449 if (e && isDotOpDispatch(e))
6450 {
0fb57034 6451 auto ode = e;
5fee5ec3
IB
6452 uint errors = global.startGagging();
6453 e = resolvePropertiesX(sc, e);
0fb57034
IB
6454 // Any error or if 'e' is not resolved, go to UFCS
6455 if (global.endGagging(errors) || e is ode)
5fee5ec3
IB
6456 e = null; /* fall down to UFCS */
6457 else
6458 {
6459 result = e;
6460 return;
6461 }
6462 }
6463 if (!e) // if failed to find the property
6464 {
6465 /* If ident is not a valid property, rewrite:
6466 * e1.ident
6467 * as:
6468 * .ident(e1)
6469 */
6470 e = resolveUFCSProperties(sc, exp);
6471 }
6472 result = e;
6473 }
6474
6475 override void visit(DotTemplateExp e)
6476 {
6477 if (e.type)
6478 {
6479 result = e;
6480 return;
6481 }
6482 if (Expression ex = unaSemantic(e, sc))
6483 {
6484 result = ex;
6485 return;
6486 }
6487 // 'void' like TemplateExp
6488 e.type = Type.tvoid;
6489 result = e;
6490 }
6491
6492 override void visit(DotVarExp exp)
6493 {
6494 static if (LOGSEMANTIC)
6495 {
6496 printf("DotVarExp::semantic('%s')\n", exp.toChars());
6497 }
6498 if (exp.type)
6499 {
6500 result = exp;
6501 return;
6502 }
6503
6504 exp.var = exp.var.toAlias().isDeclaration();
6505
6506 exp.e1 = exp.e1.expressionSemantic(sc);
6507
6508 if (auto tup = exp.var.isTupleDeclaration())
6509 {
6510 /* Replace:
6511 * e1.tuple(a, b, c)
6512 * with:
6513 * tuple(e1.a, e1.b, e1.c)
6514 */
6515 Expression e0;
6516 Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6517
6518 auto exps = new Expressions();
6519 exps.reserve(tup.objects.dim);
6520 for (size_t i = 0; i < tup.objects.dim; i++)
6521 {
6522 RootObject o = (*tup.objects)[i];
6523 Expression e;
6524 Declaration var;
6525 if (o.dyncast() == DYNCAST.expression)
6526 {
6527 e = cast(Expression)o;
6528 if (auto se = e.isDsymbolExp())
6529 var = se.s.isDeclaration();
6530 else if (auto ve = e.isVarExp())
6531 if (!ve.var.isFuncDeclaration())
6532 // Exempt functions for backwards compatibility reasons.
6533 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6534 var = ve.var;
6535 }
6536 else if (o.dyncast() == DYNCAST.dsymbol)
6537 {
6538 Dsymbol s = cast(Dsymbol) o;
6539 Declaration d = s.isDeclaration();
6540 if (!d || d.isFuncDeclaration())
6541 // Exempt functions for backwards compatibility reasons.
6542 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6543 e = new DsymbolExp(exp.loc, s);
6544 else
6545 var = d;
6546 }
6547 else if (o.dyncast() == DYNCAST.type)
6548 {
6549 e = new TypeExp(exp.loc, cast(Type)o);
6550 }
6551 else
6552 {
6553 exp.error("`%s` is not an expression", o.toChars());
6554 return setError();
6555 }
6556 if (var)
6557 e = new DotVarExp(exp.loc, ev, var);
6558 exps.push(e);
6559 }
6560
6561 Expression e = new TupleExp(exp.loc, e0, exps);
6562 e = e.expressionSemantic(sc);
6563 result = e;
6564 return;
6565 }
6566
6567 exp.e1 = exp.e1.addDtorHook(sc);
6568
6569 Type t1 = exp.e1.type;
6570
6571 if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6572 {
6573 // for functions, do checks after overload resolution
6574 if (!fd.functionSemantic())
6575 return setError();
6576
6577 /* https://issues.dlang.org/show_bug.cgi?id=13843
6578 * If fd obviously has no overloads, we should
6579 * normalize AST, and it will give a chance to wrap fd with FuncExp.
6580 */
6581 if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6582 {
6583 // (e1, fd)
6584 auto e = symbolToExp(fd, exp.loc, sc, false);
6585 result = Expression.combine(exp.e1, e);
6586 return;
6587 }
6588
6589 exp.type = fd.type;
6590 assert(exp.type);
6591 }
6592 else if (OverDeclaration od = exp.var.isOverDeclaration())
6593 {
6594 exp.type = Type.tvoid; // ambiguous type?
6595 }
6596 else
6597 {
6598 exp.type = exp.var.type;
6599 if (!exp.type && global.errors) // var is goofed up, just return error.
6600 return setError();
6601 assert(exp.type);
6602
6603 if (t1.ty == Tpointer)
6604 t1 = t1.nextOf();
6605
6606 exp.type = exp.type.addMod(t1.mod);
6607
6608 Dsymbol vparent = exp.var.toParent();
6609 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6610 if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6611 exp.e1 = e1x;
6612 else
6613 {
6614 /* Later checkRightThis will report correct error for invalid field variable access.
6615 */
6616 Expression e = new VarExp(exp.loc, exp.var);
6617 e = e.expressionSemantic(sc);
6618 result = e;
6619 return;
6620 }
6621 checkAccess(exp.loc, sc, exp.e1, exp.var);
6622
6623 VarDeclaration v = exp.var.isVarDeclaration();
6624 if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6625 {
6626 Expression e = expandVar(WANTvalue, v);
6627 if (e)
6628 {
6629 result = e;
6630 return;
6631 }
6632 }
6633
6634 if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6635 (!v.needThis() && v.semanticRun > PASS.init))) // fix https://issues.dlang.org/show_bug.cgi?id=17258
6636 {
6637 // (e1, v)
6638 checkAccess(exp.loc, sc, exp.e1, v);
6639 Expression e = new VarExp(exp.loc, v);
6640 e = new CommaExp(exp.loc, exp.e1, e);
6641 e = e.expressionSemantic(sc);
6642 result = e;
6643 return;
6644 }
6645 }
6646 //printf("-DotVarExp::semantic('%s')\n", toChars());
6647 result = exp;
6648 }
6649
6650 override void visit(DotTemplateInstanceExp exp)
6651 {
6652 static if (LOGSEMANTIC)
6653 {
6654 printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6655 }
0fb57034
IB
6656 if (exp.type)
6657 {
6658 result = exp;
6659 return;
6660 }
5fee5ec3
IB
6661 // Indicate we need to resolve by UFCS.
6662 Expression e = exp.semanticY(sc, 1);
6663 if (!e)
6664 e = resolveUFCSProperties(sc, exp);
0fb57034
IB
6665 if (e is exp)
6666 e.type = Type.tvoid; // Unresolved type, because it needs inference
5fee5ec3
IB
6667 result = e;
6668 }
6669
6670 override void visit(DelegateExp e)
6671 {
6672 static if (LOGSEMANTIC)
6673 {
6674 printf("DelegateExp::semantic('%s')\n", e.toChars());
6675 }
6676 if (e.type)
6677 {
6678 result = e;
6679 return;
6680 }
6681
6682 e.e1 = e.e1.expressionSemantic(sc);
6683
6684 e.type = new TypeDelegate(e.func.type.isTypeFunction());
6685 e.type = e.type.typeSemantic(e.loc, sc);
6686
6687 FuncDeclaration f = e.func.toAliasFunc();
6688 AggregateDeclaration ad = f.toParentLocal().isAggregateDeclaration();
6689 if (f.needThis())
6690 e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
9c7d5e88 6691 if (e.e1.op == EXP.error)
5fee5ec3
IB
6692 return setError();
6693
6694 /* A delegate takes the address of e.e1 in order to set the .ptr field
6695 * https://issues.dlang.org/show_bug.cgi?id=18575
6696 */
6697 if (global.params.useDIP1000 == FeatureState.enabled && e.e1.type.toBasetype().ty == Tstruct)
6698 {
6699 if (auto v = expToVariable(e.e1))
6700 {
6701 if (!checkAddressVar(sc, e.e1, v))
6702 return setError();
6703 }
6704 }
6705
6706 if (f.type.ty == Tfunction)
6707 {
6708 TypeFunction tf = cast(TypeFunction)f.type;
6709 if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6710 {
6711 OutBuffer thisBuf, funcBuf;
6712 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6713 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6714 e.error("%smethod `%s` is not callable using a %s`%s`",
6715 funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6716 return setError();
6717 }
6718 }
6719 if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6720 {
6721 // A downcast is required for interfaces
6722 // https://issues.dlang.org/show_bug.cgi?id=3706
6723 e.e1 = new CastExp(e.loc, e.e1, ad.type);
6724 e.e1 = e.e1.expressionSemantic(sc);
6725 }
6726 result = e;
6727 // declare dual-context container
6728 if (f.isThis2 && !sc.intypeof && sc.func)
6729 {
6730 // check access to second `this`
6731 if (AggregateDeclaration ad2 = f.isMember2())
6732 {
6733 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
9c7d5e88 6734 if (te.op != EXP.error)
5fee5ec3 6735 te = getRightThis(e.loc, sc, ad2, te, f);
9c7d5e88 6736 if (te.op == EXP.error)
5fee5ec3
IB
6737 {
6738 e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6739 return setError();
6740 }
6741 }
6742 VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6743 e.vthis2 = vthis2;
6744 Expression de = new DeclarationExp(e.loc, vthis2);
6745 result = Expression.combine(de, result);
6746 result = result.expressionSemantic(sc);
6747 }
6748 }
6749
6750 override void visit(DotTypeExp exp)
6751 {
6752 static if (LOGSEMANTIC)
6753 {
6754 printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6755 }
6756 if (exp.type)
6757 {
6758 result = exp;
6759 return;
6760 }
6761
6762 if (auto e = unaSemantic(exp, sc))
6763 {
6764 result = e;
6765 return;
6766 }
6767
6768 exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6769 result = exp;
6770 }
6771
6772 override void visit(AddrExp exp)
6773 {
6774 static if (LOGSEMANTIC)
6775 {
6776 printf("AddrExp::semantic('%s')\n", exp.toChars());
6777 }
6778 if (exp.type)
6779 {
6780 result = exp;
6781 return;
6782 }
6783
6784 if (Expression ex = unaSemantic(exp, sc))
6785 {
6786 result = ex;
6787 return;
6788 }
6789
6790 if (sc.flags & SCOPE.Cfile)
6791 {
6792 /* Special handling for &"string"
6793 * since C regards a string literal as an lvalue
6794 */
6795 if (auto se = exp.e1.isStringExp())
6796 {
6797 if (auto tp = se.type.toBasetype().isTypePointer())
6798 {
6799 /* Switch from pointer-to-char to pointer-to-static-array-of-char
6800 */
6801 auto ts = new TypeSArray(tp.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
6802 se.type = typeSemantic(ts, Loc.initial, sc).pointerTo();
6803 result = se;
6804 return;
6805 }
6806 }
6807 }
6808
9c7d5e88 6809 int wasCond = exp.e1.op == EXP.question;
5fee5ec3 6810
9c7d5e88 6811 if (exp.e1.op == EXP.dotTemplateInstance)
5fee5ec3
IB
6812 {
6813 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6814 TemplateInstance ti = dti.ti;
6815 {
6816 //assert(ti.needsTypeInference(sc));
6817 ti.dsymbolSemantic(sc);
6818 if (!ti.inst || ti.errors) // if template failed to expand
6819 return setError();
6820
6821 Dsymbol s = ti.toAlias();
6822 FuncDeclaration f = s.isFuncDeclaration();
6823 if (f)
6824 {
6825 exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6826 exp.e1 = exp.e1.expressionSemantic(sc);
6827 }
6828 }
6829 }
9c7d5e88 6830 else if (exp.e1.op == EXP.scope_)
5fee5ec3
IB
6831 {
6832 TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6833 if (ti)
6834 {
6835 //assert(ti.needsTypeInference(sc));
6836 ti.dsymbolSemantic(sc);
6837 if (!ti.inst || ti.errors) // if template failed to expand
6838 return setError();
6839
6840 Dsymbol s = ti.toAlias();
6841 FuncDeclaration f = s.isFuncDeclaration();
6842 if (f)
6843 {
6844 exp.e1 = new VarExp(exp.e1.loc, f);
6845 exp.e1 = exp.e1.expressionSemantic(sc);
6846 }
6847 }
6848 }
6849 /* https://issues.dlang.org/show_bug.cgi?id=809
6850 *
6851 * If the address of a lazy variable is taken,
6852 * the expression is rewritten so that the type
6853 * of it is the delegate type. This means that
6854 * the symbol is not going to represent a call
6855 * to the delegate anymore, but rather, the
6856 * actual symbol.
6857 */
6858 if (auto ve = exp.e1.isVarExp())
6859 {
6860 if (ve.var.storage_class & STC.lazy_)
6861 {
6862 exp.e1 = exp.e1.expressionSemantic(sc);
6863 exp.e1 = resolveProperties(sc, exp.e1);
6864 if (auto callExp = exp.e1.isCallExp())
6865 {
6866 if (callExp.e1.type.toBasetype().ty == Tdelegate)
6867 {
6868 /* https://issues.dlang.org/show_bug.cgi?id=20551
6869 *
6870 * Cannot take address of lazy parameter in @safe code
6871 * because it might end up being a pointer to undefined
6872 * memory.
6873 */
6874 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
6875 {
6876 exp.error("cannot take address of lazy parameter `%s` in `@safe` function `%s`",
6877 ve.toChars(), sc.func.toChars());
6878 setError();
6879 }
6880 else
6881 {
6882 VarExp ve2 = callExp.e1.isVarExp();
6883 ve2.delegateWasExtracted = true;
6884 ve2.var.storage_class |= STC.scope_;
6885 result = ve2;
6886 }
6887 return;
6888 }
6889 }
6890 }
6891 }
6892
6893 exp.e1 = exp.e1.toLvalue(sc, null);
9c7d5e88 6894 if (exp.e1.op == EXP.error)
5fee5ec3
IB
6895 {
6896 result = exp.e1;
6897 return;
6898 }
6899 if (checkNonAssignmentArrayOp(exp.e1))
6900 return setError();
6901
6902 if (!exp.e1.type)
6903 {
6904 exp.error("cannot take address of `%s`", exp.e1.toChars());
6905 return setError();
6906 }
6907
6908 bool hasOverloads;
6909 if (auto f = isFuncAddress(exp, &hasOverloads))
6910 {
6911 if (!hasOverloads && f.checkForwardRef(exp.loc))
6912 return setError();
6913 }
6914 else if (!exp.e1.type.deco)
6915 {
9c7d5e88 6916 if (exp.e1.op == EXP.variable)
5fee5ec3
IB
6917 {
6918 VarExp ve = cast(VarExp)exp.e1;
6919 Declaration d = ve.var;
6920 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
6921 }
6922 else
6923 exp.error("forward reference to `%s`", exp.e1.toChars());
6924 return setError();
6925 }
6926
6927 exp.type = exp.e1.type.pointerTo();
6928
6929 // See if this should really be a delegate
9c7d5e88 6930 if (exp.e1.op == EXP.dotVariable)
5fee5ec3
IB
6931 {
6932 DotVarExp dve = cast(DotVarExp)exp.e1;
6933 FuncDeclaration f = dve.var.isFuncDeclaration();
6934 if (f)
6935 {
6936 f = f.toAliasFunc(); // FIXME, should see overloads
6937 // https://issues.dlang.org/show_bug.cgi?id=1983
6938 if (!dve.hasOverloads)
6939 f.tookAddressOf++;
6940
6941 Expression e;
6942 if (f.needThis())
6943 e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
6944 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
6945 e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
6946 e = e.expressionSemantic(sc);
6947 result = e;
6948 return;
6949 }
6950
6951 // Look for misaligned pointer in @safe mode
6952 if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
6953 return setError();
6954
6955 if (global.params.useDIP1000 == FeatureState.enabled)
6956 {
6957 if (VarDeclaration v = expToVariable(dve.e1))
6958 {
6959 if (!checkAddressVar(sc, exp.e1, v))
6960 return setError();
6961 }
6962 }
6963 }
9c7d5e88 6964 else if (exp.e1.op == EXP.variable)
5fee5ec3
IB
6965 {
6966 VarExp ve = cast(VarExp)exp.e1;
6967 VarDeclaration v = ve.var.isVarDeclaration();
6968 if (v)
6969 {
6970 if (!checkAddressVar(sc, exp.e1, v))
6971 return setError();
6972
6973 ve.checkPurity(sc, v);
6974 }
6975 FuncDeclaration f = ve.var.isFuncDeclaration();
6976 if (f)
6977 {
6978 /* Because nested functions cannot be overloaded,
6979 * mark here that we took its address because castTo()
6980 * may not be called with an exact match.
6981 */
6982 if (!ve.hasOverloads || (f.isNested() && !f.needThis()))
6983 f.tookAddressOf++;
6984 if (f.isNested() && !f.needThis())
6985 {
6986 if (f.isFuncLiteralDeclaration())
6987 {
6988 if (!f.FuncDeclaration.isNested())
6989 {
6990 /* Supply a 'null' for a this pointer if no this is available
6991 */
6992 Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
6993 e = e.expressionSemantic(sc);
6994 result = e;
6995 return;
6996 }
6997 }
6998 Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
6999 e = e.expressionSemantic(sc);
7000 result = e;
7001 return;
7002 }
7003 if (f.needThis())
7004 {
7005 if (hasThis(sc))
7006 {
7007 /* Should probably supply 'this' after overload resolution,
7008 * not before.
7009 */
7010 Expression ethis = new ThisExp(exp.loc);
7011 Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
7012 e = e.expressionSemantic(sc);
7013 result = e;
7014 return;
7015 }
7016 if (sc.func && !sc.intypeof)
7017 {
7018 if (!(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7019 {
7020 exp.error("`this` reference necessary to take address of member `%s` in `@safe` function `%s`", f.toChars(), sc.func.toChars());
7021 }
7022 }
7023 }
7024 }
7025 }
9c7d5e88 7026 else if ((exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_) && global.params.useDIP1000 == FeatureState.enabled)
5fee5ec3
IB
7027 {
7028 if (VarDeclaration v = expToVariable(exp.e1))
7029 {
7030 if (!checkAddressVar(sc, exp.e1, v))
7031 return setError();
7032 }
7033 }
9c7d5e88 7034 else if (exp.e1.op == EXP.call)
5fee5ec3
IB
7035 {
7036 CallExp ce = cast(CallExp)exp.e1;
7037 if (ce.e1.type.ty == Tfunction)
7038 {
7039 TypeFunction tf = cast(TypeFunction)ce.e1.type;
9c7d5e88
IB
7040 if (tf.isref && sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_)
7041 && tf.next.hasPointers() && sc.func.setUnsafe())
5fee5ec3
IB
7042 {
7043 exp.error("cannot take address of `ref return` of `%s()` in `@safe` function `%s`",
7044 ce.e1.toChars(), sc.func.toChars());
7045 }
7046 }
7047 }
9c7d5e88 7048 else if (exp.e1.op == EXP.index)
5fee5ec3
IB
7049 {
7050 /* For:
7051 * int[3] a;
7052 * &a[i]
7053 * check 'a' the same as for a regular variable
7054 */
7055 if (VarDeclaration v = expToVariable(exp.e1))
7056 {
7057 if (global.params.useDIP1000 == FeatureState.enabled && !checkAddressVar(sc, exp.e1, v))
7058 return setError();
7059
7060 exp.e1.checkPurity(sc, v);
7061 }
7062 }
7063 else if (wasCond)
7064 {
7065 /* a ? b : c was transformed to *(a ? &b : &c), but we still
7066 * need to do safety checks
7067 */
9c7d5e88 7068 assert(exp.e1.op == EXP.star);
5fee5ec3 7069 PtrExp pe = cast(PtrExp)exp.e1;
9c7d5e88 7070 assert(pe.e1.op == EXP.question);
5fee5ec3 7071 CondExp ce = cast(CondExp)pe.e1;
9c7d5e88
IB
7072 assert(ce.e1.op == EXP.address);
7073 assert(ce.e2.op == EXP.address);
5fee5ec3
IB
7074
7075 // Re-run semantic on the address expressions only
7076 ce.e1.type = null;
7077 ce.e1 = ce.e1.expressionSemantic(sc);
7078 ce.e2.type = null;
7079 ce.e2 = ce.e2.expressionSemantic(sc);
7080 }
7081 result = exp.optimize(WANTvalue);
7082 }
7083
7084 override void visit(PtrExp exp)
7085 {
7086 static if (LOGSEMANTIC)
7087 {
7088 printf("PtrExp::semantic('%s')\n", exp.toChars());
7089 }
7090 if (exp.type)
7091 {
7092 result = exp;
7093 return;
7094 }
7095
7096 Expression e = exp.op_overload(sc);
7097 if (e)
7098 {
7099 result = e;
7100 return;
7101 }
7102
7103 Type tb = exp.e1.type.toBasetype();
7104 switch (tb.ty)
7105 {
7106 case Tpointer:
7107 exp.type = (cast(TypePointer)tb).next;
7108 break;
7109
7110 case Tsarray:
7111 case Tarray:
7112 if (isNonAssignmentArrayOp(exp.e1))
7113 goto default;
7114 exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
7115 exp.type = (cast(TypeArray)tb).next;
7116 exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
7117 break;
7118
7119 case Terror:
7120 return setError();
7121
7122 case Tnull:
7123 exp.type = Type.tnoreturn; // typeof(*null) is bottom type
7124 break;
7125
7126 default:
7127 exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
7128 goto case Terror;
7129 }
7130
7131 if (exp.checkValue())
7132 return setError();
7133
7134 result = exp;
7135 }
7136
7137 override void visit(NegExp exp)
7138 {
7139 static if (LOGSEMANTIC)
7140 {
7141 printf("NegExp::semantic('%s')\n", exp.toChars());
7142 }
7143 if (exp.type)
7144 {
7145 result = exp;
7146 return;
7147 }
7148
7149 Expression e = exp.op_overload(sc);
7150 if (e)
7151 {
7152 result = e;
7153 return;
7154 }
7155
7156 fix16997(sc, exp);
7157 exp.type = exp.e1.type;
7158 Type tb = exp.type.toBasetype();
7159 if (tb.ty == Tarray || tb.ty == Tsarray)
7160 {
7161 if (!isArrayOpValid(exp.e1))
7162 {
7163 result = arrayOpInvalidError(exp);
7164 return;
7165 }
7166 result = exp;
7167 return;
7168 }
7169 if (!target.isVectorOpSupported(tb, exp.op))
7170 {
7171 result = exp.incompatibleTypes();
7172 return;
7173 }
7174 if (exp.e1.checkNoBool())
7175 return setError();
7176 if (exp.e1.checkArithmetic() ||
7177 exp.e1.checkSharedAccess(sc))
7178 return setError();
7179
7180 result = exp;
7181 }
7182
7183 override void visit(UAddExp exp)
7184 {
7185 static if (LOGSEMANTIC)
7186 {
7187 printf("UAddExp::semantic('%s')\n", exp.toChars());
7188 }
7189 assert(!exp.type);
7190
7191 Expression e = exp.op_overload(sc);
7192 if (e)
7193 {
7194 result = e;
7195 return;
7196 }
7197
7198 fix16997(sc, exp);
7199 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
7200 {
7201 result = exp.incompatibleTypes();
7202 return;
7203 }
7204 if (exp.e1.checkNoBool())
7205 return setError();
7206 if (exp.e1.checkArithmetic())
7207 return setError();
7208 if (exp.e1.checkSharedAccess(sc))
7209 return setError();
7210
7211 result = exp.e1;
7212 }
7213
7214 override void visit(ComExp exp)
7215 {
7216 if (exp.type)
7217 {
7218 result = exp;
7219 return;
7220 }
7221
7222 Expression e = exp.op_overload(sc);
7223 if (e)
7224 {
7225 result = e;
7226 return;
7227 }
7228
7229 fix16997(sc, exp);
7230 exp.type = exp.e1.type;
7231 Type tb = exp.type.toBasetype();
7232 if (tb.ty == Tarray || tb.ty == Tsarray)
7233 {
7234 if (!isArrayOpValid(exp.e1))
7235 {
7236 result = arrayOpInvalidError(exp);
7237 return;
7238 }
7239 result = exp;
7240 return;
7241 }
7242 if (!target.isVectorOpSupported(tb, exp.op))
7243 {
7244 result = exp.incompatibleTypes();
7245 return;
7246 }
7247 if (exp.e1.checkNoBool())
7248 return setError();
7249 if (exp.e1.checkIntegral() ||
7250 exp.e1.checkSharedAccess(sc))
7251 return setError();
7252
7253 result = exp;
7254 }
7255
7256 override void visit(NotExp e)
7257 {
7258 if (e.type)
7259 {
7260 result = e;
7261 return;
7262 }
7263
7264 e.setNoderefOperand();
7265
7266 // Note there is no operator overload
7267 if (Expression ex = unaSemantic(e, sc))
7268 {
7269 result = ex;
7270 return;
7271 }
7272
7273 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 7274 if (e.e1.op == EXP.type)
5fee5ec3
IB
7275 e.e1 = resolveAliasThis(sc, e.e1);
7276
7277 e.e1 = resolveProperties(sc, e.e1);
7278 e.e1 = e.e1.toBoolean(sc);
7279 if (e.e1.type == Type.terror)
7280 {
7281 result = e.e1;
7282 return;
7283 }
7284
7285 if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7286 {
7287 result = e.incompatibleTypes();
7288 }
7289 // https://issues.dlang.org/show_bug.cgi?id=13910
7290 // Today NotExp can take an array as its operand.
7291 if (checkNonAssignmentArrayOp(e.e1))
7292 return setError();
7293
7294 e.type = Type.tbool;
7295 result = e;
7296 }
7297
7298 override void visit(DeleteExp exp)
7299 {
7300 if (!sc.isDeprecated)
7301 {
7302 // @@@DEPRECATED_2019-02@@@
7303 // 1. Deprecation for 1 year
7304 // 2. Error for 1 year
7305 // 3. Removal of keyword, "delete" can be used for other identities
7306 if (!exp.isRAII)
7307 deprecation(exp.loc, "The `delete` keyword has been deprecated. Use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead.");
7308 }
7309
7310 if (Expression ex = unaSemantic(exp, sc))
7311 {
7312 result = ex;
7313 return;
7314 }
7315 exp.e1 = resolveProperties(sc, exp.e1);
7316 exp.e1 = exp.e1.modifiableLvalue(sc, null);
9c7d5e88 7317 if (exp.e1.op == EXP.error)
5fee5ec3
IB
7318 {
7319 result = exp.e1;
7320 return;
7321 }
7322 exp.type = Type.tvoid;
7323
7324 AggregateDeclaration ad = null;
7325 Type tb = exp.e1.type.toBasetype();
7326 switch (tb.ty)
7327 {
7328 case Tclass:
7329 {
7330 auto cd = (cast(TypeClass)tb).sym;
7331 if (cd.isCOMinterface())
7332 {
7333 /* Because COM classes are deleted by IUnknown.Release()
7334 */
7335 exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7336 return setError();
7337 }
7338 ad = cd;
7339 break;
7340 }
7341 case Tpointer:
7342 tb = (cast(TypePointer)tb).next.toBasetype();
7343 if (tb.ty == Tstruct)
7344 {
7345 ad = (cast(TypeStruct)tb).sym;
7346 semanticTypeInfo(sc, tb);
7347 }
7348 break;
7349
7350 case Tarray:
7351 {
7352 Type tv = tb.nextOf().baseElemOf();
7353 if (tv.ty == Tstruct)
7354 {
7355 ad = (cast(TypeStruct)tv).sym;
7356 if (ad.dtor)
7357 semanticTypeInfo(sc, ad.type);
7358 }
7359 break;
7360 }
7361 default:
7362 exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7363 return setError();
7364 }
7365
7366 bool err = false;
7367 if (ad)
7368 {
7369 if (ad.dtor)
7370 {
7371 err |= !ad.dtor.functionSemantic();
7372 err |= exp.checkPurity(sc, ad.dtor);
7373 err |= exp.checkSafety(sc, ad.dtor);
7374 err |= exp.checkNogc(sc, ad.dtor);
7375 }
7376 if (err)
7377 return setError();
7378 }
7379
7380 if (!sc.intypeof && sc.func &&
7381 !exp.isRAII &&
7382 !(sc.flags & SCOPE.debug_) &&
7383 sc.func.setUnsafe())
7384 {
7385 exp.error("`%s` is not `@safe` but is used in `@safe` function `%s`", exp.toChars(), sc.func.toChars());
7386 err = true;
7387 }
7388 if (err)
7389 return setError();
7390
7391 result = exp;
7392 }
7393
7394 override void visit(CastExp exp)
7395 {
7396 static if (LOGSEMANTIC)
7397 {
7398 printf("CastExp::semantic('%s')\n", exp.toChars());
7399 }
7400 //static int x; assert(++x < 10);
7401 if (exp.type)
7402 {
7403 result = exp;
7404 return;
7405 }
7406
7407 if ((sc && sc.flags & SCOPE.Cfile) &&
7408 exp.to && exp.to.ty == Tident &&
9c7d5e88
IB
7409 (exp.e1.op == EXP.address || exp.e1.op == EXP.star ||
7410 exp.e1.op == EXP.uadd || exp.e1.op == EXP.negate))
5fee5ec3
IB
7411 {
7412 /* Ambiguous cases arise from CParser if type-name is just an identifier.
7413 * ( identifier ) cast-expression
7414 * If we determine that `identifier` is a variable, and cast-expression
7415 * is one of the unary operators (& * + -), then rewrite this cast
7416 * as a binary expression.
7417 */
7418 Loc loc = exp.loc;
7419 Type t;
7420 Expression e;
7421 Dsymbol s;
7422 exp.to.resolve(loc, sc, e, t, s);
7423 if (e !is null)
7424 {
7425 if (auto ex = exp.e1.isAddrExp()) // (ident) &exp -> (ident & exp)
7426 result = new AndExp(loc, e, ex.e1);
7427 else if (auto ex = exp.e1.isPtrExp()) // (ident) *exp -> (ident * exp)
7428 result = new MulExp(loc, e, ex.e1);
7429 else if (auto ex = exp.e1.isUAddExp()) // (ident) +exp -> (ident + exp)
7430 result = new AddExp(loc, e, ex.e1);
7431 else if (auto ex = exp.e1.isNegExp()) // (ident) -exp -> (ident - exp)
7432 result = new MinExp(loc, e, ex.e1);
7433
7434 assert(result);
7435 result = result.expressionSemantic(sc);
7436 return;
7437 }
7438 }
7439
7440 if (exp.to)
7441 {
7442 exp.to = exp.to.typeSemantic(exp.loc, sc);
7443 if (exp.to == Type.terror)
7444 return setError();
7445
7446 if (!exp.to.hasPointers())
7447 exp.setNoderefOperand();
7448
7449 // When e1 is a template lambda, this cast may instantiate it with
7450 // the type 'to'.
7451 exp.e1 = inferType(exp.e1, exp.to);
7452 }
7453
7454 if (auto e = unaSemantic(exp, sc))
7455 {
7456 result = e;
7457 return;
7458 }
7459
7460 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 7461 if (exp.e1.op == EXP.type)
5fee5ec3
IB
7462 exp.e1 = resolveAliasThis(sc, exp.e1);
7463
7464 auto e1x = resolveProperties(sc, exp.e1);
9c7d5e88 7465 if (e1x.op == EXP.error)
5fee5ec3
IB
7466 {
7467 result = e1x;
7468 return;
7469 }
7470 if (e1x.checkType())
7471 return setError();
7472 exp.e1 = e1x;
7473
7474 if (!exp.e1.type)
7475 {
7476 exp.error("cannot cast `%s`", exp.e1.toChars());
7477 return setError();
7478 }
7479
7480 // https://issues.dlang.org/show_bug.cgi?id=19954
7481 if (exp.e1.type.ty == Ttuple)
7482 {
7483 TupleExp te = exp.e1.isTupleExp();
7484 if (te.exps.dim == 1)
7485 exp.e1 = (*te.exps)[0];
7486 }
7487
7488 // only allow S(x) rewrite if cast specified S explicitly.
7489 // See https://issues.dlang.org/show_bug.cgi?id=18545
7490 const bool allowImplicitConstruction = exp.to !is null;
7491
7492 if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7493 {
7494 exp.to = exp.e1.type.castMod(exp.mod);
7495 exp.to = exp.to.typeSemantic(exp.loc, sc);
7496
7497 if (exp.to == Type.terror)
7498 return setError();
7499 }
7500
7501 if (exp.to.ty == Ttuple)
7502 {
7503 exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
7504 return setError();
7505 }
7506
7507 // cast(void) is used to mark e1 as unused, so it is safe
7508 if (exp.to.ty == Tvoid)
7509 {
7510 exp.type = exp.to;
7511 result = exp;
7512 return;
7513 }
7514
7515 if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7516 {
7517 if (Expression e = exp.op_overload(sc))
7518 {
7519 result = e.implicitCastTo(sc, exp.to);
7520 return;
7521 }
7522 }
7523
7524 Type t1b = exp.e1.type.toBasetype();
7525 Type tob = exp.to.toBasetype();
7526
7527 if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7528 {
7529 /* Look to replace:
7530 * cast(S)t
7531 * with:
7532 * S(t)
7533 */
7534
7535 // Rewrite as to.call(e1)
7536 Expression e = new TypeExp(exp.loc, exp.to);
7537 e = new CallExp(exp.loc, e, exp.e1);
7538 e = e.trySemantic(sc);
7539 if (e)
7540 {
7541 result = e;
7542 return;
7543 }
7544 }
7545
7546 if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7547 {
7548 if (checkNonAssignmentArrayOp(exp.e1))
7549 return setError();
7550 }
7551
7552 // Look for casting to a vector type
7553 if (tob.ty == Tvector && t1b.ty != Tvector)
7554 {
7555 result = new VectorExp(exp.loc, exp.e1, exp.to);
7556 result = result.expressionSemantic(sc);
7557 return;
7558 }
7559
7560 Expression ex = exp.e1.castTo(sc, exp.to);
9c7d5e88 7561 if (ex.op == EXP.error)
5fee5ec3
IB
7562 {
7563 result = ex;
7564 return;
7565 }
7566
7567 // Check for unsafe casts
7568 if (!sc.intypeof &&
7569 !(sc.flags & SCOPE.debug_) &&
7570 !isSafeCast(ex, t1b, tob) &&
7571 (!sc.func && sc.stc & STC.safe || sc.func && sc.func.setUnsafe()))
7572 {
7573 exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
7574 return setError();
7575 }
7576
7577 // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7578 // to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out.
7579 // See `e2ir.toElemCast` for other types of casts. If `object.__ArrayCast` is improved to support more
7580 // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7581 if (tob.ty == Tarray)
7582 {
7583 // https://issues.dlang.org/show_bug.cgi?id=19840
7584 if (auto ad = isAggregate(t1b))
7585 {
7586 if (ad.aliasthis)
7587 {
7588 Expression e = resolveAliasThis(sc, exp.e1);
7589 e = new CastExp(exp.loc, e, exp.to);
7590 result = e.expressionSemantic(sc);
7591 return;
7592 }
7593 }
7594
9c7d5e88 7595 if(t1b.ty == Tarray && exp.e1.op != EXP.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
5fee5ec3
IB
7596 {
7597 auto tFrom = t1b.nextOf();
7598 auto tTo = tob.nextOf();
7599
7600 // https://issues.dlang.org/show_bug.cgi?id=20130
9c7d5e88 7601 if (exp.e1.op != EXP.string_ || !ex.isStringExp)
5fee5ec3
IB
7602 {
7603 const uint fromSize = cast(uint)tFrom.size();
7604 const uint toSize = cast(uint)tTo.size();
9c7d5e88
IB
7605 if (fromSize == SIZE_INVALID || toSize == SIZE_INVALID)
7606 return setError();
5fee5ec3
IB
7607
7608 // If array element sizes do not match, we must adjust the dimensions
7609 if (fromSize != toSize)
7610 {
7611 if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7612 return setError();
7613
7614 // A runtime check is needed in case arrays don't line up. That check should
7615 // be done in the implementation of `object.__ArrayCast`
7616 if (toSize == 0 || (fromSize % toSize) != 0)
7617 {
7618 // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7619
7620 // fully qualify as `object.__ArrayCast`
7621 Expression id = new IdentifierExp(exp.loc, Id.empty);
7622 auto dotid = new DotIdExp(exp.loc, id, Id.object);
7623
7624 auto tiargs = new Objects();
7625 tiargs.push(tFrom);
7626 tiargs.push(tTo);
7627 auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7628
7629 auto arguments = new Expressions();
7630 arguments.push(exp.e1);
7631 Expression ce = new CallExp(exp.loc, dt, arguments);
7632
7633 result = expressionSemantic(ce, sc);
7634 return;
7635 }
7636 }
7637 }
7638 }
7639 }
7640
7641 if (sc && sc.flags & SCOPE.Cfile)
7642 {
7643 /* C11 6.5.4-5: A cast does not yield an lvalue.
7644 * So ensure that castTo does not strip away the cast so that this
7645 * can be enforced in other semantic visitor methods.
7646 */
7647 if (!ex.isCastExp())
7648 {
7649 ex = new CastExp(exp.loc, ex, exp.to);
7650 ex.type = exp.to;
7651 }
7652 }
7653 result = ex;
7654 }
7655
7656 override void visit(VectorExp exp)
7657 {
7658 static if (LOGSEMANTIC)
7659 {
7660 printf("VectorExp::semantic('%s')\n", exp.toChars());
7661 }
7662 if (exp.type)
7663 {
7664 result = exp;
7665 return;
7666 }
7667
7668 exp.e1 = exp.e1.expressionSemantic(sc);
7669 exp.type = exp.to.typeSemantic(exp.loc, sc);
9c7d5e88 7670 if (exp.e1.op == EXP.error || exp.type.ty == Terror)
5fee5ec3
IB
7671 {
7672 result = exp.e1;
7673 return;
7674 }
7675
7676 Type tb = exp.type.toBasetype();
7677 assert(tb.ty == Tvector);
7678 TypeVector tv = cast(TypeVector)tb;
7679 Type te = tv.elementType();
7680 exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7681
7682 bool checkElem(Expression elem)
7683 {
7684 if (elem.isConst() == 1)
7685 return false;
7686
7687 exp.error("constant expression expected, not `%s`", elem.toChars());
7688 return true;
7689 }
7690
7691 exp.e1 = exp.e1.optimize(WANTvalue);
7692 bool res;
9c7d5e88 7693 if (exp.e1.op == EXP.arrayLiteral)
5fee5ec3
IB
7694 {
7695 foreach (i; 0 .. exp.dim)
7696 {
7697 // Do not stop on first error - check all AST nodes even if error found
7698 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7699 }
7700 }
7701 else if (exp.e1.type.ty == Tvoid)
7702 checkElem(exp.e1);
7703
7704 result = res ? ErrorExp.get() : exp;
7705 }
7706
7707 override void visit(VectorArrayExp e)
7708 {
7709 static if (LOGSEMANTIC)
7710 {
7711 printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7712 }
7713 if (!e.type)
7714 {
7715 unaSemantic(e, sc);
7716 e.e1 = resolveProperties(sc, e.e1);
7717
9c7d5e88 7718 if (e.e1.op == EXP.error)
5fee5ec3
IB
7719 {
7720 result = e.e1;
7721 return;
7722 }
7723 assert(e.e1.type.ty == Tvector);
7724 e.type = e.e1.type.isTypeVector().basetype;
7725 }
7726 result = e;
7727 }
7728
7729 override void visit(SliceExp exp)
7730 {
7731 static if (LOGSEMANTIC)
7732 {
7733 printf("SliceExp::semantic('%s')\n", exp.toChars());
7734 }
7735 if (exp.type)
7736 {
7737 result = exp;
7738 return;
7739 }
7740
7741 // operator overloading should be handled in ArrayExp already.
7742 if (Expression ex = unaSemantic(exp, sc))
7743 {
7744 result = ex;
7745 return;
7746 }
7747 exp.e1 = resolveProperties(sc, exp.e1);
9c7d5e88 7748 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
5fee5ec3
IB
7749 {
7750 if (exp.lwr || exp.upr)
7751 {
7752 exp.error("cannot slice type `%s`", exp.e1.toChars());
7753 return setError();
7754 }
7755 Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7756 result = e.expressionSemantic(sc);
7757 return;
7758 }
7759 if (!exp.lwr && !exp.upr)
7760 {
9c7d5e88 7761 if (exp.e1.op == EXP.arrayLiteral)
5fee5ec3
IB
7762 {
7763 // Convert [a,b,c][] to [a,b,c]
7764 Type t1b = exp.e1.type.toBasetype();
7765 Expression e = exp.e1;
7766 if (t1b.ty == Tsarray)
7767 {
7768 e = e.copy();
7769 e.type = t1b.nextOf().arrayOf();
7770 }
7771 result = e;
7772 return;
7773 }
9c7d5e88 7774 if (exp.e1.op == EXP.slice)
5fee5ec3
IB
7775 {
7776 // Convert e[][] to e[]
7777 SliceExp se = cast(SliceExp)exp.e1;
7778 if (!se.lwr && !se.upr)
7779 {
7780 result = se;
7781 return;
7782 }
7783 }
7784 if (isArrayOpOperand(exp.e1))
7785 {
7786 // Convert (a[]+b[])[] to a[]+b[]
7787 result = exp.e1;
7788 return;
7789 }
7790 }
9c7d5e88 7791 if (exp.e1.op == EXP.error)
5fee5ec3
IB
7792 {
7793 result = exp.e1;
7794 return;
7795 }
7796 if (exp.e1.type.ty == Terror)
7797 return setError();
7798
7799 Type t1b = exp.e1.type.toBasetype();
7800 if (t1b.ty == Tpointer)
7801 {
7802 if (t1b.isPtrToFunction())
7803 {
7804 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7805 return setError();
7806 }
7807 if (!exp.lwr || !exp.upr)
7808 {
7809 exp.error("need upper and lower bound to slice pointer");
7810 return setError();
7811 }
7812 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
7813 {
7814 exp.error("pointer slicing not allowed in safe functions");
7815 return setError();
7816 }
7817 }
7818 else if (t1b.ty == Tarray)
7819 {
7820 }
7821 else if (t1b.ty == Tsarray)
7822 {
7823 if (!exp.arrayop && global.params.useDIP1000 == FeatureState.enabled)
7824 {
7825 /* Slicing a static array is like taking the address of it.
7826 * Perform checks as if e[] was &e
7827 */
7828 if (VarDeclaration v = expToVariable(exp.e1))
7829 {
9c7d5e88 7830 if (exp.e1.op == EXP.dotVariable)
5fee5ec3
IB
7831 {
7832 DotVarExp dve = cast(DotVarExp)exp.e1;
9c7d5e88 7833 if ((dve.e1.op == EXP.this_ || dve.e1.op == EXP.super_) &&
5fee5ec3
IB
7834 !(v.storage_class & STC.ref_))
7835 {
7836 // because it's a class
7837 v = null;
7838 }
7839 }
7840
7841 if (v && !checkAddressVar(sc, exp.e1, v))
7842 return setError();
7843 }
7844 }
7845 }
7846 else if (t1b.ty == Ttuple)
7847 {
7848 if (!exp.lwr && !exp.upr)
7849 {
7850 result = exp.e1;
7851 return;
7852 }
7853 if (!exp.lwr || !exp.upr)
7854 {
7855 exp.error("need upper and lower bound to slice tuple");
7856 return setError();
7857 }
7858 }
7859 else if (t1b.ty == Tvector)
7860 {
7861 // Convert e1 to corresponding static array
7862 TypeVector tv1 = cast(TypeVector)t1b;
7863 t1b = tv1.basetype;
7864 t1b = t1b.castMod(tv1.mod);
7865 exp.e1.type = t1b;
7866 }
7867 else
7868 {
7869 exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7870 return setError();
7871 }
7872
7873 /* Run semantic on lwr and upr.
7874 */
7875 Scope* scx = sc;
7876 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7877 {
7878 // Create scope for 'length' variable
7879 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7880 sym.parent = sc.scopesym;
7881 sc = sc.push(sym);
7882 }
7883 if (exp.lwr)
7884 {
7885 if (t1b.ty == Ttuple)
7886 sc = sc.startCTFE();
7887 exp.lwr = exp.lwr.expressionSemantic(sc);
7888 exp.lwr = resolveProperties(sc, exp.lwr);
7889 if (t1b.ty == Ttuple)
7890 sc = sc.endCTFE();
7891 exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7892 }
7893 if (exp.upr)
7894 {
7895 if (t1b.ty == Ttuple)
7896 sc = sc.startCTFE();
7897 exp.upr = exp.upr.expressionSemantic(sc);
7898 exp.upr = resolveProperties(sc, exp.upr);
7899 if (t1b.ty == Ttuple)
7900 sc = sc.endCTFE();
7901 exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7902 }
7903 if (sc != scx)
7904 sc = sc.pop();
7905 if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7906 return setError();
7907
7908 if (t1b.ty == Ttuple)
7909 {
7910 exp.lwr = exp.lwr.ctfeInterpret();
7911 exp.upr = exp.upr.ctfeInterpret();
7912 uinteger_t i1 = exp.lwr.toUInteger();
7913 uinteger_t i2 = exp.upr.toUInteger();
7914
7915 TupleExp te;
7916 TypeTuple tup;
7917 size_t length;
9c7d5e88 7918 if (exp.e1.op == EXP.tuple) // slicing an expression tuple
5fee5ec3
IB
7919 {
7920 te = cast(TupleExp)exp.e1;
7921 tup = null;
7922 length = te.exps.dim;
7923 }
9c7d5e88 7924 else if (exp.e1.op == EXP.type) // slicing a type tuple
5fee5ec3
IB
7925 {
7926 te = null;
7927 tup = cast(TypeTuple)t1b;
7928 length = Parameter.dim(tup.arguments);
7929 }
7930 else
7931 assert(0);
7932
7933 if (i2 < i1 || length < i2)
7934 {
7935 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
7936 return setError();
7937 }
7938
7939 size_t j1 = cast(size_t)i1;
7940 size_t j2 = cast(size_t)i2;
7941 Expression e;
9c7d5e88 7942 if (exp.e1.op == EXP.tuple)
5fee5ec3
IB
7943 {
7944 auto exps = new Expressions(j2 - j1);
7945 for (size_t i = 0; i < j2 - j1; i++)
7946 {
7947 (*exps)[i] = (*te.exps)[j1 + i];
7948 }
7949 e = new TupleExp(exp.loc, te.e0, exps);
7950 }
7951 else
7952 {
7953 auto args = new Parameters();
7954 args.reserve(j2 - j1);
7955 for (size_t i = j1; i < j2; i++)
7956 {
7957 Parameter arg = Parameter.getNth(tup.arguments, i);
7958 args.push(arg);
7959 }
7960 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
7961 }
7962 e = e.expressionSemantic(sc);
7963 result = e;
7964 return;
7965 }
7966
7967 exp.type = t1b.nextOf().arrayOf();
7968 // Allow typedef[] -> typedef[]
7969 if (exp.type.equals(t1b))
7970 exp.type = exp.e1.type;
7971
7972 // We might know $ now
7973 setLengthVarIfKnown(exp.lengthVar, t1b);
7974
7975 if (exp.lwr && exp.upr)
7976 {
7977 exp.lwr = exp.lwr.optimize(WANTvalue);
7978 exp.upr = exp.upr.optimize(WANTvalue);
7979
7980 IntRange lwrRange = getIntRange(exp.lwr);
7981 IntRange uprRange = getIntRange(exp.upr);
7982
7983 if (t1b.ty == Tsarray || t1b.ty == Tarray)
7984 {
7985 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
7986 el = el.expressionSemantic(sc);
7987 el = el.optimize(WANTvalue);
9c7d5e88 7988 if (el.op == EXP.int64)
5fee5ec3
IB
7989 {
7990 // Array length is known at compile-time. Upper is in bounds if it fits length.
7991 dinteger_t length = el.toInteger();
7992 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
7993 exp.upperIsInBounds = bounds.contains(uprRange);
9c7d5e88 7994 if (exp.lwr.op == EXP.int64 && exp.upr.op == EXP.int64 && exp.lwr.toInteger() > exp.upr.toInteger())
0fb57034
IB
7995 {
7996 exp.error("in slice `%s[%llu .. %llu]`, lower bound is greater than upper bound", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger());
7997 return setError();
7998 }
9c7d5e88 7999 if (exp.upr.op == EXP.int64 && exp.upr.toInteger() > length)
0fb57034
IB
8000 {
8001 exp.error("in slice `%s[%llu .. %llu]`, upper bound is greater than array length `%llu`", exp.e1.toChars, exp.lwr.toInteger(), exp.upr.toInteger(), length);
8002 return setError();
8003 }
5fee5ec3 8004 }
9c7d5e88 8005 else if (exp.upr.op == EXP.int64 && exp.upr.toInteger() == 0)
5fee5ec3
IB
8006 {
8007 // Upper slice expression is '0'. Value is always in bounds.
8008 exp.upperIsInBounds = true;
8009 }
9c7d5e88 8010 else if (exp.upr.op == EXP.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
5fee5ec3
IB
8011 {
8012 // Upper slice expression is '$'. Value is always in bounds.
8013 exp.upperIsInBounds = true;
8014 }
8015 }
8016 else if (t1b.ty == Tpointer)
8017 {
8018 exp.upperIsInBounds = true;
8019 }
8020 else
8021 assert(0);
8022
8023 exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
8024
8025 //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
8026 }
8027
8028 result = exp;
8029 }
8030
8031 override void visit(ArrayLengthExp e)
8032 {
8033 static if (LOGSEMANTIC)
8034 {
8035 printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
8036 }
8037 if (e.type)
8038 {
8039 result = e;
8040 return;
8041 }
8042
8043 if (Expression ex = unaSemantic(e, sc))
8044 {
8045 result = ex;
8046 return;
8047 }
8048 e.e1 = resolveProperties(sc, e.e1);
8049
8050 e.type = Type.tsize_t;
8051 result = e;
8052 }
8053
8054 override void visit(ArrayExp exp)
8055 {
8056 static if (LOGSEMANTIC)
8057 {
8058 printf("ArrayExp::semantic('%s')\n", exp.toChars());
8059 }
8060 assert(!exp.type);
0fb57034
IB
8061
8062 result = exp.carraySemantic(sc); // C semantics
8063 if (result)
8064 return;
8065
5fee5ec3
IB
8066 Expression e = exp.op_overload(sc);
8067 if (e)
8068 {
8069 result = e;
8070 return;
8071 }
8072
8073 if (isAggregate(exp.e1.type))
8074 exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
9c7d5e88 8075 else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
5fee5ec3
IB
8076 exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
8077 else if (isIndexableNonAggregate(exp.e1.type))
8078 exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
8079 else
8080 exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
8081
8082 result = ErrorExp.get();
8083 }
8084
8085 override void visit(DotExp exp)
8086 {
8087 static if (LOGSEMANTIC)
8088 {
8089 printf("DotExp::semantic('%s')\n", exp.toChars());
8090 if (exp.type)
8091 printf("\ttype = %s\n", exp.type.toChars());
8092 }
8093 exp.e1 = exp.e1.expressionSemantic(sc);
8094 exp.e2 = exp.e2.expressionSemantic(sc);
8095
9c7d5e88 8096 if (exp.e1.op == EXP.type)
5fee5ec3
IB
8097 {
8098 result = exp.e2;
8099 return;
8100 }
9c7d5e88 8101 if (exp.e2.op == EXP.type)
5fee5ec3
IB
8102 {
8103 result = exp.e2;
8104 return;
8105 }
9c7d5e88 8106 if (exp.e2.op == EXP.template_)
5fee5ec3
IB
8107 {
8108 auto td = (cast(TemplateExp)exp.e2).td;
8109 Expression e = new DotTemplateExp(exp.loc, exp.e1, td);
8110 result = e.expressionSemantic(sc);
8111 return;
8112 }
8113 if (!exp.type)
8114 exp.type = exp.e2.type;
8115 result = exp;
8116 }
8117
8118 override void visit(CommaExp e)
8119 {
0fb57034 8120 //printf("Semantic.CommaExp() %s\n", e.toChars());
5fee5ec3
IB
8121 if (e.type)
8122 {
8123 result = e;
8124 return;
8125 }
8126
8127 // Allow `((a,b),(x,y))`
8128 if (e.allowCommaExp)
8129 {
8130 CommaExp.allow(e.e1);
8131 CommaExp.allow(e.e2);
8132 }
8133
8134 if (Expression ex = binSemanticProp(e, sc))
8135 {
8136 result = ex;
8137 return;
8138 }
8139 e.e1 = e.e1.addDtorHook(sc);
8140
8141 if (checkNonAssignmentArrayOp(e.e1))
8142 return setError();
8143
0fb57034
IB
8144 // Comma expressions trigger this conversion
8145 e.e2 = e.e2.arrayFuncConv(sc);
8146
5fee5ec3
IB
8147 e.type = e.e2.type;
8148 if (e.type is Type.tvoid)
8149 discardValue(e.e1);
0fb57034 8150 else if (!e.allowCommaExp && !e.isGenerated && !(sc.flags & SCOPE.Cfile))
5fee5ec3
IB
8151 e.error("Using the result of a comma expression is not allowed");
8152 result = e;
8153 }
8154
8155 override void visit(IntervalExp e)
8156 {
8157 static if (LOGSEMANTIC)
8158 {
8159 printf("IntervalExp::semantic('%s')\n", e.toChars());
8160 }
8161 if (e.type)
8162 {
8163 result = e;
8164 return;
8165 }
8166
8167 Expression le = e.lwr;
8168 le = le.expressionSemantic(sc);
8169 le = resolveProperties(sc, le);
8170
8171 Expression ue = e.upr;
8172 ue = ue.expressionSemantic(sc);
8173 ue = resolveProperties(sc, ue);
8174
9c7d5e88 8175 if (le.op == EXP.error)
5fee5ec3
IB
8176 {
8177 result = le;
8178 return;
8179 }
9c7d5e88 8180 if (ue.op == EXP.error)
5fee5ec3
IB
8181 {
8182 result = ue;
8183 return;
8184 }
8185
8186 e.lwr = le;
8187 e.upr = ue;
8188
8189 e.type = Type.tvoid;
8190 result = e;
8191 }
8192
8193 override void visit(DelegatePtrExp e)
8194 {
8195 static if (LOGSEMANTIC)
8196 {
8197 printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
8198 }
8199 if (!e.type)
8200 {
8201 unaSemantic(e, sc);
8202 e.e1 = resolveProperties(sc, e.e1);
8203
9c7d5e88 8204 if (e.e1.op == EXP.error)
5fee5ec3
IB
8205 {
8206 result = e.e1;
8207 return;
8208 }
8209 e.type = Type.tvoidptr;
8210 }
8211 result = e;
8212 }
8213
8214 override void visit(DelegateFuncptrExp e)
8215 {
8216 static if (LOGSEMANTIC)
8217 {
8218 printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
8219 }
8220 if (!e.type)
8221 {
8222 unaSemantic(e, sc);
8223 e.e1 = resolveProperties(sc, e.e1);
9c7d5e88 8224 if (e.e1.op == EXP.error)
5fee5ec3
IB
8225 {
8226 result = e.e1;
8227 return;
8228 }
8229 e.type = e.e1.type.nextOf().pointerTo();
8230 }
8231 result = e;
8232 }
8233
8234 override void visit(IndexExp exp)
8235 {
8236 static if (LOGSEMANTIC)
8237 {
8238 printf("IndexExp::semantic('%s')\n", exp.toChars());
8239 }
8240 if (exp.type)
8241 {
8242 result = exp;
8243 return;
8244 }
8245
8246 // operator overloading should be handled in ArrayExp already.
8247 if (!exp.e1.type)
0fb57034 8248 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
5fee5ec3 8249 assert(exp.e1.type); // semantic() should already be run on it
9c7d5e88 8250 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
5fee5ec3
IB
8251 {
8252 exp.e2 = exp.e2.expressionSemantic(sc);
8253 exp.e2 = resolveProperties(sc, exp.e2);
8254 Type nt;
9c7d5e88 8255 if (exp.e2.op == EXP.type)
5fee5ec3
IB
8256 nt = new TypeAArray(exp.e1.type, exp.e2.type);
8257 else
8258 nt = new TypeSArray(exp.e1.type, exp.e2);
8259 Expression e = new TypeExp(exp.loc, nt);
8260 result = e.expressionSemantic(sc);
8261 return;
8262 }
9c7d5e88 8263 if (exp.e1.op == EXP.error)
5fee5ec3
IB
8264 {
8265 result = exp.e1;
8266 return;
8267 }
8268 if (exp.e1.type.ty == Terror)
8269 return setError();
8270
8271 // Note that unlike C we do not implement the int[ptr]
8272
8273 Type t1b = exp.e1.type.toBasetype();
8274
8275 if (t1b.ty == Tvector)
8276 {
8277 // Convert e1 to corresponding static array
8278 TypeVector tv1 = cast(TypeVector)t1b;
8279 t1b = tv1.basetype;
8280 t1b = t1b.castMod(tv1.mod);
8281 exp.e1.type = t1b;
8282 }
8283
8284 /* Run semantic on e2
8285 */
8286 Scope* scx = sc;
8287 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
8288 {
8289 // Create scope for 'length' variable
8290 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
8291 sym.parent = sc.scopesym;
8292 sc = sc.push(sym);
8293 }
8294 if (t1b.ty == Ttuple)
8295 sc = sc.startCTFE();
0fb57034 8296 exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
5fee5ec3
IB
8297 exp.e2 = resolveProperties(sc, exp.e2);
8298 if (t1b.ty == Ttuple)
8299 sc = sc.endCTFE();
9c7d5e88 8300 if (exp.e2.op == EXP.tuple)
5fee5ec3
IB
8301 {
8302 TupleExp te = cast(TupleExp)exp.e2;
8303 if (te.exps && te.exps.dim == 1)
8304 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
8305 }
8306 if (sc != scx)
8307 sc = sc.pop();
8308 if (exp.e2.type == Type.terror)
8309 return setError();
8310
8311 if (checkNonAssignmentArrayOp(exp.e1))
8312 return setError();
8313
8314 switch (t1b.ty)
8315 {
8316 case Tpointer:
8317 if (t1b.isPtrToFunction())
8318 {
8319 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
8320 return setError();
8321 }
8322 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8323 if (exp.e2.type == Type.terror)
8324 return setError();
8325 exp.e2 = exp.e2.optimize(WANTvalue);
9c7d5e88 8326 if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
5fee5ec3
IB
8327 {
8328 }
8329 else if (sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
8330 {
8331 exp.error("safe function `%s` cannot index pointer `%s`", sc.func.toPrettyChars(), exp.e1.toChars());
8332 return setError();
8333 }
8334 exp.type = (cast(TypeNext)t1b).next;
8335 break;
8336
8337 case Tarray:
8338 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8339 if (exp.e2.type == Type.terror)
8340 return setError();
8341 exp.type = (cast(TypeNext)t1b).next;
8342 break;
8343
8344 case Tsarray:
8345 {
8346 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8347 if (exp.e2.type == Type.terror)
8348 return setError();
8349 exp.type = t1b.nextOf();
8350 break;
8351 }
8352 case Taarray:
8353 {
8354 TypeAArray taa = cast(TypeAArray)t1b;
8355 /* We can skip the implicit conversion if they differ only by
8356 * constness
8357 * https://issues.dlang.org/show_bug.cgi?id=2684
8358 * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8359 */
8360 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8361 {
8362 exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8363 if (exp.e2.type == Type.terror)
8364 return setError();
8365 }
8366
8367 semanticTypeInfo(sc, taa);
8368
8369 exp.type = taa.next;
8370 break;
8371 }
8372 case Ttuple:
8373 {
8374 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8375 if (exp.e2.type == Type.terror)
8376 return setError();
8377
8378 exp.e2 = exp.e2.ctfeInterpret();
8379 uinteger_t index = exp.e2.toUInteger();
8380
8381 TupleExp te;
8382 TypeTuple tup;
8383 size_t length;
9c7d5e88 8384 if (exp.e1.op == EXP.tuple)
5fee5ec3
IB
8385 {
8386 te = cast(TupleExp)exp.e1;
8387 tup = null;
8388 length = te.exps.dim;
8389 }
9c7d5e88 8390 else if (exp.e1.op == EXP.type)
5fee5ec3
IB
8391 {
8392 te = null;
8393 tup = cast(TypeTuple)t1b;
8394 length = Parameter.dim(tup.arguments);
8395 }
8396 else
8397 assert(0);
8398
8399 if (length <= index)
8400 {
8401 exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8402 return setError();
8403 }
8404 Expression e;
9c7d5e88 8405 if (exp.e1.op == EXP.tuple)
5fee5ec3
IB
8406 {
8407 e = (*te.exps)[cast(size_t)index];
8408 e = Expression.combine(te.e0, e);
8409 }
8410 else
8411 e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8412 result = e;
8413 return;
8414 }
8415 default:
8416 exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8417 return setError();
8418 }
8419
8420 // We might know $ now
8421 setLengthVarIfKnown(exp.lengthVar, t1b);
8422
8423 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8424 {
8425 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8426 el = el.expressionSemantic(sc);
8427 el = el.optimize(WANTvalue);
9c7d5e88 8428 if (el.op == EXP.int64)
5fee5ec3
IB
8429 {
8430 exp.e2 = exp.e2.optimize(WANTvalue);
8431 dinteger_t length = el.toInteger();
8432 if (length)
8433 {
8434 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8435 exp.indexIsInBounds = bounds.contains(getIntRange(exp.e2));
8436 }
8437 }
8438 }
8439
8440 result = exp;
8441 }
8442
8443 override void visit(PostExp exp)
8444 {
8445 static if (LOGSEMANTIC)
8446 {
8447 printf("PostExp::semantic('%s')\n", exp.toChars());
8448 }
8449 if (exp.type)
8450 {
8451 result = exp;
8452 return;
8453 }
8454
8455 if (Expression ex = binSemantic(exp, sc))
8456 {
8457 result = ex;
8458 return;
8459 }
8460 Expression e1x = resolveProperties(sc, exp.e1);
9c7d5e88 8461 if (e1x.op == EXP.error)
5fee5ec3
IB
8462 {
8463 result = e1x;
8464 return;
8465 }
8466 exp.e1 = e1x;
8467
8468 Expression e = exp.op_overload(sc);
8469 if (e)
8470 {
8471 result = e;
8472 return;
8473 }
8474
8475 if (exp.e1.checkReadModifyWrite(exp.op))
8476 return setError();
8477
9c7d5e88 8478 if (exp.e1.op == EXP.slice)
5fee5ec3 8479 {
9c7d5e88 8480 const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
5fee5ec3
IB
8481 exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8482 return setError();
8483 }
8484
8485 Type t1 = exp.e1.type.toBasetype();
9c7d5e88 8486 if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == EXP.arrayLength)
5fee5ec3
IB
8487 {
8488 /* Check for operator overloading,
8489 * but rewrite in terms of ++e instead of e++
8490 */
8491
8492 /* If e1 is not trivial, take a reference to it
8493 */
8494 Expression de = null;
9c7d5e88 8495 if (exp.e1.op != EXP.variable && exp.e1.op != EXP.arrayLength)
5fee5ec3
IB
8496 {
8497 // ref v = e1;
8498 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8499 de = new DeclarationExp(exp.loc, v);
8500 exp.e1 = new VarExp(exp.e1.loc, v);
8501 }
8502
8503 /* Rewrite as:
8504 * auto tmp = e1; ++e1; tmp
8505 */
8506 auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8507 Expression ea = new DeclarationExp(exp.loc, tmp);
8508
8509 Expression eb = exp.e1.syntaxCopy();
9c7d5e88 8510 eb = new PreExp(exp.op == EXP.plusPlus ? EXP.prePlusPlus : EXP.preMinusMinus, exp.loc, eb);
5fee5ec3
IB
8511
8512 Expression ec = new VarExp(exp.loc, tmp);
8513
8514 // Combine de,ea,eb,ec
8515 if (de)
8516 ea = new CommaExp(exp.loc, de, ea);
8517 e = new CommaExp(exp.loc, ea, eb);
8518 e = new CommaExp(exp.loc, e, ec);
8519 e = e.expressionSemantic(sc);
8520 result = e;
8521 return;
8522 }
8523
8524 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8525 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
8526
8527 e = exp;
8528 if (exp.e1.checkScalar() ||
8529 exp.e1.checkSharedAccess(sc))
8530 return setError();
8531 if (exp.e1.checkNoBool())
8532 return setError();
8533
8534 if (exp.e1.type.ty == Tpointer)
8535 e = scaleFactor(exp, sc);
8536 else
8537 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8538 e.type = exp.e1.type;
8539 result = e;
8540 }
8541
8542 override void visit(PreExp exp)
8543 {
8544 Expression e = exp.op_overload(sc);
8545 // printf("PreExp::semantic('%s')\n", toChars());
8546 if (e)
8547 {
8548 result = e;
8549 return;
8550 }
8551
8552 // Rewrite as e1+=1 or e1-=1
9c7d5e88 8553 if (exp.op == EXP.prePlusPlus)
5fee5ec3
IB
8554 e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8555 else
8556 e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8557 result = e.expressionSemantic(sc);
8558 }
8559
8560 /*
8561 * Get the expression initializer for a specific struct
8562 *
8563 * Params:
8564 * sd = the struct for which the expression initializer is needed
8565 * loc = the location of the initializer
8566 * sc = the scope where the expression is located
8567 * t = the type of the expression
8568 *
8569 * Returns:
8570 * The expression initializer or error expression if any errors occured
8571 */
8572 private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8573 {
8574 if (sd.zeroInit && !sd.isNested())
8575 {
8576 // https://issues.dlang.org/show_bug.cgi?id=14606
8577 // Always use BlitExp for the special expression: (struct = 0)
8578 return IntegerExp.literal!0;
8579 }
8580
8581 if (sd.isNested())
8582 {
8583 auto sle = new StructLiteralExp(loc, sd, null, t);
8584 if (!sd.fill(loc, sle.elements, true))
8585 return ErrorExp.get();
8586 if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
8587 return ErrorExp.get();
8588
8589 sle.type = t;
8590 return sle;
8591 }
8592
8593 return t.defaultInit(loc);
8594 }
8595
8596 override void visit(AssignExp exp)
8597 {
8598 static if (LOGSEMANTIC)
8599 {
8600 printf("AssignExp::semantic('%s')\n", exp.toChars());
8601 }
9c7d5e88
IB
8602 //printf("exp.e1.op = %d, '%s'\n", exp.e1.op, EXPtoString(exp.e1.op).ptr);
8603 //printf("exp.e2.op = %d, '%s'\n", exp.e2.op, EXPtoString(exp.e2.op).ptr);
5fee5ec3
IB
8604
8605 void setResult(Expression e, int line = __LINE__)
8606 {
8607 //printf("line %d\n", line);
8608 result = e;
8609 }
8610
8611 if (exp.type)
8612 {
8613 return setResult(exp);
8614 }
8615
8616 Expression e1old = exp.e1;
8617
8618 if (auto e2comma = exp.e2.isCommaExp())
8619 {
0fb57034 8620 if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
5fee5ec3
IB
8621 exp.error("Using the result of a comma expression is not allowed");
8622
8623 /* Rewrite to get rid of the comma from rvalue
8624 * e1=(e0,e2) => e0,(e1=e2)
8625 */
8626 Expression e0;
8627 exp.e2 = Expression.extractLast(e2comma, e0);
8628 Expression e = Expression.combine(e0, exp);
8629 return setResult(e.expressionSemantic(sc));
8630 }
8631
8632 /* Look for operator overloading of a[arguments] = e2.
8633 * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8634 * converted to unary operator overloading already.
8635 */
8636 if (auto ae = exp.e1.isArrayExp())
8637 {
8638 Expression res;
8639
8640 ae.e1 = ae.e1.expressionSemantic(sc);
8641 ae.e1 = resolveProperties(sc, ae.e1);
8642 Expression ae1old = ae.e1;
8643
8644 const(bool) maybeSlice =
8645 (ae.arguments.dim == 0 ||
9c7d5e88 8646 ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
5fee5ec3
IB
8647
8648 IntervalExp ie = null;
8649 if (maybeSlice && ae.arguments.dim)
8650 {
9c7d5e88 8651 assert((*ae.arguments)[0].op == EXP.interval);
5fee5ec3
IB
8652 ie = cast(IntervalExp)(*ae.arguments)[0];
8653 }
8654 while (true)
8655 {
9c7d5e88 8656 if (ae.e1.op == EXP.error)
5fee5ec3
IB
8657 return setResult(ae.e1);
8658
8659 Expression e0 = null;
8660 Expression ae1save = ae.e1;
8661 ae.lengthVar = null;
8662
8663 Type t1b = ae.e1.type.toBasetype();
8664 AggregateDeclaration ad = isAggregate(t1b);
8665 if (!ad)
8666 break;
8667 if (search_function(ad, Id.indexass))
8668 {
8669 // Deal with $
8670 res = resolveOpDollar(sc, ae, &e0);
8671 if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8672 goto Lfallback;
9c7d5e88 8673 if (res.op == EXP.error)
5fee5ec3
IB
8674 return setResult(res);
8675
8676 res = exp.e2.expressionSemantic(sc);
9c7d5e88 8677 if (res.op == EXP.error)
5fee5ec3
IB
8678 return setResult(res);
8679 exp.e2 = res;
8680
8681 /* Rewrite (a[arguments] = e2) as:
8682 * a.opIndexAssign(e2, arguments)
8683 */
8684 Expressions* a = ae.arguments.copy();
8685 a.insert(0, exp.e2);
8686 res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8687 res = new CallExp(exp.loc, res, a);
8688 if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8689 res = res.trySemantic(sc);
8690 else
8691 res = res.expressionSemantic(sc);
8692 if (res)
8693 return setResult(Expression.combine(e0, res));
8694 }
8695
8696 Lfallback:
8697 if (maybeSlice && search_function(ad, Id.sliceass))
8698 {
8699 // Deal with $
8700 res = resolveOpDollar(sc, ae, ie, &e0);
9c7d5e88 8701 if (res.op == EXP.error)
5fee5ec3
IB
8702 return setResult(res);
8703
8704 res = exp.e2.expressionSemantic(sc);
9c7d5e88 8705 if (res.op == EXP.error)
5fee5ec3
IB
8706 return setResult(res);
8707
8708 exp.e2 = res;
8709
8710 /* Rewrite (a[i..j] = e2) as:
8711 * a.opSliceAssign(e2, i, j)
8712 */
8713 auto a = new Expressions();
8714 a.push(exp.e2);
8715 if (ie)
8716 {
8717 a.push(ie.lwr);
8718 a.push(ie.upr);
8719 }
8720 res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8721 res = new CallExp(exp.loc, res, a);
8722 res = res.expressionSemantic(sc);
8723 return setResult(Expression.combine(e0, res));
8724 }
8725
8726 // No operator overloading member function found yet, but
8727 // there might be an alias this to try.
8728 if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
8729 {
8730 /* Rewrite (a[arguments] op e2) as:
8731 * a.aliasthis[arguments] op e2
8732 */
8733 ae.e1 = resolveAliasThis(sc, ae1save, true);
8734 if (ae.e1)
8735 continue;
8736 }
8737 break;
8738 }
8739 ae.e1 = ae1old; // recovery
8740 ae.lengthVar = null;
8741 }
8742
8743 /* Run this.e1 semantic.
8744 */
8745 {
8746 Expression e1x = exp.e1;
8747
8748 /* With UFCS, e.f = value
8749 * Could mean:
8750 * .f(e, value)
8751 * or:
8752 * .f(e) = value
8753 */
8754 if (auto dti = e1x.isDotTemplateInstanceExp())
8755 {
8756 Expression e = dti.semanticY(sc, 1);
8757 if (!e)
8758 {
8759 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8760 }
8761
8762 e1x = e;
8763 }
0fb57034
IB
8764 else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
8765 {
8766 auto die = e1x.isDotIdExp();
8767 e1x = fieldLookup(die.e1, sc, die.ident);
8768 }
5fee5ec3
IB
8769 else if (auto die = e1x.isDotIdExp())
8770 {
8771 Expression e = die.semanticY(sc, 1);
8772 if (e && isDotOpDispatch(e))
8773 {
8774 /* https://issues.dlang.org/show_bug.cgi?id=19687
8775 *
8776 * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8777 * but that call is done with gagged errors. That is the only time when
8778 * semantic gets ran on e2, that is why the error never gets to be printed.
8779 * In order to make sure that UFCS is tried with correct parameters, e2
8780 * needs to have semantic ran on it.
8781 */
0fb57034 8782 auto ode = e;
5fee5ec3
IB
8783 exp.e2 = exp.e2.expressionSemantic(sc);
8784 uint errors = global.startGagging();
8785 e = resolvePropertiesX(sc, e, exp.e2);
0fb57034
IB
8786 // Any error or if 'e' is not resolved, go to UFCS
8787 if (global.endGagging(errors) || e is ode)
5fee5ec3
IB
8788 e = null; /* fall down to UFCS */
8789 else
8790 return setResult(e);
8791 }
8792 if (!e)
8793 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8794 e1x = e;
8795 }
8796 else
8797 {
8798 if (auto se = e1x.isSliceExp())
8799 se.arrayop = true;
8800
8801 e1x = e1x.expressionSemantic(sc);
8802 }
8803
8804 /* We have f = value.
8805 * Could mean:
8806 * f(value)
8807 * or:
8808 * f() = value
8809 */
8810 if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8811 return setResult(e);
8812
8813 if (e1x.checkRightThis(sc))
8814 {
8815 return setError();
8816 }
8817 exp.e1 = e1x;
8818 assert(exp.e1.type);
8819 }
8820 Type t1 = exp.e1.type.toBasetype();
8821
8822 /* Run this.e2 semantic.
8823 * Different from other binary expressions, the analysis of e2
8824 * depends on the result of e1 in assignments.
8825 */
8826 {
8827 Expression e2x = inferType(exp.e2, t1.baseElemOf());
8828 e2x = e2x.expressionSemantic(sc);
0fb57034
IB
8829 if (!t1.isTypeSArray())
8830 e2x = e2x.arrayFuncConv(sc);
5fee5ec3 8831 e2x = resolveProperties(sc, e2x);
9c7d5e88 8832 if (e2x.op == EXP.type)
5fee5ec3 8833 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 8834 if (e2x.op == EXP.error)
5fee5ec3 8835 return setResult(e2x);
0fb57034 8836 // We delay checking the value for structs/classes as these might have
5fee5ec3
IB
8837 // an opAssign defined.
8838 if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
8839 e2x.checkSharedAccess(sc))
8840 return setError();
8841 exp.e2 = e2x;
8842 }
8843
8844 /* Rewrite tuple assignment as a tuple of assignments.
8845 */
8846 {
8847 Expression e2x = exp.e2;
8848
8849 Ltupleassign:
9c7d5e88 8850 if (exp.e1.op == EXP.tuple && e2x.op == EXP.tuple)
5fee5ec3
IB
8851 {
8852 TupleExp tup1 = cast(TupleExp)exp.e1;
8853 TupleExp tup2 = cast(TupleExp)e2x;
8854 size_t dim = tup1.exps.dim;
8855 Expression e = null;
8856 if (dim != tup2.exps.dim)
8857 {
8858 exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
8859 return setError();
8860 }
8861 if (dim == 0)
8862 {
8863 e = IntegerExp.literal!0;
8864 e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8865 e = Expression.combine(tup1.e0, tup2.e0, e);
8866 }
8867 else
8868 {
8869 auto exps = new Expressions(dim);
8870 for (size_t i = 0; i < dim; i++)
8871 {
8872 Expression ex1 = (*tup1.exps)[i];
8873 Expression ex2 = (*tup2.exps)[i];
8874 (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8875 }
8876 e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8877 }
8878 return setResult(e.expressionSemantic(sc));
8879 }
8880
8881 /* Look for form: e1 = e2.aliasthis.
8882 */
9c7d5e88 8883 if (exp.e1.op == EXP.tuple)
5fee5ec3
IB
8884 {
8885 TupleDeclaration td = isAliasThisTuple(e2x);
8886 if (!td)
8887 goto Lnomatch;
8888
8889 assert(exp.e1.type.ty == Ttuple);
8890 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8891
8892 Expression e0;
8893 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
8894
8895 auto iexps = new Expressions();
8896 iexps.push(ev);
8897 for (size_t u = 0; u < iexps.dim; u++)
8898 {
8899 Lexpand:
8900 Expression e = (*iexps)[u];
8901
8902 Parameter arg = Parameter.getNth(tt.arguments, u);
8903 //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
8904 //printf("e = (%s %s, %s), ", Token::tochars[e.op], e.toChars(), e.type.toChars());
8905 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
8906
8907 if (!arg || !e.type.implicitConvTo(arg.type))
8908 {
8909 // expand initializer to tuple
8910 if (expandAliasThisTuples(iexps, u) != -1)
8911 {
8912 if (iexps.dim <= u)
8913 break;
8914 goto Lexpand;
8915 }
8916 goto Lnomatch;
8917 }
8918 }
8919 e2x = new TupleExp(e2x.loc, e0, iexps);
8920 e2x = e2x.expressionSemantic(sc);
9c7d5e88 8921 if (e2x.op == EXP.error)
5fee5ec3
IB
8922 {
8923 result = e2x;
8924 return;
8925 }
8926 // Do not need to overwrite this.e2
8927 goto Ltupleassign;
8928 }
8929 Lnomatch:
8930 }
8931
8932 /* Inside constructor, if this is the first assignment of object field,
8933 * rewrite this to initializing the field.
8934 */
9c7d5e88 8935 if (exp.op == EXP.assign
5fee5ec3
IB
8936 && exp.e1.checkModifiable(sc) == Modifiable.initialization)
8937 {
8938 //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
8939 auto t = exp.type;
8940 exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
8941 exp.type = t;
8942
8943 // https://issues.dlang.org/show_bug.cgi?id=13515
8944 // set Index::modifiable flag for complex AA element initialization
8945 if (auto ie1 = exp.e1.isIndexExp())
8946 {
8947 Expression e1x = ie1.markSettingAAElem();
9c7d5e88 8948 if (e1x.op == EXP.error)
5fee5ec3
IB
8949 {
8950 result = e1x;
8951 return;
8952 }
8953 }
8954 }
9c7d5e88 8955 else if (exp.op == EXP.construct && exp.e1.op == EXP.variable &&
5fee5ec3
IB
8956 (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
8957 {
8958 exp.memset = MemorySet.referenceInit;
8959 }
8960
9c7d5e88 8961 if (exp.op == EXP.assign) // skip EXP.blit and EXP.construct, which are initializations
5fee5ec3
IB
8962 {
8963 exp.e1.checkSharedAccess(sc);
8964 checkUnsafeAccess(sc, exp.e1, false, true);
8965 }
8966
8967 checkUnsafeAccess(sc, exp.e2, true, true); // Initializer must always be checked
8968
8969 /* If it is an assignment from a 'foreign' type,
8970 * check for operator overloading.
8971 */
8972 if (exp.memset == MemorySet.referenceInit)
8973 {
8974 // If this is an initialization of a reference,
8975 // do nothing
8976 }
8977 else if (t1.ty == Tstruct)
8978 {
8979 auto e1x = exp.e1;
8980 auto e2x = exp.e2;
8981 auto sd = (cast(TypeStruct)t1).sym;
8982
9c7d5e88 8983 if (exp.op == EXP.construct)
5fee5ec3
IB
8984 {
8985 Type t2 = e2x.type.toBasetype();
8986 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
8987 {
8988 sd.size(exp.loc);
8989 if (sd.sizeok != Sizeok.done)
8990 return setError();
8991 if (!sd.ctor)
8992 sd.ctor = sd.searchCtor();
8993
8994 // https://issues.dlang.org/show_bug.cgi?id=15661
8995 // Look for the form from last of comma chain.
8996 auto e2y = lastComma(e2x);
8997
9c7d5e88
IB
8998 CallExp ce = (e2y.op == EXP.call) ? cast(CallExp)e2y : null;
8999 DotVarExp dve = (ce && ce.e1.op == EXP.dotVariable)
5fee5ec3
IB
9000 ? cast(DotVarExp)ce.e1 : null;
9001 if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
9002 // https://issues.dlang.org/show_bug.cgi?id=19389
9c7d5e88 9003 dve.e1.op != EXP.dotVariable &&
5fee5ec3
IB
9004 e2y.type.implicitConvTo(t1))
9005 {
9006 /* Look for form of constructor call which is:
9007 * __ctmp.ctor(arguments...)
9008 */
9009
9010 /* Before calling the constructor, initialize
9011 * variable with a bit copy of the default
9012 * initializer
9013 */
9014 Expression einit = getInitExp(sd, exp.loc, sc, t1);
9c7d5e88 9015 if (einit.op == EXP.error)
5fee5ec3
IB
9016 {
9017 result = einit;
9018 return;
9019 }
9020
9021 auto ae = new BlitExp(exp.loc, exp.e1, einit);
9022 ae.type = e1x.type;
9023
9024 /* Replace __ctmp being constructed with e1.
9025 * We need to copy constructor call expression,
9026 * because it may be used in other place.
9027 */
9028 auto dvx = cast(DotVarExp)dve.copy();
9029 dvx.e1 = e1x;
9030 auto cx = cast(CallExp)ce.copy();
9031 cx.e1 = dvx;
9032 if (checkConstructorEscape(sc, cx, false))
9033 return setError();
9034
9035 Expression e0;
9036 Expression.extractLast(e2x, e0);
9037
9038 auto e = Expression.combine(e0, ae, cx);
9039 e = e.expressionSemantic(sc);
9040 result = e;
9041 return;
9042 }
9043 // https://issues.dlang.org/show_bug.cgi?id=21586
9044 // Rewrite CondExp or e1 will miss direct construction, e.g.
9045 // e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
9046 // a temporary created and an extra destructor call.
9047 // AST will be rewritten to:
9048 // a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
9c7d5e88 9049 if (e2x.op == EXP.question)
5fee5ec3
IB
9050 {
9051 /* Rewrite as:
9052 * a ? e1 = b : e1 = c;
9053 */
9054 CondExp econd = cast(CondExp)e2x;
9055 Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
9056 Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
9057 Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
9058 result = e.expressionSemantic(sc);
9059 return;
9060 }
9061 if (sd.postblit || sd.hasCopyCtor)
9062 {
9063 /* We have a copy constructor for this
9064 */
9065
9066 if (e2x.isLvalue())
9067 {
9068 if (sd.hasCopyCtor)
9069 {
9070 /* Rewrite as:
9071 * e1 = init, e1.copyCtor(e2);
9072 */
9073 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
9074 einit.type = e1x.type;
9075
9076 Expression e;
9077 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9078 e = new CallExp(exp.loc, e, e2x);
9079 e = new CommaExp(exp.loc, einit, e);
9080
9081 //printf("e: %s\n", e.toChars());
9082
9083 result = e.expressionSemantic(sc);
9084 return;
9085 }
9086 else
9087 {
9088 if (!e2x.type.implicitConvTo(e1x.type))
9089 {
9090 exp.error("conversion error from `%s` to `%s`",
9091 e2x.type.toChars(), e1x.type.toChars());
9092 return setError();
9093 }
9094
9095 /* Rewrite as:
9096 * (e1 = e2).postblit();
9097 *
9098 * Blit assignment e1 = e2 returns a reference to the original e1,
9099 * then call the postblit on it.
9100 */
9101 Expression e = e1x.copy();
9102 e.type = e.type.mutableOf();
9103 if (e.type.isShared && !sd.type.isShared)
9104 e.type = e.type.unSharedOf();
9105 e = new BlitExp(exp.loc, e, e2x);
9106 e = new DotVarExp(exp.loc, e, sd.postblit, false);
9107 e = new CallExp(exp.loc, e);
9108 result = e.expressionSemantic(sc);
9109 return;
9110 }
9111 }
9112 else
9113 {
9114 /* The struct value returned from the function is transferred
9115 * so should not call the destructor on it.
9116 */
9117 e2x = valueNoDtor(e2x);
9118 }
9119 }
9120
9121 // https://issues.dlang.org/show_bug.cgi?id=19251
9122 // if e2 cannot be converted to e1.type, maybe there is an alias this
9123 if (!e2x.implicitConvTo(t1))
9124 {
9125 AggregateDeclaration ad2 = isAggregate(e2x.type);
9126 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9127 {
9128 /* Rewrite (e1 op e2) as:
9129 * (e1 op e2.aliasthis)
9130 */
9131 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9132 result = exp.expressionSemantic(sc);
9133 return;
9134 }
9135 }
9136 }
9137 else if (!e2x.implicitConvTo(t1))
9138 {
9139 sd.size(exp.loc);
9140 if (sd.sizeok != Sizeok.done)
9141 return setError();
9142 if (!sd.ctor)
9143 sd.ctor = sd.searchCtor();
9144
9145 if (sd.ctor)
9146 {
9147 /* Look for implicit constructor call
9148 * Rewrite as:
9149 * e1 = init, e1.ctor(e2)
9150 */
9151
9152 /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
9153 * Using `new` to initialize a struct object is a common mistake, but
9154 * the error message from the compiler is not very helpful in that
9155 * case. If exp.e2 is a NewExp and the type of new is the same as
9156 * the type as exp.e1 (struct in this case), then we know for sure
9157 * that the user wants to instantiate a struct. This is done to avoid
9158 * issuing an error when the user actually wants to call a constructor
9159 * which receives a class object.
9160 *
9161 * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
9162 * which receives an instance of a Foo2 class
9163 */
9c7d5e88 9164 if (exp.e2.op == EXP.new_)
5fee5ec3
IB
9165 {
9166 auto newExp = cast(NewExp)(exp.e2);
9167 if (newExp.newtype && newExp.newtype == t1)
9168 {
9169 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
9170 newExp.toChars(), newExp.type.toChars(), t1.toChars());
9171 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
9172 return setError();
9173 }
9174 }
9175
9176 Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
9177 einit.type = e1x.type;
9178
9179 Expression e;
9180 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9181 e = new CallExp(exp.loc, e, e2x);
9182 e = new CommaExp(exp.loc, einit, e);
9183 e = e.expressionSemantic(sc);
9184 result = e;
9185 return;
9186 }
9187 if (search_function(sd, Id.call))
9188 {
9189 /* Look for static opCall
9190 * https://issues.dlang.org/show_bug.cgi?id=2702
9191 * Rewrite as:
9192 * e1 = typeof(e1).opCall(arguments)
9193 */
9194 e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
9195 e2x = new CallExp(exp.loc, e2x, exp.e2);
9196
9197 e2x = e2x.expressionSemantic(sc);
9198 e2x = resolveProperties(sc, e2x);
9c7d5e88 9199 if (e2x.op == EXP.error)
5fee5ec3
IB
9200 {
9201 result = e2x;
9202 return;
9203 }
9204 if (e2x.checkValue() || e2x.checkSharedAccess(sc))
9205 return setError();
9206 }
9207 }
9208 else // https://issues.dlang.org/show_bug.cgi?id=11355
9209 {
9210 AggregateDeclaration ad2 = isAggregate(e2x.type);
9211 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9212 {
9213 /* Rewrite (e1 op e2) as:
9214 * (e1 op e2.aliasthis)
9215 */
9216 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9217 result = exp.expressionSemantic(sc);
9218 return;
9219 }
9220 }
9221 }
9c7d5e88 9222 else if (exp.op == EXP.assign)
5fee5ec3 9223 {
9c7d5e88 9224 if (e1x.op == EXP.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
5fee5ec3
IB
9225 {
9226 /*
9227 * Rewrite:
9228 * aa[key] = e2;
9229 * as:
9230 * ref __aatmp = aa;
9231 * ref __aakey = key;
9232 * ref __aaval = e2;
9233 * (__aakey in __aatmp
9234 * ? __aatmp[__aakey].opAssign(__aaval)
9235 * : ConstructExp(__aatmp[__aakey], __aaval));
9236 */
9237 // ensure we keep the expr modifiable
9238 Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
9c7d5e88 9239 if (esetting.op == EXP.error)
5fee5ec3
IB
9240 {
9241 result = esetting;
9242 return;
9243 }
9c7d5e88 9244 assert(esetting.op == EXP.index);
5fee5ec3
IB
9245 IndexExp ie = cast(IndexExp) esetting;
9246 Type t2 = e2x.type.toBasetype();
9247
9248 Expression e0 = null;
9249 Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
9250 Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
9251 Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
9252
9253 AssignExp ae = cast(AssignExp)exp.copy();
9254 ae.e1 = new IndexExp(exp.loc, ea, ek);
9255 ae.e1 = ae.e1.expressionSemantic(sc);
9256 ae.e1 = ae.e1.optimize(WANTvalue);
9257 ae.e2 = ev;
9258 Expression e = ae.op_overload(sc);
9259 if (e)
9260 {
9261 Expression ey = null;
9262 if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
9263 {
9264 ey = ev;
9265 }
9266 else if (!ev.implicitConvTo(ie.type) && sd.ctor)
9267 {
9268 // Look for implicit constructor call
9269 // Rewrite as S().ctor(e2)
9270 ey = new StructLiteralExp(exp.loc, sd, null);
9271 ey = new DotIdExp(exp.loc, ey, Id.ctor);
9272 ey = new CallExp(exp.loc, ey, ev);
9273 ey = ey.trySemantic(sc);
9274 }
9275 if (ey)
9276 {
9277 Expression ex;
9278 ex = new IndexExp(exp.loc, ea, ek);
9279 ex = ex.expressionSemantic(sc);
9280 ex = ex.modifiableLvalue(sc, ex); // allocate new slot
9281 ex = ex.optimize(WANTvalue);
9282
9283 ey = new ConstructExp(exp.loc, ex, ey);
9284 ey = ey.expressionSemantic(sc);
9c7d5e88 9285 if (ey.op == EXP.error)
5fee5ec3
IB
9286 {
9287 result = ey;
9288 return;
9289 }
9290 ex = e;
9291
9292 // https://issues.dlang.org/show_bug.cgi?id=14144
9293 // The whole expression should have the common type
9294 // of opAssign() return and assigned AA entry.
9295 // Even if there's no common type, expression should be typed as void.
9c7d5e88 9296 if (!typeMerge(sc, EXP.question, ex, ey))
5fee5ec3
IB
9297 {
9298 ex = new CastExp(ex.loc, ex, Type.tvoid);
9299 ey = new CastExp(ey.loc, ey, Type.tvoid);
9300 }
9301 e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
9302 }
9303 e = Expression.combine(e0, e);
9304 e = e.expressionSemantic(sc);
9305 result = e;
9306 return;
9307 }
9308 }
9309 else
9310 {
9311 Expression e = exp.op_overload(sc);
9312 if (e)
9313 {
9314 result = e;
9315 return;
9316 }
9317 }
9318 }
9319 else
9c7d5e88 9320 assert(exp.op == EXP.blit);
5fee5ec3 9321
0fb57034
IB
9322 if (e2x.checkValue())
9323 return setError();
9324
5fee5ec3
IB
9325 exp.e1 = e1x;
9326 exp.e2 = e2x;
9327 }
9328 else if (t1.ty == Tclass)
9329 {
9330 // Disallow assignment operator overloads for same type
9c7d5e88 9331 if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
5fee5ec3
IB
9332 {
9333 Expression e = exp.op_overload(sc);
9334 if (e)
9335 {
9336 result = e;
9337 return;
9338 }
9339 }
0fb57034
IB
9340 if (exp.e2.checkValue())
9341 return setError();
5fee5ec3
IB
9342 }
9343 else if (t1.ty == Tsarray)
9344 {
9345 // SliceExp cannot have static array type without context inference.
9c7d5e88 9346 assert(exp.e1.op != EXP.slice);
5fee5ec3
IB
9347 Expression e1x = exp.e1;
9348 Expression e2x = exp.e2;
9349
9350 if (e2x.implicitConvTo(e1x.type))
9351 {
9c7d5e88 9352 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()))
5fee5ec3
IB
9353 {
9354 if (e1x.checkPostblit(sc, t1))
9355 return setError();
9356 }
9357
9358 // e2 matches to t1 because of the implicit length match, so
9359 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9360 {
9361 // convert e1 to e1[]
9362 // e.g. e1[] = a[] + b[];
9363 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9364 sle.arrayop = true;
9365 e1x = sle.expressionSemantic(sc);
9366 }
9367 else
9368 {
9369 // convert e2 to t1 later
9370 // e.g. e1 = [1, 2, 3];
9371 }
9372 }
9373 else
9374 {
9375 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9376 {
9377 uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9378 uinteger_t dim2 = dim1;
9379 if (auto ale = e2x.isArrayLiteralExp())
9380 {
9381 dim2 = ale.elements ? ale.elements.dim : 0;
9382 }
9383 else if (auto se = e2x.isSliceExp())
9384 {
9385 Type tx = toStaticArrayType(se);
9386 if (tx)
9387 dim2 = (cast(TypeSArray)tx).dim.toInteger();
9388 }
9389 if (dim1 != dim2)
9390 {
9391 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9392 return setError();
9393 }
9394 }
9395
9396 // May be block or element-wise assignment, so
9397 // convert e1 to e1[]
9c7d5e88 9398 if (exp.op != EXP.assign)
5fee5ec3
IB
9399 {
9400 // If multidimensional static array, treat as one large array
9401 //
9402 // Find the appropriate array type depending on the assignment, e.g.
9403 // int[3] = int => int[3]
9404 // int[3][2] = int => int[6]
9405 // int[3][2] = int[] => int[3][2]
9406 // int[3][2][4] + int => int[24]
9407 // int[3][2][4] + int[] => int[3][8]
9408 ulong dim = t1.isTypeSArray().dim.toUInteger();
9409 auto type = t1.nextOf();
9410
9411 for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9412 {
9413 import core.checkedint : mulu;
9414
9415 // Accumulate skipped dimensions
9416 bool overflow = false;
9417 dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9418 if (overflow || dim >= uint.max)
9419 {
9420 // dym exceeds maximum array size
9421 exp.error("static array `%s` size overflowed to %llu",
9422 e1x.type.toChars(), cast(ulong) dim);
9423 return setError();
9424 }
9425
9426 // Move to the element type
9427 type = tsa.nextOf().toBasetype();
9428
9429 // Rewrite ex1 as a static array if a matching type was found
9430 if (e2x.implicitConvTo(type) > MATCH.nomatch)
9431 {
9432 e1x.type = type.sarrayOf(dim);
9433 break;
9434 }
9435 }
9436 }
9437 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9438 sle.arrayop = true;
9439 e1x = sle.expressionSemantic(sc);
9440 }
9c7d5e88 9441 if (e1x.op == EXP.error)
5fee5ec3 9442 return setResult(e1x);
9c7d5e88 9443 if (e2x.op == EXP.error)
5fee5ec3
IB
9444 return setResult(e2x);
9445
9446 exp.e1 = e1x;
9447 exp.e2 = e2x;
9448 t1 = e1x.type.toBasetype();
9449 }
9450 /* Check the mutability of e1.
9451 */
9452 if (auto ale = exp.e1.isArrayLengthExp())
9453 {
9454 // e1 is not an lvalue, but we let code generator handle it
9455
9456 auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9c7d5e88 9457 if (ale1x.op == EXP.error)
5fee5ec3
IB
9458 return setResult(ale1x);
9459 ale.e1 = ale1x;
9460
9461 Type tn = ale.e1.type.toBasetype().nextOf();
9462 checkDefCtor(ale.loc, tn);
9463
9464 Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9465 if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9466 return setError();
9467
9468 exp.e2 = exp.e2.expressionSemantic(sc);
9469 auto lc = lastComma(exp.e2);
9470 lc = lc.optimize(WANTvalue);
9471 // use slice expression when arr.length = 0 to avoid runtime call
9c7d5e88 9472 if(lc.op == EXP.int64 && lc.toInteger() == 0)
5fee5ec3
IB
9473 {
9474 Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
9475 Expression as = new AssignExp(ale.loc, ale.e1, se);
9476 as = as.expressionSemantic(sc);
9477 auto res = Expression.combine(as, exp.e2);
9478 res.type = ale.type;
9479 return setResult(res);
9480 }
9481
9482 // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9483 Expression id = new IdentifierExp(ale.loc, Id.empty);
9484 id = new DotIdExp(ale.loc, id, Id.object);
9485 auto tiargs = new Objects();
9486 tiargs.push(ale.e1.type);
9487 id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9488 id = new DotIdExp(ale.loc, id, hook);
9489 id = id.expressionSemantic(sc);
9490
9491 auto arguments = new Expressions();
9492 arguments.reserve(5);
9493 if (global.params.tracegc)
9494 {
9495 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9496 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9497 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9498 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9499 }
9500 arguments.push(ale.e1);
9501 arguments.push(exp.e2);
9502
9503 Expression ce = new CallExp(ale.loc, id, arguments);
9504 auto res = ce.expressionSemantic(sc);
9505 // if (global.params.verbose)
9506 // message("lowered %s =>\n %s", exp.toChars(), res.toChars());
9507 return setResult(res);
9508 }
9509 else if (auto se = exp.e1.isSliceExp())
9510 {
9511 Type tn = se.type.nextOf();
9512 const fun = sc.func;
9c7d5e88 9513 if (exp.op == EXP.assign && !tn.isMutable() &&
5fee5ec3
IB
9514 // allow modifiation in module ctor, see
9515 // https://issues.dlang.org/show_bug.cgi?id=9884
9516 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9517 {
9518 exp.error("slice `%s` is not mutable", se.toChars());
9519 return setError();
9520 }
9521
9c7d5e88 9522 if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
5fee5ec3
IB
9523 {
9524 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9525 exp.e1.toChars(), tn.baseElemOf().toChars());
9526 result = ErrorExp.get();
9527 return;
9528 }
9529
9530 // For conditional operator, both branches need conversion.
9c7d5e88 9531 while (se.e1.op == EXP.slice)
5fee5ec3 9532 se = cast(SliceExp)se.e1;
9c7d5e88 9533 if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray)
5fee5ec3
IB
9534 {
9535 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9c7d5e88 9536 if (se.e1.op == EXP.error)
5fee5ec3
IB
9537 return setResult(se.e1);
9538 }
9539 }
9540 else
9541 {
9c7d5e88 9542 if (t1.ty == Tsarray && exp.op == EXP.assign)
5fee5ec3
IB
9543 {
9544 Type tn = exp.e1.type.nextOf();
9545 if (tn && !tn.baseElemOf().isAssignable())
9546 {
9547 exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9548 exp.e1.toChars(), tn.baseElemOf().toChars());
9549 result = ErrorExp.get();
9550 return;
9551 }
9552 }
9553
9554 Expression e1x = exp.e1;
9555
9556 // Try to do a decent error message with the expression
9557 // before it gets constant folded
9c7d5e88 9558 if (exp.op == EXP.assign)
5fee5ec3
IB
9559 e1x = e1x.modifiableLvalue(sc, e1old);
9560
9561 e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
9562
9c7d5e88 9563 if (e1x.op == EXP.error)
5fee5ec3
IB
9564 {
9565 result = e1x;
9566 return;
9567 }
9568 exp.e1 = e1x;
9569 }
9570
9571 /* Tweak e2 based on the type of e1.
9572 */
9573 Expression e2x = exp.e2;
9574 Type t2 = e2x.type.toBasetype();
9575
9576 // If it is a array, get the element type. Note that it may be
9577 // multi-dimensional.
9578 Type telem = t1;
9579 while (telem.ty == Tarray)
9580 telem = telem.nextOf();
9581
9c7d5e88
IB
9582 if (exp.e1.op == EXP.slice && t1.nextOf() &&
9583 (telem.ty != Tvoid || e2x.op == EXP.null_) &&
5fee5ec3
IB
9584 e2x.implicitConvTo(t1.nextOf()))
9585 {
9586 // Check for block assignment. If it is of type void[], void[][], etc,
9587 // '= null' is the only allowable block assignment (Bug 7493)
9588 exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is
9589 e2x = e2x.implicitCastTo(sc, t1.nextOf());
9c7d5e88 9590 if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
5fee5ec3
IB
9591 return setError();
9592 }
9c7d5e88 9593 else if (exp.e1.op == EXP.slice &&
5fee5ec3
IB
9594 (t2.ty == Tarray || t2.ty == Tsarray) &&
9595 t2.nextOf().implicitConvTo(t1.nextOf()))
9596 {
9597 // Check element-wise assignment.
9598
9599 /* If assigned elements number is known at compile time,
9600 * check the mismatch.
9601 */
9602 SliceExp se1 = cast(SliceExp)exp.e1;
9603 TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9604 TypeSArray tsa2 = null;
9605 if (auto ale = e2x.isArrayLiteralExp())
9606 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
9607 else if (auto se = e2x.isSliceExp())
9608 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9609 else
9610 tsa2 = t2.isTypeSArray();
9611 if (tsa1 && tsa2)
9612 {
9613 uinteger_t dim1 = tsa1.dim.toInteger();
9614 uinteger_t dim2 = tsa2.dim.toInteger();
9615 if (dim1 != dim2)
9616 {
9617 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9618 return setError();
9619 }
9620 }
9621
9c7d5e88
IB
9622 if (exp.op != EXP.blit &&
9623 (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9624 e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9625 e2x.op != EXP.slice && e2x.isLvalue()))
5fee5ec3
IB
9626 {
9627 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9628 return setError();
9629 }
9630
9c7d5e88
IB
9631 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9632 e2x.op != EXP.slice && e2x.op != EXP.assign &&
9633 e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
9634 !(e2x.op == EXP.add || e2x.op == EXP.min ||
9635 e2x.op == EXP.mul || e2x.op == EXP.div ||
9636 e2x.op == EXP.mod || e2x.op == EXP.xor ||
9637 e2x.op == EXP.and || e2x.op == EXP.or ||
9638 e2x.op == EXP.pow ||
9639 e2x.op == EXP.tilde || e2x.op == EXP.negate))
5fee5ec3
IB
9640 {
9641 const(char)* e1str = exp.e1.toChars();
9642 const(char)* e2str = e2x.toChars();
9643 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9644 }
9645
9646 Type t2n = t2.nextOf();
9647 Type t1n = t1.nextOf();
9648 int offset;
9649 if (t2n.equivalent(t1n) ||
9650 t1n.isBaseOf(t2n, &offset) && offset == 0)
9651 {
9652 /* Allow copy of distinct qualifier elements.
9653 * eg.
9654 * char[] dst; const(char)[] src;
9655 * dst[] = src;
9656 *
9657 * class C {} class D : C {}
9658 * C[2] ca; D[] da;
9659 * ca[] = da;
9660 */
9661 if (isArrayOpValid(e2x))
9662 {
9663 // Don't add CastExp to keep AST for array operations
9664 e2x = e2x.copy();
9665 e2x.type = exp.e1.type.constOf();
9666 }
9667 else
9668 e2x = e2x.castTo(sc, exp.e1.type.constOf());
9669 }
9670 else
9671 {
9672 /* https://issues.dlang.org/show_bug.cgi?id=15778
9673 * A string literal has an array type of immutable
9674 * elements by default, and normally it cannot be convertible to
9675 * array type of mutable elements. But for element-wise assignment,
9676 * elements need to be const at best. So we should give a chance
9677 * to change code unit size for polysemous string literal.
9678 */
9c7d5e88 9679 if (e2x.op == EXP.string_)
5fee5ec3
IB
9680 e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9681 else
9682 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9683 }
9684 if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9685 {
9686 if (!sc.intypeof && sc.func && !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
9687 {
9688 exp.error("cannot copy `void[]` to `void[]` in `@safe` code");
9689 return setError();
9690 }
9691 }
9692 }
9693 else
9694 {
9c7d5e88 9695 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
5fee5ec3 9696 t1.ty == Tarray && t2.ty == Tsarray &&
9c7d5e88 9697 e2x.op != EXP.slice &&
5fee5ec3
IB
9698 t2.implicitConvTo(t1))
9699 {
9700 // Disallow ar[] = sa (Converted to ar[] = sa[])
9701 // Disallow da = sa (Converted to da = sa[])
9702 const(char)* e1str = exp.e1.toChars();
9703 const(char)* e2str = e2x.toChars();
9c7d5e88 9704 const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
5fee5ec3
IB
9705 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9706 }
9c7d5e88 9707 if (exp.op == EXP.blit)
5fee5ec3
IB
9708 e2x = e2x.castTo(sc, exp.e1.type);
9709 else
9710 {
9711 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9712
9713 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9714
9715 // If the implicit cast has failed and the assign expression is
9716 // the initialization of a struct member field
9c7d5e88 9717 if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
5fee5ec3
IB
9718 {
9719 scope sd = (cast(TypeStruct)t1).sym;
9720 Dsymbol opAssign = search_function(sd, Id.assign);
9721
9722 // and the struct defines an opAssign
9723 if (opAssign)
9724 {
9725 // offer more information about the cause of the problem
9726 errorSupplemental(exp.loc,
9727 "`%s` is the first assignment of `%s` therefore it represents its initialization",
9728 exp.toChars(), exp.e1.toChars());
9729 errorSupplemental(exp.loc,
9730 "`opAssign` methods are not used for initialization, but for subsequent assignments");
9731 }
9732 }
9733 }
9734 }
9c7d5e88 9735 if (e2x.op == EXP.error)
5fee5ec3
IB
9736 {
9737 result = e2x;
9738 return;
9739 }
9740 exp.e2 = e2x;
9741 t2 = exp.e2.type.toBasetype();
9742
9743 /* Look for array operations
9744 */
9745 if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9746 {
9747 // Look for valid array operations
9748 if (exp.memset != MemorySet.blockAssign &&
9c7d5e88 9749 exp.e1.op == EXP.slice &&
5fee5ec3
IB
9750 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9751 {
9752 exp.type = exp.e1.type;
9c7d5e88 9753 if (exp.op == EXP.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
5fee5ec3
IB
9754 // tweak mutability of e1 element
9755 exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9756 result = arrayOp(exp, sc);
9757 return;
9758 }
9759
9760 // Drop invalid array operations in e2
9761 // d = a[] + b[], d = (a[] + b[])[0..2], etc
9c7d5e88 9762 if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == EXP.assign))
5fee5ec3
IB
9763 return setError();
9764
9765 // Remains valid array assignments
9766 // d = d[], d = [1,2,3], etc
9767 }
9768
9769 /* Don't allow assignment to classes that were allocated on the stack with:
9770 * scope Class c = new Class();
9771 */
9c7d5e88 9772 if (exp.e1.op == EXP.variable && exp.op == EXP.assign)
5fee5ec3
IB
9773 {
9774 VarExp ve = cast(VarExp)exp.e1;
9775 VarDeclaration vd = ve.var.isVarDeclaration();
9776 if (vd && (vd.onstack || vd.mynew))
9777 {
9778 assert(t1.ty == Tclass);
9779 exp.error("cannot rebind scope variables");
9780 }
9781 }
9782
9c7d5e88 9783 if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
5fee5ec3
IB
9784 {
9785 exp.error("cannot modify compiler-generated variable `__ctfe`");
9786 }
9787
9788 exp.type = exp.e1.type;
9789 assert(exp.type);
9c7d5e88 9790 auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
0fb57034
IB
9791 Expression tmp;
9792 /* https://issues.dlang.org/show_bug.cgi?id=22366
9793 *
9794 * `reorderSettingAAElem` creates a tree of comma expressions, however,
9795 * `checkAssignExp` expects only AssignExps.
9796 */
9797 checkAssignEscape(sc, Expression.extractLast(res, tmp), false);
9c7d5e88
IB
9798
9799 if (auto ae = res.isConstructExp())
9800 {
9801 Type t1b = ae.e1.type.toBasetype();
9802 if (t1b.ty != Tsarray && t1b.ty != Tarray)
9803 return setResult(res);
9804
9805 /* Do not lower Rvalues and references, as they need to be moved,
9806 * not copied.
9807 * Skip the lowering when the RHS is an array literal, as e2ir
9808 * already handles such cases more elegantly.
9809 */
9810 const isArrayCtor =
9811 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
9812 ae.e2.isLvalue &&
9813 !(ae.e1.isVarExp &&
9814 ae.e1.isVarExp.var.isVarDeclaration.isReference) &&
9815 (ae.e2.isVarExp ||
9816 ae.e2.isSliceExp ||
9817 (ae.e2.type.ty == Tsarray && !ae.e2.isArrayLiteralExp)) &&
9818 ae.e1.type.nextOf &&
9819 ae.e2.type.nextOf &&
9820 ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
9821
9822 const isArraySetCtor =
9823 (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
9824 ae.e2.isLvalue &&
9825 (ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
9826 ae.e1.type.nextOf &&
9827 ae.e1.type.nextOf.equivalent(ae.e2.type);
9828
9829 if (isArrayCtor || isArraySetCtor)
9830 {
9831 const ts = t1b.nextOf().baseElemOf().isTypeStruct();
9832 if (!ts || (!ts.sym.postblit && !ts.sym.dtor))
9833 return setResult(res);
9834
9835 auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
9836 const other = isArrayCtor ? "other array" : "value";
9837 if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
9838 return setError();
9839
9840 // Lower to object._d_array{,set}ctor(e1, e2)
9841 Expression id = new IdentifierExp(exp.loc, Id.empty);
9842 id = new DotIdExp(exp.loc, id, Id.object);
9843 id = new DotIdExp(exp.loc, id, func);
9844 id = id.expressionSemantic(sc);
9845
9846 auto arguments = new Expressions();
9847 arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
9848 if (isArrayCtor)
9849 {
9850 arguments.push(new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf).expressionSemantic(sc));
9851 Expression ce = new CallExp(exp.loc, id, arguments);
9852 res = ce.expressionSemantic(sc);
9853 }
9854 else
9855 {
9856 Expression e0;
9857 // If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access
9858 if (!ae.e2.isVarExp)
9859 {
9860 auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
9861 e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
9862 arguments.push(new VarExp(vd.loc, vd).expressionSemantic(sc));
9863 }
9864 else
9865 arguments.push(ae.e2);
9866
9867 Expression ce = new CallExp(exp.loc, id, arguments);
9868 res = Expression.combine(e0, ce).expressionSemantic(sc);
9869 }
9870
9871 if (global.params.verbose)
9872 message("lowered %s =>\n %s", exp.toChars(), res.toChars());
9873 }
9874 }
9875
5fee5ec3
IB
9876 return setResult(res);
9877 }
9878
9879 override void visit(PowAssignExp exp)
9880 {
9881 if (exp.type)
9882 {
9883 result = exp;
9884 return;
9885 }
9886
9887 Expression e = exp.op_overload(sc);
9888 if (e)
9889 {
9890 result = e;
9891 return;
9892 }
9893
9894 if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
9895 return setError();
9896
9897 assert(exp.e1.type && exp.e2.type);
9c7d5e88 9898 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5fee5ec3
IB
9899 {
9900 if (checkNonAssignmentArrayOp(exp.e1))
9901 return setError();
9902
9903 // T[] ^^= ...
9904 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
9905 {
9906 // T[] ^^= T
9907 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
9908 }
9909 else if (Expression ex = typeCombine(exp, sc))
9910 {
9911 result = ex;
9912 return;
9913 }
9914
9915 // Check element types are arithmetic
9916 Type tb1 = exp.e1.type.nextOf().toBasetype();
9917 Type tb2 = exp.e2.type.toBasetype();
9918 if (tb2.ty == Tarray || tb2.ty == Tsarray)
9919 tb2 = tb2.nextOf().toBasetype();
9920 if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
9921 {
9922 exp.type = exp.e1.type;
9923 result = arrayOp(exp, sc);
9924 return;
9925 }
9926 }
9927 else
9928 {
9929 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9930 }
9931
9932 if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
9933 {
9934 Expression e0 = null;
9935 e = exp.reorderSettingAAElem(sc);
9936 e = Expression.extractLast(e, e0);
9937 assert(e == exp);
9938
9c7d5e88 9939 if (exp.e1.op == EXP.variable)
5fee5ec3
IB
9940 {
9941 // Rewrite: e1 = e1 ^^ e2
9942 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
9943 e = new AssignExp(exp.loc, exp.e1, e);
9944 }
9945 else
9946 {
9947 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
9948 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
9949 auto de = new DeclarationExp(exp.e1.loc, v);
9950 auto ve = new VarExp(exp.e1.loc, v);
9951 e = new PowExp(exp.loc, ve, exp.e2);
9952 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
9953 e = new CommaExp(exp.loc, de, e);
9954 }
9955 e = Expression.combine(e0, e);
9956 e = e.expressionSemantic(sc);
9957 result = e;
9958 return;
9959 }
9960 result = exp.incompatibleTypes();
9961 }
9962
9963 override void visit(CatAssignExp exp)
9964 {
9965 if (exp.type)
9966 {
9967 result = exp;
9968 return;
9969 }
9970
9971 //printf("CatAssignExp::semantic() %s\n", exp.toChars());
9972 Expression e = exp.op_overload(sc);
9973 if (e)
9974 {
9975 result = e;
9976 return;
9977 }
9978
9c7d5e88 9979 if (exp.e1.op == EXP.slice)
5fee5ec3
IB
9980 {
9981 SliceExp se = cast(SliceExp)exp.e1;
9982 if (se.e1.type.toBasetype().ty == Tsarray)
9983 {
9984 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
9985 return setError();
9986 }
9987 }
9988
9989 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
9c7d5e88 9990 if (exp.e1.op == EXP.error)
5fee5ec3
IB
9991 {
9992 result = exp.e1;
9993 return;
9994 }
9c7d5e88 9995 if (exp.e2.op == EXP.error)
5fee5ec3
IB
9996 {
9997 result = exp.e2;
9998 return;
9999 }
10000
10001 if (checkNonAssignmentArrayOp(exp.e2))
10002 return setError();
10003
10004 Type tb1 = exp.e1.type.toBasetype();
10005 Type tb1next = tb1.nextOf();
10006 Type tb2 = exp.e2.type.toBasetype();
10007
10008 /* Possibilities:
9c7d5e88
IB
10009 * EXP.concatenateAssign: appending T[] to T[]
10010 * EXP.concatenateElemAssign: appending T to T[]
10011 * EXP.concatenateDcharAssign: appending dchar to T[]
5fee5ec3
IB
10012 */
10013 if ((tb1.ty == Tarray) &&
10014 (tb2.ty == Tarray || tb2.ty == Tsarray) &&
10015 (exp.e2.implicitConvTo(exp.e1.type) ||
10016 (tb2.nextOf().implicitConvTo(tb1next) &&
10017 (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
10018 {
9c7d5e88
IB
10019 // EXP.concatenateAssign
10020 assert(exp.op == EXP.concatenateAssign);
5fee5ec3
IB
10021 if (exp.e1.checkPostblit(sc, tb1next))
10022 return setError();
10023
10024 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
10025 }
10026 else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
10027 {
10028 /* https://issues.dlang.org/show_bug.cgi?id=19782
10029 *
10030 * If e2 is implicitly convertible to tb1next, the conversion
10031 * might be done through alias this, in which case, e2 needs to
10032 * be modified accordingly (e2 => e2.aliasthis).
10033 */
10034 if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
10035 goto Laliasthis;
10036 if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
10037 goto Laliasthis;
10038 // Append element
10039 if (exp.e2.checkPostblit(sc, tb2))
10040 return setError();
10041
10042 if (checkNewEscape(sc, exp.e2, false))
10043 return setError();
10044
10045 exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
10046 exp.e2 = doCopyOrMove(sc, exp.e2);
10047 }
10048 else if (tb1.ty == Tarray &&
10049 (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
10050 exp.e2.type.ty != tb1next.ty &&
10051 exp.e2.implicitConvTo(Type.tdchar))
10052 {
10053 // Append dchar to char[] or wchar[]
10054 exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
10055
10056 /* Do not allow appending wchar to char[] because if wchar happens
10057 * to be a surrogate pair, nothing good can result.
10058 */
10059 }
10060 else
10061 {
10062 // Try alias this on first operand
10063 static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
10064 {
10065 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
10066 if (!ad1 || !ad1.aliasthis)
10067 return null;
10068
10069 /* Rewrite (e1 op e2) as:
10070 * (e1.aliasthis op e2)
10071 */
10072 if (isRecursiveAliasThis(exp.att1, exp.e1.type))
10073 return null;
10074 //printf("att %s e1 = %s\n", Token::toChars(e.op), e.e1.type.toChars());
10075 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
10076 BinExp be = cast(BinExp)exp.copy();
10077 be.e1 = e1;
10078 return be.trySemantic(sc);
10079 }
10080
10081 // Try alias this on second operand
10082 static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
10083 {
10084 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
10085 if (!ad2 || !ad2.aliasthis)
10086 return null;
10087 /* Rewrite (e1 op e2) as:
10088 * (e1 op e2.aliasthis)
10089 */
10090 if (isRecursiveAliasThis(exp.att2, exp.e2.type))
10091 return null;
10092 //printf("att %s e2 = %s\n", Token::toChars(e.op), e.e2.type.toChars());
10093 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
10094 BinExp be = cast(BinExp)exp.copy();
10095 be.e2 = e2;
10096 return be.trySemantic(sc);
10097 }
10098
10099 Laliasthis:
10100 result = tryAliasThisForLhs(exp, sc);
10101 if (result)
10102 return;
10103
10104 result = tryAliasThisForRhs(exp, sc);
10105 if (result)
10106 return;
10107
10108 exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
10109 return setError();
10110 }
10111
10112 if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
10113 return setError();
10114
10115 exp.type = exp.e1.type;
10116 auto res = exp.reorderSettingAAElem(sc);
9c7d5e88 10117 if ((exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign) &&
5fee5ec3
IB
10118 global.params.useDIP1000 == FeatureState.enabled)
10119 checkAssignEscape(sc, res, false);
10120 result = res;
10121 }
10122
10123 override void visit(AddExp exp)
10124 {
10125 static if (LOGSEMANTIC)
10126 {
10127 printf("AddExp::semantic('%s')\n", exp.toChars());
10128 }
10129 if (exp.type)
10130 {
10131 result = exp;
10132 return;
10133 }
10134
10135 if (Expression ex = binSemanticProp(exp, sc))
10136 {
10137 result = ex;
10138 return;
10139 }
10140 Expression e = exp.op_overload(sc);
10141 if (e)
10142 {
10143 result = e;
10144 return;
10145 }
10146
0fb57034
IB
10147 /* ImportC: convert arrays to pointers, functions to pointers to functions
10148 */
10149 exp.e1 = exp.e1.arrayFuncConv(sc);
10150 exp.e2 = exp.e2.arrayFuncConv(sc);
10151
5fee5ec3
IB
10152 Type tb1 = exp.e1.type.toBasetype();
10153 Type tb2 = exp.e2.type.toBasetype();
10154
10155 bool err = false;
10156 if (tb1.ty == Tdelegate || tb1.isPtrToFunction())
10157 {
10158 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10159 }
10160 if (tb2.ty == Tdelegate || tb2.isPtrToFunction())
10161 {
10162 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10163 }
10164 if (err)
10165 return setError();
10166
10167 if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
10168 {
10169 result = scaleFactor(exp, sc);
10170 return;
10171 }
10172
10173 if (tb1.ty == Tpointer && tb2.ty == Tpointer)
10174 {
10175 result = exp.incompatibleTypes();
10176 return;
10177 }
10178
10179 if (Expression ex = typeCombine(exp, sc))
10180 {
10181 result = ex;
10182 return;
10183 }
10184
10185 Type tb = exp.type.toBasetype();
10186 if (tb.ty == Tarray || tb.ty == Tsarray)
10187 {
10188 if (!isArrayOpValid(exp))
10189 {
10190 result = arrayOpInvalidError(exp);
10191 return;
10192 }
10193 result = exp;
10194 return;
10195 }
10196
10197 tb1 = exp.e1.type.toBasetype();
10198 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
10199 {
10200 result = exp.incompatibleTypes();
10201 return;
10202 }
10203 if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
10204 {
10205 switch (exp.type.toBasetype().ty)
10206 {
10207 case Tfloat32:
10208 case Timaginary32:
10209 exp.type = Type.tcomplex32;
10210 break;
10211
10212 case Tfloat64:
10213 case Timaginary64:
10214 exp.type = Type.tcomplex64;
10215 break;
10216
10217 case Tfloat80:
10218 case Timaginary80:
10219 exp.type = Type.tcomplex80;
10220 break;
10221
10222 default:
10223 assert(0);
10224 }
10225 }
10226 result = exp;
10227 }
10228
10229 override void visit(MinExp exp)
10230 {
10231 static if (LOGSEMANTIC)
10232 {
10233 printf("MinExp::semantic('%s')\n", exp.toChars());
10234 }
10235 if (exp.type)
10236 {
10237 result = exp;
10238 return;
10239 }
10240
10241 if (Expression ex = binSemanticProp(exp, sc))
10242 {
10243 result = ex;
10244 return;
10245 }
10246 Expression e = exp.op_overload(sc);
10247 if (e)
10248 {
10249 result = e;
10250 return;
10251 }
10252
0fb57034
IB
10253 /* ImportC: convert arrays to pointers, functions to pointers to functions
10254 */
10255 exp.e1 = exp.e1.arrayFuncConv(sc);
10256 exp.e2 = exp.e2.arrayFuncConv(sc);
10257
5fee5ec3
IB
10258 Type t1 = exp.e1.type.toBasetype();
10259 Type t2 = exp.e2.type.toBasetype();
10260
10261 bool err = false;
10262 if (t1.ty == Tdelegate || t1.isPtrToFunction())
10263 {
10264 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10265 }
10266 if (t2.ty == Tdelegate || t2.isPtrToFunction())
10267 {
10268 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10269 }
10270 if (err)
10271 return setError();
10272
10273 if (t1.ty == Tpointer)
10274 {
10275 if (t2.ty == Tpointer)
10276 {
10277 // https://dlang.org/spec/expression.html#add_expressions
10278 // "If both operands are pointers, and the operator is -, the pointers are
10279 // subtracted and the result is divided by the size of the type pointed to
10280 // by the operands. It is an error if the pointers point to different types."
10281 Type p1 = t1.nextOf();
10282 Type p2 = t2.nextOf();
10283
10284 if (!p1.equivalent(p2))
10285 {
10286 // Deprecation to remain for at least a year, after which this should be
10287 // changed to an error
10288 // See https://github.com/dlang/dmd/pull/7332
10289 deprecation(exp.loc,
10290 "cannot subtract pointers to different types: `%s` and `%s`.",
10291 t1.toChars(), t2.toChars());
10292 }
10293
10294 // Need to divide the result by the stride
10295 // Replace (ptr - ptr) with (ptr - ptr) / stride
10296 d_int64 stride;
10297
10298 // make sure pointer types are compatible
10299 if (Expression ex = typeCombine(exp, sc))
10300 {
10301 result = ex;
10302 return;
10303 }
10304
10305 exp.type = Type.tptrdiff_t;
10306 stride = t2.nextOf().size();
10307 if (stride == 0)
10308 {
10309 e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
10310 }
9c7d5e88
IB
10311 else if (stride == cast(d_int64)SIZE_INVALID)
10312 e = ErrorExp.get();
5fee5ec3
IB
10313 else
10314 {
10315 e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
10316 e.type = Type.tptrdiff_t;
10317 }
10318 }
10319 else if (t2.isintegral())
10320 e = scaleFactor(exp, sc);
10321 else
10322 {
10323 exp.error("can't subtract `%s` from pointer", t2.toChars());
10324 e = ErrorExp.get();
10325 }
10326 result = e;
10327 return;
10328 }
10329 if (t2.ty == Tpointer)
10330 {
10331 exp.type = exp.e2.type;
10332 exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
10333 return setError();
10334 }
10335
10336 if (Expression ex = typeCombine(exp, sc))
10337 {
10338 result = ex;
10339 return;
10340 }
10341
10342 Type tb = exp.type.toBasetype();
10343 if (tb.ty == Tarray || tb.ty == Tsarray)
10344 {
10345 if (!isArrayOpValid(exp))
10346 {
10347 result = arrayOpInvalidError(exp);
10348 return;
10349 }
10350 result = exp;
10351 return;
10352 }
10353
10354 t1 = exp.e1.type.toBasetype();
10355 t2 = exp.e2.type.toBasetype();
10356 if (!target.isVectorOpSupported(t1, exp.op, t2))
10357 {
10358 result = exp.incompatibleTypes();
10359 return;
10360 }
10361 if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
10362 {
10363 switch (exp.type.ty)
10364 {
10365 case Tfloat32:
10366 case Timaginary32:
10367 exp.type = Type.tcomplex32;
10368 break;
10369
10370 case Tfloat64:
10371 case Timaginary64:
10372 exp.type = Type.tcomplex64;
10373 break;
10374
10375 case Tfloat80:
10376 case Timaginary80:
10377 exp.type = Type.tcomplex80;
10378 break;
10379
10380 default:
10381 assert(0);
10382 }
10383 }
10384 result = exp;
10385 return;
10386 }
10387
10388 override void visit(CatExp exp)
10389 {
10390 // https://dlang.org/spec/expression.html#cat_expressions
10391 //printf("CatExp.semantic() %s\n", toChars());
10392 if (exp.type)
10393 {
10394 result = exp;
10395 return;
10396 }
10397
10398 if (Expression ex = binSemanticProp(exp, sc))
10399 {
10400 result = ex;
10401 return;
10402 }
10403 Expression e = exp.op_overload(sc);
10404 if (e)
10405 {
10406 result = e;
10407 return;
10408 }
10409
10410 Type tb1 = exp.e1.type.toBasetype();
10411 Type tb2 = exp.e2.type.toBasetype();
10412
10413 auto f1 = checkNonAssignmentArrayOp(exp.e1);
10414 auto f2 = checkNonAssignmentArrayOp(exp.e2);
10415 if (f1 || f2)
10416 return setError();
10417
10418 Type tb1next = tb1.nextOf();
10419 Type tb2next = tb2.nextOf();
10420
10421 // Check for: array ~ array
9c7d5e88 10422 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)))
5fee5ec3
IB
10423 {
10424 /* https://issues.dlang.org/show_bug.cgi?id=9248
10425 * Here to avoid the case of:
10426 * void*[] a = [cast(void*)1];
10427 * void*[] b = [cast(void*)2];
10428 * a ~ b;
10429 * becoming:
10430 * a ~ [cast(void*)b];
10431 */
10432
10433 /* https://issues.dlang.org/show_bug.cgi?id=14682
10434 * Also to avoid the case of:
10435 * int[][] a;
10436 * a ~ [];
10437 * becoming:
10438 * a ~ cast(int[])[];
10439 */
10440 goto Lpeer;
10441 }
10442
10443 // Check for: array ~ element
10444 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10445 {
9c7d5e88 10446 if (exp.e1.op == EXP.arrayLiteral)
5fee5ec3
IB
10447 {
10448 exp.e2 = doCopyOrMove(sc, exp.e2);
10449 // https://issues.dlang.org/show_bug.cgi?id=14686
10450 // Postblit call appears in AST, and this is
10451 // finally translated to an ArrayLiteralExp in below optimize().
10452 }
9c7d5e88 10453 else if (exp.e1.op == EXP.string_)
5fee5ec3
IB
10454 {
10455 // No postblit call exists on character (integer) value.
10456 }
10457 else
10458 {
10459 if (exp.e2.checkPostblit(sc, tb2))
10460 return setError();
10461 // Postblit call will be done in runtime helper function
10462 }
10463
9c7d5e88 10464 if (exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
5fee5ec3
IB
10465 {
10466 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10467 exp.type = tb2.arrayOf();
10468 goto L2elem;
10469 }
10470 if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10471 {
10472 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10473 exp.type = tb1next.arrayOf();
10474 L2elem:
10475 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10476 {
10477 // Make e2 into [e2]
10478 exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10479 }
10480 else if (checkNewEscape(sc, exp.e2, false))
10481 return setError();
10482 result = exp.optimize(WANTvalue);
10483 return;
10484 }
10485 }
10486 // Check for: element ~ array
10487 if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10488 {
9c7d5e88 10489 if (exp.e2.op == EXP.arrayLiteral)
5fee5ec3
IB
10490 {
10491 exp.e1 = doCopyOrMove(sc, exp.e1);
10492 }
9c7d5e88 10493 else if (exp.e2.op == EXP.string_)
5fee5ec3
IB
10494 {
10495 }
10496 else
10497 {
10498 if (exp.e1.checkPostblit(sc, tb1))
10499 return setError();
10500 }
10501
9c7d5e88 10502 if (exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
5fee5ec3
IB
10503 {
10504 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10505 exp.type = tb1.arrayOf();
10506 goto L1elem;
10507 }
10508 if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10509 {
10510 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10511 exp.type = tb2next.arrayOf();
10512 L1elem:
10513 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10514 {
10515 // Make e1 into [e1]
10516 exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10517 }
10518 else if (checkNewEscape(sc, exp.e1, false))
10519 return setError();
10520 result = exp.optimize(WANTvalue);
10521 return;
10522 }
10523 }
10524
10525 Lpeer:
10526 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10527 {
10528 Type t1 = tb1next.mutableOf().constOf().arrayOf();
10529 Type t2 = tb2next.mutableOf().constOf().arrayOf();
9c7d5e88 10530 if (exp.e1.op == EXP.string_ && !(cast(StringExp)exp.e1).committed)
5fee5ec3
IB
10531 exp.e1.type = t1;
10532 else
10533 exp.e1 = exp.e1.castTo(sc, t1);
9c7d5e88 10534 if (exp.e2.op == EXP.string_ && !(cast(StringExp)exp.e2).committed)
5fee5ec3
IB
10535 exp.e2.type = t2;
10536 else
10537 exp.e2 = exp.e2.castTo(sc, t2);
10538 }
10539
10540 if (Expression ex = typeCombine(exp, sc))
10541 {
10542 result = ex;
10543 return;
10544 }
10545 exp.type = exp.type.toHeadMutable();
10546
10547 Type tb = exp.type.toBasetype();
10548 if (tb.ty == Tsarray)
10549 exp.type = tb.nextOf().arrayOf();
10550 if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10551 {
10552 exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10553 }
10554 if (Type tbn = tb.nextOf())
10555 {
10556 if (exp.checkPostblit(sc, tbn))
10557 return setError();
10558 }
10559 Type t1 = exp.e1.type.toBasetype();
10560 Type t2 = exp.e2.type.toBasetype();
10561 if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10562 (t2.ty == Tarray || t2.ty == Tsarray))
10563 {
10564 // Normalize to ArrayLiteralExp or StringExp as far as possible
10565 e = exp.optimize(WANTvalue);
10566 }
10567 else
10568 {
10569 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10570 result = exp.incompatibleTypes();
10571 return;
10572 }
10573
10574 result = e;
10575 }
10576
10577 override void visit(MulExp exp)
10578 {
10579 version (none)
10580 {
10581 printf("MulExp::semantic() %s\n", exp.toChars());
10582 }
10583 if (exp.type)
10584 {
10585 result = exp;
10586 return;
10587 }
10588
10589 if (Expression ex = binSemanticProp(exp, sc))
10590 {
10591 result = ex;
10592 return;
10593 }
10594 Expression e = exp.op_overload(sc);
10595 if (e)
10596 {
10597 result = e;
10598 return;
10599 }
10600
10601 if (Expression ex = typeCombine(exp, sc))
10602 {
10603 result = ex;
10604 return;
10605 }
10606
10607 Type tb = exp.type.toBasetype();
10608 if (tb.ty == Tarray || tb.ty == Tsarray)
10609 {
10610 if (!isArrayOpValid(exp))
10611 {
10612 result = arrayOpInvalidError(exp);
10613 return;
10614 }
10615 result = exp;
10616 return;
10617 }
10618
10619 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10620 return setError();
10621
10622 if (exp.type.isfloating())
10623 {
10624 Type t1 = exp.e1.type;
10625 Type t2 = exp.e2.type;
10626
10627 if (t1.isreal())
10628 {
10629 exp.type = t2;
10630 }
10631 else if (t2.isreal())
10632 {
10633 exp.type = t1;
10634 }
10635 else if (t1.isimaginary())
10636 {
10637 if (t2.isimaginary())
10638 {
10639 switch (t1.toBasetype().ty)
10640 {
10641 case Timaginary32:
10642 exp.type = Type.tfloat32;
10643 break;
10644
10645 case Timaginary64:
10646 exp.type = Type.tfloat64;
10647 break;
10648
10649 case Timaginary80:
10650 exp.type = Type.tfloat80;
10651 break;
10652
10653 default:
10654 assert(0);
10655 }
10656
10657 // iy * iv = -yv
10658 exp.e1.type = exp.type;
10659 exp.e2.type = exp.type;
10660 e = new NegExp(exp.loc, exp);
10661 e = e.expressionSemantic(sc);
10662 result = e;
10663 return;
10664 }
10665 else
10666 exp.type = t2; // t2 is complex
10667 }
10668 else if (t2.isimaginary())
10669 {
10670 exp.type = t1; // t1 is complex
10671 }
10672 }
10673 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10674 {
10675 result = exp.incompatibleTypes();
10676 return;
10677 }
10678 result = exp;
10679 }
10680
10681 override void visit(DivExp exp)
10682 {
10683 if (exp.type)
10684 {
10685 result = exp;
10686 return;
10687 }
10688
10689 if (Expression ex = binSemanticProp(exp, sc))
10690 {
10691 result = ex;
10692 return;
10693 }
10694 Expression e = exp.op_overload(sc);
10695 if (e)
10696 {
10697 result = e;
10698 return;
10699 }
10700
10701 if (Expression ex = typeCombine(exp, sc))
10702 {
10703 result = ex;
10704 return;
10705 }
10706
10707 Type tb = exp.type.toBasetype();
10708 if (tb.ty == Tarray || tb.ty == Tsarray)
10709 {
10710 if (!isArrayOpValid(exp))
10711 {
10712 result = arrayOpInvalidError(exp);
10713 return;
10714 }
10715 result = exp;
10716 return;
10717 }
10718
10719 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10720 return setError();
10721
10722 if (exp.type.isfloating())
10723 {
10724 Type t1 = exp.e1.type;
10725 Type t2 = exp.e2.type;
10726
10727 if (t1.isreal())
10728 {
10729 exp.type = t2;
10730 if (t2.isimaginary())
10731 {
10732 // x/iv = i(-x/v)
10733 exp.e2.type = t1;
10734 e = new NegExp(exp.loc, exp);
10735 e = e.expressionSemantic(sc);
10736 result = e;
10737 return;
10738 }
10739 }
10740 else if (t2.isreal())
10741 {
10742 exp.type = t1;
10743 }
10744 else if (t1.isimaginary())
10745 {
10746 if (t2.isimaginary())
10747 {
10748 switch (t1.toBasetype().ty)
10749 {
10750 case Timaginary32:
10751 exp.type = Type.tfloat32;
10752 break;
10753
10754 case Timaginary64:
10755 exp.type = Type.tfloat64;
10756 break;
10757
10758 case Timaginary80:
10759 exp.type = Type.tfloat80;
10760 break;
10761
10762 default:
10763 assert(0);
10764 }
10765 }
10766 else
10767 exp.type = t2; // t2 is complex
10768 }
10769 else if (t2.isimaginary())
10770 {
10771 exp.type = t1; // t1 is complex
10772 }
10773 }
10774 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10775 {
10776 result = exp.incompatibleTypes();
10777 return;
10778 }
10779 result = exp;
10780 }
10781
10782 override void visit(ModExp exp)
10783 {
10784 if (exp.type)
10785 {
10786 result = exp;
10787 return;
10788 }
10789
10790 if (Expression ex = binSemanticProp(exp, sc))
10791 {
10792 result = ex;
10793 return;
10794 }
10795 Expression e = exp.op_overload(sc);
10796 if (e)
10797 {
10798 result = e;
10799 return;
10800 }
10801
10802 if (Expression ex = typeCombine(exp, sc))
10803 {
10804 result = ex;
10805 return;
10806 }
10807
10808 Type tb = exp.type.toBasetype();
10809 if (tb.ty == Tarray || tb.ty == Tsarray)
10810 {
10811 if (!isArrayOpValid(exp))
10812 {
10813 result = arrayOpInvalidError(exp);
10814 return;
10815 }
10816 result = exp;
10817 return;
10818 }
10819 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10820 {
10821 result = exp.incompatibleTypes();
10822 return;
10823 }
10824
10825 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10826 return setError();
10827
10828 if (exp.type.isfloating())
10829 {
10830 exp.type = exp.e1.type;
10831 if (exp.e2.type.iscomplex())
10832 {
10833 exp.error("cannot perform modulo complex arithmetic");
10834 return setError();
10835 }
10836 }
10837 result = exp;
10838 }
10839
10840 override void visit(PowExp exp)
10841 {
10842 if (exp.type)
10843 {
10844 result = exp;
10845 return;
10846 }
10847
10848 //printf("PowExp::semantic() %s\n", toChars());
10849 if (Expression ex = binSemanticProp(exp, sc))
10850 {
10851 result = ex;
10852 return;
10853 }
10854 Expression e = exp.op_overload(sc);
10855 if (e)
10856 {
10857 result = e;
10858 return;
10859 }
10860
10861 if (Expression ex = typeCombine(exp, sc))
10862 {
10863 result = ex;
10864 return;
10865 }
10866
10867 Type tb = exp.type.toBasetype();
10868 if (tb.ty == Tarray || tb.ty == Tsarray)
10869 {
10870 if (!isArrayOpValid(exp))
10871 {
10872 result = arrayOpInvalidError(exp);
10873 return;
10874 }
10875 result = exp;
10876 return;
10877 }
10878
10879 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10880 return setError();
10881
10882 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
10883 {
10884 result = exp.incompatibleTypes();
10885 return;
10886 }
10887
10888 // First, attempt to fold the expression.
10889 e = exp.optimize(WANTvalue);
9c7d5e88 10890 if (e.op != EXP.pow)
5fee5ec3
IB
10891 {
10892 e = e.expressionSemantic(sc);
10893 result = e;
10894 return;
10895 }
10896
10897 Module mmath = loadStdMath();
10898 if (!mmath)
10899 {
10900 e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
10901 return setError();
10902 }
10903 e = new ScopeExp(exp.loc, mmath);
10904
9c7d5e88 10905 if (exp.e2.op == EXP.float64 && exp.e2.toReal() == CTFloat.half)
5fee5ec3
IB
10906 {
10907 // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
10908 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
10909 }
10910 else
10911 {
10912 // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
10913 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
10914 }
10915 e = e.expressionSemantic(sc);
10916 result = e;
10917 return;
10918 }
10919
10920 override void visit(ShlExp exp)
10921 {
10922 //printf("ShlExp::semantic(), type = %p\n", type);
10923 if (exp.type)
10924 {
10925 result = exp;
10926 return;
10927 }
10928
10929 if (Expression ex = binSemanticProp(exp, sc))
10930 {
10931 result = ex;
10932 return;
10933 }
10934 Expression e = exp.op_overload(sc);
10935 if (e)
10936 {
10937 result = e;
10938 return;
10939 }
10940
10941 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10942 return setError();
10943
10944 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10945 {
10946 result = exp.incompatibleTypes();
10947 return;
10948 }
10949 exp.e1 = integralPromotions(exp.e1, sc);
10950 if (exp.e2.type.toBasetype().ty != Tvector)
10951 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10952
10953 exp.type = exp.e1.type;
10954 result = exp;
10955 }
10956
10957 override void visit(ShrExp exp)
10958 {
10959 if (exp.type)
10960 {
10961 result = exp;
10962 return;
10963 }
10964
10965 if (Expression ex = binSemanticProp(exp, sc))
10966 {
10967 result = ex;
10968 return;
10969 }
10970 Expression e = exp.op_overload(sc);
10971 if (e)
10972 {
10973 result = e;
10974 return;
10975 }
10976
10977 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
10978 return setError();
10979
10980 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
10981 {
10982 result = exp.incompatibleTypes();
10983 return;
10984 }
10985 exp.e1 = integralPromotions(exp.e1, sc);
10986 if (exp.e2.type.toBasetype().ty != Tvector)
10987 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
10988
10989 exp.type = exp.e1.type;
10990 result = exp;
10991 }
10992
10993 override void visit(UshrExp exp)
10994 {
10995 if (exp.type)
10996 {
10997 result = exp;
10998 return;
10999 }
11000
11001 if (Expression ex = binSemanticProp(exp, sc))
11002 {
11003 result = ex;
11004 return;
11005 }
11006 Expression e = exp.op_overload(sc);
11007 if (e)
11008 {
11009 result = e;
11010 return;
11011 }
11012
11013 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11014 return setError();
11015
11016 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11017 {
11018 result = exp.incompatibleTypes();
11019 return;
11020 }
11021 exp.e1 = integralPromotions(exp.e1, sc);
11022 if (exp.e2.type.toBasetype().ty != Tvector)
11023 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11024
11025 exp.type = exp.e1.type;
11026 result = exp;
11027 }
11028
11029 override void visit(AndExp exp)
11030 {
11031 if (exp.type)
11032 {
11033 result = exp;
11034 return;
11035 }
11036
11037 if (Expression ex = binSemanticProp(exp, sc))
11038 {
11039 result = ex;
11040 return;
11041 }
11042 Expression e = exp.op_overload(sc);
11043 if (e)
11044 {
11045 result = e;
11046 return;
11047 }
11048
11049 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11050 {
11051 exp.type = exp.e1.type;
11052 result = exp;
11053 return;
11054 }
11055
11056 if (Expression ex = typeCombine(exp, sc))
11057 {
11058 result = ex;
11059 return;
11060 }
11061
11062 Type tb = exp.type.toBasetype();
11063 if (tb.ty == Tarray || tb.ty == Tsarray)
11064 {
11065 if (!isArrayOpValid(exp))
11066 {
11067 result = arrayOpInvalidError(exp);
11068 return;
11069 }
11070 result = exp;
11071 return;
11072 }
11073 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11074 {
11075 result = exp.incompatibleTypes();
11076 return;
11077 }
11078 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11079 return setError();
11080
11081 result = exp;
11082 }
11083
11084 override void visit(OrExp exp)
11085 {
11086 if (exp.type)
11087 {
11088 result = exp;
11089 return;
11090 }
11091
11092 if (Expression ex = binSemanticProp(exp, sc))
11093 {
11094 result = ex;
11095 return;
11096 }
11097 Expression e = exp.op_overload(sc);
11098 if (e)
11099 {
11100 result = e;
11101 return;
11102 }
11103
11104 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11105 {
11106 exp.type = exp.e1.type;
11107 result = exp;
11108 return;
11109 }
11110
11111 if (Expression ex = typeCombine(exp, sc))
11112 {
11113 result = ex;
11114 return;
11115 }
11116
11117 Type tb = exp.type.toBasetype();
11118 if (tb.ty == Tarray || tb.ty == Tsarray)
11119 {
11120 if (!isArrayOpValid(exp))
11121 {
11122 result = arrayOpInvalidError(exp);
11123 return;
11124 }
11125 result = exp;
11126 return;
11127 }
11128 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11129 {
11130 result = exp.incompatibleTypes();
11131 return;
11132 }
11133 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11134 return setError();
11135
11136 result = exp;
11137 }
11138
11139 override void visit(XorExp exp)
11140 {
11141 if (exp.type)
11142 {
11143 result = exp;
11144 return;
11145 }
11146
11147 if (Expression ex = binSemanticProp(exp, sc))
11148 {
11149 result = ex;
11150 return;
11151 }
11152 Expression e = exp.op_overload(sc);
11153 if (e)
11154 {
11155 result = e;
11156 return;
11157 }
11158
11159 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11160 {
11161 exp.type = exp.e1.type;
11162 result = exp;
11163 return;
11164 }
11165
11166 if (Expression ex = typeCombine(exp, sc))
11167 {
11168 result = ex;
11169 return;
11170 }
11171
11172 Type tb = exp.type.toBasetype();
11173 if (tb.ty == Tarray || tb.ty == Tsarray)
11174 {
11175 if (!isArrayOpValid(exp))
11176 {
11177 result = arrayOpInvalidError(exp);
11178 return;
11179 }
11180 result = exp;
11181 return;
11182 }
11183 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11184 {
11185 result = exp.incompatibleTypes();
11186 return;
11187 }
11188 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11189 return setError();
11190
11191 result = exp;
11192 }
11193
11194 override void visit(LogicalExp exp)
11195 {
11196 static if (LOGSEMANTIC)
11197 {
11198 printf("LogicalExp::semantic() %s\n", exp.toChars());
11199 }
11200
11201 if (exp.type)
11202 {
11203 result = exp;
11204 return;
11205 }
11206
11207 exp.setNoderefOperands();
11208
11209 Expression e1x = exp.e1.expressionSemantic(sc);
11210
11211 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 11212 if (e1x.op == EXP.type)
5fee5ec3
IB
11213 e1x = resolveAliasThis(sc, e1x);
11214
11215 e1x = resolveProperties(sc, e1x);
11216 e1x = e1x.toBoolean(sc);
11217
11218 if (sc.flags & SCOPE.condition)
11219 {
11220 /* If in static if, don't evaluate e2 if we don't have to.
11221 */
11222 e1x = e1x.optimize(WANTvalue);
9c7d5e88 11223 if (e1x.toBool().hasValue(exp.op == EXP.orOr))
5fee5ec3 11224 {
9c7d5e88 11225 result = IntegerExp.createBool(exp.op == EXP.orOr);
5fee5ec3
IB
11226 return;
11227 }
11228 }
11229
11230 CtorFlow ctorflow = sc.ctorflow.clone();
11231 Expression e2x = exp.e2.expressionSemantic(sc);
11232 sc.merge(exp.loc, ctorflow);
11233 ctorflow.freeFieldinit();
11234
11235 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 11236 if (e2x.op == EXP.type)
5fee5ec3
IB
11237 e2x = resolveAliasThis(sc, e2x);
11238
11239 e2x = resolveProperties(sc, e2x);
11240
11241 auto f1 = checkNonAssignmentArrayOp(e1x);
11242 auto f2 = checkNonAssignmentArrayOp(e2x);
11243 if (f1 || f2)
11244 return setError();
11245
11246 // Unless the right operand is 'void', the expression is converted to 'bool'.
11247 if (e2x.type.ty != Tvoid)
11248 e2x = e2x.toBoolean(sc);
11249
9c7d5e88 11250 if (e2x.op == EXP.type || e2x.op == EXP.scope_)
5fee5ec3
IB
11251 {
11252 exp.error("`%s` is not an expression", exp.e2.toChars());
11253 return setError();
11254 }
9c7d5e88 11255 if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
5fee5ec3
IB
11256 {
11257 result = e1x;
11258 return;
11259 }
9c7d5e88 11260 if (e2x.op == EXP.error)
5fee5ec3
IB
11261 {
11262 result = e2x;
11263 return;
11264 }
11265
11266 // The result type is 'bool', unless the right operand has type 'void'.
11267 if (e2x.type.ty == Tvoid)
11268 exp.type = Type.tvoid;
11269 else
11270 exp.type = Type.tbool;
11271
11272 exp.e1 = e1x;
11273 exp.e2 = e2x;
11274 result = exp;
11275 }
11276
11277
11278 override void visit(CmpExp exp)
11279 {
11280 static if (LOGSEMANTIC)
11281 {
11282 printf("CmpExp::semantic('%s')\n", exp.toChars());
11283 }
11284 if (exp.type)
11285 {
11286 result = exp;
11287 return;
11288 }
11289
11290 exp.setNoderefOperands();
11291
11292 if (Expression ex = binSemanticProp(exp, sc))
11293 {
11294 result = ex;
11295 return;
11296 }
11297 Type t1 = exp.e1.type.toBasetype();
11298 Type t2 = exp.e2.type.toBasetype();
9c7d5e88 11299 if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
5fee5ec3
IB
11300 {
11301 exp.error("do not use `null` when comparing class types");
11302 return setError();
11303 }
11304
9c7d5e88 11305 EXP cmpop;
5fee5ec3
IB
11306 if (auto e = exp.op_overload(sc, &cmpop))
11307 {
11308 if (!e.type.isscalar() && e.type.equals(exp.e1.type))
11309 {
11310 exp.error("recursive `opCmp` expansion");
11311 return setError();
11312 }
9c7d5e88 11313 if (e.op == EXP.call)
5fee5ec3
IB
11314 {
11315 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
11316 e = e.expressionSemantic(sc);
11317 }
11318 result = e;
11319 return;
11320 }
11321
11322 if (Expression ex = typeCombine(exp, sc))
11323 {
11324 result = ex;
11325 return;
11326 }
11327
11328 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11329 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11330 if (f1 || f2)
11331 return setError();
11332
11333 exp.type = Type.tbool;
11334
11335 // Special handling for array comparisons
11336 Expression arrayLowering = null;
11337 t1 = exp.e1.type.toBasetype();
11338 t2 = exp.e2.type.toBasetype();
11339 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
11340 {
11341 Type t1next = t1.nextOf();
11342 Type t2next = t2.nextOf();
11343 if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
11344 {
11345 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
11346 return setError();
11347 }
11348 if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
11349 {
11350 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
11351 return setError();
11352
11353 // Lower to object.__cmp(e1, e2)
11354 Expression al = new IdentifierExp(exp.loc, Id.empty);
11355 al = new DotIdExp(exp.loc, al, Id.object);
11356 al = new DotIdExp(exp.loc, al, Id.__cmp);
11357 al = al.expressionSemantic(sc);
11358
11359 auto arguments = new Expressions(2);
11360 (*arguments)[0] = exp.e1;
11361 (*arguments)[1] = exp.e2;
11362
11363 al = new CallExp(exp.loc, al, arguments);
11364 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
11365
11366 arrayLowering = al;
11367 }
11368 }
11369 else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
11370 {
11371 if (t2.ty == Tstruct)
11372 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
11373 else
11374 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
11375 return setError();
11376 }
11377 else if (t1.iscomplex() || t2.iscomplex())
11378 {
11379 exp.error("compare not defined for complex operands");
11380 return setError();
11381 }
11382 else if (t1.ty == Taarray || t2.ty == Taarray)
11383 {
9c7d5e88 11384 exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
5fee5ec3
IB
11385 return setError();
11386 }
11387 else if (!target.isVectorOpSupported(t1, exp.op, t2))
11388 {
11389 result = exp.incompatibleTypes();
11390 return;
11391 }
11392 else
11393 {
11394 bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
11395 bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
11396 if (r1 || r2)
11397 return setError();
11398 }
11399
11400 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
11401 if (arrayLowering)
11402 {
11403 arrayLowering = arrayLowering.expressionSemantic(sc);
11404 result = arrayLowering;
11405 return;
11406 }
11407 result = exp;
11408 return;
11409 }
11410
11411 override void visit(InExp exp)
11412 {
11413 if (exp.type)
11414 {
11415 result = exp;
11416 return;
11417 }
11418
11419 if (Expression ex = binSemanticProp(exp, sc))
11420 {
11421 result = ex;
11422 return;
11423 }
11424 Expression e = exp.op_overload(sc);
11425 if (e)
11426 {
11427 result = e;
11428 return;
11429 }
11430
11431 Type t2b = exp.e2.type.toBasetype();
11432 switch (t2b.ty)
11433 {
11434 case Taarray:
11435 {
11436 TypeAArray ta = cast(TypeAArray)t2b;
11437
11438 // Special handling for array keys
11439 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11440 {
11441 // Convert key to type of key
11442 exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11443 }
11444
11445 semanticTypeInfo(sc, ta.index);
11446
11447 // Return type is pointer to value
11448 exp.type = ta.nextOf().pointerTo();
11449 break;
11450 }
11451
11452 case Terror:
11453 return setError();
11454
11455 default:
11456 result = exp.incompatibleTypes();
11457 return;
11458 }
11459 result = exp;
11460 }
11461
11462 override void visit(RemoveExp e)
11463 {
11464 if (Expression ex = binSemantic(e, sc))
11465 {
11466 result = ex;
11467 return;
11468 }
11469 result = e;
11470 }
11471
11472 override void visit(EqualExp exp)
11473 {
11474 //printf("EqualExp::semantic('%s')\n", exp.toChars());
11475 if (exp.type)
11476 {
11477 result = exp;
11478 return;
11479 }
11480
11481 exp.setNoderefOperands();
11482
11483 if (auto e = binSemanticProp(exp, sc))
11484 {
11485 result = e;
11486 return;
11487 }
9c7d5e88 11488 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
5fee5ec3
IB
11489 {
11490 /* https://issues.dlang.org/show_bug.cgi?id=12520
11491 * empty tuples are represented as types so special cases are added
11492 * so that they can be compared for equality with tuples of values.
11493 */
11494 static auto extractTypeTupAndExpTup(Expression e)
11495 {
11496 static struct Result { bool ttEmpty; bool te; }
9c7d5e88 11497 auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
5fee5ec3
IB
11498 return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
11499 }
11500 auto tups1 = extractTypeTupAndExpTup(exp.e1);
11501 auto tups2 = extractTypeTupAndExpTup(exp.e2);
11502 // AliasSeq!() == AliasSeq!(<at least a value>)
11503 if (tups1.ttEmpty && tups2.te)
11504 {
9c7d5e88 11505 result = IntegerExp.createBool(exp.op != EXP.equal);
5fee5ec3
IB
11506 return;
11507 }
11508 // AliasSeq!(<at least a value>) == AliasSeq!()
11509 else if (tups1.te && tups2.ttEmpty)
11510 {
9c7d5e88 11511 result = IntegerExp.createBool(exp.op != EXP.equal);
5fee5ec3
IB
11512 return;
11513 }
11514 // AliasSeq!() == AliasSeq!()
11515 else if (tups1.ttEmpty && tups2.ttEmpty)
11516 {
9c7d5e88 11517 result = IntegerExp.createBool(exp.op == EXP.equal);
5fee5ec3
IB
11518 return;
11519 }
11520 // otherwise, two types are really not comparable
11521 result = exp.incompatibleTypes();
11522 return;
11523 }
11524
11525 {
11526 auto t1 = exp.e1.type;
11527 auto t2 = exp.e2.type;
11528 if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11529 exp.error("Comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11530 t1.toChars(), t2.toChars());
11531 }
11532
11533 /* Before checking for operator overloading, check to see if we're
11534 * comparing the addresses of two statics. If so, we can just see
11535 * if they are the same symbol.
11536 */
9c7d5e88 11537 if (exp.e1.op == EXP.address && exp.e2.op == EXP.address)
5fee5ec3
IB
11538 {
11539 AddrExp ae1 = cast(AddrExp)exp.e1;
11540 AddrExp ae2 = cast(AddrExp)exp.e2;
9c7d5e88 11541 if (ae1.e1.op == EXP.variable && ae2.e1.op == EXP.variable)
5fee5ec3
IB
11542 {
11543 VarExp ve1 = cast(VarExp)ae1.e1;
11544 VarExp ve2 = cast(VarExp)ae2.e1;
11545 if (ve1.var == ve2.var)
11546 {
11547 // They are the same, result is 'true' for ==, 'false' for !=
9c7d5e88 11548 result = IntegerExp.createBool(exp.op == EXP.equal);
5fee5ec3
IB
11549 return;
11550 }
11551 }
11552 }
11553
11554 Type t1 = exp.e1.type.toBasetype();
11555 Type t2 = exp.e2.type.toBasetype();
11556
11557 // Indicates whether the comparison of the 2 specified array types
11558 // requires an object.__equals() lowering.
11559 static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11560 {
11561 Type t1n = t1.nextOf().toBasetype();
11562 Type t2n = t2.nextOf().toBasetype();
11563 if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11564 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11565 {
11566 return false;
11567 }
11568 if (t1n.constOf() != t2n.constOf())
11569 return true;
11570
11571 Type t = t1n;
11572 while (t.toBasetype().nextOf())
11573 t = t.nextOf().toBasetype();
11574 if (auto ts = t.isTypeStruct())
11575 {
11576 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11577 if (global.params.useTypeInfo && Type.dtypeinfo)
11578 semanticTypeInfo(sc, ts);
11579
11580 return ts.sym.hasIdentityEquals; // has custom opEquals
11581 }
11582
11583 return false;
11584 }
11585
11586 if (auto e = exp.op_overload(sc))
11587 {
11588 result = e;
11589 return;
11590 }
11591
11592
11593 const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11594 (t2.ty == Tarray || t2.ty == Tsarray);
11595 const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11596
11597 if (!needsArrayLowering)
11598 {
11599 if (auto e = typeCombine(exp, sc))
11600 {
11601 result = e;
11602 return;
11603 }
11604 }
11605
11606 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11607 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11608 if (f1 || f2)
11609 return setError();
11610
11611 exp.type = Type.tbool;
11612
11613 if (!isArrayComparison)
11614 {
11615 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11616 {
11617 // Cast both to complex
11618 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11619 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11620 }
11621 }
11622
11623 // lower some array comparisons to object.__equals(e1, e2)
11624 if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
11625 {
11626 //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
11627
11628 if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
11629 return setError();
11630
11631 Expression __equals = new IdentifierExp(exp.loc, Id.empty);
11632 Identifier id = Identifier.idPool("__equals");
11633 __equals = new DotIdExp(exp.loc, __equals, Id.object);
11634 __equals = new DotIdExp(exp.loc, __equals, id);
11635
11636 auto arguments = new Expressions(2);
11637 (*arguments)[0] = exp.e1;
11638 (*arguments)[1] = exp.e2;
11639
11640 __equals = new CallExp(exp.loc, __equals, arguments);
9c7d5e88 11641 if (exp.op == EXP.notEqual)
5fee5ec3
IB
11642 {
11643 __equals = new NotExp(exp.loc, __equals);
11644 }
11645 __equals = __equals.trySemantic(sc); // for better error message
11646 if (!__equals)
11647 {
11648 exp.error("incompatible types for array comparison: `%s` and `%s`",
11649 exp.e1.type.toChars(), exp.e2.type.toChars());
11650 __equals = ErrorExp.get();
11651 }
11652
11653 result = __equals;
11654 return;
11655 }
11656
11657 if (exp.e1.type.toBasetype().ty == Taarray)
11658 semanticTypeInfo(sc, exp.e1.type.toBasetype());
11659
11660
11661 if (!target.isVectorOpSupported(t1, exp.op, t2))
11662 {
11663 result = exp.incompatibleTypes();
11664 return;
11665 }
11666
11667 result = exp;
11668 }
11669
11670 override void visit(IdentityExp exp)
11671 {
11672 if (exp.type)
11673 {
11674 result = exp;
11675 return;
11676 }
11677
11678 exp.setNoderefOperands();
11679
11680 if (auto e = binSemanticProp(exp, sc))
11681 {
11682 result = e;
11683 return;
11684 }
11685
11686 if (auto e = typeCombine(exp, sc))
11687 {
11688 result = e;
11689 return;
11690 }
11691
11692 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11693 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11694 if (f1 || f2)
11695 return setError();
11696
9c7d5e88 11697 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
5fee5ec3
IB
11698 {
11699 result = exp.incompatibleTypes();
11700 return;
11701 }
11702
11703 exp.type = Type.tbool;
11704
11705 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
11706 {
11707 // Cast both to complex
11708 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
11709 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
11710 }
11711
11712 auto tb1 = exp.e1.type.toBasetype();
11713 auto tb2 = exp.e2.type.toBasetype();
11714 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
11715 {
11716 result = exp.incompatibleTypes();
11717 return;
11718 }
11719
9c7d5e88 11720 if (exp.e1.op == EXP.call)
5fee5ec3 11721 exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
9c7d5e88 11722 if (exp.e2.op == EXP.call)
5fee5ec3
IB
11723 exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
11724
11725 if (exp.e1.type.toBasetype().ty == Tsarray ||
11726 exp.e2.type.toBasetype().ty == Tsarray)
11727 exp.deprecation("identity comparison of static arrays "
11728 ~ "implicitly coerces them to slices, "
11729 ~ "which are compared by reference");
11730
11731 result = exp;
11732 }
11733
11734 override void visit(CondExp exp)
11735 {
11736 static if (LOGSEMANTIC)
11737 {
11738 printf("CondExp::semantic('%s')\n", exp.toChars());
11739 }
11740 if (exp.type)
11741 {
11742 result = exp;
11743 return;
11744 }
11745
9c7d5e88 11746 if (exp.econd.op == EXP.dotIdentifier)
5fee5ec3
IB
11747 (cast(DotIdExp)exp.econd).noderef = true;
11748
11749 Expression ec = exp.econd.expressionSemantic(sc);
11750 ec = resolveProperties(sc, ec);
11751 ec = ec.toBoolean(sc);
11752
11753 CtorFlow ctorflow_root = sc.ctorflow.clone();
0fb57034 11754 Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
5fee5ec3
IB
11755 e1x = resolveProperties(sc, e1x);
11756
11757 CtorFlow ctorflow1 = sc.ctorflow;
11758 sc.ctorflow = ctorflow_root;
0fb57034 11759 Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
5fee5ec3
IB
11760 e2x = resolveProperties(sc, e2x);
11761
11762 sc.merge(exp.loc, ctorflow1);
11763 ctorflow1.freeFieldinit();
11764
9c7d5e88 11765 if (ec.op == EXP.error)
5fee5ec3
IB
11766 {
11767 result = ec;
11768 return;
11769 }
11770 if (ec.type == Type.terror)
11771 return setError();
11772 exp.econd = ec;
11773
9c7d5e88 11774 if (e1x.op == EXP.error)
5fee5ec3
IB
11775 {
11776 result = e1x;
11777 return;
11778 }
11779 if (e1x.type == Type.terror)
11780 return setError();
11781 exp.e1 = e1x;
11782
9c7d5e88 11783 if (e2x.op == EXP.error)
5fee5ec3
IB
11784 {
11785 result = e2x;
11786 return;
11787 }
11788 if (e2x.type == Type.terror)
11789 return setError();
11790 exp.e2 = e2x;
11791
11792 auto f0 = checkNonAssignmentArrayOp(exp.econd);
11793 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11794 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11795 if (f0 || f1 || f2)
11796 return setError();
11797
11798 Type t1 = exp.e1.type;
11799 Type t2 = exp.e2.type;
11800 if (t1.ty == Tnoreturn)
11801 {
11802 exp.type = t2;
11803 }
11804 else if (t2.ty == Tnoreturn)
11805 {
11806 exp.type = t1;
11807 }
11808 // If either operand is void the result is void, we have to cast both
11809 // the expression to void so that we explicitly discard the expression
11810 // value if any
11811 // https://issues.dlang.org/show_bug.cgi?id=16598
11812 else if (t1.ty == Tvoid || t2.ty == Tvoid)
11813 {
11814 exp.type = Type.tvoid;
11815 exp.e1 = exp.e1.castTo(sc, exp.type);
11816 exp.e2 = exp.e2.castTo(sc, exp.type);
11817 }
11818 else if (t1 == t2)
11819 exp.type = t1;
11820 else
11821 {
11822 if (Expression ex = typeCombine(exp, sc))
11823 {
11824 result = ex;
11825 return;
11826 }
11827
11828 switch (exp.e1.type.toBasetype().ty)
11829 {
11830 case Tcomplex32:
11831 case Tcomplex64:
11832 case Tcomplex80:
11833 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
11834 break;
11835 default:
11836 break;
11837 }
11838 switch (exp.e2.type.toBasetype().ty)
11839 {
11840 case Tcomplex32:
11841 case Tcomplex64:
11842 case Tcomplex80:
11843 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
11844 break;
11845 default:
11846 break;
11847 }
11848 if (exp.type.toBasetype().ty == Tarray)
11849 {
11850 exp.e1 = exp.e1.castTo(sc, exp.type);
11851 exp.e2 = exp.e2.castTo(sc, exp.type);
11852 }
11853 }
11854 exp.type = exp.type.merge2();
11855 version (none)
11856 {
11857 printf("res: %s\n", exp.type.toChars());
11858 printf("e1 : %s\n", exp.e1.type.toChars());
11859 printf("e2 : %s\n", exp.e2.type.toChars());
11860 }
11861
11862 /* https://issues.dlang.org/show_bug.cgi?id=14696
11863 * If either e1 or e2 contain temporaries which need dtor,
11864 * make them conditional.
11865 * Rewrite:
11866 * cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
11867 * to:
11868 * (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
11869 * and replace edtors of __tmp1 and __tmp2 with:
11870 * __tmp1.edtor --> __cond && __tmp1.dtor()
11871 * __tmp2.edtor --> __cond || __tmp2.dtor()
11872 */
11873 exp.hookDtors(sc);
11874
11875 result = exp;
11876 }
11877
11878 override void visit(GenericExp exp)
11879 {
11880 static if (LOGSEMANTIC)
11881 {
11882 printf("GenericExp::semantic('%s')\n", exp.toChars());
11883 }
11884 // C11 6.5.1.1 Generic Selection
11885
11886 auto ec = exp.cntlExp.expressionSemantic(sc);
11887 bool errors = ec.isErrorExp() !is null;
11888 auto tc = ec.type;
11889
11890 auto types = (*exp.types)[];
11891 foreach (i, ref t; types)
11892 {
11893 if (!t)
11894 continue; // `default:` case
11895 t = t.typeSemantic(ec.loc, sc);
11896 if (t.isTypeError())
11897 {
11898 errors = true;
11899 continue;
11900 }
11901
11902 /* C11 6.5.1-2 duplicate check
11903 */
11904 /* C11 distinguishes int, long, and long long. But D doesn't, so depending on the
11905 * C target, a long may have the same type as `int` in the D type system.
11906 * So, skip checks when this may be the case. Later pick the first match
11907 */
11908 if (
11909 (t.ty == Tint32 || t.ty == Tuns32) && target.c.longsize == 4 ||
11910 (t.ty == Tint64 || t.ty == Tuns64) && target.c.longsize == 8 ||
11911 (t.ty == Tfloat64 || t.ty == Timaginary64 || t.ty == Tcomplex64) && target.c.long_doublesize == 8
11912 )
11913 continue;
11914
11915 foreach (t2; types[0 .. i])
11916 {
11917 if (t2 && t2.equals(t))
11918 {
11919 error(ec.loc, "generic association type `%s` can only appear once", t.toChars());
11920 errors = true;
11921 break;
11922 }
11923 }
11924 }
11925
11926 auto exps = (*exp.exps)[];
11927 foreach (ref e; exps)
11928 {
11929 e = e.expressionSemantic(sc);
11930 if (e.isErrorExp())
11931 errors = true;
11932 }
11933
11934 if (errors)
11935 return setError();
11936
11937 enum size_t None = ~0;
11938 size_t imatch = None;
11939 size_t idefault = None;
11940 foreach (const i, t; types)
11941 {
11942 if (t)
11943 {
11944 /* if tc is compatible with t, it's a match
11945 * C11 6.2.7 defines a compatible type as being the same type, including qualifiers
11946 */
11947 if (tc.equals(t))
11948 {
11949 assert(imatch == None);
11950 imatch = i;
11951 break; // pick first match
11952 }
11953 }
11954 else
11955 idefault = i; // multiple defaults are not allowed, and are caught by cparse
11956 }
11957
11958 if (imatch == None)
11959 imatch = idefault;
11960 if (imatch == None)
11961 {
11962 error(exp.loc, "no compatible generic association type for controlling expression type `%s`", tc.toChars());
11963 return setError();
11964 }
11965
11966 result = exps[imatch];
11967 }
11968
11969 override void visit(FileInitExp e)
11970 {
11971 //printf("FileInitExp::semantic()\n");
11972 e.type = Type.tstring;
11973 result = e;
11974 }
11975
11976 override void visit(LineInitExp e)
11977 {
11978 e.type = Type.tint32;
11979 result = e;
11980 }
11981
11982 override void visit(ModuleInitExp e)
11983 {
11984 //printf("ModuleInitExp::semantic()\n");
11985 e.type = Type.tstring;
11986 result = e;
11987 }
11988
11989 override void visit(FuncInitExp e)
11990 {
11991 //printf("FuncInitExp::semantic()\n");
11992 e.type = Type.tstring;
11993 if (sc.func)
11994 {
11995 result = e.resolveLoc(Loc.initial, sc);
11996 return;
11997 }
11998 result = e;
11999 }
12000
12001 override void visit(PrettyFuncInitExp e)
12002 {
12003 //printf("PrettyFuncInitExp::semantic()\n");
12004 e.type = Type.tstring;
12005 if (sc.func)
12006 {
12007 result = e.resolveLoc(Loc.initial, sc);
12008 return;
12009 }
12010
12011 result = e;
12012 }
12013}
12014
12015/**********************************
12016 * Try to run semantic routines.
12017 * If they fail, return NULL.
12018 */
12019Expression trySemantic(Expression exp, Scope* sc)
12020{
12021 //printf("+trySemantic(%s)\n", exp.toChars());
12022 uint errors = global.startGagging();
12023 Expression e = expressionSemantic(exp, sc);
12024 if (global.endGagging(errors))
12025 {
12026 e = null;
12027 }
12028 //printf("-trySemantic(%s)\n", exp.toChars());
12029 return e;
12030}
12031
12032/**************************
12033 * Helper function for easy error propagation.
12034 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12035 */
12036Expression unaSemantic(UnaExp e, Scope* sc)
12037{
12038 static if (LOGSEMANTIC)
12039 {
12040 printf("UnaExp::semantic('%s')\n", e.toChars());
12041 }
12042 Expression e1x = e.e1.expressionSemantic(sc);
9c7d5e88 12043 if (e1x.op == EXP.error)
5fee5ec3
IB
12044 return e1x;
12045 e.e1 = e1x;
12046 return null;
12047}
12048
12049/**************************
12050 * Helper function for easy error propagation.
12051 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12052 */
12053Expression binSemantic(BinExp e, Scope* sc)
12054{
12055 static if (LOGSEMANTIC)
12056 {
12057 printf("BinExp::semantic('%s')\n", e.toChars());
12058 }
12059 Expression e1x = e.e1.expressionSemantic(sc);
12060 Expression e2x = e.e2.expressionSemantic(sc);
12061
12062 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 12063 if (e1x.op == EXP.type)
5fee5ec3 12064 e1x = resolveAliasThis(sc, e1x);
9c7d5e88 12065 if (e2x.op == EXP.type)
5fee5ec3
IB
12066 e2x = resolveAliasThis(sc, e2x);
12067
9c7d5e88 12068 if (e1x.op == EXP.error)
5fee5ec3 12069 return e1x;
9c7d5e88 12070 if (e2x.op == EXP.error)
5fee5ec3
IB
12071 return e2x;
12072 e.e1 = e1x;
12073 e.e2 = e2x;
12074 return null;
12075}
12076
12077Expression binSemanticProp(BinExp e, Scope* sc)
12078{
12079 if (Expression ex = binSemantic(e, sc))
12080 return ex;
12081 Expression e1x = resolveProperties(sc, e.e1);
12082 Expression e2x = resolveProperties(sc, e.e2);
9c7d5e88 12083 if (e1x.op == EXP.error)
5fee5ec3 12084 return e1x;
9c7d5e88 12085 if (e2x.op == EXP.error)
5fee5ec3
IB
12086 return e2x;
12087 e.e1 = e1x;
12088 e.e2 = e2x;
12089 return null;
12090}
12091
12092// entrypoint for semantic ExpressionSemanticVisitor
12093extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
12094{
12095 scope v = new ExpressionSemanticVisitor(sc);
12096 e.accept(v);
12097 return v.result;
12098}
12099
12100Expression semanticX(DotIdExp exp, Scope* sc)
12101{
12102 //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
12103 if (Expression ex = unaSemantic(exp, sc))
12104 return ex;
12105
12106 if (exp.ident == Id._mangleof)
12107 {
12108 // symbol.mangleof
0fb57034
IB
12109
12110 // return mangleof as an Expression
12111 static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
5fee5ec3 12112 {
0fb57034
IB
12113 assert(ds);
12114 if (auto f = ds.isFuncDeclaration())
5fee5ec3 12115 {
0fb57034
IB
12116 if (f.checkForwardRef(loc))
12117 return ErrorExp.get();
12118
12119 if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
12120 FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
5fee5ec3 12121 {
0fb57034
IB
12122 f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
12123 return ErrorExp.get();
5fee5ec3 12124 }
5fee5ec3 12125 }
0fb57034
IB
12126 OutBuffer buf;
12127 mangleToBuffer(ds, &buf);
12128 Expression e = new StringExp(loc, buf.extractSlice());
12129 return e.expressionSemantic(sc);
12130 }
12131
12132 Dsymbol ds;
12133 switch (exp.e1.op)
12134 {
9c7d5e88
IB
12135 case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
12136 case EXP.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
12137 case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
12138 case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
12139 case EXP.template_:
0fb57034
IB
12140 {
12141 TemplateExp te = exp.e1.isTemplateExp();
12142 return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
12143 }
12144
12145 default:
12146 break;
5fee5ec3
IB
12147 }
12148 }
12149
0fb57034 12150 if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
5fee5ec3
IB
12151 {
12152 // bypass checkPurity
12153 return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
12154 }
12155
0fb57034 12156 if (!exp.e1.isDotExp())
5fee5ec3
IB
12157 {
12158 exp.e1 = resolvePropertiesX(sc, exp.e1);
12159 }
0fb57034
IB
12160
12161 if (auto te = exp.e1.isTupleExp())
5fee5ec3 12162 {
0fb57034 12163 if (exp.ident == Id.offsetof)
5fee5ec3 12164 {
0fb57034
IB
12165 /* 'distribute' the .offsetof to each of the tuple elements.
12166 */
12167 auto exps = new Expressions(te.exps.dim);
12168 foreach (i, e; (*te.exps)[])
12169 {
12170 (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
12171 }
12172 // Don't evaluate te.e0 in runtime
12173 Expression e = new TupleExp(exp.loc, null, exps);
5fee5ec3 12174 e = e.expressionSemantic(sc);
0fb57034
IB
12175 return e;
12176 }
12177 if (exp.ident == Id.length)
12178 {
12179 // Don't evaluate te.e0 in runtime
12180 return new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
5fee5ec3 12181 }
5fee5ec3
IB
12182 }
12183
12184 // https://issues.dlang.org/show_bug.cgi?id=14416
12185 // Template has no built-in properties except for 'stringof'.
0fb57034 12186 if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
5fee5ec3
IB
12187 {
12188 exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12189 return ErrorExp.get();
12190 }
12191 if (!exp.e1.type)
12192 {
12193 exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12194 return ErrorExp.get();
12195 }
12196
12197 return exp;
12198}
12199
0fb57034
IB
12200/******************************
12201 * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
12202 * Params:
12203 * exp = expression to resolve
12204 * sc = context
12205 * flag = if 1 then do not emit error messages, just return null
12206 * Returns:
12207 * resolved expression, null if error
12208 */
5fee5ec3
IB
12209Expression semanticY(DotIdExp exp, Scope* sc, int flag)
12210{
12211 //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
12212
12213 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
12214
12215 /* Special case: rewrite this.id and super.id
12216 * to be classtype.id and baseclasstype.id
12217 * if we have no this pointer.
12218 */
0fb57034 12219 if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
5fee5ec3
IB
12220 {
12221 if (AggregateDeclaration ad = sc.getStructClassScope())
12222 {
0fb57034 12223 if (exp.e1.isThisExp())
5fee5ec3
IB
12224 {
12225 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
12226 }
12227 else
12228 {
0fb57034
IB
12229 if (auto cd = ad.isClassDeclaration())
12230 {
12231 if (cd.baseClass)
12232 exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
12233 }
5fee5ec3
IB
12234 }
12235 }
12236 }
12237
0fb57034
IB
12238 {
12239 Expression e = semanticX(exp, sc);
12240 if (e != exp)
12241 return e;
12242 }
5fee5ec3
IB
12243
12244 Expression eleft;
12245 Expression eright;
0fb57034 12246 if (auto de = exp.e1.isDotExp())
5fee5ec3 12247 {
5fee5ec3
IB
12248 eleft = de.e1;
12249 eright = de.e2;
12250 }
12251 else
12252 {
12253 eleft = null;
12254 eright = exp.e1;
12255 }
12256
12257 Type t1b = exp.e1.type.toBasetype();
12258
0fb57034 12259 if (auto ie = eright.isScopeExp()) // also used for template alias's
5fee5ec3 12260 {
0fb57034 12261 auto flags = SearchLocalsOnly;
5fee5ec3
IB
12262 /* Disable access to another module's private imports.
12263 * The check for 'is sds our current module' is because
12264 * the current module should have access to its own imports.
12265 */
12266 if (ie.sds.isModule() && ie.sds != sc._module)
12267 flags |= IgnorePrivateImports;
12268 if (sc.flags & SCOPE.ignoresymbolvisibility)
12269 flags |= IgnoreSymbolVisibility;
12270 Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
12271 /* Check for visibility before resolving aliases because public
12272 * aliases to private symbols are public.
12273 */
12274 if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
12275 {
12276 s = null;
12277 }
12278 if (s)
12279 {
12280 auto p = s.isPackage();
12281 if (p && checkAccess(sc, p))
12282 {
12283 s = null;
12284 }
12285 }
12286 if (s)
12287 {
12288 // if 's' is a tuple variable, the tuple is returned.
12289 s = s.toAlias();
12290
12291 exp.checkDeprecated(sc, s);
12292 exp.checkDisabled(sc, s);
12293
0fb57034 12294 if (auto em = s.isEnumMember())
5fee5ec3
IB
12295 {
12296 return em.getVarExp(exp.loc, sc);
12297 }
0fb57034 12298 if (auto v = s.isVarDeclaration())
5fee5ec3
IB
12299 {
12300 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
12301 if (!v.type ||
12302 !v.type.deco && v.inuse)
12303 {
12304 if (v.inuse)
12305 exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
12306 else
12307 exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
12308 return ErrorExp.get();
12309 }
0fb57034 12310 if (v.type.isTypeError())
5fee5ec3
IB
12311 return ErrorExp.get();
12312
12313 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
12314 {
12315 /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
12316 * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
12317 * be reverted. `wantsym` is the hack to work around the problem.
12318 */
12319 if (v.inuse)
12320 {
12321 error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
12322 return ErrorExp.get();
12323 }
0fb57034 12324 auto e = v.expandInitializer(exp.loc);
5fee5ec3
IB
12325 v.inuse++;
12326 e = e.expressionSemantic(sc);
12327 v.inuse--;
12328 return e;
12329 }
12330
0fb57034 12331 Expression e;
5fee5ec3
IB
12332 if (v.needThis())
12333 {
12334 if (!eleft)
12335 eleft = new ThisExp(exp.loc);
12336 e = new DotVarExp(exp.loc, eleft, v);
12337 e = e.expressionSemantic(sc);
12338 }
12339 else
12340 {
12341 e = new VarExp(exp.loc, v);
12342 if (eleft)
12343 {
12344 e = new CommaExp(exp.loc, eleft, e);
12345 e.type = v.type;
12346 }
12347 }
12348 e = e.deref();
12349 return e.expressionSemantic(sc);
12350 }
12351
0fb57034 12352 if (auto f = s.isFuncDeclaration())
5fee5ec3
IB
12353 {
12354 //printf("it's a function\n");
12355 if (!f.functionSemantic())
12356 return ErrorExp.get();
0fb57034 12357 Expression e;
5fee5ec3
IB
12358 if (f.needThis())
12359 {
12360 if (!eleft)
12361 eleft = new ThisExp(exp.loc);
12362 e = new DotVarExp(exp.loc, eleft, f, true);
12363 e = e.expressionSemantic(sc);
12364 }
12365 else
12366 {
12367 e = new VarExp(exp.loc, f, true);
12368 if (eleft)
12369 {
12370 e = new CommaExp(exp.loc, eleft, e);
12371 e.type = f.type;
12372 }
12373 }
12374 return e;
12375 }
12376 if (auto td = s.isTemplateDeclaration())
12377 {
0fb57034 12378 Expression e;
5fee5ec3
IB
12379 if (eleft)
12380 e = new DotTemplateExp(exp.loc, eleft, td);
12381 else
12382 e = new TemplateExp(exp.loc, td);
12383 e = e.expressionSemantic(sc);
12384 return e;
12385 }
12386 if (OverDeclaration od = s.isOverDeclaration())
12387 {
0fb57034 12388 Expression e = new VarExp(exp.loc, od, true);
5fee5ec3
IB
12389 if (eleft)
12390 {
12391 e = new CommaExp(exp.loc, eleft, e);
12392 e.type = Type.tvoid; // ambiguous type?
12393 }
12394 return e;
12395 }
0fb57034 12396 if (auto o = s.isOverloadSet())
5fee5ec3
IB
12397 {
12398 //printf("'%s' is an overload set\n", o.toChars());
12399 return new OverExp(exp.loc, o);
12400 }
12401
12402 if (auto t = s.getType())
12403 {
12404 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
12405 }
12406
0fb57034 12407 if (auto tup = s.isTupleDeclaration())
5fee5ec3
IB
12408 {
12409 if (eleft)
12410 {
0fb57034 12411 Expression e = new DotVarExp(exp.loc, eleft, tup);
5fee5ec3
IB
12412 e = e.expressionSemantic(sc);
12413 return e;
12414 }
0fb57034 12415 Expression e = new TupleExp(exp.loc, tup);
5fee5ec3
IB
12416 e = e.expressionSemantic(sc);
12417 return e;
12418 }
12419
0fb57034 12420 if (auto sds = s.isScopeDsymbol())
5fee5ec3
IB
12421 {
12422 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
0fb57034 12423 Expression e = new ScopeExp(exp.loc, sds);
5fee5ec3
IB
12424 e = e.expressionSemantic(sc);
12425 if (eleft)
12426 e = new DotExp(exp.loc, eleft, e);
12427 return e;
12428 }
12429
0fb57034 12430 if (auto imp = s.isImport())
5fee5ec3 12431 {
0fb57034
IB
12432 Expression se = new ScopeExp(exp.loc, imp.pkg);
12433 return se.expressionSemantic(sc);
5fee5ec3
IB
12434 }
12435 // BUG: handle other cases like in IdentifierExp::semantic()
12436 debug
12437 {
12438 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
12439 }
12440 assert(0);
12441 }
12442 else if (exp.ident == Id.stringof)
12443 {
0fb57034 12444 Expression e = new StringExp(exp.loc, ie.toString());
5fee5ec3
IB
12445 e = e.expressionSemantic(sc);
12446 return e;
12447 }
12448 if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
12449 {
12450 flag = 0;
12451 }
12452 if (flag)
12453 return null;
12454 s = ie.sds.search_correct(exp.ident);
12455 if (s && symbolIsVisible(sc, s))
12456 {
12457 if (s.isPackage())
12458 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
12459 else
12460 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());
12461 }
12462 else
12463 exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
12464 return ErrorExp.get();
12465 }
12466 else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum && exp.ident != Id._init && exp.ident != Id.__sizeof && exp.ident != Id.__xalignof && exp.ident != Id.offsetof && exp.ident != Id._mangleof && exp.ident != Id.stringof)
12467 {
12468 Type t1bn = t1b.nextOf();
12469 if (flag)
12470 {
0fb57034
IB
12471 if (AggregateDeclaration ad = isAggregate(t1bn))
12472 {
12473 if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
12474 return null;
12475 }
5fee5ec3
IB
12476 }
12477
12478 /* Rewrite:
12479 * p.ident
12480 * as:
12481 * (*p).ident
12482 */
12483 if (flag && t1bn.ty == Tvoid)
12484 return null;
0fb57034 12485 Expression e = new PtrExp(exp.loc, exp.e1);
5fee5ec3
IB
12486 e = e.expressionSemantic(sc);
12487 return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12488 }
12489 else if (exp.ident == Id.__xalignof &&
12490 exp.e1.isVarExp() &&
12491 exp.e1.isVarExp().var.isVarDeclaration() &&
0fb57034 12492 !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
5fee5ec3
IB
12493 {
12494 // For `x.alignof` get the alignment of the variable, not the alignment of its type
12495 const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
12496 const naturalAlignment = exp.e1.type.alignsize();
0fb57034
IB
12497 const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
12498 Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
5fee5ec3
IB
12499 return e;
12500 }
12501 else
12502 {
0fb57034 12503 if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
5fee5ec3 12504 flag = 0;
0fb57034 12505 Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
5fee5ec3
IB
12506 if (e)
12507 e = e.expressionSemantic(sc);
12508 return e;
12509 }
12510}
12511
12512// Resolve e1.ident!tiargs without seeing UFCS.
12513// If flag == 1, stop "not a property" error and return NULL.
12514Expression semanticY(DotTemplateInstanceExp exp, Scope* sc, int flag)
12515{
12516 static if (LOGSEMANTIC)
12517 {
12518 printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
12519 }
12520
12521 static Expression errorExp()
12522 {
12523 return ErrorExp.get();
12524 }
12525
12526 Expression e1 = exp.e1;
12527
12528 if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
12529 {
12530 // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
12531 // and do the symbol search in that context (Issue: 19476)
12532 auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
12533 e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12534 }
12535
12536 auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12537
12538 Expression e = die.semanticX(sc);
12539 if (e == die)
12540 {
12541 exp.e1 = die.e1; // take back
12542 Type t1b = exp.e1.type.toBasetype();
12543 if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12544 {
12545 /* No built-in type has templatized properties, so do shortcut.
12546 * It is necessary in: 1024.max!"a < b"
12547 */
12548 if (flag)
12549 return null;
12550 }
12551 e = die.semanticY(sc, flag);
12552 if (flag)
12553 {
12554 if (!e ||
12555 isDotOpDispatch(e))
12556 {
12557 /* opDispatch!tiargs would be a function template that needs IFTI,
12558 * so it's not a template
12559 */
12560 return null;
12561 }
12562 }
12563 }
12564 assert(e);
12565
9c7d5e88 12566 if (e.op == EXP.error)
5fee5ec3 12567 return e;
9c7d5e88 12568 if (e.op == EXP.dotVariable)
5fee5ec3
IB
12569 {
12570 DotVarExp dve = cast(DotVarExp)e;
12571 if (FuncDeclaration fd = dve.var.isFuncDeclaration())
12572 {
12573 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12574 {
12575 e = new DotTemplateExp(dve.loc, dve.e1, td);
12576 e = e.expressionSemantic(sc);
12577 }
12578 }
12579 else if (OverDeclaration od = dve.var.isOverDeclaration())
12580 {
12581 exp.e1 = dve.e1; // pull semantic() result
12582
12583 if (!exp.findTempDecl(sc))
12584 goto Lerr;
12585 if (exp.ti.needsTypeInference(sc))
12586 return exp;
12587 exp.ti.dsymbolSemantic(sc);
12588 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12589 return errorExp();
12590
12591 if (Declaration v = exp.ti.toAlias().isDeclaration())
12592 {
12593 if (v.type && !v.type.deco)
12594 v.type = v.type.typeSemantic(v.loc, sc);
12595 return new DotVarExp(exp.loc, exp.e1, v)
12596 .expressionSemantic(sc);
12597 }
12598 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12599 .expressionSemantic(sc);
12600 }
12601 }
9c7d5e88 12602 else if (e.op == EXP.variable)
5fee5ec3
IB
12603 {
12604 VarExp ve = cast(VarExp)e;
12605 if (FuncDeclaration fd = ve.var.isFuncDeclaration())
12606 {
12607 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
12608 {
12609 e = new TemplateExp(ve.loc, td)
12610 .expressionSemantic(sc);
12611 }
12612 }
12613 else if (OverDeclaration od = ve.var.isOverDeclaration())
12614 {
12615 exp.ti.tempdecl = od;
12616 return new ScopeExp(exp.loc, exp.ti)
12617 .expressionSemantic(sc);
12618 }
12619 }
12620
9c7d5e88 12621 if (e.op == EXP.dotTemplateDeclaration)
5fee5ec3
IB
12622 {
12623 DotTemplateExp dte = cast(DotTemplateExp)e;
12624 exp.e1 = dte.e1; // pull semantic() result
12625
12626 exp.ti.tempdecl = dte.td;
12627 if (!exp.ti.semanticTiargs(sc))
12628 return errorExp();
12629 if (exp.ti.needsTypeInference(sc))
12630 return exp;
12631 exp.ti.dsymbolSemantic(sc);
12632 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12633 return errorExp();
12634
12635 if (Declaration v = exp.ti.toAlias().isDeclaration())
12636 {
12637 if (v.isFuncDeclaration() || v.isVarDeclaration())
12638 {
12639 return new DotVarExp(exp.loc, exp.e1, v)
12640 .expressionSemantic(sc);
12641 }
12642 }
12643 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12644 .expressionSemantic(sc);
12645 }
9c7d5e88 12646 else if (e.op == EXP.template_)
5fee5ec3
IB
12647 {
12648 exp.ti.tempdecl = (cast(TemplateExp)e).td;
12649 return new ScopeExp(exp.loc, exp.ti)
12650 .expressionSemantic(sc);
12651 }
9c7d5e88 12652 else if (e.op == EXP.dot)
5fee5ec3
IB
12653 {
12654 DotExp de = cast(DotExp)e;
12655
9c7d5e88 12656 if (de.e2.op == EXP.overloadSet)
5fee5ec3
IB
12657 {
12658 if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
12659 {
12660 return errorExp();
12661 }
12662 if (exp.ti.needsTypeInference(sc))
12663 return exp;
12664 exp.ti.dsymbolSemantic(sc);
12665 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
12666 return errorExp();
12667
12668 if (Declaration v = exp.ti.toAlias().isDeclaration())
12669 {
12670 if (v.type && !v.type.deco)
12671 v.type = v.type.typeSemantic(v.loc, sc);
12672 return new DotVarExp(exp.loc, exp.e1, v)
12673 .expressionSemantic(sc);
12674 }
12675 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
12676 .expressionSemantic(sc);
12677 }
12678 }
9c7d5e88 12679 else if (e.op == EXP.overloadSet)
5fee5ec3
IB
12680 {
12681 OverExp oe = cast(OverExp)e;
12682 exp.ti.tempdecl = oe.vars;
12683 return new ScopeExp(exp.loc, exp.ti)
12684 .expressionSemantic(sc);
12685 }
12686
12687Lerr:
12688 exp.error("`%s` isn't a template", e.toChars());
12689 return errorExp();
12690}
12691
12692/***************************************
12693 * If expression is shared, check that we can access it.
12694 * Give error message if not.
12695 *
12696 * Params:
12697 * e = expression to check
12698 * sc = context
12699 * returnRef = Whether this expression is for a `return` statement
12700 * off a `ref` function, in which case a single level
12701 * of dereference is allowed (e.g. `shared(int)*`).
12702 * Returns:
12703 * true on error
12704 */
12705bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
12706{
12707 if (!global.params.noSharedAccess ||
12708 sc.intypeof ||
12709 sc.flags & SCOPE.ctfe)
12710 {
12711 return false;
12712 }
12713
12714 //printf("checkSharedAccess() %s\n", e.toChars());
12715
12716 static extern(C++) final class SharedCheckVisitor : SemanticTimeTransitiveVisitor
12717 {
12718 /// In case we don't know which expression triggered it,
12719 /// e.g. for `visit(Type)` overload
12720 Expression original;
12721 /// Where the result is stored (`true` == error)
12722 bool result;
12723 /// Whether we should allow one level of dereferencing
12724 bool allowRef;
12725
12726 /// Ctor
12727 this(Expression oe, bool allowRef_)
12728 {
12729 this.original = oe;
12730 this.allowRef = allowRef_;
12731 }
12732
12733 void sharedError(Expression e)
12734 {
12735 // https://dlang.org/phobos/core_atomic.html
12736 e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
12737 this.result = true;
12738 }
12739
12740 /// Introduce base class overrides
12741 alias visit = SemanticTimeTransitiveVisitor.visit;
12742
12743 // Error by default
12744 override void visit(Expression e)
12745 {
12746 if (e.type.isShared())
12747 this.sharedError(e);
12748 }
12749
12750 /// Ditto
12751 override void visit(Type t)
12752 {
12753 // Note: This handles things like `new shared(Throwable).msg`,
12754 // where accessing `msg` would violate `shared`.
12755 if (t.isShared())
12756 this.sharedError(this.original);
12757 }
12758
12759 // Those have no indirections / can be ignored
12760 override void visit(ErrorExp e) {}
12761 override void visit(ComplexExp e) {}
12762 override void visit(IntegerExp e) {}
12763 override void visit(NullExp e) {}
12764
12765 override void visit(VarExp e)
12766 {
12767 if (!this.allowRef && e.var.type.isShared())
12768 this.sharedError(e);
12769 }
12770
12771 override void visit(AddrExp e)
12772 {
12773 this.allowRef = true;
12774 e.e1.accept(this);
12775 }
12776
12777 override void visit(PtrExp e)
12778 {
12779 if (!this.allowRef && e.type.isShared())
12780 return this.sharedError(e);
12781
12782 if (e.e1.type.isShared())
12783 return this.sharedError(e);
12784
12785 this.allowRef = false;
12786 e.e1.accept(this);
12787 }
12788
12789 override void visit(DotVarExp e)
12790 {
12791 auto fd = e.var.isFuncDeclaration();
12792 const sharedFunc = fd && fd.type.isShared;
12793
12794 if (!this.allowRef && e.type.isShared() && !sharedFunc)
12795 return this.sharedError(e);
12796
12797 // Allow to use `DotVarExp` within value types
12798 if (e.e1.type.ty == Tsarray || e.e1.type.ty == Tstruct)
12799 return e.e1.accept(this);
12800
12801 // If we end up with a single `VarExp`, it might be a `ref` param
12802 // `shared ref T` param == `shared(T)*`.
12803 if (auto ve = e.e1.isVarExp())
12804 {
12805 this.allowRef = this.allowRef && (ve.var.storage_class & STC.ref_);
12806 return e.e1.accept(this);
12807 }
12808
12809 this.allowRef = false;
12810 return e.e1.accept(this);
12811 }
12812
12813 override void visit(IndexExp e)
12814 {
12815 if (!this.allowRef && e.type.isShared())
12816 return this.sharedError(e);
12817
12818 if (e.e1.type.isShared())
12819 return this.sharedError(e);
12820
12821 this.allowRef = false;
12822 e.e1.accept(this);
12823 }
12824
12825 override void visit(CommaExp e)
12826 {
12827 // Cannot be `return ref` since we can't use the return,
12828 // but it's better to show that error than an unrelated `shared` one
12829 this.allowRef = true;
12830 e.e2.accept(this);
12831 }
12832 }
12833
12834 scope visitor = new SharedCheckVisitor(e, returnRef);
12835 e.accept(visitor);
12836 return visitor.result;
12837}
12838
12839
12840
12841/****************************************************
12842 * Determine if `exp`, which gets its address taken, can do so safely.
12843 * Params:
12844 * sc = context
12845 * exp = expression having its address taken
12846 * v = the variable getting its address taken
12847 * Returns:
12848 * `true` if ok, `false` for error
12849 */
12850bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
12851{
12852 //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
12853 if (v)
12854 {
12855 if (!v.canTakeAddressOf())
12856 {
12857 exp.error("cannot take address of `%s`", exp.toChars());
12858 return false;
12859 }
12860 if (sc.func && !sc.intypeof && !v.isDataseg())
12861 {
12862 const(char)* p = v.isParameter() ? "parameter" : "local";
12863 if (global.params.useDIP1000 == FeatureState.enabled)
12864 {
12865 // Taking the address of v means it cannot be set to 'scope' later
12866 v.storage_class &= ~STC.maybescope;
12867 v.doNotInferScope = true;
12868 if (exp.type.hasPointers() && v.storage_class & STC.scope_ &&
12869 !(v.storage_class & STC.temp) &&
12870 !(sc.flags & SCOPE.debug_) && sc.func.setUnsafe())
12871 {
12872 exp.error("cannot take address of `scope` %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12873 return false;
12874 }
12875 }
12876 else if (!(sc.flags & SCOPE.debug_) &&
12877 !(v.storage_class & STC.temp) &&
12878 sc.func.setUnsafe())
12879 {
12880 exp.error("cannot take address of %s `%s` in `@safe` function `%s`", p, v.toChars(), sc.func.toChars());
12881 return false;
12882 }
12883 }
12884 }
12885 return true;
12886}
12887
12888/*******************************
12889 * Checks the attributes of a function.
12890 * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
12891 * and usage of `deprecated` and `@disabled`-ed symbols are checked.
12892 *
12893 * Params:
12894 * exp = expression to check attributes for
12895 * sc = scope of the function
12896 * f = function to be checked
12897 * Returns: `true` if error occur.
12898 */
12899private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
12900{
12901 with(exp)
12902 {
12903 bool error = checkDisabled(sc, f);
12904 error |= checkDeprecated(sc, f);
12905 error |= checkPurity(sc, f);
12906 error |= checkSafety(sc, f);
12907 error |= checkNogc(sc, f);
12908 return error;
12909 }
12910}
12911
12912/*******************************
12913 * Helper function for `getRightThis()`.
12914 * Gets `this` of the next outer aggregate.
12915 * Params:
12916 * loc = location to use for error messages
12917 * sc = context
12918 * s = the parent symbol of the existing `this`
12919 * ad = struct or class we need the correct `this` for
12920 * e1 = existing `this`
12921 * t = type of the existing `this`
12922 * var = the specific member of ad we're accessing
12923 * flag = if true, return `null` instead of throwing an error
12924 * Returns:
12925 * Expression representing the `this` for the var
12926 */
12927Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
12928{
12929 int n = 0;
12930 while (s && s.isFuncDeclaration())
12931 {
12932 FuncDeclaration f = s.isFuncDeclaration();
12933 if (f.vthis)
12934 {
12935 n++;
12936 e1 = new VarExp(loc, f.vthis);
12937 if (f.isThis2)
12938 {
12939 // (*__this)[i]
12940 if (n > 1)
12941 e1 = e1.expressionSemantic(sc);
12942 e1 = new PtrExp(loc, e1);
12943 uint i = f.followInstantiationContext(ad);
12944 e1 = new IndexExp(loc, e1, new IntegerExp(i));
12945 s = f.toParentP(ad);
12946 continue;
12947 }
12948 }
12949 else
12950 {
12951 if (flag)
12952 return null;
12953 e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
12954 e1 = ErrorExp.get();
12955 return e1;
12956 }
12957 s = s.toParent2();
12958 }
9c7d5e88 12959 if (n > 1 || e1.op == EXP.index)
5fee5ec3
IB
12960 e1 = e1.expressionSemantic(sc);
12961 if (s && e1.type.equivalent(Type.tvoidptr))
12962 {
12963 if (auto sad = s.isAggregateDeclaration())
12964 {
12965 Type ta = sad.handleType();
12966 if (ta.ty == Tstruct)
12967 ta = ta.pointerTo();
12968 e1.type = ta;
12969 }
12970 }
12971 e1.type = e1.type.addMod(t.mod);
12972 return e1;
12973}
12974
12975/*******************************
12976 * Make a dual-context container for use as a `this` argument.
12977 * Params:
12978 * loc = location to use for error messages
12979 * sc = current scope
12980 * fd = target function that will take the `this` argument
12981 * Returns:
12982 * Temporary closure variable.
12983 * Note:
12984 * The function `fd` is added to the nested references of the
12985 * newly created variable such that a closure is made for the variable when
12986 * the address of `fd` is taken.
12987 */
12988VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
12989{
12990 Type tthis2 = Type.tvoidptr.sarrayOf(2);
12991 VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
12992 vthis2.storage_class |= STC.temp;
12993 vthis2.dsymbolSemantic(sc);
12994 vthis2.parent = sc.parent;
12995 // make it a closure var
12996 assert(sc.func);
12997 sc.func.closureVars.push(vthis2);
12998 // add `fd` to the nested refs
12999 vthis2.nestedrefs.push(fd);
13000 return vthis2;
13001}
13002
13003/*******************************
13004 * Make sure that the runtime hook `id` exists.
13005 * Params:
13006 * loc = location to use for error messages
13007 * sc = current scope
13008 * id = the hook identifier
13009 * description = what the hook does
13010 * module_ = what module the hook is located in
13011 * Returns:
13012 * a `bool` indicating if the hook is present.
13013 */
13014bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
13015{
13016 auto rootSymbol = sc.search(loc, Id.empty, null);
13017 if (auto moduleSymbol = rootSymbol.search(loc, module_))
13018 if (moduleSymbol.search(loc, id))
13019 return true;
13020 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);
13021 return false;
13022}
13023
13024/***************************************
13025 * Fit elements[] to the corresponding types of the `sd`'s fields.
13026 *
13027 * Params:
13028 * sd = the struct declaration
13029 * loc = location to use for error messages
13030 * sc = context
13031 * elements = explicit arguments used to construct object
13032 * stype = the constructed object type.
13033 * Returns:
13034 * false if any errors occur,
13035 * otherwise true and elements[] are rewritten for the output.
13036 */
13037private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
13038{
13039 if (!elements)
13040 return true;
13041
13042 const nfields = sd.nonHiddenFields();
13043 size_t offset = 0;
13044 for (size_t i = 0; i < elements.dim; i++)
13045 {
13046 Expression e = (*elements)[i];
13047 if (!e)
13048 continue;
13049
13050 e = resolveProperties(sc, e);
13051 if (i >= nfields)
13052 {
9c7d5e88 13053 if (i <= sd.fields.dim && e.op == EXP.null_)
5fee5ec3
IB
13054 {
13055 // CTFE sometimes creates null as hidden pointer; we'll allow this.
13056 continue;
13057 }
13058 .error(loc, "more initializers than fields (%zu) of `%s`", nfields, sd.toChars());
13059 return false;
13060 }
13061 VarDeclaration v = sd.fields[i];
13062 if (v.offset < offset)
13063 {
13064 .error(loc, "overlapping initialization for `%s`", v.toChars());
13065 if (!sd.isUnionDeclaration())
13066 {
13067 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
13068 " must initialize only the first member of a `union`. All subsequent" ~
13069 " non-overlapping fields are default initialized";
13070 .errorSupplemental(loc, errorMsg);
13071 }
13072 return false;
13073 }
9c7d5e88
IB
13074 const vsize = v.type.size();
13075 if (vsize == SIZE_INVALID)
13076 return false;
13077 offset = cast(uint)(v.offset + vsize);
5fee5ec3
IB
13078
13079 Type t = v.type;
13080 if (stype)
13081 t = t.addMod(stype.mod);
13082 Type origType = t;
13083 Type tb = t.toBasetype();
13084
13085 const hasPointers = tb.hasPointers();
13086 if (hasPointers)
13087 {
0fb57034 13088 if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
5fee5ec3
IB
13089 (v.offset & (target.ptrsize - 1))) &&
13090 (sc.func && sc.func.setUnsafe()))
13091 {
13092 .error(loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
13093 sd.toChars(), v.toChars());
13094 return false;
13095 }
13096 }
13097
13098 /* Look for case of initializing a static array with a too-short
13099 * string literal, such as:
13100 * char[5] foo = "abc";
13101 * Allow this by doing an explicit cast, which will lengthen the string
13102 * literal.
13103 */
9c7d5e88 13104 if (e.op == EXP.string_ && tb.ty == Tsarray)
5fee5ec3
IB
13105 {
13106 StringExp se = cast(StringExp)e;
13107 Type typeb = se.type.toBasetype();
13108 TY tynto = tb.nextOf().ty;
13109 if (!se.committed &&
13110 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
13111 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
13112 {
13113 e = se.castTo(sc, t);
13114 goto L1;
13115 }
13116 }
13117
13118 while (!e.implicitConvTo(t) && tb.ty == Tsarray)
13119 {
13120 /* Static array initialization, as in:
13121 * T[3][5] = e;
13122 */
13123 t = tb.nextOf();
13124 tb = t.toBasetype();
13125 }
13126 if (!e.implicitConvTo(t))
13127 t = origType; // restore type for better diagnostic
13128
13129 e = e.implicitCastTo(sc, t);
13130 L1:
9c7d5e88 13131 if (e.op == EXP.error)
5fee5ec3
IB
13132 return false;
13133
13134 (*elements)[i] = doCopyOrMove(sc, e);
13135 }
13136 return true;
13137}
13138
13139
13140/**
13141 * Returns `em` as a VariableExp
13142 * Params:
13143 * em = the EnumMember to wrap
13144 * loc = location of use of em
13145 * sc = scope of use of em
13146 * Returns:
13147 * VarExp referenceing `em` or ErrorExp if `em` if disabled/deprecated
13148 */
13149Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
13150{
13151 dsymbolSemantic(em, sc);
13152 if (em.errors)
13153 return ErrorExp.get();
13154 em.checkDisabled(loc, sc);
13155
13156 if (em.depdecl && !em.depdecl._scope)
13157 em.depdecl._scope = sc;
13158 em.checkDeprecated(loc, sc);
13159
13160 if (em.errors)
13161 return ErrorExp.get();
13162 Expression e = new VarExp(loc, em);
13163 return e.expressionSemantic(sc);
13164}
13165
13166
13167/*****************************
13168 * Try to treat `exp` as a boolean,
13169 * Params:
13170 * exp = the expression
13171 * sc = scope to evalute `exp` in
13172 * Returns:
13173 * Modified expression on success, ErrorExp on error
13174 */
13175Expression toBoolean(Expression exp, Scope* sc)
13176{
13177 switch(exp.op)
13178 {
9c7d5e88 13179 case EXP.delete_:
5fee5ec3
IB
13180 exp.error("`delete` does not give a boolean result");
13181 return ErrorExp.get();
13182
9c7d5e88 13183 case EXP.comma:
5fee5ec3
IB
13184 auto ce = exp.isCommaExp();
13185 auto ex2 = ce.e2.toBoolean(sc);
9c7d5e88 13186 if (ex2.op == EXP.error)
5fee5ec3
IB
13187 return ex2;
13188 ce.e2 = ex2;
13189 ce.type = ce.e2.type;
13190 return ce;
13191
9c7d5e88
IB
13192 case EXP.assign:
13193 case EXP.construct:
13194 case EXP.blit:
5fee5ec3
IB
13195 // Things like:
13196 // if (a = b) ...
13197 // are usually mistakes.
13198 exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
13199 return ErrorExp.get();
13200
13201 //LogicalExp
9c7d5e88
IB
13202 case EXP.andAnd:
13203 case EXP.orOr:
5fee5ec3
IB
13204 auto le = exp.isLogicalExp();
13205 auto ex2 = le.e2.toBoolean(sc);
9c7d5e88 13206 if (ex2.op == EXP.error)
5fee5ec3
IB
13207 return ex2;
13208 le.e2 = ex2;
13209 return le;
13210
9c7d5e88 13211 case EXP.question:
5fee5ec3
IB
13212 auto ce = exp.isCondExp();
13213 auto ex1 = ce.e1.toBoolean(sc);
13214 auto ex2 = ce.e2.toBoolean(sc);
9c7d5e88 13215 if (ex1.op == EXP.error)
5fee5ec3 13216 return ex1;
9c7d5e88 13217 if (ex2.op == EXP.error)
5fee5ec3
IB
13218 return ex2;
13219 ce.e1 = ex1;
13220 ce.e2 = ex2;
13221 return ce;
13222
13223
13224 default:
13225 // Default is 'yes' - do nothing
13226 Expression e = exp;
13227 Type t = exp.type;
13228 Type tb = t.toBasetype();
13229 Type att = null;
13230
13231 while (1)
13232 {
13233 // Structs can be converted to bool using opCast(bool)()
13234 if (auto ts = tb.isTypeStruct())
13235 {
13236 AggregateDeclaration ad = ts.sym;
13237 /* Don't really need to check for opCast first, but by doing so we
13238 * get better error messages if it isn't there.
13239 */
13240 if (Dsymbol fd = search_function(ad, Id._cast))
13241 {
13242 e = new CastExp(exp.loc, e, Type.tbool);
13243 e = e.expressionSemantic(sc);
13244 return e;
13245 }
13246
13247 // Forward to aliasthis.
13248 if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
13249 {
13250 e = resolveAliasThis(sc, e);
13251 t = e.type;
13252 tb = e.type.toBasetype();
13253 continue;
13254 }
13255 }
13256 break;
13257 }
13258
13259 if (!t.isBoolean())
13260 {
13261 if (tb != Type.terror)
13262 exp.error("expression `%s` of type `%s` does not have a boolean value",
13263 exp.toChars(), t.toChars());
13264 return ErrorExp.get();
13265 }
13266 return e;
13267 }
13268}