2 * Semantic analysis of expressions.
4 * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions)
6 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d)
10 * Documentation: https://dlang.org/phobos/dmd_expressionsem.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/expressionsem.d
14 module dmd.expressionsem;
16 import core.stdc.stdio;
22 import dmd.arraytypes;
24 import dmd.astcodegen;
31 import dmd.declaration;
34 import dmd.delegatize;
37 import dmd.dinterpret;
41 import dmd.dsymbolsem;
45 import dmd.expression;
46 import dmd.file_manager;
51 import dmd.identifier;
66 import dmd.root.array;
67 import dmd.root.ctfloat;
69 import dmd.root.filename;
70 import dmd.common.outbuffer;
71 import dmd.root.rootobject;
72 import dmd.root.string;
76 import dmd.sideeffect;
86 enum LOGSEMANTIC = false;
88 /********************************************************
89 * Perform semantic analysis and CTFE on expressions to produce
92 * buf = append generated string to buffer
94 * exps = array of Expressions
98 bool expressionsToString(ref OutBuffer buf, Scope* sc, Expressions* exps)
107 auto sc2 = sc.startCTFE();
108 auto e2 = ex.expressionSemantic(sc2);
109 auto e3 = resolveProperties(sc2, e2);
112 // allowed to contain types as well as expressions
113 auto e4 = ctfeInterpretForPragmaMsg(e3);
114 if (!e4 || e4.op == EXP.error)
118 if (auto te = e4.isTupleExp())
120 if (expressionsToString(buf, sc, te.exps))
124 // char literals exp `.toStringExp` return `null` but we cant override it
125 // because in most contexts we don't want the conversion to succeed.
126 IntegerExp ie = e4.isIntegerExp();
127 const ty = (ie && ie.type) ? ie.type.ty : Terror;
130 auto tsa = new TypeSArray(ie.type, IntegerExp.literal!1);
131 e4 = new ArrayLiteralExp(ex.loc, tsa, ie);
134 if (StringExp se = e4.toStringExp())
135 buf.writestring(se.toUTF8(sc).peekString());
137 buf.writestring(e4.toString());
143 /***********************************************************
144 * Resolve `exp` as a compile-time known string.
147 * exp = Expression which expected as a string
148 * s = What the string is expected for, will be used in error diagnostic.
150 * String literal, or `null` if error happens.
152 StringExp semanticString(Scope *sc, Expression exp, const char* s)
155 exp = exp.expressionSemantic(sc);
156 exp = resolveProperties(sc, exp);
159 if (exp.op == EXP.error)
163 if (exp.type.isString())
165 e = e.ctfeInterpret();
166 if (e.op == EXP.error)
170 auto se = e.toStringExp();
173 exp.error("`string` expected for %s, not `(%s)` of type `%s`",
174 s, exp.toChars(), exp.type.toChars());
180 private Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
183 Expression e1 = Expression.extractLast(ue.e1, e0);
184 // https://issues.dlang.org/show_bug.cgi?id=12585
185 // Extract the side effect part if ue.e1 is comma.
187 if ((sc.flags & SCOPE.ctfe) ? hasSideEffect(e1) : !isTrivialExp(e1)) // match logic in extractSideEffect()
189 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
191 * e1.opIndex( ... use of $ ... )
192 * e1.opSlice( ... use of $ ... )
194 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
195 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
197 e1 = extractSideEffect(sc, "__dop", e0, e1, false);
198 assert(e1.isVarExp());
199 e1.isVarExp().var.storage_class |= STC.exptemp; // lifetime limited to expression
205 /**************************************
206 * Runs semantic on ae.arguments. Declares temporary variables
209 Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
211 assert(!ae.lengthVar);
213 AggregateDeclaration ad = isAggregate(ae.e1.type);
214 Dsymbol slice = search_function(ad, Id.slice);
215 //printf("slice = %s %s\n", slice.kind(), slice.toChars());
216 foreach (i, e; *ae.arguments)
219 *pe0 = extractOpDollarSideEffect(sc, ae);
221 if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
224 if (ae.arguments.length == 1)
226 ae.error("multi-dimensional slicing requires template `opSlice`");
227 return ErrorExp.get();
229 //printf("[%d] e = %s\n", i, e.toChars());
231 // Create scope for '$' variable for this dimension
232 auto sym = new ArrayScopeSymbol(sc, ae);
233 sym.parent = sc.scopesym;
235 ae.lengthVar = null; // Create it only if required
236 ae.currentDimension = i; // Dimension for $, if required
238 e = e.expressionSemantic(sc);
239 e = resolveProperties(sc, e);
241 if (ae.lengthVar && sc.func)
243 // If $ was used, declare it now
244 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
245 de = de.expressionSemantic(sc);
246 *pe0 = Expression.combine(*pe0, de);
250 if (auto ie = e.isIntervalExp())
252 auto tiargs = new Objects();
253 Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
254 edim = edim.expressionSemantic(sc);
257 auto fargs = new Expressions(2);
258 (*fargs)[0] = ie.lwr;
259 (*fargs)[1] = ie.upr;
261 uint xerrors = global.startGagging();
263 FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, FuncResolveFlag.quiet);
265 global.endGagging(xerrors);
269 e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
270 e = new CallExp(ae.loc, e, fargs);
271 e = e.expressionSemantic(sc);
276 ae.error("`%s` has no value", e.toChars());
279 if (e.op == EXP.error)
282 (*ae.arguments)[i] = e;
287 /**************************************
288 * Runs semantic on se.lwr and se.upr. Declares a temporary variable
291 * ae, or ErrorExp if errors occurred
293 Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
295 //assert(!ae.lengthVar);
299 VarDeclaration lengthVar = ae.lengthVar;
302 // create scope for '$'
303 auto sym = new ArrayScopeSymbol(sc, ae);
304 sym.parent = sc.scopesym;
307 Expression sem(Expression e)
309 e = e.expressionSemantic(sc);
310 e = resolveProperties(sc, e);
313 ae.error("`%s` has no value", e.toChars());
319 ie.lwr = sem(ie.lwr);
320 ie.upr = sem(ie.upr);
322 if (ie.lwr.isErrorExp() || ie.upr.isErrorExp())
325 if (lengthVar != ae.lengthVar && sc.func)
327 // If $ was used, declare it now
328 Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
329 de = de.expressionSemantic(sc);
330 *pe0 = Expression.combine(*pe0, de);
335 return errors ? ErrorExp.get() : ae;
338 /******************************
339 * Perform semantic() on an array of Expressions.
341 extern(D) bool arrayExpressionSemantic(
342 Expression[] exps, Scope* sc, bool preserveErrors = false)
345 foreach (ref e; exps)
347 if (e is null) continue;
348 auto e2 = e.expressionSemantic(sc);
349 if (e2.op == EXP.error)
351 if (preserveErrors || e2.op != EXP.error)
358 Checks if `exp` contains a direct access to a `noreturn`
359 variable. If that is the case, an `assert(0)` expression
360 is generated and returned. This function should be called
361 only after semantic analysis has been performed on `exp`.
364 exp = expression that is checked
367 An `assert(0)` expression if `exp` contains a `noreturn`
368 variable access, `exp` otherwise.
371 Expression checkNoreturnVarAccess(Expression exp)
375 Expression result = exp;
376 if (exp.type.isTypeNoreturn() && !exp.isAssertExp() &&
377 !exp.isThrowExp() && !exp.isCallExp())
379 auto msg = new StringExp(exp.loc, "Accessed expression of type `noreturn`");
380 msg.type = Type.tstring;
381 result = new AssertExp(exp.loc, IntegerExp.literal!0, msg);
382 result.type = exp.type;
388 /******************************
389 * Check the tail CallExp is really property function call.
391 * This doesn't appear to do anything.
393 private bool checkPropertyCall(Expression e)
397 if (auto ce = e.isCallExp())
401 auto tf = ce.f.type.isTypeFunction();
402 /* If a forward reference to ce.f, try to resolve it
404 if (!tf.deco && ce.f.semanticRun < PASS.semanticdone)
406 ce.f.dsymbolSemantic(null);
407 tf = ce.f.type.isTypeFunction();
410 else if (!ce.e1.type.isFunction_Delegate_PtrToFunction())
416 /******************************
417 * Find symbol in accordance with the UFCS name look up rule
419 private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
421 //printf("searchUFCS(ident = %s)\n", ident.toChars());
424 // TODO: merge with Scope.search.searchScopes()
425 Dsymbol searchScopes(int flags)
428 for (Scope* scx = sc; scx; scx = scx.enclosing)
432 if (scx.scopesym.isModule())
433 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
434 s = scx.scopesym.search(loc, ident, flags);
437 // overload set contains only module scope symbols.
438 if (s.isOverloadSet())
440 // selective/renamed imports also be picked up
441 if (AliasDeclaration ad = s.isAliasDeclaration())
446 // See only module scope symbols for UFCS target.
447 Dsymbol p = s.toParent2();
448 if (p && p.isModule())
453 // Stop when we hit a module, but keep going if that is not just under the global scope
454 if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
463 if (sc.flags & SCOPE.ignoresymbolvisibility)
464 flags |= IgnoreSymbolVisibility;
466 // First look in local scopes
467 s = searchScopes(flags | SearchLocalsOnly);
470 // Second look in imported modules
471 s = searchScopes(flags | SearchImportsOnly);
475 return ue.e1.type.getProperty(sc, loc, ident, 0, ue.e1);
477 FuncDeclaration f = s.isFuncDeclaration();
480 TemplateDeclaration td = getFuncTemplateDecl(f);
489 if (auto dti = ue.isDotTemplateInstanceExp())
491 auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
492 if (!ti.updateTempDecl(sc, s))
493 return ErrorExp.get();
494 return new ScopeExp(loc, ti);
498 //printf("-searchUFCS() %s\n", s.toChars());
499 return new DsymbolExp(loc, s);
503 /******************************
504 * Pull out callable entity with UFCS.
506 private Expression resolveUFCS(Scope* sc, CallExp ce)
512 if (auto die = ce.e1.isDotIdExp())
514 Identifier ident = die.ident;
516 Expression ex = die.dotIdSemanticPropX(sc);
524 Type t = eleft.type.toBasetype();
525 if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
527 /* Built-in types and arrays have no callable properties, so do shortcut.
528 * It is necessary in: e.init()
531 else if (t.ty == Taarray)
533 if (ident == Id.remove)
536 * aa.remove(arg) into delete aa[arg]
538 if (!ce.arguments || ce.arguments.length != 1)
540 ce.error("expected key as argument to `aa.remove()`");
541 return ErrorExp.get();
543 if (!eleft.type.isMutable())
545 ce.error("cannot remove key from `%s` associative array `%s`", MODtoChars(t.mod), eleft.toChars());
546 return ErrorExp.get();
548 Expression key = (*ce.arguments)[0];
549 key = key.expressionSemantic(sc);
550 key = resolveProperties(sc, key);
552 TypeAArray taa = t.isTypeAArray();
553 key = key.implicitCastTo(sc, taa.index);
555 if (key.checkValue() || key.checkSharedAccess(sc))
556 return ErrorExp.get();
558 semanticTypeInfo(sc, taa.index);
560 return new RemoveExp(loc, eleft, key);
565 if (Expression ey = die.dotIdSemanticProp(sc, 1))
567 if (ey.op == EXP.error)
570 if (isDotOpDispatch(ey))
572 // even opDispatch and UFCS must have valid arguments,
573 // so now that we've seen indication of a problem,
574 // check them for issues.
575 Expressions* originalArguments = Expression.arraySyntaxCopy(ce.arguments);
577 uint errors = global.startGagging();
578 e = ce.expressionSemantic(sc);
579 if (!global.endGagging(errors))
582 if (arrayExpressionSemantic(originalArguments.peekSlice(), sc))
583 return ErrorExp.get();
585 /* fall down to UFCS */
592 /* https://issues.dlang.org/show_bug.cgi?id=13953
594 * If a struct has an alias this to an associative array
595 * and remove is used on a struct instance, we have to
596 * check first if there is a remove function that can be called
597 * on the struct. If not we must check the alias this.
611 const errors = global.startGagging();
612 e = searchUFCS(sc, die, ident);
613 // if there were any errors and the identifier was remove
614 if (global.endGagging(errors))
616 if (ident == Id.remove)
619 Expression alias_e = resolveAliasThis(sc, die.e1, 1);
620 if (alias_e && alias_e != die.e1)
623 CallExp ce2 = ce.syntaxCopy();
625 e = ce2.isCallExp().trySemantic(sc);
630 // if alias this did not work out, print the initial errors
631 searchUFCS(sc, die, ident);
634 else if (auto dti = ce.e1.isDotTemplateInstanceExp())
636 if (Expression ey = dti.dotTemplateSemanticProp(sc, 1))
642 e = searchUFCS(sc, dti, dti.ti.name);
650 ce.arguments = new Expressions();
651 ce.arguments.shift(eleft);
656 /******************************
657 * Pull out property with UFCS.
659 private Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
665 if (auto die = e1.isDotIdExp())
668 e = searchUFCS(sc, die, die.ident);
670 else if (auto dti = e1.isDotTemplateInstanceExp())
673 e = searchUFCS(sc, dti, dti.ti.name);
684 // run semantic without gagging
685 e2 = e2.expressionSemantic(sc);
689 Expression ex = e.copy();
690 auto a1 = new Expressions(1);
692 ex = new CallExp(loc, ex, a1);
693 auto e1PassSemantic = ex.trySemantic(sc);
697 auto a2 = new Expressions(2);
700 e = new CallExp(loc, e, a2);
701 e = e.trySemantic(sc);
702 if (!e1PassSemantic && !e)
704 /* https://issues.dlang.org/show_bug.cgi?id=20448
706 * If both versions have failed to pass semantic,
707 * f(e1) = e2 gets priority in error printing
708 * because f might be a templated function that
709 * failed to instantiate and we have to print
710 * the instantiation errors.
712 return e1.expressionSemantic(sc);
716 checkPropertyCall(ex);
717 ex = new AssignExp(loc, ex, e2);
718 return ex.expressionSemantic(sc);
722 // strict setter prints errors if fails
723 e = e.expressionSemantic(sc);
725 checkPropertyCall(e);
732 auto arguments = new Expressions(1);
733 (*arguments)[0] = eleft;
734 e = new CallExp(loc, e, arguments);
735 e = e.expressionSemantic(sc);
736 checkPropertyCall(e);
737 return e.expressionSemantic(sc);
741 /******************************
742 * If e1 is a property function (template), resolve it.
744 Expression resolvePropertiesOnly(Scope* sc, Expression e1)
746 //printf("e1 = %s %s\n", Token.toChars(e1.op), e1.toChars());
748 Expression handleOverloadSet(OverloadSet os)
753 auto fd = s.isFuncDeclaration();
754 auto td = s.isTemplateDeclaration();
757 if (fd.type.isTypeFunction().isproperty)
758 return resolveProperties(sc, e1);
760 else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
762 if (fd.type.isTypeFunction().isproperty ||
763 (fd.storage_class2 & STC.property) ||
764 (td._scope.stc & STC.property))
765 return resolveProperties(sc, e1);
771 Expression handleTemplateDecl(TemplateDeclaration td)
776 if (auto fd = td.onemember.isFuncDeclaration())
778 if (fd.type.isTypeFunction().isproperty ||
779 (fd.storage_class2 & STC.property) ||
780 (td._scope.stc & STC.property))
781 return resolveProperties(sc, e1);
787 Expression handleFuncDecl(FuncDeclaration fd)
790 if (fd.type.isTypeFunction().isproperty)
791 return resolveProperties(sc, e1);
795 if (auto de = e1.isDotExp())
797 if (auto os = de.e2.isOverExp())
798 return handleOverloadSet(os.vars);
800 else if (auto oe = e1.isOverExp())
801 return handleOverloadSet(oe.vars);
802 else if (auto dti = e1.isDotTemplateInstanceExp())
805 if (auto td = dti.ti.tempdecl.isTemplateDeclaration())
806 return handleTemplateDecl(td);
808 else if (auto dte = e1.isDotTemplateExp())
809 return handleTemplateDecl(dte.td);
810 else if (auto se = e1.isScopeExp())
813 TemplateInstance ti = s.isTemplateInstance();
814 if (ti && !ti.semanticRun && ti.tempdecl)
815 if (auto td = ti.tempdecl.isTemplateDeclaration())
816 return handleTemplateDecl(td);
818 else if (auto et = e1.isTemplateExp())
819 return handleTemplateDecl(et.td);
820 else if (e1.isDotVarExp() && e1.type.isTypeFunction())
822 DotVarExp dve = e1.isDotVarExp();
823 return handleFuncDecl(dve.var.isFuncDeclaration());
825 else if (e1.isVarExp() && e1.type && e1.type.isTypeFunction() && (sc.intypeof || !e1.isVarExp().var.needThis()))
826 return handleFuncDecl(e1.isVarExp().var.isFuncDeclaration());
830 /****************************************
831 * Turn symbol `s` into the expression it represents.
834 * s = symbol to resolve
835 * loc = location of use of `s`
837 * hasOverloads = applies if `s` represents a function.
838 * true means it's overloaded and will be resolved later,
839 * false means it's the exact function symbol.
841 * `s` turned into an expression, `ErrorExp` if an error occurred
843 Expression symbolToExp(Dsymbol s, const ref Loc loc, Scope *sc, bool hasOverloads)
845 static if (LOGSEMANTIC)
847 printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
853 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
854 //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
856 Declaration d = s.isDeclaration();
857 if (d && (d.storage_class & STC.templateparameter))
863 // functions are checked after overloading
864 // templates are checked after matching constraints
865 if (!s.isFuncDeclaration() && !s.isTemplateDeclaration())
867 s.checkDeprecated(loc, sc);
869 d.checkDisabled(loc, sc);
872 // https://issues.dlang.org/show_bug.cgi?id=12023
873 // if 's' is a tuple variable, the tuple is returned.
876 //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
877 if (s != olds && !s.isFuncDeclaration() && !s.isTemplateDeclaration())
879 s.checkDeprecated(loc, sc);
881 d.checkDisabled(loc, sc);
884 if (auto sd = s.isDeclaration())
888 if (sc.setUnsafePreview(global.params.systemVariables, false, loc,
889 "cannot access `@system` variable `%s` in @safe code", sd))
891 return ErrorExp.get();
897 if (auto em = s.isEnumMember())
899 return em.getVarExp(loc, sc);
901 if (auto v = s.isVarDeclaration())
903 //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
904 if (sc.intypeof == 1 && !v.inuse)
905 v.dsymbolSemantic(sc);
906 if (!v.type || // during variable type inference
907 !v.type.deco && v.inuse) // during variable type semantic
909 if (v.inuse) // variable type depends on the variable itself
910 error(loc, "circular reference to %s `%s`", v.kind(), v.toPrettyChars());
911 else // variable type cannot be determined
912 error(loc, "forward reference to %s `%s`", v.kind(), v.toPrettyChars());
913 return ErrorExp.get();
915 if (v.type.ty == Terror)
916 return ErrorExp.get();
918 if ((v.storage_class & STC.manifest) && v._init)
922 error(loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
923 return ErrorExp.get();
925 e = v.expandInitializer(loc);
927 e = e.expressionSemantic(sc);
932 // We need to run semantics to correctly set 'STC.field' if it is a member variable
933 // that could be forward referenced. This is needed for 'v.needThis()' to work
935 v.dsymbolSemantic(sc);
937 // Change the ancestor lambdas to delegate before hasThis(sc) call.
938 if (v.checkNestedReference(sc, loc))
939 return ErrorExp.get();
941 if (v.needThis() && hasThis(sc))
942 e = new DotVarExp(loc, new ThisExp(loc), v);
944 e = new VarExp(loc, v);
945 e = e.expressionSemantic(sc);
948 if (auto fld = s.isFuncLiteralDeclaration())
950 //printf("'%s' is a function literal\n", fld.toChars());
951 e = new FuncExp(loc, fld);
952 return e.expressionSemantic(sc);
954 if (auto f = s.isFuncDeclaration())
957 if (!f.functionSemantic())
958 return ErrorExp.get();
960 if (!hasOverloads && f.checkForwardRef(loc))
961 return ErrorExp.get();
963 auto fd = s.isFuncDeclaration();
965 return new VarExp(loc, fd, hasOverloads);
967 if (OverDeclaration od = s.isOverDeclaration())
969 e = new VarExp(loc, od, true);
973 if (OverloadSet o = s.isOverloadSet())
975 //printf("'%s' is an overload set\n", o.toChars());
976 return new OverExp(loc, o);
979 if (Import imp = s.isImport())
983 .error(loc, "forward reference of import `%s`", imp.toChars());
984 return ErrorExp.get();
986 auto ie = new ScopeExp(loc, imp.pkg);
987 return ie.expressionSemantic(sc);
989 if (Package pkg = s.isPackage())
991 auto ie = new ScopeExp(loc, pkg);
992 return ie.expressionSemantic(sc);
994 if (Module mod = s.isModule())
996 auto ie = new ScopeExp(loc, mod);
997 return ie.expressionSemantic(sc);
999 if (Nspace ns = s.isNspace())
1001 auto ie = new ScopeExp(loc, ns);
1002 return ie.expressionSemantic(sc);
1005 if (Type t = s.getType())
1007 return (new TypeExp(loc, t)).expressionSemantic(sc);
1010 if (TupleDeclaration tup = s.isTupleDeclaration())
1012 if (tup.needThis() && hasThis(sc))
1013 e = new DotVarExp(loc, new ThisExp(loc), tup);
1015 e = new TupleExp(loc, tup);
1016 e = e.expressionSemantic(sc);
1020 if (TemplateInstance ti = s.isTemplateInstance())
1022 ti.dsymbolSemantic(sc);
1023 if (!ti.inst || ti.errors)
1024 return ErrorExp.get();
1026 if (!s.isTemplateInstance())
1028 e = new ScopeExp(loc, ti);
1029 e = e.expressionSemantic(sc);
1032 if (TemplateDeclaration td = s.isTemplateDeclaration())
1034 Dsymbol p = td.toParentLocal();
1035 FuncDeclaration fdthis = hasThis(sc);
1036 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
1037 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
1039 e = new DotTemplateExp(loc, new ThisExp(loc), td);
1042 e = new TemplateExp(loc, td);
1043 e = e.expressionSemantic(sc);
1047 .error(loc, "%s `%s` is not a variable", s.kind(), s.toChars());
1048 return ErrorExp.get();
1051 /*************************************************************
1052 * Given var, get the
1053 * right `this` pointer if var is in an outer class, but our
1054 * existing `this` pointer is in an inner class.
1056 * loc = location to use for error messages
1058 * ad = struct or class we need the correct `this` for
1059 * e1 = existing `this`
1060 * var = the specific member of ad we're accessing
1061 * flag = if true, return `null` instead of throwing an error
1063 * Expression representing the `this` for the var
1065 private Expression getRightThis(const ref Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Dsymbol var, int flag = 0)
1067 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
1069 Type t = e1.type.toBasetype();
1070 //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
1072 if (e1.op == EXP.objcClassReference)
1074 // We already have an Objective-C class reference, just use that as 'this'.
1077 else if (ad && ad.isClassDeclaration && ad.isClassDeclaration.classKind == ClassKind.objc &&
1078 var.isFuncDeclaration && var.isFuncDeclaration.isStatic &&
1079 var.isFuncDeclaration.objc.selector)
1081 return new ObjcClassReferenceExp(e1.loc, ad.isClassDeclaration());
1084 /* Access of a member which is a template parameter in dual-scope scenario
1085 * class A { inc(alias m)() { ++m; } } // `m` needs `this` of `B`
1086 * class B {int m; inc() { new A().inc!m(); } }
1088 if (e1.op == EXP.this_)
1090 FuncDeclaration f = hasThis(sc);
1091 if (f && f.hasDualContext())
1093 if (f.followInstantiationContext(ad))
1095 e1 = new VarExp(loc, f.vthis);
1096 e1 = new PtrExp(loc, e1);
1097 e1 = new IndexExp(loc, e1, IntegerExp.literal!1);
1098 e1 = getThisSkipNestedFuncs(loc, sc, f.toParent2(), ad, e1, t, var);
1099 if (e1.op == EXP.error)
1106 /* If e1 is not the 'this' pointer for ad
1109 !(t.isTypePointer() && t.nextOf().isTypeStruct() && t.nextOf().isTypeStruct().sym == ad) &&
1110 !(t.isTypeStruct() && t.isTypeStruct().sym == ad))
1112 ClassDeclaration cd = ad.isClassDeclaration();
1113 ClassDeclaration tcd = t.isClassHandle();
1115 /* e1 is the right this if ad is a base class of e1
1117 if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
1119 /* Only classes can be inner classes with an 'outer'
1120 * member pointing to the enclosing class instance
1122 if (tcd && tcd.isNested())
1124 /* e1 is the 'this' pointer for an inner class: tcd.
1125 * Rewrite it as the 'this' pointer for the outer class.
1127 auto vthis = tcd.followInstantiationContext(ad) ? tcd.vthis2 : tcd.vthis;
1128 e1 = new DotVarExp(loc, e1, vthis);
1129 e1.type = vthis.type;
1130 e1.type = e1.type.addMod(t.mod);
1131 // Do not call ensureStaticLinkTo()
1132 //e1 = e1.semantic(sc);
1134 // Skip up over nested functions, and get the enclosing
1136 e1 = getThisSkipNestedFuncs(loc, sc, tcd.toParentP(ad), ad, e1, t, var);
1137 if (e1.op == EXP.error)
1142 /* Can't find a path from e1 to ad
1146 e1.error("`this` for `%s` needs to be type `%s` not type `%s`", var.toChars(), ad.toChars(), t.toChars());
1147 return ErrorExp.get();
1153 /***************************************
1154 * Pull out any properties.
1156 private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
1158 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", EXPtoString(e1.op).ptr, e1.toChars(), e2 ? e2.toChars() : null);
1165 if (auto de = e1.isDotExp())
1167 if (auto oe = de.e2.isOverExp())
1175 else if (e1.isOverExp())
1179 os = e1.isOverExp().vars;
1182 FuncDeclaration fd = null;
1185 e2 = e2.expressionSemantic(sc);
1186 if (e2.op == EXP.error)
1187 return ErrorExp.get();
1188 e2 = resolveProperties(sc, e2);
1193 for (size_t i = 0; i < os.a.length; i++)
1195 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
1198 return ErrorExp.get();
1200 assert(fd.type.ty == Tfunction);
1205 Expression e = new CallExp(loc, e1, e2);
1206 return e.expressionSemantic(sc);
1210 for (size_t i = 0; i < os.a.length; i++)
1212 if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
1215 return ErrorExp.get();
1217 assert(fd.type.ty == Tfunction);
1218 auto tf = fd.type.isTypeFunction();
1219 if (!tf.isref && e2)
1221 error(loc, "%s is not an lvalue", e1.toChars());
1222 return ErrorExp.get();
1228 Expression e = new CallExp(loc, e1);
1230 e = new AssignExp(loc, e, e2);
1231 return e.expressionSemantic(sc);
1237 else if (auto dti = e1.isDotTemplateInstanceExp())
1239 if (!dti.findTempDecl(sc))
1241 if (!dti.ti.semanticTiargs(sc))
1243 tiargs = dti.ti.tiargs;
1244 tthis = dti.e1.type;
1245 if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
1247 if ((s = dti.ti.tempdecl) !is null)
1250 else if (auto dte = e1.isDotTemplateExp())
1254 tthis = dte.e1.type;
1257 else if (auto se = e1.isScopeExp())
1260 TemplateInstance ti = s.isTemplateInstance();
1261 if (ti && !ti.semanticRun && ti.tempdecl)
1263 //assert(ti.needsTypeInference(sc));
1264 if (!ti.semanticTiargs(sc))
1268 if ((os = ti.tempdecl.isOverloadSet()) !is null)
1270 if ((s = ti.tempdecl) !is null)
1274 else if (auto te = e1.isTemplateExp())
1281 else if (e1.isDotVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isDotVarExp().var.isOverDeclaration()))
1283 DotVarExp dve = e1.isDotVarExp();
1286 tthis = dve.e1.type;
1289 else if (sc && sc.flags & SCOPE.Cfile && e1.isVarExp() && !e2)
1291 // ImportC: do not implicitly call function if no ( ) are present
1293 else if (e1.isVarExp() && e1.type && (e1.type.toBasetype().isTypeFunction() || e1.isVarExp().var.isOverDeclaration()))
1295 s = e1.isVarExp().var;
1302 e2 = e2.expressionSemantic(sc);
1303 if (e2.op == EXP.error)
1304 return ErrorExp.get();
1305 e2 = resolveProperties(sc, e2);
1310 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, FuncResolveFlag.quiet);
1314 return ErrorExp.get();
1315 if (!checkSymbolAccess(sc, fd))
1317 // @@@DEPRECATED_2.105@@@
1318 // When turning into error, uncomment the return statement
1319 TypeFunction tf = fd.type.isTypeFunction();
1320 deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
1321 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1322 //return ErrorExp.get();
1324 assert(fd.type.ty == Tfunction);
1325 Expression e = new CallExp(loc, e1, e2);
1326 return e.expressionSemantic(sc);
1330 FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, FuncResolveFlag.quiet);
1334 return ErrorExp.get();
1335 TypeFunction tf = fd.type.isTypeFunction();
1336 if (!e2 || tf.isref)
1338 if (!checkSymbolAccess(sc, fd))
1340 // @@@DEPRECATED_2.105@@@
1341 // When turning into error, uncomment the return statement
1342 deprecation(loc, "function `%s` of type `%s` is not accessible from module `%s`",
1343 fd.toPrettyChars(), tf.toChars, sc._module.toChars);
1344 //return ErrorExp.get();
1346 Expression e = new CallExp(loc, e1);
1348 e = new AssignExp(loc, e, e2);
1349 return e.expressionSemantic(sc);
1353 if (FuncDeclaration fd = s.isFuncDeclaration())
1355 // Keep better diagnostic message for invalid property usage of functions
1356 assert(fd.type.ty == Tfunction);
1357 Expression e = new CallExp(loc, e1, e2);
1358 return e.expressionSemantic(sc);
1363 if (auto ve = e1.isVarExp())
1365 if (auto v = ve.var.isVarDeclaration())
1367 if (ve.checkPurity(sc, v))
1368 return ErrorExp.get();
1374 if (e1.type && !e1.isTypeExp()) // function type is not a property
1376 /* Look for e1 being a lazy parameter; rewrite as delegate call
1377 * only if the symbol wasn't already treated as a delegate
1379 auto ve = e1.isVarExp();
1380 if (ve && ve.var.storage_class & STC.lazy_ && !ve.delegateWasExtracted)
1382 Expression e = new CallExp(loc, e1);
1383 return e.expressionSemantic(sc);
1385 else if (e1.isDotVarExp())
1387 // Check for reading overlapped pointer field in @safe code.
1388 if (checkUnsafeAccess(sc, e1, true, true))
1389 return ErrorExp.get();
1391 else if (auto ce = e1.isCallExp())
1393 // Check for reading overlapped pointer field in @safe code.
1394 if (checkUnsafeAccess(sc, ce.e1, true, true))
1395 return ErrorExp.get();
1401 error(loc, "cannot resolve type for %s", e1.toChars());
1402 e1 = ErrorExp.get();
1407 error(loc, "not a property %s", e1.toChars());
1408 return ErrorExp.get();
1411 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
1413 //printf("resolveProperties(%s)\n", e.toChars());
1414 e = resolvePropertiesX(sc, e);
1415 if (e.checkRightThis(sc))
1416 return ErrorExp.get();
1420 /****************************************
1421 * The common type is determined by applying ?: to each pair.
1423 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1425 * The common type, or `null` if an error has occured
1427 private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps)
1429 /* Still have a problem with:
1430 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1431 * which works if the array literal is initialized top down with the ubyte[][]
1432 * type, but fails with this function doing bottom up typing.
1435 //printf("arrayExpressionToCommonType()\n");
1436 scope IntegerExp integerexp = IntegerExp.literal!0;
1437 scope CondExp condexp = new CondExp(Loc.initial, integerexp, null, null);
1440 Expression e0 = null;
1443 for (size_t i = 0; i < exps.length; i++)
1445 Expression e = exps[i];
1449 e = resolveProperties(sc, e);
1452 e.error("`%s` has no value", e.toChars());
1456 if (e.op == EXP.type)
1458 foundType = true; // do not break immediately, there might be more errors
1459 e.checkValue(); // report an error "type T has no value"
1463 if (e.type.ty == Tvoid)
1465 // void expressions do not concur to the determination of the common
1469 if (checkNonAssignmentArrayOp(e))
1475 e = doCopyOrMove(sc, e);
1477 if (!foundType && t0 && !t0.equals(e.type))
1479 /* This applies ?: to merge the types. It's backwards;
1480 * ?: should call this function to merge types.
1482 condexp.type = null;
1485 condexp.loc = e.loc;
1486 Expression ex = condexp.expressionSemantic(sc);
1487 if (ex.op == EXP.error)
1491 // Convert to common type
1492 exps[i] = condexp.e1.castTo(sc, condexp.type);
1493 e = condexp.e2.castTo(sc, condexp.type);
1498 if (e.op != EXP.error)
1502 // [] is typed as void[]
1506 // It's an error, don't do the cast
1507 if (t0.ty == Terror)
1510 for (size_t i = 0; i < exps.length; i++)
1512 Expression e = exps[i];
1516 e = e.implicitCastTo(sc, t0);
1517 if (e.op == EXP.error)
1519 /* https://issues.dlang.org/show_bug.cgi?id=13024
1520 * a workaround for the bug in typeMerge -
1521 * it should paint e1 and e2 by deduced common type,
1522 * but doesn't in this particular case.
1531 private Expression opAssignToOp(const ref Loc loc, EXP op, Expression e1, Expression e2)
1537 e = new AddExp(loc, e1, e2);
1541 e = new MinExp(loc, e1, e2);
1545 e = new MulExp(loc, e1, e2);
1549 e = new DivExp(loc, e1, e2);
1553 e = new ModExp(loc, e1, e2);
1557 e = new AndExp(loc, e1, e2);
1561 e = new OrExp(loc, e1, e2);
1565 e = new XorExp(loc, e1, e2);
1568 case EXP.leftShiftAssign:
1569 e = new ShlExp(loc, e1, e2);
1572 case EXP.rightShiftAssign:
1573 e = new ShrExp(loc, e1, e2);
1576 case EXP.unsignedRightShiftAssign:
1577 e = new UshrExp(loc, e1, e2);
1586 /*********************
1588 * array.length op= e2
1590 * array.length = array.length op e2
1592 * auto tmp = &array;
1593 * (*tmp).length = (*tmp).length op e2
1595 private Expression rewriteOpAssign(BinExp exp)
1597 ArrayLengthExp ale = exp.e1.isArrayLengthExp();
1598 if (ale.e1.isVarExp())
1600 Expression e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
1601 e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
1606 /* auto tmp = &array;
1607 * (*tmp).length = (*tmp).length op e2
1609 auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
1611 Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
1612 Expression elvalue = e1.syntaxCopy();
1613 Expression e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
1614 e = new AssignExp(exp.loc, elvalue, e);
1615 e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
1620 /****************************************
1621 * Preprocess arguments to function.
1623 * reportErrors whether or not to report errors here. Some callers are not
1624 * checking actual function params, so they'll do their own error reporting
1626 * exps[] tuples expanded, properties resolved, rewritten in place
1628 * true a semantic error occurred
1630 private bool preFunctionParameters(Scope* sc, Expressions* exps, const bool reportErrors = true)
1637 for (size_t i = 0; i < exps.length; i++)
1639 Expression arg = (*exps)[i];
1640 arg = resolveProperties(sc, arg);
1641 arg = arg.arrayFuncConv(sc);
1642 if (arg.op == EXP.type)
1644 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1645 arg = resolveAliasThis(sc, arg);
1647 if (arg.op == EXP.type)
1651 arg.error("cannot pass type `%s` as a function argument", arg.toChars());
1652 arg = ErrorExp.get();
1657 else if (arg.type.toBasetype().ty == Tfunction)
1661 arg.error("cannot pass function `%s` as a function argument", arg.toChars());
1662 arg = ErrorExp.get();
1666 else if (checkNonAssignmentArrayOp(arg))
1668 arg = ErrorExp.get();
1677 /********************************************
1678 * Issue an error if default construction is disabled for type t.
1679 * Default construction is required for arrays and 'out' parameters.
1681 * true an error was issued
1683 private bool checkDefCtor(Loc loc, Type t)
1685 if (auto ts = t.baseElemOf().isTypeStruct())
1687 StructDeclaration sd = ts.sym;
1688 if (sd.noDefaultCtor)
1690 sd.error(loc, "default construction is disabled");
1697 /****************************************
1698 * Now that we know the exact type of the function we're calling,
1699 * the arguments[] need to be adjusted:
1700 * 1. implicitly convert argument to the corresponding parameter type
1701 * 2. add default arguments for any missing arguments
1702 * 3. do default promotions on arguments corresponding to ...
1703 * 4. add hidden _arguments[] argument
1704 * 5. call copy constructor for struct value arguments
1706 * loc = location of function call
1708 * tf = type of the function
1709 * ethis = `this` argument, `null` if none or not known
1710 * tthis = type of `this` argument, `null` if no `this` argument
1711 * arguments = array of actual arguments to function call
1712 * fd = the function being called, `null` if called indirectly
1713 * prettype = set to return type of function
1714 * peprefix = set to expression to execute before `arguments[]` are evaluated, `null` if none
1716 * true errors happened
1718 private bool functionParameters(const ref Loc loc, Scope* sc,
1719 TypeFunction tf, Expression ethis, Type tthis, Expressions* arguments, FuncDeclaration fd,
1720 Type* prettype, Expression* peprefix)
1722 //printf("functionParameters() %s\n", fd ? fd.toChars() : "");
1724 assert(fd || tf.next);
1725 size_t nargs = arguments ? arguments.length : 0;
1726 const size_t nparams = tf.parameterList.length;
1727 const olderrors = global.errors;
1729 *prettype = Type.terror;
1730 Expression eprefix = null;
1733 if (nargs > nparams && tf.parameterList.varargs == VarArg.none)
1735 error(loc, "expected %llu arguments, not %llu for non-variadic function type `%s`", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1739 // If inferring return type, and semantic3() needs to be run if not already run
1740 if (!tf.next && fd.inferRetType)
1742 fd.functionSemantic();
1744 else if (fd && fd.parent)
1746 TemplateInstance ti = fd.parent.isTemplateInstance();
1747 if (ti && ti.tempdecl)
1749 fd.functionSemantic3();
1753 /* If calling a pragma(inline, true) function,
1754 * set flag to later scan for inlines.
1756 if (fd && fd.inlining == PINLINE.always)
1759 sc._module.hasAlwaysInlines = true;
1761 sc.func.hasAlwaysInlines = true;
1764 const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1766 const size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1768 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1769 * based on the actual argument types.
1770 * Start with the `this` argument, later on merge into wildmatch the mod bits of the rest
1773 MOD wildmatch = (tthis && !isCtorCall) ? tthis.Type.deduceWild(tf, false) : 0;
1776 foreach (const i; 0 .. n)
1778 Expression arg = (i < nargs) ? (*arguments)[i] : null;
1784 error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1788 Parameter p = tf.parameterList[i];
1794 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams)
1799 arg = inlineCopy(arg, sc);
1800 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1801 arg = arg.resolveLoc(loc, sc);
1802 arguments.push(arg);
1807 if (isDefaultInitOp(arg.op))
1809 arg = arg.resolveLoc(loc, sc);
1810 (*arguments)[i] = arg;
1815 if (tf.parameterList.varargs == VarArg.typesafe && i + 1 == nparams) // https://dlang.org/spec/function.html#variadic
1817 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
1820 if ((m = arg.implicitConvTo(p.type)) > MATCH.nomatch)
1822 if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1824 else if (nargs != nparams)
1830 Type tb = p.type.toBasetype();
1836 /* Create a static array variable v of type arg.type:
1837 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1839 * The array literal in the initializer of the hidden variable
1841 * https://issues.dlang.org/show_bug.cgi?id=2356
1843 Type tbn = (cast(TypeArray)tb).next; // array element type
1844 Type tret = p.isLazyArray();
1846 auto elements = new Expressions(nargs - i);
1847 foreach (u; 0 .. elements.length)
1849 Expression a = (*arguments)[i + u];
1850 if (tret && a.implicitConvTo(tret))
1852 // p is a lazy array of delegates, tret is return type of the delegates
1853 a = a.implicitCastTo(sc, tret)
1854 .optimize(WANTvalue)
1855 .toDelegate(tret, sc);
1858 a = a.implicitCastTo(sc, tbn);
1859 a = a.addDtorHook(sc);
1862 // https://issues.dlang.org/show_bug.cgi?id=14395
1863 // Convert to a static array literal, or its slice.
1864 arg = new ArrayLiteralExp(loc, tbn.sarrayOf(nargs - i), elements);
1865 if (tb.ty == Tarray)
1867 arg = new SliceExp(loc, arg, null, null);
1875 * new Tclass(arg0, arg1, ..., argn)
1877 auto args = new Expressions(nargs - i);
1878 foreach (u; i .. nargs)
1879 (*args)[u - i] = (*arguments)[u];
1880 arg = new NewExp(loc, null, p.type, args);
1886 error(loc, "not enough arguments");
1891 arg = arg.expressionSemantic(sc);
1892 //printf("\targ = '%s'\n", arg.toChars());
1893 arguments.setDim(i + 1);
1894 (*arguments)[i] = arg;
1900 if (!(p.isLazy() && p.type.ty == Tvoid))
1902 if (ubyte wm = arg.type.deduceWild(p.type, p.isReference()))
1904 wildmatch = wildmatch ? MODmerge(wildmatch, wm) : wm;
1905 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p.type.toChars(), arg.type.toChars(), wm, wildmatch);
1912 if ((wildmatch == MODFlags.mutable || wildmatch == MODFlags.immutable_) &&
1913 tf.next && tf.next.hasWild() &&
1914 (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1916 bool errorInout(MOD wildmatch)
1918 const(char)* s = wildmatch == MODFlags.mutable ? "mutable" : MODtoChars(wildmatch);
1919 error(loc, "modify `inout` to `%s` is not allowed inside `inout` function", s);
1925 /* If the called function may return the reference to
1926 * outer inout data, it should be rejected.
1928 * void foo(ref inout(int) x) {
1929 * ref inout(int) bar(inout(int)) { return x; }
1931 * ref inout(int) bar() inout { return x; }
1932 * ref inout(int) baz(alias a)() inout { return x; }
1934 * bar(int.init) = 1; // bad!
1935 * S().bar() = 1; // bad!
1940 * s.baz!a() = 1; // bad!
1944 bool checkEnclosingWild(Dsymbol s)
1946 bool checkWild(Dsymbol s)
1950 if (auto ad = s.isAggregateDeclaration())
1953 return checkEnclosingWild(s);
1955 else if (auto ff = s.isFuncDeclaration())
1957 if (ff.type.isTypeFunction().iswild)
1958 return errorInout(wildmatch);
1960 if (ff.isNested() || ff.isThis())
1961 return checkEnclosingWild(s);
1966 Dsymbol ctx0 = s.toParent2();
1967 Dsymbol ctx1 = s.toParentLocal();
1968 if (checkWild(ctx0))
1971 return checkWild(ctx1);
1974 if ((fd.isThis() || fd.isNested()) && checkEnclosingWild(fd))
1977 else if (tf.isWild())
1978 return errorInout(wildmatch);
1981 Expression firstArg = ((tf.next && tf.next.ty == Tvoid || isCtorCall) &&
1983 tthis.isMutable() && tthis.toBasetype().ty == Tstruct &&
1984 tthis.hasPointers())
1987 assert(nargs >= nparams);
1988 foreach (const i, arg; (*arguments)[0 .. nargs])
1993 Parameter p = tf.parameterList[i];
1994 Type targ = arg.type; // keep original type for isCopyable() because alias this
1995 // resolution may hide an uncopyable type
1997 if (!(p.isLazy() && p.type.ty == Tvoid))
1999 Type tprm = p.type.hasWild()
2000 ? p.type.substWildTo(wildmatch)
2003 const hasCopyCtor = arg.type.isTypeStruct() && arg.type.isTypeStruct().sym.hasCopyCtor;
2004 const typesMatch = arg.type.mutableOf().unSharedOf().equals(tprm.mutableOf().unSharedOf());
2005 if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
2007 //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
2008 arg = arg.implicitCastTo(sc, tprm);
2009 arg = arg.optimize(WANTvalue, p.isReference());
2013 // Support passing rvalue to `in` parameters
2014 if ((p.storageClass & (STC.in_ | STC.ref_)) == (STC.in_ | STC.ref_))
2016 if (!arg.isLvalue())
2018 auto v = copyToTemp(STC.exptemp, "__rvalue", arg);
2019 Expression ev = new DeclarationExp(arg.loc, v);
2020 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2021 arg = ev.expressionSemantic(sc);
2023 arg = arg.toLvalue(sc, arg);
2025 // Look for mutable misaligned pointer, etc., in @safe mode
2026 err |= checkUnsafeAccess(sc, arg, false, true);
2028 else if (p.storageClass & STC.ref_)
2030 if (global.params.rvalueRefParam == FeatureState.enabled &&
2033 { /* allow rvalues to be passed to ref parameters by copying
2034 * them to a temp, then pass the temp as the argument
2036 auto v = copyToTemp(0, "__rvalue", arg);
2037 Expression ev = new DeclarationExp(arg.loc, v);
2038 ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v));
2039 arg = ev.expressionSemantic(sc);
2041 arg = arg.toLvalue(sc, arg);
2043 // Look for mutable misaligned pointer, etc., in @safe mode
2044 err |= checkUnsafeAccess(sc, arg, false, true);
2046 else if (p.storageClass & STC.out_)
2049 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
2051 arg.error("cannot modify struct `%s` with immutable members", arg.toChars());
2056 // Look for misaligned pointer, etc., in @safe mode
2057 err |= checkUnsafeAccess(sc, arg, false, true);
2058 err |= checkDefCtor(arg.loc, t); // t must be default constructible
2060 arg = arg.toLvalue(sc, arg);
2062 else if (p.isLazy())
2064 // Convert lazy argument to a delegate
2065 auto t = (p.type.ty == Tvoid) ? p.type : arg.type;
2066 arg = toDelegate(arg, t, sc);
2068 //printf("arg: %s\n", arg.toChars());
2069 //printf("type: %s\n", arg.type.toChars());
2070 //printf("param: %s\n", p.toChars());
2072 const pStc = tf.parameterStorageClass(tthis, p);
2074 if (firstArg && (pStc & STC.return_))
2076 /* Argument value can be assigned to firstArg.
2077 * Check arg to see if it matters.
2079 err |= checkParamArgumentReturn(sc, firstArg, arg, p, false);
2081 // Allow 'lazy' to imply 'scope' - lazy parameters can be passed along
2082 // as lazy parameters to the next function, but that isn't escaping.
2083 else if (!(pStc & STC.lazy_))
2085 /* Argument value can escape from the called function.
2086 * Check arg to see if it matters.
2088 VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null;
2089 err |= checkParamArgumentEscape(sc, fd, p.ident, vPar, cast(STC) pStc, arg, false, false);
2092 // Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
2093 // may be unreliable when scope violations only manifest as deprecation warnings.
2094 // However, existing `@nogc` code may rely on it, so still do it when the parameter is explicitly marked `scope`
2095 const explicitScope = p.isLazy() ||
2096 ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred));
2097 if ((pStc & (STC.scope_ | STC.lazy_)) &&
2098 ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) &&
2099 !(pStc & STC.return_))
2101 /* Argument value cannot escape from the called function.
2104 if (auto ce = a.isCastExp())
2107 ArrayLiteralExp ale;
2108 if (p.type.toBasetype().ty == Tarray &&
2109 (ale = a.isArrayLiteralExp()) !is null && ale.elements && ale.elements.length > 0)
2111 // allocate the array literal as temporary static array on the stack
2112 ale.type = ale.type.nextOf().sarrayOf(ale.elements.length);
2113 auto tmp = copyToTemp(0, "__arrayliteral_on_stack", ale);
2114 auto declareTmp = new DeclarationExp(ale.loc, tmp);
2115 auto castToSlice = new CastExp(ale.loc, new VarExp(ale.loc, tmp),
2116 p.type.substWildTo(MODFlags.mutable));
2117 arg = CommaExp.combine(declareTmp, castToSlice);
2118 arg = arg.expressionSemantic(sc);
2120 else if (auto fe = a.isFuncExp())
2122 /* Function literals can only appear once, so if this
2123 * appearance was scoped, there cannot be any others.
2125 fe.fd.tookAddressOf = 0;
2127 else if (auto de = a.isDelegateExp())
2129 /* For passing a delegate to a scoped parameter,
2130 * this doesn't count as taking the address of it.
2131 * We only worry about 'escaping' references to the function.
2133 if (auto ve = de.e1.isVarExp())
2135 if (auto f = ve.var.isFuncDeclaration())
2137 if (f.tookAddressOf)
2139 //printf("--tookAddressOf = %d\n", f.tookAddressOf);
2144 if (!p.isReference())
2145 err |= arg.checkSharedAccess(sc);
2147 arg = arg.optimize(WANTvalue, p.isReference());
2149 /* Determine if this parameter is the "first reference" parameter through which
2150 * later "return" arguments can be stored.
2152 if (i == 0 && !tthis && p.isReference() && p.type &&
2153 (tf.next && tf.next.ty == Tvoid || isCtorCall))
2155 Type tb = p.type.baseElemOf();
2156 if (tb.isMutable() && tb.hasPointers())
2164 // These will be the trailing ... arguments
2165 // If not D linkage, do promotions
2166 if (tf.linkage != LINK.d)
2168 // Promote bytes, words, etc., to ints
2169 arg = integralPromotions(arg, sc);
2171 // Promote floats to doubles
2172 switch (arg.type.ty)
2175 arg = arg.castTo(sc, Type.tfloat64);
2179 arg = arg.castTo(sc, Type.timaginary64);
2185 if (tf.parameterList.varargs == VarArg.variadic)
2187 const(char)* p = tf.linkage == LINK.c ? "extern(C)" : "extern(C++)";
2188 if (arg.type.ty == Tarray)
2190 arg.error("cannot pass dynamic arrays to `%s` vararg functions", p);
2193 if (arg.type.ty == Tsarray)
2195 arg.error("cannot pass static arrays to `%s` vararg functions", p);
2201 // Do not allow types that need destructors or copy constructors.
2202 if (arg.type.needsDestruction())
2204 arg.error("cannot pass types that need destruction as variadic arguments");
2207 if (arg.type.needsCopyOrPostblit())
2209 arg.error("cannot pass types with postblits or copy constructors as variadic arguments");
2213 // Convert static arrays to dynamic arrays
2214 // BUG: I don't think this is right for D2
2215 Type tb = arg.type.toBasetype();
2216 if (auto ts = tb.isTypeSArray())
2218 Type ta = ts.next.arrayOf();
2219 if (ts.size(arg.loc) == 0)
2220 arg = new NullExp(arg.loc, ta);
2222 arg = arg.castTo(sc, ta);
2224 if (tb.ty == Tstruct)
2226 //arg = callCpCtor(sc, arg);
2228 // Give error for overloaded function addresses
2229 if (auto se = arg.isSymOffExp())
2231 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
2233 arg.error("function `%s` is overloaded", arg.toChars());
2237 err |= arg.checkValue();
2238 err |= arg.checkSharedAccess(sc);
2239 arg = arg.optimize(WANTvalue);
2241 (*arguments)[i] = arg;
2244 /* If calling C scanf(), printf(), or any variants, check the format string against the arguments
2246 const isVa_list = tf.parameterList.varargs == VarArg.none;
2247 if (fd && fd.printf)
2249 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2251 checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2254 else if (fd && fd.scanf)
2256 if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
2258 checkScanfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
2263 // TODO: not checking the "v" functions yet (for those, check format string only, not args)
2266 /* Remaining problems:
2267 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
2268 * implemented by calling a function) we'll defer this for now.
2269 * 2. value structs (or static arrays of them) that need to be copy constructed
2270 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
2271 * function gets called.
2272 * 4. value structs need to be destructed after the function call for platforms where the caller destroys the arguments.
2273 * 2, 3 and 4 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
2274 * up properly. Pushing arguments on the stack then cannot fail.
2277 /* TODO: tackle problem 1)
2279 const bool leftToRight = true; // TODO: Any cases that need rightToLeft?
2281 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
2283 /* Does Problem (4) apply?
2285 const bool callerDestroysArgs = !target.isCalleeDestroyingArgs(tf);
2287 const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
2288 const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
2289 const ptrdiff_t step = (leftToRight ? 1 : -1);
2291 /* Compute indices of last throwing argument and first arg needing destruction.
2292 * Used to not set up destructors unless an arg needs destruction on a throw
2293 * in a later argument.
2295 ptrdiff_t lastthrow = -1; // last argument that may throw
2296 ptrdiff_t firstdtor = -1; // first argument that needs destruction
2297 ptrdiff_t lastdtor = -1; // last argument that needs destruction
2298 for (ptrdiff_t i = start; i != end; i += step)
2300 Expression arg = (*arguments)[i];
2301 if (canThrow(arg, sc.func, false))
2303 if (arg.type.needsDestruction())
2305 Parameter p = (i >= nparams ? null : tf.parameterList[i]);
2306 if (!(p && (p.isLazy() || p.isReference())))
2308 if (firstdtor == -1)
2315 /* Do we need 'eprefix' for problems 3 or 4?
2317 const bool needsPrefix = callerDestroysArgs
2318 ? firstdtor >= 0 // true if any argument needs destruction
2319 : firstdtor >= 0 && lastthrow >= 0 &&
2320 (lastthrow - firstdtor) * step > 0; // last throw after first destruction
2321 const ptrdiff_t lastPrefix = callerDestroysArgs
2322 ? lastdtor // up to last argument requiring destruction
2323 : lastthrow; // up to last potentially throwing argument
2325 /* Problem 3: initialize 'eprefix' by declaring the gate
2327 VarDeclaration gate;
2328 if (needsPrefix && !callerDestroysArgs)
2330 // eprefix => bool __gate [= false]
2331 Identifier idtmp = Identifier.generateId("__gate");
2332 gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
2333 gate.storage_class |= STC.temp | STC.ctfe | STC.volatile_;
2334 gate.dsymbolSemantic(sc);
2336 auto ae = new DeclarationExp(loc, gate);
2337 eprefix = ae.expressionSemantic(sc);
2340 for (ptrdiff_t i = start; i != end; i += step)
2342 Expression arg = (*arguments)[i];
2343 //printf("arg[%d]: %s\n", cast(int)i, arg.toChars());
2345 Parameter parameter = (i >= nparams ? null : tf.parameterList[i]);
2346 const bool isRef = parameter && parameter.isReference();
2347 const bool isLazy = parameter && parameter.isLazy();
2349 /* Skip lazy parameters
2354 /* Do we have 'eprefix' and aren't past 'lastPrefix' yet?
2355 * Then declare a temporary variable for this arg and append that declaration
2356 * to 'eprefix', which will implicitly take care of potential problem 2) for
2358 * 'eprefix' will therefore finally contain all args up to and including 'lastPrefix',
2359 * excluding all lazy parameters.
2361 if (needsPrefix && (lastPrefix - i) * step >= 0)
2363 const bool needsDtor = !isRef && arg.type.needsDestruction() &&
2364 // Problem 3: last throwing arg doesn't require dtor patching
2365 (callerDestroysArgs || i != lastPrefix);
2367 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
2369 auto tmp = copyToTemp(
2370 (parameter ? parameter.storageClass : tf.parameterList.stc) & (STC.scope_),
2371 needsDtor ? "__pfx" : "__pfy",
2372 !isRef ? arg : arg.addressOf());
2373 tmp.dsymbolSemantic(sc);
2375 if (callerDestroysArgs)
2377 /* Problem 4: Normal temporary, destructed after the call
2380 tmp.isArgDtorVar = true; // mark it so that the backend passes it by ref to the function being called
2384 /* Problem 3: Modify the destructor so it only runs if gate==false,
2385 * i.e., only if there was a throw while constructing the args
2391 assert(i == lastPrefix);
2397 // edtor => (__gate || edtor)
2399 Expression e = tmp.edtor;
2400 e = new LogicalExp(e.loc, EXP.orOr, new VarExp(e.loc, gate), e);
2401 tmp.edtor = e.expressionSemantic(sc);
2402 //printf("edtor: %s\n", tmp.edtor.toChars());
2406 // eprefix => (eprefix, auto __pfx/y = arg)
2407 auto ae = new DeclarationExp(loc, tmp);
2408 eprefix = Expression.combine(eprefix, ae.expressionSemantic(sc));
2411 arg = new VarExp(loc, tmp);
2412 arg = arg.expressionSemantic(sc);
2415 arg = new PtrExp(loc, arg);
2416 arg = arg.expressionSemantic(sc);
2419 /* Problem 3: Last throwing arg?
2420 * Then finalize eprefix => (eprefix, gate = true), i.e., disable the
2421 * dtors right after constructing the last throwing arg.
2422 * From now on, the callee will take care of destructing the args because
2423 * the args are implicitly moved into function parameters.
2425 if (!callerDestroysArgs && i == lastPrefix)
2427 auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), IntegerExp.createBool(true));
2428 eprefix = Expression.combine(eprefix, e.expressionSemantic(sc));
2431 else // not part of 'eprefix'
2433 /* Handle problem 2) by calling the copy constructor for value structs
2434 * (or static arrays of them) if appropriate.
2436 Type tv = arg.type.baseElemOf();
2437 if (!isRef && tv.ty == Tstruct)
2438 arg = doCopyOrMove(sc, arg, parameter ? parameter.type : null);
2441 (*arguments)[i] = arg;
2444 //if (eprefix) printf("eprefix: %s\n", eprefix.toChars());
2446 /* Test compliance with DIP1021
2448 if (global.params.useDIP1021 &&
2449 tf.trust != TRUST.system && tf.trust != TRUST.trusted)
2450 err |= checkMutableArguments(sc, fd, tf, ethis, arguments, false);
2452 // If D linkage and variadic, add _arguments[] as first argument
2453 if (tf.isDstyleVariadic())
2455 assert(arguments.length >= nparams);
2457 auto args = new Parameters(arguments.length - nparams);
2458 for (size_t i = 0; i < arguments.length - nparams; i++)
2460 auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
2463 auto tup = new TypeTuple(args);
2464 Expression e = (new TypeidExp(loc, tup)).expressionSemantic(sc);
2465 arguments.insert(0, e);
2468 /* Determine function return type: tret
2470 Type tret = tf.next;
2473 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd.toChars(), fd.type.toChars(),
2474 // wildmatch, tf.isWild(), fd.isReturnIsolated());
2477 assert(sc.intypeof || global.errors);
2478 tthis = fd.isThis().type.addMod(fd.type.mod);
2480 if (tf.isWild() && !fd.isReturnIsolated())
2483 tret = tret.substWildTo(wildmatch);
2485 if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
2487 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
2488 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
2489 .error(loc, "`inout` constructor `%s` creates%s object, not%s", fd.toPrettyChars(), s1, s2);
2495 else if (wildmatch && tret)
2497 /* Adjust function return type based on wildmatch
2499 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2500 tret = tret.substWildTo(wildmatch);
2504 *peprefix = eprefix;
2505 return (err || olderrors != global.errors);
2509 * Determines whether a symbol represents a module or package
2510 * (Used as a helper for is(type == module) and is(type == package))
2513 * sym = the symbol to be checked
2516 * the symbol which `sym` represents (or `null` if it doesn't represent a `Package`)
2518 Package resolveIsPackage(Dsymbol sym)
2521 if (Import imp = sym.isImport())
2523 if (imp.pkg is null)
2525 .error(sym.loc, "internal compiler error: unable to process forward-referenced import `%s`",
2531 else if (auto mod = sym.isModule())
2532 pkg = mod.isPackageFile ? mod.pkg : sym.isPackage();
2534 pkg = sym.isPackage();
2536 pkg.resolvePKGunknown();
2541 private extern (C++) final class ExpressionSemanticVisitor : Visitor
2543 alias visit = Visitor.visit;
2553 private void setError()
2555 result = ErrorExp.get();
2558 /**************************
2559 * Semantically analyze Expression.
2560 * Determine types, fold constants, etc.
2562 override void visit(Expression e)
2564 static if (LOGSEMANTIC)
2566 printf("Expression::semantic() %s\n", e.toChars());
2569 e.type = e.type.typeSemantic(e.loc, sc);
2571 e.type = Type.tvoid;
2575 override void visit(IntegerExp e)
2578 if (e.type.ty == Terror)
2581 assert(e.type.deco);
2582 e.setInteger(e.getInteger());
2586 override void visit(RealExp e)
2589 e.type = Type.tfloat64;
2591 e.type = e.type.typeSemantic(e.loc, sc);
2595 override void visit(ComplexExp e)
2598 e.type = Type.tcomplex80;
2600 e.type = e.type.typeSemantic(e.loc, sc);
2604 override void visit(IdentifierExp exp)
2606 static if (LOGSEMANTIC)
2608 printf("IdentifierExp::semantic('%s')\n", exp.ident.toChars());
2610 if (exp.type) // This is used as the dummy expression
2617 Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym);
2625 /* See if the symbol was a member of an enclosing 'with'
2627 WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
2628 if (withsym && withsym.withstate.wthis && symbolIsVisible(sc, s))
2630 /* Disallow shadowing
2632 // First find the scope of the with
2634 while (scwith.scopesym != scopesym)
2636 scwith = scwith.enclosing;
2639 // Look at enclosing scopes for symbols with the same name,
2640 // in the same function
2641 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
2644 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
2646 exp.error("with symbol `%s` is shadowing local symbol `%s`", s.toPrettyChars(), s2.toPrettyChars());
2652 // Same as wthis.ident
2653 // TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
2654 // The redudancy should be removed.
2655 e = new VarExp(exp.loc, withsym.withstate.wthis);
2656 e = new DotIdExp(exp.loc, e, exp.ident);
2657 e = e.expressionSemantic(sc);
2663 if (withsym.withstate.exp.type.ty != Tvoid)
2665 // 'with (exp)' is a type expression
2666 // or 's' is not visible there (for error message)
2667 e = new TypeExp(exp.loc, withsym.withstate.exp.type);
2671 // 'with (exp)' is a Package/Module
2672 e = withsym.withstate.exp;
2674 e = new DotIdExp(exp.loc, e, exp.ident);
2675 result = e.expressionSemantic(sc);
2679 /* If f is really a function template,
2680 * then replace f with the function template declaration.
2682 FuncDeclaration f = s.isFuncDeclaration();
2685 TemplateDeclaration td = getFuncTemplateDecl(f);
2688 if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
2689 td = td.overroot; // then get the start
2690 e = new TemplateExp(exp.loc, td, f);
2691 e = e.expressionSemantic(sc);
2697 if (global.params.fixAliasThis)
2699 ExpressionDsymbol expDsym = scopesym.isExpressionDsymbol();
2702 //printf("expDsym = %s\n", expDsym.exp.toChars());
2703 result = expDsym.exp.expressionSemantic(sc);
2707 // Haven't done overload resolution yet, so pass 1
2708 e = symbolToExp(s, exp.loc, sc, true);
2714 if (!global.params.fixAliasThis && hasThis(sc))
2716 for (AggregateDeclaration ad = sc.getStructClassScope(); ad;)
2721 e = new ThisExp(exp.loc);
2722 e = new DotIdExp(exp.loc, e, ad.aliasthis.ident);
2723 e = new DotIdExp(exp.loc, e, exp.ident);
2724 e = e.trySemantic(sc);
2732 auto cd = ad.isClassDeclaration();
2733 if (cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
2742 if (exp.ident == Id.ctfe)
2744 if (sc.flags & SCOPE.ctfe)
2746 exp.error("variable `__ctfe` cannot be read at compile time");
2750 // Create the magic __ctfe bool variable
2751 auto vd = new VarDeclaration(exp.loc, Type.tbool, Id.ctfe, null);
2752 vd.storage_class |= STC.temp;
2753 vd.semanticRun = PASS.semanticdone;
2754 Expression e = new VarExp(exp.loc, vd);
2755 e = e.expressionSemantic(sc);
2760 // If we've reached this point and are inside a with() scope then we may
2761 // try one last attempt by checking whether the 'wthis' object supports
2762 // dynamic dispatching via opDispatch.
2763 // This is done by rewriting this expression as wthis.ident.
2764 // The innermost with() scope of the hierarchy to satisfy the condition
2766 // https://issues.dlang.org/show_bug.cgi?id=6400
2767 for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing)
2772 if (auto ss = sc2.scopesym.isWithScopeSymbol())
2774 if (ss.withstate.wthis)
2777 e = new VarExp(exp.loc, ss.withstate.wthis);
2778 e = new DotIdExp(exp.loc, e, exp.ident);
2779 e = e.trySemantic(sc);
2786 // Try Type.opDispatch (so the static version)
2787 else if (ss.withstate.exp && ss.withstate.exp.op == EXP.type)
2789 if (Type t = ss.withstate.exp.isTypeExp().type)
2792 e = new TypeExp(exp.loc, t);
2793 e = new DotIdExp(exp.loc, e, exp.ident);
2794 e = e.trySemantic(sc);
2805 /* Look for what user might have meant
2807 if (const n = importHint(exp.ident.toString()))
2808 exp.error("`%s` is not defined, perhaps `import %.*s;` is needed?", exp.ident.toChars(), cast(int)n.length, n.ptr);
2809 else if (auto s2 = sc.search_correct(exp.ident))
2810 exp.error("undefined identifier `%s`, did you mean %s `%s`?", exp.ident.toChars(), s2.kind(), s2.toChars());
2811 else if (const p = Scope.search_correct_C(exp.ident))
2812 exp.error("undefined identifier `%s`, did you mean `%s`?", exp.ident.toChars(), p);
2813 else if (exp.ident == Id.dollar)
2814 exp.error("undefined identifier `$`");
2816 exp.error("undefined identifier `%s`", exp.ident.toChars());
2818 result = ErrorExp.get();
2821 override void visit(DsymbolExp e)
2823 result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
2826 override void visit(ThisExp e)
2828 static if (LOGSEMANTIC)
2830 printf("ThisExp::semantic()\n");
2838 FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2839 AggregateDeclaration ad;
2841 /* Special case for typeof(this) and typeof(super) since both
2842 * should work even if they are not inside a non-static member function
2844 if (!fd && sc.intypeof == 1)
2846 // Find enclosing struct or class
2847 for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
2851 e.error("`%s` is not in a class or struct scope", e.toChars());
2854 ClassDeclaration cd = s.isClassDeclaration();
2861 StructDeclaration sd = s.isStructDeclaration();
2875 assert(e.var.parent);
2876 ad = fd.isMemberLocal();
2878 ad = fd.isMember2();
2880 e.type = ad.type.addMod(e.var.type.mod);
2882 if (e.var.checkNestedReference(sc, e.loc))
2889 e.error("`this` is only defined in non-static member functions, not `%s`", sc.parent.toChars());
2890 result = ErrorExp.get();
2893 override void visit(SuperExp e)
2895 static if (LOGSEMANTIC)
2897 printf("SuperExp::semantic('%s')\n", e.toChars());
2905 FuncDeclaration fd = hasThis(sc);
2906 ClassDeclaration cd;
2909 /* Special case for typeof(this) and typeof(super) since both
2910 * should work even if they are not inside a non-static member function
2912 if (!fd && sc.intypeof == 1)
2914 // Find enclosing class
2915 for (s = sc.getStructClassScope(); 1; s = s.parent)
2919 e.error("`%s` is not in a class scope", e.toChars());
2922 cd = s.isClassDeclaration();
2928 e.error("class `%s` has no `super`", s.toChars());
2941 assert(e.var && e.var.parent);
2943 s = fd.toParentDecl();
2944 if (s.isTemplateDeclaration()) // allow inside template constraint
2947 cd = s.isClassDeclaration();
2948 //printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
2953 e.error("no base class for `%s`", cd.toChars());
2954 e.type = cd.type.addMod(e.var.type.mod);
2958 e.type = cd.baseClass.type;
2959 e.type = e.type.castMod(e.var.type.mod);
2962 if (e.var.checkNestedReference(sc, e.loc))
2969 e.error("`super` is only allowed in non-static class member functions");
2970 result = ErrorExp.get();
2973 override void visit(NullExp e)
2975 static if (LOGSEMANTIC)
2977 printf("NullExp::semantic('%s')\n", e.toChars());
2979 // NULL is the same as (void *)0
2985 e.type = Type.tnull;
2989 override void visit(StringExp e)
2991 static if (LOGSEMANTIC)
2993 printf("StringExp::semantic() %s\n", e.toChars());
3009 for (u = 0; u < e.len;)
3011 if (const p = utf_decodeChar(e.peekString(), u, c))
3013 e.error("%.*s", cast(int)p.length, p.ptr);
3023 e.setData(buffer.extractData(), newlen, 4);
3024 if (sc && sc.flags & SCOPE.Cfile)
3025 e.type = Type.tuns32.sarrayOf(e.len + 1);
3027 e.type = Type.tdchar.immutableOf().arrayOf();
3032 for (u = 0; u < e.len;)
3034 if (const p = utf_decodeChar(e.peekString(), u, c))
3036 e.error("%.*s", cast(int)p.length, p.ptr);
3041 buffer.writeUTF16(c);
3047 buffer.writeUTF16(0);
3048 e.setData(buffer.extractData(), newlen, 2);
3049 if (sc && sc.flags & SCOPE.Cfile)
3050 e.type = Type.tuns16.sarrayOf(e.len + 1);
3052 e.type = Type.twchar.immutableOf().arrayOf();
3061 if (sc && sc.flags & SCOPE.Cfile)
3062 e.type = Type.tchar.sarrayOf(e.len + 1);
3064 e.type = Type.tchar.immutableOf().arrayOf();
3067 e.type = e.type.typeSemantic(e.loc, sc);
3068 //type = type.immutableOf();
3069 //printf("type = %s\n", type.toChars());
3074 override void visit(TupleExp exp)
3076 static if (LOGSEMANTIC)
3078 printf("+TupleExp::semantic(%s)\n", exp.toChars());
3087 exp.e0 = exp.e0.expressionSemantic(sc);
3089 // Run semantic() on each argument
3091 for (size_t i = 0; i < exp.exps.length; i++)
3093 Expression e = (*exp.exps)[i];
3094 e = e.expressionSemantic(sc);
3097 exp.error("`%s` has no value", e.toChars());
3100 else if (e.op == EXP.error)
3108 expandTuples(exp.exps);
3110 exp.type = new TypeTuple(exp.exps);
3111 exp.type = exp.type.typeSemantic(exp.loc, sc);
3112 //printf("-TupleExp::semantic(%s)\n", toChars());
3116 override void visit(ArrayLiteralExp e)
3118 static if (LOGSEMANTIC)
3120 printf("ArrayLiteralExp::semantic('%s')\n", e.toChars());
3128 /* Perhaps an empty array literal [ ] should be rewritten as null?
3132 e.basis = e.basis.expressionSemantic(sc);
3133 if (arrayExpressionSemantic(e.elements.peekSlice(), sc) || (e.basis && e.basis.op == EXP.error))
3136 expandTuples(e.elements);
3139 e.elements.push(e.basis);
3140 Type t0 = arrayExpressionToCommonType(sc, *e.elements);
3142 e.basis = e.elements.pop();
3146 e.type = t0.arrayOf();
3147 e.type = e.type.typeSemantic(e.loc, sc);
3149 /* Disallow array literals of type void being used.
3151 if (e.elements.length > 0 && t0.ty == Tvoid)
3153 e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
3157 if (global.params.useTypeInfo && Type.dtypeinfo)
3158 semanticTypeInfo(sc, e.type);
3163 override void visit(AssocArrayLiteralExp e)
3165 static if (LOGSEMANTIC)
3167 printf("AssocArrayLiteralExp::semantic('%s')\n", e.toChars());
3175 // Run semantic() on each element
3176 bool err_keys = arrayExpressionSemantic(e.keys.peekSlice(), sc);
3177 bool err_vals = arrayExpressionSemantic(e.values.peekSlice(), sc);
3178 if (err_keys || err_vals)
3181 expandTuples(e.keys);
3182 expandTuples(e.values);
3183 if (e.keys.length != e.values.length)
3185 e.error("number of keys is %llu, must match number of values %llu",
3186 cast(ulong) e.keys.length, cast(ulong) e.values.length);
3190 Type tkey = arrayExpressionToCommonType(sc, *e.keys);
3191 Type tvalue = arrayExpressionToCommonType(sc, *e.values);
3192 if (tkey is null || tvalue is null)
3195 e.type = new TypeAArray(tvalue, tkey);
3196 e.type = e.type.typeSemantic(e.loc, sc);
3198 semanticTypeInfo(sc, e.type);
3200 if (checkAssocArrayLiteralEscape(sc, e, false))
3206 override void visit(StructLiteralExp e)
3208 static if (LOGSEMANTIC)
3210 printf("StructLiteralExp::semantic('%s')\n", e.toChars());
3219 if (e.sd.sizeok != Sizeok.done)
3222 // run semantic() on each element
3223 if (arrayExpressionSemantic(e.elements.peekSlice(), sc))
3226 expandTuples(e.elements);
3228 /* Fit elements[] to the corresponding type of field[].
3230 if (!e.sd.fit(e.loc, sc, e.elements, e.stype))
3233 /* Fill out remainder of elements[] with default initializers for fields[]
3235 if (!e.sd.fill(e.loc, *e.elements, false))
3237 /* An error in the initializer needs to be recorded as an error
3238 * in the enclosing function or template, since the initializer
3239 * will be part of the stuct declaration.
3241 global.increaseErrorCount();
3245 if (checkFrameAccess(e.loc, sc, e.sd, e.elements.length))
3248 e.type = e.stype ? e.stype : e.sd.type;
3252 override void visit(CompoundLiteralExp cle)
3254 static if (LOGSEMANTIC)
3256 printf("CompoundLiteralExp::semantic('%s')\n", cle.toChars());
3258 Type t = cle.type.typeSemantic(cle.loc, sc);
3259 auto init = initializerSemantic(cle.initializer, sc, t, INITnointerpret);
3260 auto e = initializerToExpression(init, t, (sc.flags & SCOPE.Cfile) != 0);
3263 error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars());
3270 override void visit(TypeExp exp)
3272 if (exp.type.ty == Terror)
3275 //printf("TypeExp::semantic(%s)\n", exp.type.toChars());
3280 dmd.typesem.resolve(exp.type, exp.loc, sc, e, t, s, true);
3283 // `(Type)` is actually `(var)` so if `(var)` is a member requiring `this`
3284 // then rewrite as `(this.var)` in case it would be followed by a DotVar
3285 // to fix https://issues.dlang.org/show_bug.cgi?id=9490
3286 VarExp ve = e.isVarExp();
3287 if (ve && ve.var && exp.parens && !ve.var.isStatic() && !(sc.stc & STC.static_) &&
3288 sc.func && sc.func.needThis && ve.var.isMember2())
3290 // printf("apply fix for issue 9490: add `this.` to `%s`...\n", e.toChars());
3291 e = new DotVarExp(exp.loc, new ThisExp(exp.loc), ve.var, false);
3293 //printf("e = %s %s\n", Token.toChars(e.op), e.toChars());
3294 e = e.expressionSemantic(sc);
3298 //printf("t = %d %s\n", t.ty, t.toChars());
3299 exp.type = t.typeSemantic(exp.loc, sc);
3304 //printf("s = %s %s\n", s.kind(), s.toChars());
3305 e = symbolToExp(s, exp.loc, sc, true);
3310 exp.type.checkComplexTransition(exp.loc, sc);
3315 override void visit(ScopeExp exp)
3317 static if (LOGSEMANTIC)
3319 printf("+ScopeExp::semantic(%p '%s')\n", exp, exp.toChars());
3327 ScopeDsymbol sds2 = exp.sds;
3328 TemplateInstance ti = sds2.isTemplateInstance();
3331 WithScopeSymbol withsym;
3332 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
3334 if (withsym && withsym.withstate.wthis)
3336 Expression e = new VarExp(exp.loc, withsym.withstate.wthis);
3337 e = new DotTemplateInstanceExp(exp.loc, e, ti);
3338 result = e.expressionSemantic(sc);
3341 if (ti.needsTypeInference(sc))
3343 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
3345 Dsymbol p = td.toParentLocal();
3346 FuncDeclaration fdthis = hasThis(sc);
3347 AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
3348 if (fdthis && ad && fdthis.isMemberLocal() == ad && (td._scope.stc & STC.static_) == 0)
3350 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3351 result = e.expressionSemantic(sc);
3355 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
3357 FuncDeclaration fdthis = hasThis(sc);
3358 AggregateDeclaration ad = os.parent.isAggregateDeclaration();
3359 if (fdthis && ad && fdthis.isMemberLocal() == ad)
3361 Expression e = new DotTemplateInstanceExp(exp.loc, new ThisExp(exp.loc), ti);
3362 result = e.expressionSemantic(sc);
3366 // ti is an instance which requires IFTI.
3368 exp.type = Type.tvoid;
3372 ti.dsymbolSemantic(sc);
3373 if (!ti.inst || ti.errors)
3376 Dsymbol s = ti.toAlias();
3380 exp.type = Type.tvoid;
3384 sds2 = s.isScopeDsymbol();
3387 ti = sds2.isTemplateInstance();
3388 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3392 if (auto v = s.isVarDeclaration())
3396 exp.error("forward reference of %s `%s`", v.kind(), v.toChars());
3399 if ((v.storage_class & STC.manifest) && v._init)
3401 /* When an instance that will be converted to a constant exists,
3402 * the instance representation "foo!tiargs" is treated like a
3403 * variable name, and its recursive appearance check (note that
3404 * it's equivalent with a recursive instantiation of foo) is done
3405 * separately from the circular initialization check for the
3406 * eponymous enum variable declaration.
3409 * enum bool foo = foo; // recursive definition check (v.inuse)
3412 * enum bool bar = bar!T; // recursive instantiation check (ti.inuse)
3417 exp.error("recursive expansion of %s `%s`", ti.kind(), ti.toPrettyChars());
3420 v.checkDeprecated(exp.loc, sc);
3421 auto e = v.expandInitializer(exp.loc);
3423 e = e.expressionSemantic(sc);
3430 //printf("s = %s, '%s'\n", s.kind(), s.toChars());
3431 auto e = symbolToExp(s, exp.loc, sc, true);
3432 //printf("-1ScopeExp::semantic()\n");
3437 //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
3438 //printf("\tparent = '%s'\n", sds2.parent.toChars());
3439 sds2.dsymbolSemantic(sc);
3441 // (Aggregate|Enum)Declaration
3442 if (auto t = sds2.getType())
3444 result = (new TypeExp(exp.loc, t)).expressionSemantic(sc);
3448 if (auto td = sds2.isTemplateDeclaration())
3450 result = (new TemplateExp(exp.loc, td)).expressionSemantic(sc);
3455 exp.type = Type.tvoid;
3456 //printf("-2ScopeExp::semantic() %s\n", toChars());
3460 override void visit(NewExp exp)
3462 static if (LOGSEMANTIC)
3464 printf("NewExp::semantic() %s\n", exp.toChars());
3466 printf("\tthisexp = %s\n", exp.thisexp.toChars());
3467 printf("\tnewtype: %s\n", exp.newtype.toChars());
3469 if (exp.type) // if semantic() already run
3475 //for error messages if the argument in [] is not convertible to size_t
3476 const originalNewtype = exp.newtype;
3478 // https://issues.dlang.org/show_bug.cgi?id=11581
3479 // With the syntax `new T[edim]` or `thisexp.new T[edim]`,
3480 // T should be analyzed first and edim should go into arguments iff it's
3482 Expression edim = null;
3483 if (!exp.arguments && exp.newtype.isTypeSArray())
3485 auto ts = exp.newtype.isTypeSArray();
3486 // check `new Value[Key]`
3487 ts.dim = ts.dim.expressionSemantic(sc);
3488 if (ts.dim.op == EXP.type)
3490 exp.newtype = new TypeAArray(ts.next, ts.dim.isTypeExp().type);
3495 exp.newtype = ts.next;
3499 ClassDeclaration cdthis = null;
3502 exp.thisexp = exp.thisexp.expressionSemantic(sc);
3503 if (exp.thisexp.op == EXP.error)
3506 cdthis = exp.thisexp.type.isClassHandle();
3509 exp.error("`this` for nested class must be a class type, not `%s`", exp.thisexp.type.toChars());
3513 sc = sc.push(cdthis);
3514 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3519 exp.type = exp.newtype.typeSemantic(exp.loc, sc);
3521 if (exp.type.ty == Terror)
3526 if (exp.type.toBasetype().ty == Ttuple)
3529 exp.type = new TypeSArray(exp.type, edim);
3530 exp.type = exp.type.typeSemantic(exp.loc, sc);
3531 if (exp.type.ty == Terror)
3536 // --> new T[](edim)
3537 exp.arguments = new Expressions();
3538 exp.arguments.push(edim);
3539 exp.type = exp.type.arrayOf();
3543 exp.newtype = exp.type; // in case type gets cast to something else
3544 Type tb = exp.type.toBasetype();
3545 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
3546 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc))
3550 if (preFunctionParameters(sc, exp.arguments))
3555 if (exp.thisexp && tb.ty != Tclass)
3557 exp.error("`.new` is only for allocating nested classes, not `%s`", tb.toChars());
3561 const size_t nargs = exp.arguments ? exp.arguments.length : 0;
3562 Expression newprefix = null;
3564 if (auto tc = tb.isTypeClass())
3570 if (cd.sizeok != Sizeok.done)
3573 cd.ctor = cd.searchCtor();
3574 if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
3576 exp.error("default construction is disabled for type `%s`", cd.type.toChars());
3580 if (cd.isInterfaceDeclaration())
3582 exp.error("cannot create instance of interface `%s`", cd.toChars());
3586 if (cd.isAbstract())
3588 exp.error("cannot create instance of abstract class `%s`", cd.toChars());
3589 for (size_t i = 0; i < cd.vtbl.length; i++)
3591 FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
3592 if (fd && fd.isAbstract())
3594 errorSupplemental(exp.loc, "function `%s` is not implemented",
3595 fd.toFullSignature());
3600 // checkDeprecated() is already done in newtype.typeSemantic().
3604 /* We need a 'this' pointer for the nested class.
3605 * Ensure we have the right one.
3607 Dsymbol s = cd.toParentLocal();
3609 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
3610 if (auto cdn = s.isClassDeclaration())
3614 void noReferenceToOuterClass()
3617 exp.error("cannot construct anonymous nested class because no implicit `this` reference to outer class is available");
3619 exp.error("cannot construct nested class `%s` because no implicit `this` reference to outer class `%s` is available",
3620 cd.toChars(), cdn.toChars());
3625 return noReferenceToOuterClass();
3627 // Supply an implicit 'this' and try again
3628 exp.thisexp = new ThisExp(exp.loc);
3629 for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
3632 return noReferenceToOuterClass();
3633 ClassDeclaration cdp = sp.isClassDeclaration();
3636 if (cdp == cdn || cdn.isBaseOf(cdp, null))
3638 // Add a '.outer' and try again
3639 exp.thisexp = new DotIdExp(exp.loc, exp.thisexp, Id.outer);
3642 exp.thisexp = exp.thisexp.expressionSemantic(sc);
3643 if (exp.thisexp.op == EXP.error)
3645 cdthis = exp.thisexp.type.isClassHandle();
3647 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
3649 //printf("cdthis = %s\n", cdthis.toChars());
3650 exp.error("`this` for nested class must be of type `%s`, not `%s`",
3651 cdn.toChars(), exp.thisexp.type.toChars());
3654 if (!MODimplicitConv(exp.thisexp.type.mod, exp.newtype.mod))
3656 exp.error("nested type `%s` should have the same or weaker constancy as enclosing type `%s`",
3657 exp.newtype.toChars(), exp.thisexp.type.toChars());
3661 else if (exp.thisexp)
3663 exp.error("`.new` is only for allocating nested classes");
3666 else if (auto fdn = s.isFuncDeclaration())
3668 // make sure the parent context fdn of cd is reachable from sc
3669 if (!ensureStaticLinkTo(sc.parent, fdn))
3671 exp.error("outer function context of `%s` is needed to `new` nested class `%s`",
3672 fdn.toPrettyChars(), cd.toPrettyChars());
3679 else if (exp.thisexp)
3681 exp.error("`.new` is only for allocating nested classes");
3687 if (AggregateDeclaration ad2 = cd.isMember2())
3689 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
3690 if (te.op != EXP.error)
3691 te = getRightThis(exp.loc, sc, ad2, te, cd);
3692 if (te.op == EXP.error)
3694 exp.error("need `this` of type `%s` needed to `new` nested class `%s`", ad2.toChars(), cd.toChars());
3700 if (cd.disableNew && !exp.onstack)
3702 exp.error("cannot allocate `class %s` with `new` because it is annotated with `@disable new()`",
3703 originalNewtype.toChars());
3709 FuncDeclaration f = resolveFuncCall(exp.loc, sc, cd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3713 checkFunctionAttributes(exp, sc, f);
3714 checkAccess(cd, exp.loc, sc, f);
3716 TypeFunction tf = f.type.isTypeFunction();
3718 exp.arguments = new Expressions();
3719 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3722 exp.member = f.isCtorDeclaration();
3729 exp.error("no constructor for `%s`", cd.toChars());
3733 // https://issues.dlang.org/show_bug.cgi?id=19941
3734 // Run semantic on all field initializers to resolve any forward
3735 // references. This is the same as done for structs in sd.fill().
3736 for (ClassDeclaration c = cd; c; c = c.baseClass)
3738 foreach (v; c.fields)
3740 if (v.inuse || v._scope is null || v._init is null ||
3741 v._init.isVoidInitializer())
3744 v._init = v._init.initializerSemantic(v._scope, v.type, INITinterpret);
3750 // When using `@nogc` exception handling, lower `throw new E(args)` to
3751 // `throw (__tmp = _d_newThrowable!E(), __tmp.__ctor(args), __tmp)`.
3752 if (global.params.ehnogc && exp.thrownew &&
3753 !cd.isCOMclass() && !cd.isCPPclass())
3757 Expression id = new IdentifierExp(exp.loc, Id.empty);
3758 id = new DotIdExp(exp.loc, id, Id.object);
3760 auto tiargs = new Objects();
3761 tiargs.push(exp.newtype);
3762 id = new DotTemplateInstanceExp(exp.loc, id, Id._d_newThrowable, tiargs);
3763 id = new CallExp(exp.loc, id).expressionSemantic(sc);
3766 Expression tmp = extractSideEffect(sc, "__tmpThrowable", idVal, id, true);
3767 // auto castTmp = new CastExp(exp.loc, tmp, exp.type);
3769 auto ctor = new DotIdExp(exp.loc, tmp, Id.ctor).expressionSemantic(sc);
3770 auto ctorCall = new CallExp(exp.loc, ctor, exp.arguments);
3772 id = Expression.combine(idVal, exp.argprefix).expressionSemantic(sc);
3773 id = Expression.combine(id, ctorCall).expressionSemantic(sc);
3774 // id = Expression.combine(id, castTmp).expressionSemantic(sc);
3776 result = id.expressionSemantic(sc);
3780 else if (auto ts = tb.isTypeStruct())
3784 if (sd.sizeok != Sizeok.done)
3787 sd.ctor = sd.searchCtor();
3788 if (sd.noDefaultCtor && !nargs)
3790 exp.error("default construction is disabled for type `%s`", sd.type.toChars());
3793 // checkDeprecated() is already done in newtype.typeSemantic().
3797 exp.error("cannot allocate `struct %s` with `new` because it is annotated with `@disable new()`",
3798 originalNewtype.toChars());
3802 // https://issues.dlang.org/show_bug.cgi?id=22639
3803 // If the new expression has arguments, we either should call a
3804 // regular constructor of a copy constructor if the first argument
3805 // is the same type as the struct
3806 if (nargs && (sd.hasRegularCtor() || (sd.ctor && (*exp.arguments)[0].type.mutableOf() == sd.type.mutableOf())))
3808 FuncDeclaration f = resolveFuncCall(exp.loc, sc, sd.ctor, null, tb, exp.arguments, FuncResolveFlag.standard);
3812 checkFunctionAttributes(exp, sc, f);
3813 checkAccess(sd, exp.loc, sc, f);
3815 TypeFunction tf = f.type.isTypeFunction();
3817 exp.arguments = new Expressions();
3818 if (functionParameters(exp.loc, sc, tf, null, exp.type, exp.arguments, f, &exp.type, &exp.argprefix))
3821 exp.member = f.isCtorDeclaration();
3824 if (checkFrameAccess(exp.loc, sc, sd, sd.fields.length))
3830 exp.arguments = new Expressions();
3832 if (!sd.fit(exp.loc, sc, exp.arguments, tb))
3835 if (!sd.fill(exp.loc, *exp.arguments, false))
3838 if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.length : 0))
3841 /* Since a `new` allocation may escape, check each of the arguments for escaping
3843 foreach (arg; *exp.arguments)
3845 if (arg && checkNewEscape(sc, arg, false))
3850 exp.type = exp.type.pointerTo();
3852 else if (tb.ty == Tarray)
3856 // https://issues.dlang.org/show_bug.cgi?id=20422
3857 // Without this check the compiler would give a misleading error
3858 exp.error("missing length argument for array");
3862 Type tn = tb.nextOf().baseElemOf();
3863 Dsymbol s = tn.toDsymbol(sc);
3864 AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
3865 if (ad && ad.noDefaultCtor)
3867 exp.error("default construction is disabled for type `%s`", tb.nextOf().toChars());
3870 for (size_t i = 0; i < nargs; i++)
3872 if (tb.ty != Tarray)
3874 exp.error("too many arguments for array");
3878 Expression arg = (*exp.arguments)[i];
3879 arg = resolveProperties(sc, arg);
3880 arg = arg.implicitCastTo(sc, Type.tsize_t);
3881 if (arg.op == EXP.error)
3883 arg = arg.optimize(WANTvalue);
3884 if (arg.op == EXP.int64 && cast(sinteger_t)arg.toInteger() < 0)
3886 exp.error("negative array index `%s`", arg.toChars());
3889 (*exp.arguments)[i] = arg;
3890 tb = tb.isTypeDArray().next.toBasetype();
3893 else if (tb.isscalar())
3898 else if (nargs == 1)
3900 Expression e = (*exp.arguments)[0];
3901 e = e.implicitCastTo(sc, tb);
3902 (*exp.arguments)[0] = e;
3906 exp.error("more than one argument for construction of `%s`", exp.type.toChars());
3910 exp.type = exp.type.pointerTo();
3912 else if (tb.ty == Taarray)
3914 // e.g. `new Alias(args)`
3917 exp.error("`new` cannot take arguments for an associative array");
3923 exp.error("cannot create a `%s` with `new`", exp.type.toChars());
3927 //printf("NewExp: '%s'\n", toChars());
3928 //printf("NewExp:type '%s'\n", type.toChars());
3929 semanticTypeInfo(sc, exp.type);
3933 result = Expression.combine(newprefix, exp);
3939 override void visit(NewAnonClassExp e)
3941 static if (LOGSEMANTIC)
3943 printf("NewAnonClassExp::semantic() %s\n", e.toChars());
3944 //printf("thisexp = %p\n", thisexp);
3945 //printf("type: %s\n", type.toChars());
3948 Expression d = new DeclarationExp(e.loc, e.cd);
3949 sc = sc.push(); // just create new scope
3950 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
3951 d = d.expressionSemantic(sc);
3954 if (!e.cd.errors && sc.intypeof && !sc.parent.inNonRoot())
3956 ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
3958 sds.members = new Dsymbols();
3959 sds.members.push(e.cd);
3962 Expression n = new NewExp(e.loc, e.thisexp, e.cd.type, e.arguments);
3964 Expression c = new CommaExp(e.loc, d, n);
3965 result = c.expressionSemantic(sc);
3968 override void visit(SymOffExp e)
3970 static if (LOGSEMANTIC)
3972 printf("SymOffExp::semantic('%s')\n", e.toChars());
3974 //var.dsymbolSemantic(sc);
3976 e.type = e.var.type.pointerTo();
3978 if (auto v = e.var.isVarDeclaration())
3980 if (v.checkNestedReference(sc, e.loc))
3983 else if (auto f = e.var.isFuncDeclaration())
3985 if (f.checkNestedReference(sc, e.loc))
3992 override void visit(VarExp e)
3994 static if (LOGSEMANTIC)
3996 printf("VarExp::semantic(%s)\n", e.toChars());
3999 auto vd = e.var.isVarDeclaration();
4000 auto fd = e.var.isFuncDeclaration();
4004 //printf("L%d fd = %s\n", __LINE__, f.toChars());
4005 if (!fd.functionSemantic())
4010 e.type = e.var.type;
4011 if (e.type && !e.type.deco)
4013 auto decl = e.var.isDeclaration();
4016 e.type = e.type.typeSemantic(e.loc, sc);
4021 /* Fix for 1161 doesn't work because it causes visibility
4022 * problems when instantiating imported templates passing private
4023 * variables as alias template parameters.
4025 //checkAccess(loc, sc, NULL, var);
4029 if (vd.checkNestedReference(sc, e.loc))
4032 // https://issues.dlang.org/show_bug.cgi?id=12025
4033 // If the variable is not actually used in runtime code,
4034 // the purity violation error is redundant.
4035 //checkPurity(sc, vd);
4039 // TODO: If fd isn't yet resolved its overload, the checkNestedReference
4040 // call would cause incorrect validation.
4041 // Maybe here should be moved in CallExp, or AddrExp for functions.
4042 if (fd.checkNestedReference(sc, e.loc))
4045 else if (auto od = e.var.isOverDeclaration())
4047 e.type = Type.tvoid; // ambiguous type?
4053 override void visit(FuncExp exp)
4055 static if (LOGSEMANTIC)
4057 printf("FuncExp::semantic(%s)\n", exp.toChars());
4059 printf(" treq = %s\n", exp.fd.treq.toChars());
4071 sc = sc.push(); // just create new scope
4072 sc.flags &= ~SCOPE.ctfe; // temporary stop CTFE
4073 sc.visibility = Visibility(Visibility.Kind.public_); // https://issues.dlang.org/show_bug.cgi?id=12506
4075 /* fd.treq might be incomplete type,
4076 * so should not semantic it.
4077 * void foo(T)(T delegate(int) dg){}
4078 * foo(a=>a); // in IFTI, treq == T delegate(int)
4081 // fd.treq = fd.treq.dsymbolSemantic(loc, sc);
4085 // Set target of return type inference
4086 if (exp.fd.treq && !exp.fd.type.nextOf())
4088 TypeFunction tfv = null;
4089 if (exp.fd.treq.ty == Tdelegate || exp.fd.treq.isPtrToFunction())
4090 tfv = cast(TypeFunction)exp.fd.treq.nextOf();
4093 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4094 tfl.next = tfv.nextOf();
4098 //printf("td = %p, treq = %p\n", td, fd.treq);
4101 assert(exp.td.parameters && exp.td.parameters.length);
4102 exp.td.dsymbolSemantic(sc);
4103 exp.type = Type.tvoid; // temporary type
4105 if (exp.fd.treq) // defer type determination
4108 if (exp.matchType(exp.fd.treq, sc, &fe) > MATCH.nomatch)
4116 olderrors = global.errors;
4117 exp.fd.dsymbolSemantic(sc);
4118 if (olderrors == global.errors)
4120 exp.fd.semantic2(sc);
4121 if (olderrors == global.errors)
4122 exp.fd.semantic3(sc);
4124 if (olderrors != global.errors)
4126 if (exp.fd.type && exp.fd.type.ty == Tfunction && !exp.fd.type.nextOf())
4127 (cast(TypeFunction)exp.fd.type).next = Type.terror;
4132 // Type is a "delegate to" or "pointer to" the function literal
4133 if ((exp.fd.isNested() && exp.fd.tok == TOK.delegate_) || (exp.tok == TOK.reserved && exp.fd.treq && exp.fd.treq.ty == Tdelegate))
4135 // https://issues.dlang.org/show_bug.cgi?id=22686
4136 // if the delegate return type is an error
4137 // abort semantic of the FuncExp and propagate
4139 if (exp.fd.type.isTypeError())
4144 exp.type = new TypeDelegate(exp.fd.type.isTypeFunction());
4145 exp.type = exp.type.typeSemantic(exp.loc, sc);
4147 exp.fd.tok = TOK.delegate_;
4151 exp.type = new TypePointer(exp.fd.type);
4152 exp.type = exp.type.typeSemantic(exp.loc, sc);
4153 //type = fd.type.pointerTo();
4155 /* A lambda expression deduced to function pointer might become
4156 * to a delegate literal implicitly.
4158 * auto foo(void function() fp) { return 1; }
4159 * assert(foo({}) == 1);
4161 * So, should keep fd.tok == TOK.reserve if fd.treq == NULL.
4163 if (exp.fd.treq && exp.fd.treq.ty == Tpointer)
4165 // change to non-nested
4166 exp.fd.tok = TOK.function_;
4167 exp.fd.vthis = null;
4170 exp.fd.tookAddressOf++;
4178 * Perform semantic analysis on function literals
4180 * Test the following construct:
4182 * (x, y, z) { return x + y + z; }(42, 84, 1992);
4185 Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
4187 if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.length)
4189 for (size_t k = 0; k < arguments.length; k++)
4191 Expression checkarg = (*arguments)[k];
4192 if (checkarg.op == EXP.error)
4198 assert(exp.td.parameters && exp.td.parameters.length);
4199 exp.td.dsymbolSemantic(sc);
4201 TypeFunction tfl = cast(TypeFunction)exp.fd.type;
4202 size_t dim = tfl.parameterList.length;
4203 if (arguments.length < dim)
4205 // Default arguments are always typed, so they don't need inference.
4206 Parameter p = tfl.parameterList[arguments.length];
4208 dim = arguments.length;
4211 if ((tfl.parameterList.varargs == VarArg.none && arguments.length > dim) ||
4212 arguments.length < dim)
4215 foreach (idx, ref arg; *arguments)
4216 buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars());
4217 exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
4218 exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
4220 exp.errorSupplemental("too %s arguments, expected %d, got %d",
4221 arguments.length < dim ? "few".ptr : "many".ptr,
4222 cast(int)dim, cast(int)arguments.length);
4223 return ErrorExp.get();
4226 auto tiargs = new Objects();
4227 tiargs.reserve(exp.td.parameters.length);
4229 for (size_t i = 0; i < exp.td.parameters.length; i++)
4231 TemplateParameter tp = (*exp.td.parameters)[i];
4232 assert(dim <= tfl.parameterList.length);
4233 foreach (u, p; tfl.parameterList)
4238 if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
4240 Expression e = (*arguments)[u];
4241 tiargs.push(e.type);
4247 auto ti = new TemplateInstance(exp.loc, exp.td, tiargs);
4248 return (new ScopeExp(exp.loc, ti)).expressionSemantic(sc);
4250 return exp.expressionSemantic(sc);
4253 override void visit(CallExp exp)
4255 static if (LOGSEMANTIC)
4257 printf("CallExp::semantic() %s\n", exp.toChars());
4262 return; // semantic() already run
4265 Objects* tiargs = null; // initial list of template arguments
4266 Expression ethis = null;
4268 Expression e1org = exp.e1;
4270 if (auto ce = exp.e1.isCommaExp())
4272 /* Rewrite (a,b)(args) as (a,(b(args)))
4276 result = ce.expressionSemantic(sc);
4279 if (DelegateExp de = exp.e1.isDelegateExp())
4281 exp.e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
4285 if (FuncExp fe = exp.e1.isFuncExp())
4287 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
4288 preFunctionParameters(sc, exp.arguments))
4291 // Run e1 semantic even if arguments have any errors
4292 exp.e1 = callExpSemantic(fe, sc, exp.arguments);
4293 if (exp.e1.op == EXP.error)
4299 if (sc.flags & SCOPE.Cfile)
4301 /* See if need to rewrite the AST because of cast/call ambiguity
4303 if (auto e = castCallAmbiguity(exp, sc))
4305 result = expressionSemantic(e, sc);
4310 if (Expression ex = resolveUFCS(sc, exp))
4317 * foo!(tiargs)(funcargs)
4319 if (ScopeExp se = exp.e1.isScopeExp())
4321 TemplateInstance ti = se.sds.isTemplateInstance();
4324 /* Attempt to instantiate ti. If that works, go with it.
4325 * If not, go with partial explicit specialization.
4327 WithScopeSymbol withsym;
4328 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
4330 if (withsym && withsym.withstate.wthis)
4332 exp.e1 = new VarExp(exp.e1.loc, withsym.withstate.wthis);
4333 exp.e1 = new DotTemplateInstanceExp(exp.e1.loc, exp.e1, ti);
4336 if (ti.needsTypeInference(sc, 1))
4338 /* Go with partial explicit specialization
4341 assert(ti.tempdecl);
4342 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4343 exp.e1 = new TemplateExp(exp.loc, td);
4344 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4345 exp.e1 = new VarExp(exp.loc, od);
4347 exp.e1 = new OverExp(exp.loc, ti.tempdecl.isOverloadSet());
4351 Expression e1x = exp.e1.expressionSemantic(sc);
4352 if (e1x.op == EXP.error)
4363 * expr.foo!(tiargs)(funcargs)
4366 if (DotTemplateInstanceExp se = exp.e1.isDotTemplateInstanceExp())
4368 TemplateInstance ti = se.ti;
4370 /* Attempt to instantiate ti. If that works, go with it.
4371 * If not, go with partial explicit specialization.
4373 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
4375 if (ti.needsTypeInference(sc, 1))
4377 /* Go with partial explicit specialization
4380 assert(ti.tempdecl);
4381 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
4382 exp.e1 = new DotTemplateExp(exp.loc, se.e1, td);
4383 else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
4385 exp.e1 = new DotVarExp(exp.loc, se.e1, od, true);
4388 exp.e1 = new DotExp(exp.loc, se.e1, new OverExp(exp.loc, ti.tempdecl.isOverloadSet()));
4392 Expression e1x = exp.e1.expressionSemantic(sc);
4393 if (e1x.op == EXP.error)
4404 //printf("Lagain: %s\n", toChars());
4406 if (exp.e1.op == EXP.this_ || exp.e1.op == EXP.super_)
4408 // semantic() run later for these
4412 if (DotIdExp die = exp.e1.isDotIdExp())
4414 exp.e1 = die.expressionSemantic(sc);
4415 /* Look for e1 having been rewritten to expr.opDispatch!(string)
4416 * We handle such earlier, so go back.
4417 * Note that in the rewrite, we carefully did not run semantic() on e1
4419 if (exp.e1.op == EXP.dotTemplateInstance)
4427 if (++nest > global.recursionLimit)
4429 exp.error("recursive evaluation of `%s`", exp.toChars());
4433 Expression ex = unaSemantic(exp, sc);
4442 /* Look for e1 being a lazy parameter
4444 if (VarExp ve = exp.e1.isVarExp())
4446 if (ve.var.storage_class & STC.lazy_)
4448 // lazy parameters can be called without violating purity and safety
4449 Type tw = ve.var.type;
4450 Type tc = ve.var.type.substWildTo(MODFlags.const_);
4451 auto tf = new TypeFunction(ParameterList(), tc, LINK.d, STC.safe | STC.pure_);
4452 (tf = cast(TypeFunction)tf.typeSemantic(exp.loc, sc)).next = tw; // hack for bug7757
4453 auto t = new TypeDelegate(tf);
4454 ve.type = t.typeSemantic(exp.loc, sc);
4456 VarDeclaration v = ve.var.isVarDeclaration();
4457 if (v && ve.checkPurity(sc, v))
4461 if (exp.e1.op == EXP.symbolOffset && (cast(SymOffExp)exp.e1).hasOverloads)
4463 SymOffExp se = cast(SymOffExp)exp.e1;
4464 exp.e1 = new VarExp(se.loc, se.var, true);
4465 exp.e1 = exp.e1.expressionSemantic(sc);
4467 else if (DotExp de = exp.e1.isDotExp())
4469 if (de.e2.op == EXP.overloadSet)
4476 else if (exp.e1.op == EXP.star && exp.e1.type.ty == Tfunction)
4478 // Rewrite (*fp)(arguments) to fp(arguments)
4479 exp.e1 = (cast(PtrExp)exp.e1).e1;
4481 else if (exp.e1.op == EXP.type && (sc && sc.flags & SCOPE.Cfile))
4483 const numArgs = exp.arguments ? exp.arguments.length : 0;
4485 /* Ambiguous cases arise from CParser where there is not enough
4486 * information to determine if we have a function call or declaration.
4487 * type-name ( identifier ) ;
4488 * identifier ( identifier ) ;
4489 * If exp.e1 is a type-name, then this is a declaration. C11 does not
4490 * have type construction syntax, so don't convert this to a cast().
4494 Expression arg = (*exp.arguments)[0];
4495 if (auto ie = (*exp.arguments)[0].isIdentifierExp())
4497 TypeExp te = cast(TypeExp)exp.e1;
4498 auto initializer = new VoidInitializer(ie.loc);
4499 Dsymbol s = new VarDeclaration(ie.loc, te.type, ie.ident, initializer);
4500 auto decls = new Dsymbols(1);
4502 s = new LinkDeclaration(s.loc, LINK.c, decls);
4503 result = new DeclarationExp(exp.loc, s);
4504 result = result.expressionSemantic(sc);
4508 arg.error("identifier or `(` expected");
4509 result = ErrorExp.get();
4513 exp.error("identifier or `(` expected before `)`");
4514 result = ErrorExp.get();
4519 Type t1 = exp.e1.type ? exp.e1.type.toBasetype() : null;
4521 if (exp.e1.op == EXP.error)
4526 if (arrayExpressionSemantic(exp.arguments.peekSlice(), sc) ||
4527 preFunctionParameters(sc, exp.arguments))
4530 // Check for call operator overload
4533 if (t1.ty == Tstruct)
4535 auto sd = (cast(TypeStruct)t1).sym;
4536 sd.size(exp.loc); // Resolve forward references to construct object
4537 if (sd.sizeok != Sizeok.done)
4540 sd.ctor = sd.searchCtor();
4541 /* If `sd.ctor` is a generated copy constructor, this means that it
4542 is the single constructor that this struct has. In order to not
4543 disable default construction, the ctor is nullified. The side effect
4544 of this is that the generated copy constructor cannot be called
4545 explicitly, but that is ok, because when calling a constructor the
4546 default constructor should have priority over the generated copy
4551 auto ctor = sd.ctor.isCtorDeclaration();
4552 if (ctor && ctor.isCpCtor && ctor.isGenerated())
4556 // First look for constructor
4557 if (exp.e1.op == EXP.type && sd.ctor)
4559 if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.length))
4562 /* https://issues.dlang.org/show_bug.cgi?id=20695
4563 If all constructors are copy constructors, then
4564 try default construction.
4566 if (!sd.hasRegularCtor &&
4567 // https://issues.dlang.org/show_bug.cgi?id=22639
4568 // we might still have a copy constructor that could be called
4569 (*exp.arguments)[0].type.mutableOf != sd.type.mutableOf())
4572 auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
4573 if (!sd.fill(exp.loc, *sle.elements, true))
4575 if (checkFrameAccess(exp.loc, sc, sd, sle.elements.length))
4578 // https://issues.dlang.org/show_bug.cgi?id=14556
4579 // Set concrete type to avoid further redundant semantic().
4580 sle.type = exp.e1.type;
4582 /* Constructor takes a mutable object, so don't use
4583 * the immutable initializer symbol.
4585 sle.useStaticInit = false;
4588 if (auto cf = sd.ctor.isCtorDeclaration())
4590 e = new DotVarExp(exp.loc, e, cf, true);
4592 else if (auto td = sd.ctor.isTemplateDeclaration())
4594 e = new DotIdExp(exp.loc, e, td.ident);
4596 else if (auto os = sd.ctor.isOverloadSet())
4598 e = new DotExp(exp.loc, e, new OverExp(exp.loc, os));
4602 e = new CallExp(exp.loc, e, exp.arguments);
4603 e = e.expressionSemantic(sc);
4607 // No constructor, look for overload of opCall
4608 if (search_function(sd, Id.call))
4610 // overload of opCall, therefore it's a call
4611 if (exp.e1.op != EXP.type)
4613 if (sd.aliasthis && !isRecursiveAliasThis(exp.att1, exp.e1.type))
4615 exp.e1 = resolveAliasThis(sc, exp.e1);
4618 exp.error("%s `%s` does not overload ()", sd.kind(), sd.toChars());
4622 /* It's a struct literal
4625 Expression e = new StructLiteralExp(exp.loc, sd, exp.arguments, exp.e1.type);
4626 e = e.expressionSemantic(sc);
4630 else if (t1.ty == Tclass)
4633 // Rewrite as e1.call(arguments)
4634 Expression e = new DotIdExp(exp.loc, exp.e1, Id.call);
4635 e = new CallExp(exp.loc, e, exp.arguments);
4636 e = e.expressionSemantic(sc);
4640 else if (exp.e1.op == EXP.type && t1.isscalar())
4644 // Make sure to use the enum type itself rather than its
4646 // https://issues.dlang.org/show_bug.cgi?id=16346
4647 if (exp.e1.type.ty == Tenum)
4652 if (!exp.arguments || exp.arguments.length == 0)
4654 e = t1.defaultInitLiteral(exp.loc);
4656 else if (exp.arguments.length == 1)
4658 e = (*exp.arguments)[0];
4659 e = e.implicitCastTo(sc, t1);
4660 e = new CastExp(exp.loc, e, t1);
4664 exp.error("more than one argument for construction of `%s`", t1.toChars());
4667 e = e.expressionSemantic(sc);
4673 FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
4674 OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
4676 FuncDeclaration f = null;
4679 if (tiargs && s.isFuncDeclaration())
4681 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, FuncResolveFlag.quiet))
4687 /* Error if match in more than one overload set,
4688 * even if one is a 'better' match than the other.
4690 ScopeDsymbol.multiplyDefined(loc, f, f2);
4698 .error(loc, "no overload matches for `%s`", exp.toChars());
4699 errorSupplemental(loc, "Candidates are:");
4702 overloadApply(s, (ds){
4703 if (auto fd = ds.isFuncDeclaration())
4704 .errorSupplemental(ds.loc, "%s%s", fd.toChars(),
4705 fd.type.toTypeFunction().parameterList.parametersTypeToChars());
4707 .errorSupplemental(ds.loc, "%s", ds.toChars());
4717 bool isSuper = false;
4718 if (exp.e1.op == EXP.dotVariable && t1.ty == Tfunction || exp.e1.op == EXP.dotTemplateDeclaration)
4720 UnaExp ue = cast(UnaExp)exp.e1;
4722 Expression ue1old = ue.e1; // need for 'right this' check
4726 if (exp.e1.op == EXP.dotVariable)
4728 dve = cast(DotVarExp)exp.e1;
4736 dte = cast(DotTemplateExp)exp.e1;
4740 // Do overload resolution
4741 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, ue.e1.type, exp.arguments, FuncResolveFlag.standard);
4742 if (!exp.f || exp.f.errors || exp.f.type.ty == Terror)
4745 if (exp.f.interfaceVirtual)
4747 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
4749 auto b = exp.f.interfaceVirtual;
4751 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
4752 ue.e1 = ue.e1.expressionSemantic(sc);
4753 auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.length);
4755 exp.f = ad2.vtbl[vi].isFuncDeclaration();
4758 if (exp.f.needThis())
4760 AggregateDeclaration ad = exp.f.isMemberLocal();
4761 ue.e1 = getRightThis(exp.loc, sc, ad, ue.e1, exp.f);
4762 if (ue.e1.op == EXP.error)
4769 if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
4771 if (checkParamArgumentEscape(sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
4776 /* Cannot call public functions from inside invariant
4777 * (because then the invariant would have infinite recursion)
4779 if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == EXP.this_ && exp.f.addPostInvariant())
4781 exp.error("cannot call `public`/`export` function `%s` from invariant", exp.f.toChars());
4785 if (!exp.ignoreAttributes)
4786 checkFunctionAttributes(exp, sc, exp.f);
4787 checkAccess(exp.loc, sc, ue.e1, exp.f);
4788 if (!exp.f.needThis())
4790 exp.e1 = Expression.combine(ue.e1, new VarExp(exp.loc, exp.f, false));
4794 if (ue1old.checkRightThis(sc))
4796 if (exp.e1.op == EXP.dotVariable)
4799 exp.e1.type = exp.f.type;
4803 exp.e1 = new DotVarExp(exp.loc, dte.e1, exp.f, false);
4804 exp.e1 = exp.e1.expressionSemantic(sc);
4805 if (exp.e1.op == EXP.error)
4807 ue = cast(UnaExp)exp.e1;
4811 printf("ue.e1 = %s\n", ue.e1.toChars());
4812 printf("f = %s\n", exp.f.toChars());
4813 printf("t1 = %s\n", t1.toChars());
4814 printf("e1 = %s\n", exp.e1.toChars());
4815 printf("e1.type = %s\n", exp.e1.type.toChars());
4818 // See if we need to adjust the 'this' pointer
4819 AggregateDeclaration ad = exp.f.isThis();
4820 ClassDeclaration cd = ue.e1.type.isClassHandle();
4821 if (ad && cd && ad.isClassDeclaration())
4823 if (ue.e1.op == EXP.dotType)
4825 ue.e1 = (cast(DotTypeExp)ue.e1).e1;
4826 exp.directcall = true;
4828 else if (ue.e1.op == EXP.super_)
4829 exp.directcall = true;
4830 else if ((cd.storage_class & STC.final_) != 0) // https://issues.dlang.org/show_bug.cgi?id=14211
4831 exp.directcall = true;
4835 ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
4836 ue.e1 = ue.e1.expressionSemantic(sc);
4840 // If we've got a pointer to a function then deference it
4841 // https://issues.dlang.org/show_bug.cgi?id=16483
4842 if (exp.e1.type.isPtrToFunction())
4844 Expression e = new PtrExp(exp.loc, exp.e1);
4845 e.type = exp.e1.type.nextOf();
4850 else if (exp.e1.op == EXP.super_ || exp.e1.op == EXP.this_)
4852 auto ad = sc.func ? sc.func.isThis() : null;
4853 auto cd = ad ? ad.isClassDeclaration() : null;
4855 isSuper = exp.e1.op == EXP.super_;
4858 // Base class constructor call
4859 if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
4861 exp.error("super class constructor call must be in a constructor");
4864 if (!cd.baseClass.ctor)
4866 exp.error("no super class constructor for `%s`", cd.baseClass.toChars());
4872 // `this` call expression must be inside a
4874 if (!ad || !sc.func.isCtorDeclaration())
4876 exp.error("constructor call must be in a constructor");
4880 // https://issues.dlang.org/show_bug.cgi?id=18719
4881 // If `exp` is a call expression to another constructor
4882 // then it means that all struct/class fields will be
4883 // initialized after this call.
4884 foreach (ref field; sc.ctorflow.fieldinit)
4886 field.csx |= CSX.this_ctor;
4890 if (!sc.intypeof && !(sc.ctorflow.callSuper & CSX.halt))
4892 if (sc.inLoop || sc.ctorflow.callSuper & CSX.label)
4893 exp.error("constructor calls not allowed in loops or after labels");
4894 if (sc.ctorflow.callSuper & (CSX.super_ctor | CSX.this_ctor))
4895 exp.error("multiple constructor calls");
4896 if ((sc.ctorflow.callSuper & CSX.return_) && !(sc.ctorflow.callSuper & CSX.any_ctor))
4897 exp.error("an earlier `return` statement skips constructor");
4898 sc.ctorflow.callSuper |= CSX.any_ctor | (isSuper ? CSX.super_ctor : CSX.this_ctor);
4901 tthis = ad.type.addMod(sc.func.type.mod);
4902 auto ctor = isSuper ? cd.baseClass.ctor : ad.ctor;
4903 if (auto os = ctor.isOverloadSet())
4904 exp.f = resolveOverloadSet(exp.loc, sc, os, null, tthis, exp.arguments);
4906 exp.f = resolveFuncCall(exp.loc, sc, ctor, null, tthis, exp.arguments, FuncResolveFlag.standard);
4908 if (!exp.f || exp.f.errors)
4911 checkFunctionAttributes(exp, sc, exp.f);
4912 checkAccess(exp.loc, sc, null, exp.f);
4914 exp.e1 = new DotVarExp(exp.e1.loc, exp.e1, exp.f, false);
4915 exp.e1 = exp.e1.expressionSemantic(sc);
4916 // https://issues.dlang.org/show_bug.cgi?id=21095
4917 if (exp.e1.op == EXP.error)
4921 // BUG: this should really be done by checking the static
4923 if (exp.f == sc.func)
4925 exp.error("cyclic constructor call");
4929 else if (auto oe = exp.e1.isOverExp())
4931 exp.f = resolveOverloadSet(exp.loc, sc, oe.vars, tiargs, tthis, exp.arguments);
4935 exp.e1 = new DotVarExp(exp.loc, ethis, exp.f, false);
4937 exp.e1 = new VarExp(exp.loc, exp.f, false);
4942 exp.error("function expected before `()`, not `%s`", exp.e1.toChars());
4945 else if (t1.ty == Terror)
4949 else if (t1.ty != Tfunction)
4955 if (auto fe = exp.e1.isFuncExp())
4957 // function literal that direct called is always inferred.
4960 tf = cast(TypeFunction)exp.f.type;
4961 p = "function literal";
4963 else if (t1.ty == Tdelegate)
4965 TypeDelegate td = cast(TypeDelegate)t1;
4966 assert(td.next.ty == Tfunction);
4967 tf = cast(TypeFunction)td.next;
4970 else if (auto tfx = t1.isPtrToFunction())
4973 p = "function pointer";
4975 else if (exp.e1.op == EXP.dotVariable && (cast(DotVarExp)exp.e1).var.isOverDeclaration())
4977 DotVarExp dve = cast(DotVarExp)exp.e1;
4978 exp.f = resolveFuncCall(exp.loc, sc, dve.var, tiargs, dve.e1.type, exp.arguments, FuncResolveFlag.overloadOnly);
4981 if (exp.f.needThis())
4984 dve.type = exp.f.type;
4985 dve.hasOverloads = false;
4988 exp.e1 = new VarExp(dve.loc, exp.f, false);
4989 Expression e = new CommaExp(exp.loc, dve.e1, exp);
4990 result = e.expressionSemantic(sc);
4993 else if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.isOverDeclaration())
4995 s = (cast(VarExp)exp.e1).var;
4998 else if (exp.e1.op == EXP.template_)
5000 s = (cast(TemplateExp)exp.e1).td;
5002 exp.f = resolveFuncCall(exp.loc, sc, s, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5003 if (!exp.f || exp.f.errors)
5005 if (exp.f.needThis())
5009 // Supply an implicit 'this', as in
5011 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), exp.f, false);
5014 else if (isNeedThisScope(sc, exp.f))
5016 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5020 exp.e1 = new VarExp(exp.e1.loc, exp.f, false);
5025 exp.error("function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars());
5029 const(char)* failMessage;
5030 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5031 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5035 argExpTypesToCBuffer(&buf, exp.arguments);
5038 tthis.modToBuffer(&buf);
5040 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5041 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5042 p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5044 errorSupplemental(exp.loc, "%s", failMessage);
5047 // Purity and safety check should run after testing arguments matching
5050 exp.checkPurity(sc, exp.f);
5051 exp.checkSafety(sc, exp.f);
5052 exp.checkNogc(sc, exp.f);
5053 if (exp.f.checkNestedReference(sc, exp.loc))
5056 else if (sc.func && sc.intypeof != 1 && !(sc.flags & (SCOPE.ctfe | SCOPE.debug_)))
5059 if (!tf.purity && sc.func.setImpure())
5061 exp.error("`pure` %s `%s` cannot call impure %s `%s`",
5062 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5065 if (!tf.isnogc && sc.func.setGC())
5067 exp.error("`@nogc` %s `%s` cannot call non-@nogc %s `%s`",
5068 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5071 if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc,
5072 "`@safe` function `%s` cannot call `@system` `%s`", sc.func, exp.e1))
5074 exp.error("`@safe` %s `%s` cannot call `@system` %s `%s`",
5075 sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars());
5082 if (t1.ty == Tpointer)
5084 Expression e = new PtrExp(exp.loc, exp.e1);
5090 else if (VarExp ve = exp.e1.isVarExp())
5092 // Do overload resolution
5093 exp.f = ve.var.isFuncDeclaration();
5098 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.overloadOnly);
5101 exp.f = exp.f.toAliasFunc();
5102 TypeFunction tf = cast(TypeFunction)exp.f.type;
5103 const(char)* failMessage;
5104 Expression[] fargs = exp.arguments ? (*exp.arguments)[] : null;
5105 if (!tf.callMatch(null, fargs, 0, &failMessage, sc))
5109 argExpTypesToCBuffer(&buf, exp.arguments);
5112 //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco);
5113 .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`",
5114 exp.f.kind(), exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList), buf.peekChars());
5116 errorSupplemental(exp.loc, "%s", failMessage);
5120 if (!exp.f || exp.f.errors)
5123 if (exp.f.needThis())
5125 // Change the ancestor lambdas to delegate before hasThis(sc) call.
5126 if (exp.f.checkNestedReference(sc, exp.loc))
5131 // Supply an implicit 'this', as in
5133 exp.e1 = new DotVarExp(exp.loc, (new ThisExp(exp.loc)).expressionSemantic(sc), ve.var);
5134 // Note: we cannot use f directly, because further overload resolution
5135 // through the supplied 'this' may cause different result.
5138 else if (isNeedThisScope(sc, exp.f))
5140 // At this point it is possible that `exp.f` had an ambiguity error that was
5141 // silenced because the previous call to `resolveFuncCall` was done using
5142 // `FuncResolveFlag.overloadOnly`. To make sure that a proper error message
5143 // is printed, redo the call with `FuncResolveFlag.standard`.
5145 // https://issues.dlang.org/show_bug.cgi?id=22157
5147 exp.f = resolveFuncCall(exp.loc, sc, exp.f, tiargs, null, exp.arguments, FuncResolveFlag.standard);
5149 if (!exp.f || exp.f.errors)
5152 // If no error is printed, it means that `f` is the single matching overload
5153 // and it needs `this`.
5154 exp.error("need `this` for `%s` of type `%s`", exp.f.toChars(), exp.f.type.toChars());
5159 checkFunctionAttributes(exp, sc, exp.f);
5160 checkAccess(exp.loc, sc, null, exp.f);
5161 if (exp.f.checkNestedReference(sc, exp.loc))
5167 if (ve.hasOverloads)
5169 exp.e1 = new VarExp(ve.loc, exp.f, false);
5170 exp.e1.type = exp.f.type;
5174 assert(t1.ty == Tfunction);
5176 Expression argprefix;
5178 exp.arguments = new Expressions();
5179 if (functionParameters(exp.loc, sc, cast(TypeFunction)t1, ethis, tthis, exp.arguments, exp.f, &exp.type, &argprefix))
5184 exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922
5185 // avoid recursive expression printing
5186 exp.error("forward reference to inferred return type of function call `%s`", exp.toChars());
5190 if (exp.f && exp.f.tintro)
5194 TypeFunction tf = cast(TypeFunction)exp.f.tintro;
5195 if (tf.next.isBaseOf(t, &offset) && offset)
5198 result = Expression.combine(argprefix, exp.castTo(sc, t));
5203 // Handle the case of a direct lambda call
5204 if (exp.f && exp.f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
5206 exp.f.tookAddressOf = 0;
5209 result = Expression.combine(argprefix, exp);
5213 auto ad = sc.func ? sc.func.isThis() : null;
5214 auto cd = ad ? ad.isClassDeclaration() : null;
5215 if (cd && cd.classKind == ClassKind.cpp && exp.f && !exp.f.fbody)
5217 // if super is defined in C++, it sets the vtable pointer to the base class
5218 // so we have to restore it, but still return 'this' from super() call:
5219 // (auto __vptrTmp = this.__vptr, auto __superTmp = super()), (this.__vptr = __vptrTmp, __superTmp)
5222 auto vptr = new DotIdExp(loc, new ThisExp(loc), Id.__vptr);
5223 auto vptrTmpDecl = copyToTemp(0, "__vptrTmp", vptr);
5224 auto declareVptrTmp = new DeclarationExp(loc, vptrTmpDecl);
5226 auto superTmpDecl = copyToTemp(0, "__superTmp", result);
5227 auto declareSuperTmp = new DeclarationExp(loc, superTmpDecl);
5229 auto declareTmps = new CommaExp(loc, declareVptrTmp, declareSuperTmp);
5231 auto restoreVptr = new AssignExp(loc, vptr.syntaxCopy(), new VarExp(loc, vptrTmpDecl));
5233 Expression e = new CommaExp(loc, declareTmps, new CommaExp(loc, restoreVptr, new VarExp(loc, superTmpDecl)));
5234 result = e.expressionSemantic(sc);
5238 // declare dual-context container
5239 if (exp.f && exp.f.hasDualContext() && !sc.intypeof && sc.func)
5241 // check access to second `this`
5242 if (AggregateDeclaration ad2 = exp.f.isMember2())
5244 Expression te = new ThisExp(exp.loc).expressionSemantic(sc);
5245 if (te.op != EXP.error)
5246 te = getRightThis(exp.loc, sc, ad2, te, exp.f);
5247 if (te.op == EXP.error)
5249 exp.error("need `this` of type `%s` to call function `%s`", ad2.toChars(), exp.f.toChars());
5253 exp.vthis2 = makeThis2Argument(exp.loc, sc, exp.f);
5254 Expression de = new DeclarationExp(exp.loc, exp.vthis2);
5255 result = Expression.combine(de, result);
5256 result = result.expressionSemantic(sc);
5260 override void visit(DeclarationExp e)
5267 static if (LOGSEMANTIC)
5269 printf("DeclarationExp::semantic() %s\n", e.toChars());
5272 uint olderrors = global.errors;
5274 /* This is here to support extern(linkage) declaration,
5275 * where the extern(linkage) winds up being an AttribDeclaration
5278 Dsymbol s = e.declaration;
5282 AttribDeclaration ad = s.isAttribDeclaration();
5285 if (ad.decl && ad.decl.length == 1)
5294 //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
5295 // Insert into both local scope and function scope.
5296 // Must be unique in both.
5299 VarDeclaration v = s.isVarDeclaration();
5302 if (sc.flags & SCOPE.Cfile)
5304 /* Do semantic() on the type before inserting v into the symbol table
5306 if (!v.originalType)
5307 v.originalType = v.type.syntaxCopy();
5308 Scope* sc2 = sc.push();
5309 sc2.stc |= v.storage_class & STC.FUNCATTR;
5310 sc2.linkage = LINK.c; // account for the extern(C) in front of the declaration
5312 v.type = v.type.typeSemantic(v.loc, sc2);
5318 /* Do semantic() on initializer first so this will be illegal:
5321 e.declaration.dsymbolSemantic(sc);
5322 s.parent = sc.parent;
5328 auto conflict = sc.search(Loc.initial, s.ident, null);
5329 e.error("declaration `%s` is already defined", s.toPrettyChars());
5330 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5331 conflict.kind(), conflict.toChars());
5335 if (v && (sc.flags & SCOPE.Cfile))
5337 /* Do semantic() on initializer last so this will be legal:
5340 e.declaration.dsymbolSemantic(sc);
5341 s.parent = sc.parent;
5346 // https://issues.dlang.org/show_bug.cgi?id=11720
5347 if ((s.isFuncDeclaration() ||
5348 s.isAggregateDeclaration() ||
5349 s.isEnumDeclaration() ||
5350 s.isTemplateDeclaration() ||
5352 ) && !sc.func.localsymtab.insert(s))
5354 // Get the previous symbol
5355 Dsymbol originalSymbol = sc.func.localsymtab.lookup(s.ident);
5357 // Perturb the name mangling so that the symbols can co-exist
5358 // instead of colliding
5359 s.localNum = cast(ushort)(originalSymbol.localNum + 1);
5360 // 65535 should be enough for anyone
5363 e.error("more than 65535 symbols with name `%s` generated", s.ident.toChars());
5367 // Replace originalSymbol with s, which updates the localCount
5368 sc.func.localsymtab.update(s);
5370 // The mangling change only works for D mangling
5373 if (!(sc.flags & SCOPE.Cfile))
5375 /* https://issues.dlang.org/show_bug.cgi?id=21272
5376 * If we are in a foreach body we need to extract the
5377 * function containing the foreach
5379 FuncDeclaration fes_enclosing_func;
5380 if (sc.func && sc.func.fes)
5381 fes_enclosing_func = sc.enclosing.enclosing.func;
5383 // Disallow shadowing
5384 for (Scope* scx = sc.enclosing; scx && (scx.func == sc.func || (fes_enclosing_func && scx.func == fes_enclosing_func)); scx = scx.enclosing)
5387 if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
5389 // allow STC.local symbols to be shadowed
5390 // TODO: not really an optimal design
5391 auto decl = s2.isDeclaration();
5392 if (!decl || !(decl.storage_class & STC.local))
5396 e.deprecation("%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5400 e.error("%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
5409 if (!s.isVarDeclaration())
5412 if (sc2.stc & (STC.pure_ | STC.nothrow_ | STC.nogc))
5414 sc2.stc &= ~(STC.pure_ | STC.nothrow_ | STC.nogc);
5415 e.declaration.dsymbolSemantic(sc2);
5418 s.parent = sc.parent;
5420 if (global.errors == olderrors)
5422 e.declaration.semantic2(sc);
5423 if (global.errors == olderrors)
5425 e.declaration.semantic3(sc);
5428 // todo: error in declaration should be propagated.
5430 e.type = Type.tvoid;
5434 override void visit(TypeidExp exp)
5436 static if (LOGSEMANTIC)
5438 printf("TypeidExp::semantic() %s\n", exp.toChars());
5440 Type ta = isType(exp.obj);
5441 Expression ea = isExpression(exp.obj);
5442 Dsymbol sa = isDsymbol(exp.obj);
5443 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5447 dmd.typesem.resolve(ta, exp.loc, sc, ea, ta, sa, true);
5452 if (auto sym = getDsymbol(ea))
5453 ea = symbolToExp(sym, exp.loc, sc, false);
5455 ea = ea.expressionSemantic(sc);
5456 ea = resolveProperties(sc, ea);
5458 if (ea.op == EXP.type)
5464 //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5465 exp.error("no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
5469 ta.checkComplexTransition(exp.loc, sc);
5472 auto tb = ta.toBasetype();
5473 if (ea && tb.ty == Tclass)
5475 if (tb.toDsymbol(sc).isClassDeclaration().classKind == ClassKind.cpp)
5477 error(exp.loc, "runtime type information is not supported for `extern(C++)` classes");
5480 else if (!Type.typeinfoclass)
5482 error(exp.loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
5487 /* Get the dynamic type, which is .classinfo
5489 ea = ea.expressionSemantic(sc);
5490 e = new TypeidExp(ea.loc, ea);
5491 e.type = Type.typeinfoclass.type;
5494 else if (ta.ty == Terror)
5500 // Handle this in the glue layer
5501 e = new TypeidExp(exp.loc, ta);
5502 e.type = getTypeInfoType(exp.loc, ta, sc);
5504 semanticTypeInfo(sc, ta);
5508 e = new CommaExp(exp.loc, ea, e); // execute ea
5509 e = e.expressionSemantic(sc);
5515 override void visit(TraitsExp e)
5517 result = semanticTraits(e, sc);
5520 override void visit(HaltExp e)
5522 static if (LOGSEMANTIC)
5524 printf("HaltExp::semantic()\n");
5526 e.type = Type.tnoreturn;
5530 override void visit(IsExp e)
5532 /* is(targ id tok tspec)
5533 * is(targ id : tok2)
5534 * is(targ id == tok2)
5543 result = IntegerExp.createBool(true);
5548 Tuple tup = isTuple(tded);
5550 s = new TupleDeclaration(e.loc, e.id, &tup.objects);
5552 s = new AliasDeclaration(e.loc, e.id, tded);
5553 s.dsymbolSemantic(sc);
5555 /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
5556 * More investigation is needed.
5558 if (!tup && !sc.insert(s))
5560 auto conflict = sc.search(Loc.initial, s.ident, null);
5561 e.error("declaration `%s` is already defined", s.toPrettyChars());
5562 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5563 conflict.kind(), conflict.toChars());
5566 unSpeculative(sc, s);
5568 result = IntegerExp.createBool(true);
5572 result = IntegerExp.createBool(false);
5576 static if (LOGSEMANTIC)
5578 printf("IsExp::semantic(%s)\n", e.toChars());
5580 if (e.id && !(sc.flags & SCOPE.condition))
5582 e.error("can only declare type aliases within `static if` conditionals or `static assert`s");
5586 if (e.tok2 == TOK.package_ || e.tok2 == TOK.module_) // These is() expressions are special because they can work on modules, not just types.
5588 const oldErrors = global.startGagging();
5589 Dsymbol sym = e.targ.toDsymbol(sc);
5590 global.endGagging(oldErrors);
5594 Package p = resolveIsPackage(sym);
5597 if (e.tok2 == TOK.package_ && p.isModule()) // Note that isModule() will return null for package modules because they're not actually instances of Module.
5599 else if(e.tok2 == TOK.module_ && !(p.isModule() || p.isPackageMod()))
5606 Scope* sc2 = sc.copy(); // keep sc.flags
5609 sc2.flags |= SCOPE.fullinst;
5610 Type t = e.targ.trySemantic(e.loc, sc2);
5612 if (!t) // errors, so condition is false
5617 if (e.tok2 != TOK.reserved)
5622 if (e.targ.ty != Tstruct)
5624 if ((cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5630 if (e.targ.ty != Tstruct)
5632 if (!(cast(TypeStruct)e.targ).sym.isUnionDeclaration())
5638 if (e.targ.ty != Tclass)
5640 if ((cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5645 case TOK.interface_:
5646 if (e.targ.ty != Tclass)
5648 if (!(cast(TypeClass)e.targ).sym.isInterfaceDeclaration())
5654 if (!e.targ.isConst())
5659 case TOK.immutable_:
5660 if (!e.targ.isImmutable())
5666 if (!e.targ.isShared())
5672 if (!e.targ.isWild())
5678 // If class or interface, get the base class and interfaces
5679 if (e.targ.ty != Tclass)
5683 ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
5684 auto args = new Parameters();
5685 args.reserve(cd.baseclasses.length);
5686 if (cd.semanticRun < PASS.semanticdone)
5687 cd.dsymbolSemantic(null);
5688 for (size_t i = 0; i < cd.baseclasses.length; i++)
5690 BaseClass* b = (*cd.baseclasses)[i];
5691 args.push(new Parameter(STC.in_, b.type, null, null, null));
5693 tded = new TypeTuple(args);
5698 if (e.targ.ty != Tenum)
5701 tded = (cast(TypeEnum)e.targ).sym.getMemtype(e.loc);
5705 if (tded.ty == Terror)
5710 if (e.targ.ty != Tdelegate)
5712 tded = (cast(TypeDelegate)e.targ).next; // the underlying function type
5716 case TOK.parameters:
5718 if (e.targ.ty != Tfunction)
5722 /* Generate tuple from function parameter types.
5724 assert(tded.ty == Tfunction);
5725 auto tdedf = tded.isTypeFunction();
5726 auto args = new Parameters();
5727 foreach (i, arg; tdedf.parameterList)
5729 assert(arg && arg.type);
5730 /* If one of the default arguments was an error,
5731 don't return an invalid tuple
5733 if (e.tok2 == TOK.parameters && arg.defaultArg && arg.defaultArg.op == EXP.error)
5735 args.push(new Parameter(arg.storageClass, arg.type, (e.tok2 == TOK.parameters) ? arg.ident : null, (e.tok2 == TOK.parameters) ? arg.defaultArg : null, arg.userAttribDecl));
5737 tded = new TypeTuple(args);
5741 /* Get the 'return type' for the function,
5742 * delegate, or pointer to function.
5744 if (auto tf = e.targ.isFunction_Delegate_PtrToFunction())
5750 case TOK.argumentTypes:
5751 /* Generate a type tuple of the equivalent types used to determine if a
5752 * function argument of this type can be passed in registers.
5753 * The results of this are highly platform dependent, and intended
5754 * primarly for use in implementing va_arg().
5756 tded = target.toArgTypes(e.targ);
5759 // not valid for a parameter
5763 if (e.targ.ty != Tvector)
5765 tded = (cast(TypeVector)e.targ).basetype;
5772 // https://issues.dlang.org/show_bug.cgi?id=18753
5777 else if (e.tspec && !e.id && !(e.parameters && e.parameters.length))
5779 /* Evaluate to true if targ matches tspec
5783 e.tspec = e.tspec.typeSemantic(e.loc, sc);
5784 //printf("targ = %s, %s\n", e.targ.toChars(), e.targ.deco);
5785 //printf("tspec = %s, %s\n", e.tspec.toChars(), e.tspec.deco);
5787 if (e.tok == TOK.colon)
5789 // current scope is itself deprecated, or deprecations are not errors
5790 const bool deprecationAllowed = sc.isDeprecated
5791 || global.params.useDeprecated != DiagnosticReporting.error;
5792 const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
5794 if (preventAliasThis && e.targ.ty == Tstruct)
5796 if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5801 else if (preventAliasThis && e.targ.ty == Tclass)
5803 if ((cast(TypeClass) e.targ).implicitConvToWithoutAliasThis(e.tspec))
5808 else if (e.targ.implicitConvTo(e.tspec))
5815 if (e.targ.equals(e.tspec))
5823 /* Evaluate to true if targ matches tspec.
5824 * If true, declare id as an alias for the specialized type.
5825 * is(targ == tspec, tpl)
5826 * is(targ : tspec, tpl)
5827 * is(targ id == tspec)
5828 * is(targ id : tspec)
5829 * is(targ id == tspec, tpl)
5830 * is(targ id : tspec, tpl)
5832 Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
5833 e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
5835 Objects dedtypes = Objects(e.parameters.length);
5838 MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
5840 if (m == MATCH.nomatch || (m != MATCH.exact && e.tok == TOK.equal))
5846 tded = cast(Type)dedtypes[0];
5849 Objects tiargs = Objects(1);
5852 /* Declare trailing parameters
5854 for (size_t i = 1; i < e.parameters.length; i++)
5856 TemplateParameter tp = (*e.parameters)[i];
5857 Declaration s = null;
5859 m = tp.matchArg(e.loc, sc, &tiargs, i, e.parameters, &dedtypes, &s);
5860 if (m == MATCH.nomatch)
5862 s.dsymbolSemantic(sc);
5865 auto conflict = sc.search(Loc.initial, s.ident, null);
5866 e.error("declaration `%s` is already defined", s.toPrettyChars());
5867 errorSupplemental(conflict.loc, "`%s` `%s` is defined here",
5868 conflict.kind(), conflict.toChars());
5871 unSpeculative(sc, s);
5878 /* Declare id as an alias for type targ. Evaluate to true
5886 override void visit(BinAssignExp exp)
5894 Expression e = exp.op_overload(sc);
5901 if (exp.e1.op == EXP.arrayLength)
5903 // arr.length op= e2;
5904 e = rewriteOpAssign(exp);
5905 e = e.expressionSemantic(sc);
5909 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
5911 if (checkNonAssignmentArrayOp(exp.e1))
5914 if (exp.e1.op == EXP.slice)
5915 (cast(SliceExp)exp.e1).arrayop = true;
5918 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
5921 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
5923 else if (Expression ex = typeCombine(exp, sc))
5928 exp.type = exp.e1.type;
5929 result = arrayOp(exp, sc);
5933 exp.e1 = exp.e1.expressionSemantic(sc);
5934 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
5935 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
5936 exp.type = exp.e1.type;
5938 if (auto ad = isAggregate(exp.e1.type))
5940 if (const s = search_function(ad, Id.opOpAssign))
5942 error(exp.loc, "none of the `opOpAssign` overloads of `%s` are callable for `%s` of type `%s`", ad.toChars(), exp.e1.toChars(), exp.e1.type.toChars());
5946 if (exp.e1.checkScalar() ||
5947 exp.e1.checkReadModifyWrite(exp.op, exp.e2) ||
5948 exp.e1.checkSharedAccess(sc))
5951 int arith = (exp.op == EXP.addAssign || exp.op == EXP.minAssign || exp.op == EXP.mulAssign || exp.op == EXP.divAssign || exp.op == EXP.modAssign || exp.op == EXP.powAssign);
5952 int bitwise = (exp.op == EXP.andAssign || exp.op == EXP.orAssign || exp.op == EXP.xorAssign);
5953 int shift = (exp.op == EXP.leftShiftAssign || exp.op == EXP.rightShiftAssign || exp.op == EXP.unsignedRightShiftAssign);
5955 if (bitwise && exp.type.toBasetype().ty == Tbool)
5956 exp.e2 = exp.e2.implicitCastTo(sc, exp.type);
5957 else if (exp.checkNoBool())
5960 if ((exp.op == EXP.addAssign || exp.op == EXP.minAssign) && exp.e1.type.toBasetype().ty == Tpointer && exp.e2.type.toBasetype().isintegral())
5962 result = scaleFactor(exp, sc);
5966 if (Expression ex = typeCombine(exp, sc))
5972 if (arith && (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc)))
5974 if ((bitwise || shift) && (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc)))
5979 if (exp.e2.type.toBasetype().ty != Tvector)
5980 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
5983 if (!target.isVectorOpSupported(exp.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
5985 result = exp.incompatibleTypes();
5989 if (exp.e1.op == EXP.error || exp.e2.op == EXP.error)
5992 e = exp.checkOpAssignTypes(sc);
5993 if (e.op == EXP.error)
5999 assert(e.op == EXP.assign || e == exp);
6000 result = (cast(BinExp)e).reorderSettingAAElem(sc);
6003 private Expression compileIt(MixinExp exp)
6006 if (expressionsToString(buf, sc, exp.exps))
6009 uint errors = global.errors;
6010 const len = buf.length;
6011 const str = buf.extractChars()[0 .. len];
6012 scope p = new Parser!ASTCodegen(exp.loc, sc._module, str, false);
6014 //printf("p.loc.linnum = %d\n", p.loc.linnum);
6016 Expression e = p.parseExpression();
6017 if (global.errors != errors)
6020 if (p.token.value != TOK.endOfFile)
6022 exp.error("incomplete mixin expression `%s`", str.ptr);
6028 override void visit(MixinExp exp)
6030 /* https://dlang.org/spec/expression.html#mixin_expressions
6033 static if (LOGSEMANTIC)
6035 printf("MixinExp::semantic('%s')\n", exp.toChars());
6038 auto e = compileIt(exp);
6041 result = e.expressionSemantic(sc);
6044 override void visit(ImportExp e)
6046 static if (LOGSEMANTIC)
6048 printf("ImportExp::semantic('%s')\n", e.toChars());
6051 auto se = semanticString(sc, e.e1, "file name argument");
6056 auto namez = se.toStringz();
6057 if (!global.filePath)
6059 e.error("need `-J` switch to import text file `%s`", namez.ptr);
6063 /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
6064 * ('Path Traversal') attacks.
6065 * https://cwe.mitre.org/data/definitions/22.html
6068 if (FileName.absolute(namez))
6070 e.error("absolute path is not allowed in import expression: `%s`", se.toChars());
6074 auto idxReserved = FileName.findReservedChar(namez);
6075 if (idxReserved != size_t.max)
6077 e.error("`%s` is not a valid filename on this platform", se.toChars());
6078 e.errorSupplemental("Character `'%c'` is reserved and cannot be used", namez[idxReserved]);
6082 if (FileName.refersToParentDir(namez))
6084 e.error("path refers to parent (`..`) directory: `%s`", se.toChars());
6088 auto resolvedNamez = FileName.searchPath(global.filePath, namez, false);
6091 e.error("file `%s` cannot be found or not in a path specified with `-J`", se.toChars());
6092 e.errorSupplemental("Path(s) searched (as provided by `-J`):");
6093 foreach (idx, path; *global.filePath)
6095 const attr = FileName.exists(path);
6096 const(char)* err = attr == 2 ? "" :
6097 (attr == 1 ? " (not a directory)" : " (path not found)");
6098 e.errorSupplemental("[%llu]: `%s`%s", cast(ulong)idx, path, err);
6103 sc._module.contentImportedFiles.push(resolvedNamez.ptr);
6104 if (global.params.verbose)
6106 const slice = se.peekString();
6107 message("file %.*s\t(%s)", cast(int)slice.length, slice.ptr, resolvedNamez.ptr);
6109 if (global.params.moduleDeps.buffer !is null)
6111 OutBuffer* ob = global.params.moduleDeps.buffer;
6112 Module imod = sc._module;
6114 if (!global.params.moduleDeps.name)
6115 ob.writestring("depsFile ");
6116 ob.writestring(imod.toPrettyChars());
6117 ob.writestring(" (");
6118 escapePath(ob, imod.srcfile.toChars());
6119 ob.writestring(") : ");
6120 if (global.params.moduleDeps.name)
6121 ob.writestring("string : ");
6122 ob.write(se.peekString());
6123 ob.writestring(" (");
6124 escapePath(ob, resolvedNamez.ptr);
6125 ob.writestring(")");
6128 if (global.params.makeDeps.doOutput)
6130 global.params.makeDeps.files.push(resolvedNamez.ptr);
6134 auto fileName = FileName(resolvedNamez);
6135 if (auto fmResult = global.fileManager.lookup(fileName))
6137 se = new StringExp(e.loc, fmResult);
6141 auto readResult = File.read(resolvedNamez);
6142 if (!readResult.success)
6144 e.error("cannot read file `%s`", resolvedNamez.ptr);
6149 // take ownership of buffer (probably leaking)
6150 auto data = readResult.extractSlice();
6151 se = new StringExp(e.loc, data);
6152 global.fileManager.add(fileName, data);
6156 result = se.expressionSemantic(sc);
6159 override void visit(AssertExp exp)
6161 // https://dlang.org/spec/expression.html#assert_expressions
6162 static if (LOGSEMANTIC)
6164 printf("AssertExp::semantic('%s')\n", exp.toChars());
6167 const generateMsg = !exp.msg && global.params.checkAction == CHECKACTION.context && global.params.useAssert == CHECKENABLE.on;
6168 Expression temporariesPrefix;
6171 // no message - use assert expression as msg
6173 if (!verifyHookExist(exp.loc, *sc, Id._d_assert_fail, "generating assert messages"))
6178 auto a = e1, b = e2;
6179 assert(a == b, _d_assert_fail!"=="(a, b));
6184 Stores the result of an operand expression into a temporary
6185 if necessary, e.g. if it is an impure fuction call containing side
6186 effects as in https://issues.dlang.org/show_bug.cgi?id=20114
6189 op = an expression which may require a temporary (added to
6190 `temporariesPrefix`: `auto tmp = op`) and will be replaced
6191 by `tmp` if necessary
6193 Returns: (possibly replaced) `op`
6195 Expression maybePromoteToTmp(ref Expression op)
6197 // https://issues.dlang.org/show_bug.cgi?id=20989
6198 // Flag that _d_assert_fail will never dereference `array.ptr` to avoid safety
6199 // errors for `assert(!array.ptr)` => `_d_assert_fail!"!"(array.ptr)`
6201 auto die = op.isDotIdExp();
6202 if (die && die.ident == Id.ptr)
6206 op = op.expressionSemantic(sc);
6207 op = resolveProperties(sc, op);
6209 // Detect assert's using static operator overloads (e.g. `"var" in environment`)
6210 if (auto te = op.isTypeExp())
6212 // Replace the TypeExp with it's textual representation
6213 // Including "..." in the error message isn't quite right but
6214 // proper solutions require more drastic changes, e.g. directly
6215 // using miniFormat and combine instead of calling _d_assert_fail
6216 auto name = new StringExp(te.loc, te.toString());
6217 return name.expressionSemantic(sc);
6220 // Create a temporary for expressions with side effects
6221 // Defensively assume that function calls may have side effects even
6222 // though it's not detected by hasSideEffect (e.g. `debug puts("Hello")` )
6223 // Rewriting CallExp's also avoids some issues with the inliner/debug generation
6224 if (op.hasSideEffect(true))
6226 // Don't create an invalid temporary for void-expressions
6227 // Further semantic will issue an appropriate error
6228 if (op.type.ty == Tvoid)
6231 // https://issues.dlang.org/show_bug.cgi?id=21590
6232 // Don't create unnecessary temporaries and detect `assert(a = b)`
6233 if (op.isAssignExp() || op.isBinAssignExp())
6235 auto left = (cast(BinExp) op).e1;
6237 // Find leftmost expression to handle other rewrites,
6238 // e.g. --(++a) => a += 1 -= 1
6239 while (left.isAssignExp() || left.isBinAssignExp())
6240 left = (cast(BinExp) left).e1;
6242 // Only use the assignee if it's a variable and skip
6243 // other lvalues (e.g. ref's returned by functions)
6244 if (left.isVarExp())
6247 // Sanity check that `op` can be converted to boolean
6248 // But don't raise errors for assignments enclosed in another expression
6253 // Tuples with side-effects already receive a temporary during semantic
6254 if (op.type.isTypeTuple())
6256 auto te = op.isTupleExp();
6259 // Create a new tuple without the associated temporary
6260 auto res = new TupleExp(op.loc, te.exps);
6261 return res.expressionSemantic(sc);
6264 const stc = op.isLvalue() ? STC.ref_ : 0;
6265 auto tmp = copyToTemp(stc, "__assertOp", op);
6266 tmp.dsymbolSemantic(sc);
6268 auto decl = new DeclarationExp(op.loc, tmp);
6269 temporariesPrefix = Expression.combine(temporariesPrefix, decl);
6271 op = new VarExp(op.loc, tmp);
6272 op = op.expressionSemantic(sc);
6277 // if the assert condition is a mixin expression, try to compile it
6278 if (auto ce = exp.e1.isMixinExp())
6280 if (auto e1 = compileIt(ce))
6286 Loc loc = exp.e1.loc;
6288 const op = exp.e1.op;
6289 bool isEqualsCallExpression;
6290 if (const callExp = exp.e1.isCallExp())
6292 // https://issues.dlang.org/show_bug.cgi?id=20331
6293 // callExp.f may be null if the assert contains a call to
6294 // a function pointer or literal
6295 if (const callExpFunc = callExp.f)
6297 const callExpIdent = callExpFunc.ident;
6298 isEqualsCallExpression = callExpIdent == Id.__equals ||
6299 callExpIdent == Id.eq;
6302 if (op == EXP.equal || op == EXP.notEqual ||
6303 op == EXP.lessThan || op == EXP.greaterThan ||
6304 op == EXP.lessOrEqual || op == EXP.greaterOrEqual ||
6305 op == EXP.identity || op == EXP.notIdentity ||
6307 isEqualsCallExpression)
6309 es = new Expressions(3);
6310 tiargs = new Objects(1);
6312 if (isEqualsCallExpression)
6314 auto callExp = cast(CallExp) exp.e1;
6315 auto args = callExp.arguments;
6317 // structs with opEquals get rewritten to a DotVarExp:
6319 // https://issues.dlang.org/show_bug.cgi?id=20100
6320 if (args.length == 1)
6322 auto dv = callExp.e1.isDotVarExp();
6326 (*es)[1] = maybePromoteToTmp(dv.e1);
6327 (*es)[2] = maybePromoteToTmp((*args)[0]);
6332 (*es)[1] = maybePromoteToTmp((*args)[0]);
6333 (*es)[2] = maybePromoteToTmp((*args)[1]);
6338 auto binExp = cast(EqualExp) exp.e1;
6341 (*es)[1] = maybePromoteToTmp(binExp.e1);
6342 (*es)[2] = maybePromoteToTmp(binExp.e2);
6346 Expression comp = new StringExp(loc, isEqualsCallExpression ? "==" : EXPtoString(exp.e1.op));
6347 comp = comp.expressionSemantic(sc);
6349 (*tiargs)[0] = (*es)[1].type;
6352 // Format exp.e1 before any additional boolean conversion
6353 // Ignore &&/|| because "assert(...) failed" is more informative than "false != true"
6354 else if (op != EXP.andAnd && op != EXP.orOr)
6356 es = new Expressions(2);
6357 tiargs = new Objects(1);
6359 if (auto ne = exp.e1.isNotExp())
6361 // Fetch the (potential non-bool) expression and fold
6362 // (n) negations into (n % 2) negations, e.g. !!a => a
6363 for (bool neg = true; ; neg = !neg)
6365 if (auto ne2 = ne.e1.isNotExp())
6369 (*es)[0] = new StringExp(loc, neg ? "!" : "");
6370 (*es)[1] = maybePromoteToTmp(ne.e1);
6376 { // Simply format exp.e1
6377 (*es)[0] = new StringExp(loc, "");
6378 (*es)[1] = maybePromoteToTmp(exp.e1);
6381 (*tiargs)[0] = (*es)[1].type;
6383 // Passing __ctfe to auto ref infers ref and aborts compilation:
6384 // "cannot modify compiler-generated variable __ctfe"
6385 auto ve = (*es)[1].isVarExp();
6386 if (ve && ve.var.ident == Id.ctfe)
6388 exp.msg = new StringExp(loc, "assert(__ctfe) failed!");
6395 buf.printf("%s failed", exp.toChars());
6396 exp.msg = new StringExp(Loc.initial, buf.extractSlice());
6400 Expression __assertFail = new IdentifierExp(exp.loc, Id.empty);
6401 auto assertFail = new DotIdExp(loc, __assertFail, Id.object);
6403 auto dt = new DotTemplateInstanceExp(loc, assertFail, Id._d_assert_fail, tiargs);
6404 auto ec = CallExp.create(loc, dt, es);
6409 if (Expression ex = unaSemantic(exp, sc))
6415 exp.e1 = resolveProperties(sc, exp.e1);
6416 // BUG: see if we can do compile time elimination of the Assert
6417 exp.e1 = exp.e1.optimize(WANTvalue);
6418 exp.e1 = exp.e1.toBoolean(sc);
6420 if (exp.e1.op == EXP.error)
6428 exp.msg = expressionSemantic(exp.msg, sc);
6429 exp.msg = resolveProperties(sc, exp.msg);
6430 exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
6431 exp.msg = exp.msg.optimize(WANTvalue);
6432 checkParamArgumentEscape(sc, null, null, null, STC.undefined_, exp.msg, true, false);
6435 if (exp.msg && exp.msg.op == EXP.error)
6441 auto f1 = checkNonAssignmentArrayOp(exp.e1);
6442 auto f2 = exp.msg && checkNonAssignmentArrayOp(exp.msg);
6446 if (exp.e1.toBool().hasValue(false))
6448 /* This is an `assert(0)` which means halt program execution
6450 FuncDeclaration fd = sc.parent.isFuncDeclaration();
6452 fd.hasReturnExp |= 4;
6453 sc.ctorflow.orCSX(CSX.halt);
6455 if (global.params.useAssert == CHECKENABLE.off)
6457 Expression e = new HaltExp(exp.loc);
6458 e = e.expressionSemantic(sc);
6463 // Only override the type when it isn't already some flavour of noreturn,
6464 // e.g. when this assert was generated by defaultInitLiteral
6465 if (!exp.type || !exp.type.isTypeNoreturn())
6466 exp.type = Type.tnoreturn;
6469 exp.type = Type.tvoid;
6471 result = !temporariesPrefix
6473 : Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
6476 override void visit(ThrowExp te)
6478 import dmd.statementsem;
6480 if (StatementSemanticVisitor.throwSemantic(te.loc, te.e1, sc))
6486 override void visit(DotIdExp exp)
6488 static if (LOGSEMANTIC)
6490 printf("DotIdExp::semantic(this = %p, '%s')\n", exp, exp.toChars());
6491 //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
6494 if (sc.flags & SCOPE.Cfile)
6496 /* See if need to rewrite the AST because of cast/call ambiguity
6498 if (auto e = castCallAmbiguity(exp, sc))
6500 result = expressionSemantic(e, sc);
6504 if (exp.arrow) // ImportC only
6505 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
6507 if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
6509 // C11 6.5.3 says _Alignof only applies to types
6513 dmd.typesem.resolve(exp.e1.type, exp.e1.loc, sc, e, t, s, true);
6516 exp.e1.error("argument to `_Alignof` must be a type");
6521 // Note similarity to getProperty() implementation of __xalignof
6522 const explicitAlignment = t.alignment();
6523 const naturalAlignment = t.alignsize();
6524 const actualAlignment = (explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get());
6525 result = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
6529 exp.e1.error("argument to `_Alignof` must be a type");
6537 if (exp.ident != Id.__sizeof)
6539 result = fieldLookup(exp.e1, sc, exp.ident);
6544 Expression e = exp.dotIdSemanticProp(sc, 1);
6546 if (e && isDotOpDispatch(e))
6549 uint errors = global.startGagging();
6550 e = resolvePropertiesX(sc, e);
6551 // Any error or if 'e' is not resolved, go to UFCS
6552 if (global.endGagging(errors) || e is ode)
6553 e = null; /* fall down to UFCS */
6560 if (!e) // if failed to find the property
6562 /* If ident is not a valid property, rewrite:
6567 e = resolveUFCSProperties(sc, exp);
6572 override void visit(DotTemplateExp e)
6579 if (Expression ex = unaSemantic(e, sc))
6584 // 'void' like TemplateExp
6585 e.type = Type.tvoid;
6589 override void visit(DotVarExp exp)
6591 static if (LOGSEMANTIC)
6593 printf("DotVarExp::semantic('%s')\n", exp.toChars());
6601 exp.var = exp.var.toAlias().isDeclaration();
6603 exp.e1 = exp.e1.expressionSemantic(sc);
6605 if (auto tup = exp.var.isTupleDeclaration())
6610 * tuple(e1.a, e1.b, e1.c)
6613 Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
6615 auto exps = new Expressions();
6616 exps.reserve(tup.objects.length);
6617 for (size_t i = 0; i < tup.objects.length; i++)
6619 RootObject o = (*tup.objects)[i];
6622 switch (o.dyncast()) with (DYNCAST)
6625 e = cast(Expression)o;
6626 if (auto se = e.isDsymbolExp())
6627 var = se.s.isDeclaration();
6628 else if (auto ve = e.isVarExp())
6629 if (!ve.var.isFuncDeclaration())
6630 // Exempt functions for backwards compatibility reasons.
6631 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6635 Dsymbol s = cast(Dsymbol) o;
6636 Declaration d = s.isDeclaration();
6637 if (!d || d.isFuncDeclaration())
6638 // Exempt functions for backwards compatibility reasons.
6639 // See: https://issues.dlang.org/show_bug.cgi?id=20470#c1
6640 e = new DsymbolExp(exp.loc, s);
6645 e = new TypeExp(exp.loc, cast(Type)o);
6648 exp.error("`%s` is not an expression", o.toChars());
6652 e = new DotVarExp(exp.loc, ev, var);
6656 Expression e = new TupleExp(exp.loc, e0, exps);
6657 e = e.expressionSemantic(sc);
6661 else if (auto ad = exp.var.isAliasDeclaration())
6663 if (auto t = ad.getType())
6665 result = new TypeExp(exp.loc, t).expressionSemantic(sc);
6670 exp.e1 = exp.e1.addDtorHook(sc);
6672 Type t1 = exp.e1.type;
6674 if (FuncDeclaration fd = exp.var.isFuncDeclaration())
6676 // for functions, do checks after overload resolution
6677 if (!fd.functionSemantic())
6680 /* https://issues.dlang.org/show_bug.cgi?id=13843
6681 * If fd obviously has no overloads, we should
6682 * normalize AST, and it will give a chance to wrap fd with FuncExp.
6684 if ((fd.isNested() && !fd.isThis()) || fd.isFuncLiteralDeclaration())
6687 auto e = symbolToExp(fd, exp.loc, sc, false);
6688 result = Expression.combine(exp.e1, e);
6695 else if (OverDeclaration od = exp.var.isOverDeclaration())
6697 exp.type = Type.tvoid; // ambiguous type?
6701 exp.type = exp.var.type;
6702 if (!exp.type && global.errors) // var is goofed up, just return error.
6706 if (t1.ty == Tpointer)
6709 exp.type = exp.type.addMod(t1.mod);
6711 // https://issues.dlang.org/show_bug.cgi?id=23109
6712 // Run semantic on the DotVarExp type
6713 if (auto handle = exp.type.isClassHandle())
6715 if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
6716 handle.dsymbolSemantic(null);
6719 Dsymbol vparent = exp.var.toParent();
6720 AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
6721 if (Expression e1x = getRightThis(exp.loc, sc, ad, exp.e1, exp.var, 1))
6725 /* Later checkRightThis will report correct error for invalid field variable access.
6727 Expression e = new VarExp(exp.loc, exp.var);
6728 e = e.expressionSemantic(sc);
6732 checkAccess(exp.loc, sc, exp.e1, exp.var);
6734 VarDeclaration v = exp.var.isVarDeclaration();
6735 if (v && (v.isDataseg() || (v.storage_class & STC.manifest)))
6737 Expression e = expandVar(WANTvalue, v);
6745 if (v && (v.isDataseg() || // fix https://issues.dlang.org/show_bug.cgi?id=8238
6746 (!v.needThis() && v.semanticRun > PASS.initial))) // fix https://issues.dlang.org/show_bug.cgi?id=17258
6749 checkAccess(exp.loc, sc, exp.e1, v);
6750 Expression e = new VarExp(exp.loc, v);
6751 e = new CommaExp(exp.loc, exp.e1, e);
6752 e = e.expressionSemantic(sc);
6757 //printf("-DotVarExp::semantic('%s')\n", toChars());
6761 override void visit(DotTemplateInstanceExp exp)
6763 static if (LOGSEMANTIC)
6765 printf("DotTemplateInstanceExp::semantic('%s')\n", exp.toChars());
6772 // Indicate we need to resolve by UFCS.
6773 Expression e = exp.dotTemplateSemanticProp(sc, 1);
6775 e = resolveUFCSProperties(sc, exp);
6777 e.type = Type.tvoid; // Unresolved type, because it needs inference
6781 override void visit(DelegateExp e)
6783 static if (LOGSEMANTIC)
6785 printf("DelegateExp::semantic('%s')\n", e.toChars());
6793 e.e1 = e.e1.expressionSemantic(sc);
6795 e.type = new TypeDelegate(e.func.type.isTypeFunction());
6796 e.type = e.type.typeSemantic(e.loc, sc);
6798 FuncDeclaration f = e.func.toAliasFunc();
6799 AggregateDeclaration ad = f.isMemberLocal();
6801 e.e1 = getRightThis(e.loc, sc, ad, e.e1, f);
6802 if (e.e1.op == EXP.error)
6805 if (f.type.ty == Tfunction)
6807 TypeFunction tf = cast(TypeFunction)f.type;
6808 if (!MODmethodConv(e.e1.type.mod, f.type.mod))
6810 OutBuffer thisBuf, funcBuf;
6811 MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod);
6812 MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod);
6813 e.error("%smethod `%s` is not callable using a %s`%s`",
6814 funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars());
6818 if (ad && ad.isClassDeclaration() && ad.type != e.e1.type)
6820 // A downcast is required for interfaces
6821 // https://issues.dlang.org/show_bug.cgi?id=3706
6822 e.e1 = new CastExp(e.loc, e.e1, ad.type);
6823 e.e1 = e.e1.expressionSemantic(sc);
6826 // declare dual-context container
6827 if (f.hasDualContext() && !sc.intypeof && sc.func)
6829 // check access to second `this`
6830 if (AggregateDeclaration ad2 = f.isMember2())
6832 Expression te = new ThisExp(e.loc).expressionSemantic(sc);
6833 if (te.op != EXP.error)
6834 te = getRightThis(e.loc, sc, ad2, te, f);
6835 if (te.op == EXP.error)
6837 e.error("need `this` of type `%s` to make delegate from function `%s`", ad2.toChars(), f.toChars());
6841 VarDeclaration vthis2 = makeThis2Argument(e.loc, sc, f);
6843 Expression de = new DeclarationExp(e.loc, vthis2);
6844 result = Expression.combine(de, result);
6845 result = result.expressionSemantic(sc);
6849 override void visit(DotTypeExp exp)
6851 static if (LOGSEMANTIC)
6853 printf("DotTypeExp::semantic('%s')\n", exp.toChars());
6861 if (auto e = unaSemantic(exp, sc))
6867 exp.type = exp.sym.getType().addMod(exp.e1.type.mod);
6871 override void visit(AddrExp exp)
6873 static if (LOGSEMANTIC)
6875 printf("AddrExp::semantic('%s')\n", exp.toChars());
6883 if (Expression ex = unaSemantic(exp, sc))
6889 if (sc.flags & SCOPE.Cfile)
6891 /* Special handling for &"string"/&(T[]){0, 1}
6892 * since C regards string/array literals as lvalues
6895 if(e.isStringExp() || e.isArrayLiteralExp())
6897 e.type = typeSemantic(e.type, Loc.initial, sc);
6898 // if type is already a pointer exp is an illegal expression of the form `&(&"")`
6899 if (!e.type.isTypePointer())
6901 e.type = e.type.pointerTo();
6907 // `toLvalue` call further below is upon exp.e1, omitting & from the error message
6908 exp.toLvalue(sc, null);
6914 int wasCond = exp.e1.op == EXP.question;
6916 if (exp.e1.op == EXP.dotTemplateInstance)
6918 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)exp.e1;
6919 TemplateInstance ti = dti.ti;
6921 //assert(ti.needsTypeInference(sc));
6922 ti.dsymbolSemantic(sc);
6923 if (!ti.inst || ti.errors) // if template failed to expand
6926 Dsymbol s = ti.toAlias();
6927 FuncDeclaration f = s.isFuncDeclaration();
6930 exp.e1 = new DotVarExp(exp.e1.loc, dti.e1, f);
6931 exp.e1 = exp.e1.expressionSemantic(sc);
6935 else if (exp.e1.op == EXP.scope_)
6937 TemplateInstance ti = (cast(ScopeExp)exp.e1).sds.isTemplateInstance();
6940 //assert(ti.needsTypeInference(sc));
6941 ti.dsymbolSemantic(sc);
6942 if (!ti.inst || ti.errors) // if template failed to expand
6945 Dsymbol s = ti.toAlias();
6946 FuncDeclaration f = s.isFuncDeclaration();
6949 exp.e1 = new VarExp(exp.e1.loc, f);
6950 exp.e1 = exp.e1.expressionSemantic(sc);
6954 /* https://issues.dlang.org/show_bug.cgi?id=809
6956 * If the address of a lazy variable is taken,
6957 * the expression is rewritten so that the type
6958 * of it is the delegate type. This means that
6959 * the symbol is not going to represent a call
6960 * to the delegate anymore, but rather, the
6963 if (auto ve = exp.e1.isVarExp())
6965 if (ve.var.storage_class & STC.lazy_)
6967 exp.e1 = exp.e1.expressionSemantic(sc);
6968 exp.e1 = resolveProperties(sc, exp.e1);
6969 if (auto callExp = exp.e1.isCallExp())
6971 if (callExp.e1.type.toBasetype().ty == Tdelegate)
6973 /* https://issues.dlang.org/show_bug.cgi?id=20551
6975 * Cannot take address of lazy parameter in @safe code
6976 * because it might end up being a pointer to undefined
6981 if (sc.setUnsafe(false, exp.loc,
6982 "cannot take address of lazy parameter `%s` in `@safe` function `%s`", ve, sc.func))
6988 VarExp ve2 = callExp.e1.isVarExp();
6989 ve2.delegateWasExtracted = true;
6990 ve2.var.storage_class |= STC.scope_;
6998 exp.e1 = exp.e1.toLvalue(sc, null);
6999 if (exp.e1.op == EXP.error)
7004 if (checkNonAssignmentArrayOp(exp.e1))
7009 exp.error("cannot take address of `%s`", exp.e1.toChars());
7012 if (!checkAddressable(exp, sc))
7016 if (auto f = isFuncAddress(exp, &hasOverloads))
7018 if (!hasOverloads && f.checkForwardRef(exp.loc))
7021 else if (!exp.e1.type.deco)
7023 // try to resolve the type
7024 exp.e1.type = exp.e1.type.typeSemantic(exp.e1.loc, null);
7025 if (!exp.e1.type.deco) // still couldn't resolve it
7027 if (auto ve = exp.e1.isVarExp())
7029 Declaration d = ve.var;
7030 exp.error("forward reference to %s `%s`", d.kind(), d.toChars());
7033 exp.error("forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars());
7038 exp.type = exp.e1.type.pointerTo();
7040 // See if this should really be a delegate
7041 if (exp.e1.op == EXP.dotVariable)
7043 DotVarExp dve = cast(DotVarExp)exp.e1;
7044 FuncDeclaration f = dve.var.isFuncDeclaration();
7047 f = f.toAliasFunc(); // FIXME, should see overloads
7048 // https://issues.dlang.org/show_bug.cgi?id=1983
7049 if (!dve.hasOverloads)
7054 e = new DelegateExp(exp.loc, dve.e1, f, dve.hasOverloads);
7055 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
7056 e = new CommaExp(exp.loc, dve.e1, new AddrExp(exp.loc, new VarExp(exp.loc, f, dve.hasOverloads)));
7057 e = e.expressionSemantic(sc);
7062 // Look for misaligned pointer in @safe mode
7063 if (checkUnsafeAccess(sc, dve, !exp.type.isMutable(), true))
7066 else if (exp.e1.op == EXP.variable)
7068 VarExp ve = cast(VarExp)exp.e1;
7069 VarDeclaration v = ve.var.isVarDeclaration();
7072 if (!checkAddressVar(sc, exp.e1, v))
7075 ve.checkPurity(sc, v);
7077 FuncDeclaration f = ve.var.isFuncDeclaration();
7080 /* Because nested functions cannot be overloaded,
7081 * mark here that we took its address because castTo()
7082 * may not be called with an exact match.
7084 * https://issues.dlang.org/show_bug.cgi?id=19285 :
7085 * We also need to make sure we aren't inside a typeof. Ideally the compiler
7086 * would do typeof(...) semantic analysis speculatively then collect information
7087 * about what it used rather than relying on what are effectively semantically-global
7088 * variables but it doesn't.
7090 if (!sc.isFromSpeculativeSemanticContext() && (!ve.hasOverloads || (f.isNested() && !f.needThis())))
7092 // TODO: Refactor to use a proper interface that can keep track of causes.
7096 if (f.isNested() && !f.needThis())
7098 if (f.isFuncLiteralDeclaration())
7100 if (!f.FuncDeclaration.isNested())
7102 /* Supply a 'null' for a this pointer if no this is available
7104 Expression e = new DelegateExp(exp.loc, new NullExp(exp.loc, Type.tnull), f, ve.hasOverloads);
7105 e = e.expressionSemantic(sc);
7110 Expression e = new DelegateExp(exp.loc, exp.e1, f, ve.hasOverloads);
7111 e = e.expressionSemantic(sc);
7119 /* Should probably supply 'this' after overload resolution,
7122 Expression ethis = new ThisExp(exp.loc);
7123 Expression e = new DelegateExp(exp.loc, ethis, f, ve.hasOverloads);
7124 e = e.expressionSemantic(sc);
7128 if (sc.func && !sc.intypeof && !(sc.flags & SCOPE.debug_))
7130 sc.setUnsafe(false, exp.loc,
7131 "`this` reference necessary to take address of member `%s` in `@safe` function `%s`",
7137 else if (exp.e1.op == EXP.index)
7142 * check 'a' the same as for a regular variable
7144 if (VarDeclaration v = expToVariable(exp.e1))
7146 exp.e1.checkPurity(sc, v);
7151 /* a ? b : c was transformed to *(a ? &b : &c), but we still
7152 * need to do safety checks
7154 assert(exp.e1.op == EXP.star);
7155 PtrExp pe = cast(PtrExp)exp.e1;
7156 assert(pe.e1.op == EXP.question);
7157 CondExp ce = cast(CondExp)pe.e1;
7158 assert(ce.e1.op == EXP.address);
7159 assert(ce.e2.op == EXP.address);
7161 // Re-run semantic on the address expressions only
7163 ce.e1 = ce.e1.expressionSemantic(sc);
7165 ce.e2 = ce.e2.expressionSemantic(sc);
7167 result = exp.optimize(WANTvalue);
7170 override void visit(PtrExp exp)
7172 static if (LOGSEMANTIC)
7174 printf("PtrExp::semantic('%s')\n", exp.toChars());
7182 Expression e = exp.op_overload(sc);
7189 exp.e1 = exp.e1.arrayFuncConv(sc);
7191 Type tb = exp.e1.type.toBasetype();
7195 exp.type = (cast(TypePointer)tb).next;
7200 if (isNonAssignmentArrayOp(exp.e1))
7202 exp.error("using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars());
7203 exp.type = (cast(TypeArray)tb).next;
7204 exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo());
7211 exp.type = Type.tnoreturn; // typeof(*null) is bottom type
7215 exp.error("can only `*` a pointer, not a `%s`", exp.e1.type.toChars());
7219 if (exp.checkValue())
7225 override void visit(NegExp exp)
7227 static if (LOGSEMANTIC)
7229 printf("NegExp::semantic('%s')\n", exp.toChars());
7237 Expression e = exp.op_overload(sc);
7245 exp.type = exp.e1.type;
7246 Type tb = exp.type.toBasetype();
7247 if (tb.ty == Tarray || tb.ty == Tsarray)
7249 if (!isArrayOpValid(exp.e1))
7251 result = arrayOpInvalidError(exp);
7257 if (!target.isVectorOpSupported(tb, exp.op))
7259 result = exp.incompatibleTypes();
7262 if (exp.e1.checkNoBool())
7264 if (exp.e1.checkArithmetic() ||
7265 exp.e1.checkSharedAccess(sc))
7271 override void visit(UAddExp exp)
7273 static if (LOGSEMANTIC)
7275 printf("UAddExp::semantic('%s')\n", exp.toChars());
7279 Expression e = exp.op_overload(sc);
7287 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op))
7289 result = exp.incompatibleTypes();
7292 if (exp.e1.checkNoBool())
7294 if (exp.e1.checkArithmetic())
7296 if (exp.e1.checkSharedAccess(sc))
7302 override void visit(ComExp exp)
7310 Expression e = exp.op_overload(sc);
7318 exp.type = exp.e1.type;
7319 Type tb = exp.type.toBasetype();
7320 if (tb.ty == Tarray || tb.ty == Tsarray)
7322 if (!isArrayOpValid(exp.e1))
7324 result = arrayOpInvalidError(exp);
7330 if (!target.isVectorOpSupported(tb, exp.op))
7332 result = exp.incompatibleTypes();
7335 if (exp.e1.checkNoBool())
7337 if (exp.e1.checkIntegral() ||
7338 exp.e1.checkSharedAccess(sc))
7344 override void visit(NotExp e)
7352 e.setNoderefOperand();
7354 // Note there is no operator overload
7355 if (Expression ex = unaSemantic(e, sc))
7361 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7362 if (e.e1.op == EXP.type)
7363 e.e1 = resolveAliasThis(sc, e.e1);
7365 e.e1 = resolveProperties(sc, e.e1);
7366 e.e1 = e.e1.toBoolean(sc);
7367 if (e.e1.type == Type.terror)
7373 if (!target.isVectorOpSupported(e.e1.type.toBasetype(), e.op))
7375 result = e.incompatibleTypes();
7377 // https://issues.dlang.org/show_bug.cgi?id=13910
7378 // Today NotExp can take an array as its operand.
7379 if (checkNonAssignmentArrayOp(e.e1))
7382 e.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
7386 override void visit(DeleteExp exp)
7388 // @@@DEPRECATED_2.109@@@
7389 // 1. Deprecated since 2.079
7390 // 2. Error since 2.099
7391 // 3. Removal of keyword, "delete" can be used for other identities
7394 error(exp.loc, "the `delete` keyword is obsolete");
7395 errorSupplemental(exp.loc, "use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead");
7401 if (Expression ex = unaSemantic(exp, sc))
7406 exp.e1 = resolveProperties(sc, exp.e1);
7407 exp.e1 = exp.e1.modifiableLvalue(sc, null);
7408 if (exp.e1.op == EXP.error)
7413 exp.type = Type.tvoid;
7415 Type tb = exp.e1.type.toBasetype();
7417 /* Now that `delete` in user code is an error, we only get here when
7418 * `isRAII` has been set to true for the deletion of a `scope class`. */
7419 if (tb.ty != Tclass)
7421 exp.error("cannot delete type `%s`", exp.e1.type.toChars());
7425 ClassDeclaration cd = (cast(TypeClass)tb).sym;
7426 if (cd.isCOMinterface())
7428 /* Because COM classes are deleted by IUnknown.Release()
7430 exp.error("cannot `delete` instance of COM interface `%s`", cd.toChars());
7437 err |= !cd.dtor.functionSemantic();
7438 err |= exp.checkPurity(sc, cd.dtor);
7439 err |= exp.checkSafety(sc, cd.dtor);
7440 err |= exp.checkNogc(sc, cd.dtor);
7448 override void visit(CastExp exp)
7450 static if (LOGSEMANTIC)
7452 printf("CastExp::semantic('%s')\n", exp.toChars());
7454 //static int x; assert(++x < 10);
7461 if ((sc && sc.flags & SCOPE.Cfile) &&
7462 exp.to && (exp.to.ty == Tident || exp.to.ty == Tsarray) &&
7463 (exp.e1.op == EXP.address || exp.e1.op == EXP.star ||
7464 exp.e1.op == EXP.uadd || exp.e1.op == EXP.negate))
7466 /* Ambiguous cases arise from CParser if type-name is just an identifier.
7467 * ( identifier ) cast-expression
7468 * ( identifier [expression]) cast-expression
7469 * If we determine that `identifier` is a variable, and cast-expression
7470 * is one of the unary operators (& * + -), then rewrite this cast
7471 * as a binary expression.
7477 exp.to.resolve(loc, sc, e, t, s);
7480 if (auto ex = exp.e1.isAddrExp()) // (ident) &exp -> (ident & exp)
7481 result = new AndExp(loc, e, ex.e1);
7482 else if (auto ex = exp.e1.isPtrExp()) // (ident) *exp -> (ident * exp)
7483 result = new MulExp(loc, e, ex.e1);
7484 else if (auto ex = exp.e1.isUAddExp()) // (ident) +exp -> (ident + exp)
7485 result = new AddExp(loc, e, ex.e1);
7486 else if (auto ex = exp.e1.isNegExp()) // (ident) -exp -> (ident - exp)
7487 result = new MinExp(loc, e, ex.e1);
7490 result = result.expressionSemantic(sc);
7497 exp.to = exp.to.typeSemantic(exp.loc, sc);
7498 if (exp.to == Type.terror)
7501 if (!exp.to.hasPointers())
7502 exp.setNoderefOperand();
7504 // When e1 is a template lambda, this cast may instantiate it with
7506 exp.e1 = inferType(exp.e1, exp.to);
7509 if (auto e = unaSemantic(exp, sc))
7515 if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
7516 exp.e1 = exp.e1.arrayFuncConv(sc);
7518 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
7519 if (exp.e1.op == EXP.type)
7520 exp.e1 = resolveAliasThis(sc, exp.e1);
7522 auto e1x = resolveProperties(sc, exp.e1);
7523 if (e1x.op == EXP.error)
7528 if (e1x.checkType())
7534 exp.error("cannot cast `%s`", exp.e1.toChars());
7538 // https://issues.dlang.org/show_bug.cgi?id=19954
7539 if (exp.e1.type.ty == Ttuple)
7543 if (TypeTuple tt = exp.to.isTypeTuple())
7545 if (exp.e1.type.implicitConvTo(tt))
7547 result = exp.e1.castTo(sc, tt);
7552 TupleExp te = exp.e1.isTupleExp();
7553 if (te.exps.length == 1)
7554 exp.e1 = (*te.exps)[0];
7557 // only allow S(x) rewrite if cast specified S explicitly.
7558 // See https://issues.dlang.org/show_bug.cgi?id=18545
7559 const bool allowImplicitConstruction = exp.to !is null;
7561 if (!exp.to) // Handle cast(const) and cast(immutable), etc.
7563 exp.to = exp.e1.type.castMod(exp.mod);
7564 exp.to = exp.to.typeSemantic(exp.loc, sc);
7566 if (exp.to == Type.terror)
7570 if (exp.to.ty == Ttuple)
7572 exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
7576 // cast(void) is used to mark e1 as unused, so it is safe
7577 if (exp.to.ty == Tvoid)
7584 if (!exp.to.equals(exp.e1.type) && exp.mod == cast(ubyte)~0)
7586 if (Expression e = exp.op_overload(sc))
7588 result = e.implicitCastTo(sc, exp.to);
7593 Type t1b = exp.e1.type.toBasetype();
7594 Type tob = exp.to.toBasetype();
7596 if (allowImplicitConstruction && tob.ty == Tstruct && !tob.equals(t1b))
7604 // Rewrite as to.call(e1)
7605 Expression e = new TypeExp(exp.loc, exp.to);
7606 e = new CallExp(exp.loc, e, exp.e1);
7607 e = e.trySemantic(sc);
7615 if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
7617 if (checkNonAssignmentArrayOp(exp.e1))
7621 // Look for casting to a vector type
7622 if (tob.ty == Tvector && t1b.ty != Tvector)
7624 result = new VectorExp(exp.loc, exp.e1, exp.to);
7625 result = result.expressionSemantic(sc);
7629 Expression ex = exp.e1.castTo(sc, exp.to);
7630 if (ex.op == EXP.error)
7636 // Check for unsafe casts
7637 if (!isSafeCast(ex, t1b, tob))
7639 if (sc.setUnsafe(false, exp.loc, "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
7645 // `object.__ArrayCast` is a rewrite of an old runtime hook `_d_arraycast`. `_d_arraycast` was not built
7646 // to handle certain casts. Those casts which `object.__ArrayCast` does not support are filtered out.
7647 // See `e2ir.toElemCast` for other types of casts. If `object.__ArrayCast` is improved to support more
7648 // casts these conditions and potentially some logic in `e2ir.toElemCast` can be removed.
7649 if (tob.ty == Tarray)
7651 // https://issues.dlang.org/show_bug.cgi?id=19840
7652 if (auto ad = isAggregate(t1b))
7656 Expression e = resolveAliasThis(sc, exp.e1);
7657 e = new CastExp(exp.loc, e, exp.to);
7658 result = e.expressionSemantic(sc);
7663 if(t1b.ty == Tarray && exp.e1.op != EXP.arrayLiteral && (sc.flags & SCOPE.ctfe) == 0)
7665 auto tFrom = t1b.nextOf();
7666 auto tTo = tob.nextOf();
7668 // https://issues.dlang.org/show_bug.cgi?id=20130
7669 if (exp.e1.op != EXP.string_ || !ex.isStringExp)
7671 const uint fromSize = cast(uint)tFrom.size();
7672 const uint toSize = cast(uint)tTo.size();
7673 if (fromSize == SIZE_INVALID || toSize == SIZE_INVALID)
7676 // If array element sizes do not match, we must adjust the dimensions
7677 if (fromSize != toSize)
7679 if (!verifyHookExist(exp.loc, *sc, Id.__ArrayCast, "casting array of structs"))
7682 // A runtime check is needed in case arrays don't line up. That check should
7683 // be done in the implementation of `object.__ArrayCast`
7684 if (toSize == 0 || (fromSize % toSize) != 0)
7686 // lower to `object.__ArrayCast!(TFrom, TTo)(from)`
7688 // fully qualify as `object.__ArrayCast`
7689 Expression id = new IdentifierExp(exp.loc, Id.empty);
7690 auto dotid = new DotIdExp(exp.loc, id, Id.object);
7692 auto tiargs = new Objects();
7695 auto dt = new DotTemplateInstanceExp(exp.loc, dotid, Id.__ArrayCast, tiargs);
7697 auto arguments = new Expressions();
7698 arguments.push(exp.e1);
7699 Expression ce = new CallExp(exp.loc, dt, arguments);
7701 result = expressionSemantic(ce, sc);
7709 if (sc && sc.flags & SCOPE.Cfile)
7711 /* C11 6.5.4-5: A cast does not yield an lvalue.
7712 * So ensure that castTo does not strip away the cast so that this
7713 * can be enforced in other semantic visitor methods.
7715 if (!ex.isCastExp())
7717 ex = new CastExp(exp.loc, ex, exp.to);
7724 override void visit(VectorExp exp)
7726 static if (LOGSEMANTIC)
7728 printf("VectorExp::semantic('%s')\n", exp.toChars());
7736 exp.e1 = exp.e1.expressionSemantic(sc);
7737 exp.type = exp.to.typeSemantic(exp.loc, sc);
7738 if (exp.e1.op == EXP.error || exp.type.ty == Terror)
7744 Type tb = exp.type.toBasetype();
7745 assert(tb.ty == Tvector);
7746 TypeVector tv = cast(TypeVector)tb;
7747 Type te = tv.elementType();
7748 exp.dim = cast(int)(tv.size(exp.loc) / te.size(exp.loc));
7750 bool checkElem(Expression elem)
7752 if (elem.isConst() == 1)
7755 exp.error("constant expression expected, not `%s`", elem.toChars());
7759 exp.e1 = exp.e1.optimize(WANTvalue);
7761 if (exp.e1.op == EXP.arrayLiteral)
7763 foreach (i; 0 .. exp.dim)
7765 // Do not stop on first error - check all AST nodes even if error found
7766 res |= checkElem(exp.e1.isArrayLiteralExp()[i]);
7769 else if (exp.e1.type.ty == Tvoid)
7772 result = res ? ErrorExp.get() : exp;
7775 override void visit(VectorArrayExp e)
7777 static if (LOGSEMANTIC)
7779 printf("VectorArrayExp::semantic('%s')\n", e.toChars());
7784 e.e1 = resolveProperties(sc, e.e1);
7786 if (e.e1.op == EXP.error)
7791 assert(e.e1.type.ty == Tvector);
7792 e.type = e.e1.type.isTypeVector().basetype;
7797 override void visit(SliceExp exp)
7799 static if (LOGSEMANTIC)
7801 printf("SliceExp::semantic('%s')\n", exp.toChars());
7809 // operator overloading should be handled in ArrayExp already.
7810 if (Expression ex = unaSemantic(exp, sc))
7815 exp.e1 = resolveProperties(sc, exp.e1);
7816 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
7818 if (exp.lwr || exp.upr)
7820 exp.error("cannot slice type `%s`", exp.e1.toChars());
7823 Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf());
7824 result = e.expressionSemantic(sc);
7827 if (!exp.lwr && !exp.upr)
7829 if (exp.e1.op == EXP.arrayLiteral)
7831 // Convert [a,b,c][] to [a,b,c]
7832 Type t1b = exp.e1.type.toBasetype();
7833 Expression e = exp.e1;
7834 if (t1b.ty == Tsarray)
7837 e.type = t1b.nextOf().arrayOf();
7842 if (exp.e1.op == EXP.slice)
7844 // Convert e[][] to e[]
7845 SliceExp se = cast(SliceExp)exp.e1;
7846 if (!se.lwr && !se.upr)
7852 if (isArrayOpOperand(exp.e1))
7854 // Convert (a[]+b[])[] to a[]+b[]
7859 if (exp.e1.op == EXP.error)
7864 if (exp.e1.type.ty == Terror)
7867 Type t1b = exp.e1.type.toBasetype();
7868 if (auto tp = t1b.isTypePointer())
7870 if (t1b.isPtrToFunction())
7872 exp.error("cannot slice function pointer `%s`", exp.e1.toChars());
7875 if (!exp.lwr || !exp.upr)
7877 exp.error("upper and lower bounds are needed to slice a pointer");
7878 if (auto ad = isAggregate(tp.next.toBasetype()))
7880 auto s = search_function(ad, Id.index);
7881 if (!s) s = search_function(ad, Id.slice);
7884 auto fd = s.isFuncDeclaration();
7885 if ((fd && !fd.getParameterList().length) || s.isTemplateDeclaration())
7887 exp.errorSupplemental(
7888 "pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`",
7900 if (sc.setUnsafe(false, exp.loc, "pointer slicing not allowed in safe functions"))
7903 else if (t1b.ty == Tarray)
7906 else if (t1b.ty == Tsarray)
7909 else if (t1b.ty == Ttuple)
7911 if (!exp.lwr && !exp.upr)
7916 if (!exp.lwr || !exp.upr)
7918 exp.error("need upper and lower bound to slice tuple");
7922 else if (t1b.ty == Tvector && exp.e1.isLvalue())
7924 // Convert e1 to corresponding static array
7925 TypeVector tv1 = cast(TypeVector)t1b;
7927 t1b = t1b.castMod(tv1.mod);
7932 exp.error("`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars());
7936 /* Run semantic on lwr and upr.
7939 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
7941 // Create scope for 'length' variable
7942 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
7943 sym.parent = sc.scopesym;
7948 if (t1b.ty == Ttuple)
7949 sc = sc.startCTFE();
7950 exp.lwr = exp.lwr.expressionSemantic(sc);
7951 exp.lwr = resolveProperties(sc, exp.lwr);
7952 if (t1b.ty == Ttuple)
7954 exp.lwr = exp.lwr.implicitCastTo(sc, Type.tsize_t);
7958 if (t1b.ty == Ttuple)
7959 sc = sc.startCTFE();
7960 exp.upr = exp.upr.expressionSemantic(sc);
7961 exp.upr = resolveProperties(sc, exp.upr);
7962 if (t1b.ty == Ttuple)
7964 exp.upr = exp.upr.implicitCastTo(sc, Type.tsize_t);
7968 if (exp.lwr && exp.lwr.type == Type.terror || exp.upr && exp.upr.type == Type.terror)
7971 if (t1b.ty == Ttuple)
7973 exp.lwr = exp.lwr.ctfeInterpret();
7974 exp.upr = exp.upr.ctfeInterpret();
7975 uinteger_t i1 = exp.lwr.toUInteger();
7976 uinteger_t i2 = exp.upr.toUInteger();
7981 if (exp.e1.op == EXP.tuple) // slicing an expression tuple
7983 te = cast(TupleExp)exp.e1;
7985 length = te.exps.length;
7987 else if (exp.e1.op == EXP.type) // slicing a type tuple
7990 tup = cast(TypeTuple)t1b;
7991 length = Parameter.dim(tup.arguments);
7996 if (i2 < i1 || length < i2)
7998 exp.error("string slice `[%llu .. %llu]` is out of bounds", i1, i2);
8002 size_t j1 = cast(size_t)i1;
8003 size_t j2 = cast(size_t)i2;
8005 if (exp.e1.op == EXP.tuple)
8007 auto exps = new Expressions(j2 - j1);
8008 for (size_t i = 0; i < j2 - j1; i++)
8010 (*exps)[i] = (*te.exps)[j1 + i];
8012 e = new TupleExp(exp.loc, te.e0, exps);
8016 auto args = new Parameters();
8017 args.reserve(j2 - j1);
8018 for (size_t i = j1; i < j2; i++)
8020 Parameter arg = Parameter.getNth(tup.arguments, i);
8023 e = new TypeExp(exp.e1.loc, new TypeTuple(args));
8025 e = e.expressionSemantic(sc);
8030 exp.type = t1b.nextOf().arrayOf();
8031 // Allow typedef[] -> typedef[]
8032 if (exp.type.equals(t1b))
8033 exp.type = exp.e1.type;
8035 // We might know $ now
8036 setLengthVarIfKnown(exp.lengthVar, t1b);
8038 if (exp.lwr && exp.upr)
8040 exp.lwr = exp.lwr.optimize(WANTvalue);
8041 exp.upr = exp.upr.optimize(WANTvalue);
8043 IntRange lwrRange = getIntRange(exp.lwr);
8044 IntRange uprRange = getIntRange(exp.upr);
8046 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8048 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8049 el = el.expressionSemantic(sc);
8050 el = el.optimize(WANTvalue);
8051 if (el.op == EXP.int64)
8053 // Array length is known at compile-time. Upper is in bounds if it fits length.
8054 dinteger_t length = el.toInteger();
8055 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
8056 exp.upperIsInBounds = bounds.contains(uprRange);
8058 else if (exp.upr.op == EXP.int64 && exp.upr.toInteger() == 0)
8060 // Upper slice expression is '0'. Value is always in bounds.
8061 exp.upperIsInBounds = true;
8063 else if (exp.upr.op == EXP.variable && (cast(VarExp)exp.upr).var.ident == Id.dollar)
8065 // Upper slice expression is '$'. Value is always in bounds.
8066 exp.upperIsInBounds = true;
8069 else if (t1b.ty == Tpointer)
8071 exp.upperIsInBounds = true;
8076 exp.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
8078 //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", exp.upperIsInBounds, exp.lowerIsLessThanUpper);
8084 override void visit(ArrayLengthExp e)
8086 static if (LOGSEMANTIC)
8088 printf("ArrayLengthExp::semantic('%s')\n", e.toChars());
8096 if (Expression ex = unaSemantic(e, sc))
8101 e.e1 = resolveProperties(sc, e.e1);
8103 e.type = Type.tsize_t;
8107 override void visit(ArrayExp exp)
8109 static if (LOGSEMANTIC)
8111 printf("ArrayExp::semantic('%s')\n", exp.toChars());
8115 if (sc.flags & SCOPE.Cfile)
8117 /* See if need to rewrite the AST because of cast/call ambiguity
8119 if (auto e = castCallAmbiguity(exp, sc))
8121 result = expressionSemantic(e, sc);
8126 result = exp.carraySemantic(sc); // C semantics
8130 Expression e = exp.op_overload(sc);
8137 if (isAggregate(exp.e1.type))
8138 exp.error("no `[]` operator overload for type `%s`", exp.e1.type.toChars());
8139 else if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8140 exp.error("static array of `%s` with multiple lengths not allowed", exp.e1.type.toChars());
8141 else if (isIndexableNonAggregate(exp.e1.type))
8142 exp.error("only one index allowed to index `%s`", exp.e1.type.toChars());
8144 exp.error("cannot use `[]` operator on expression of type `%s`", exp.e1.type.toChars());
8146 result = ErrorExp.get();
8149 override void visit(DotExp exp)
8151 static if (LOGSEMANTIC)
8153 printf("DotExp::semantic('%s')\n", exp.toChars());
8155 printf("\ttype = %s\n", exp.type.toChars());
8157 exp.e1 = exp.e1.expressionSemantic(sc);
8158 exp.e2 = exp.e2.expressionSemantic(sc);
8160 if (exp.e1.op == EXP.type)
8165 if (exp.e2.op == EXP.type)
8170 if (auto te = exp.e2.isTemplateExp())
8172 Expression e = new DotTemplateExp(exp.loc, exp.e1, te.td);
8173 result = e.expressionSemantic(sc);
8177 exp.type = exp.e2.type;
8181 override void visit(CommaExp e)
8183 //printf("Semantic.CommaExp() %s\n", e.toChars());
8190 // Allow `((a,b),(x,y))`
8191 if (e.allowCommaExp)
8193 CommaExp.allow(e.e1);
8194 CommaExp.allow(e.e2);
8197 if (Expression ex = binSemanticProp(e, sc))
8202 e.e1 = e.e1.addDtorHook(sc);
8204 if (checkNonAssignmentArrayOp(e.e1))
8207 // Comma expressions trigger this conversion
8208 e.e2 = e.e2.arrayFuncConv(sc);
8213 if (sc.flags & SCOPE.Cfile)
8216 if (e.type is Type.tvoid)
8218 checkMustUse(e.e1, sc);
8221 else if (!e.allowCommaExp && !e.isGenerated)
8222 e.error("using the result of a comma expression is not allowed");
8225 override void visit(IntervalExp e)
8227 static if (LOGSEMANTIC)
8229 printf("IntervalExp::semantic('%s')\n", e.toChars());
8237 Expression le = e.lwr;
8238 le = le.expressionSemantic(sc);
8239 le = resolveProperties(sc, le);
8241 Expression ue = e.upr;
8242 ue = ue.expressionSemantic(sc);
8243 ue = resolveProperties(sc, ue);
8245 if (le.op == EXP.error)
8250 if (ue.op == EXP.error)
8259 e.type = Type.tvoid;
8263 override void visit(DelegatePtrExp e)
8265 static if (LOGSEMANTIC)
8267 printf("DelegatePtrExp::semantic('%s')\n", e.toChars());
8272 e.e1 = resolveProperties(sc, e.e1);
8274 if (e.e1.op == EXP.error)
8279 e.type = Type.tvoidptr;
8284 override void visit(DelegateFuncptrExp e)
8286 static if (LOGSEMANTIC)
8288 printf("DelegateFuncptrExp::semantic('%s')\n", e.toChars());
8293 e.e1 = resolveProperties(sc, e.e1);
8294 if (e.e1.op == EXP.error)
8299 e.type = e.e1.type.nextOf().pointerTo();
8304 override void visit(IndexExp exp)
8306 static if (LOGSEMANTIC)
8308 printf("IndexExp::semantic('%s')\n", exp.toChars());
8316 // operator overloading should be handled in ArrayExp already.
8318 exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
8319 assert(exp.e1.type); // semantic() should already be run on it
8320 if (exp.e1.op == EXP.type && exp.e1.type.ty != Ttuple)
8322 exp.e2 = exp.e2.expressionSemantic(sc);
8323 exp.e2 = resolveProperties(sc, exp.e2);
8325 if (exp.e2.op == EXP.type)
8326 nt = new TypeAArray(exp.e1.type, exp.e2.type);
8328 nt = new TypeSArray(exp.e1.type, exp.e2);
8329 Expression e = new TypeExp(exp.loc, nt);
8330 result = e.expressionSemantic(sc);
8333 if (exp.e1.op == EXP.error)
8338 if (exp.e1.type.ty == Terror)
8341 // Note that unlike C we do not implement the int[ptr]
8343 Type t1b = exp.e1.type.toBasetype();
8345 if (t1b.ty == Tvector)
8347 // Convert e1 to corresponding static array
8348 TypeVector tv1 = cast(TypeVector)t1b;
8350 t1b = t1b.castMod(tv1.mod);
8353 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8355 if (!checkAddressable(exp, sc))
8359 /* Run semantic on e2
8362 if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
8364 // Create scope for 'length' variable
8365 ScopeDsymbol sym = new ArrayScopeSymbol(sc, exp);
8366 sym.parent = sc.scopesym;
8369 if (t1b.ty == Ttuple)
8370 sc = sc.startCTFE();
8371 exp.e2 = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
8372 exp.e2 = resolveProperties(sc, exp.e2);
8373 if (t1b.ty == Ttuple)
8375 if (exp.e2.op == EXP.tuple)
8377 TupleExp te = cast(TupleExp)exp.e2;
8378 if (te.exps && te.exps.length == 1)
8379 exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
8383 if (exp.e2.type == Type.terror)
8386 if (checkNonAssignmentArrayOp(exp.e1))
8392 if (t1b.isPtrToFunction())
8394 exp.error("cannot index function pointer `%s`", exp.e1.toChars());
8397 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8398 if (exp.e2.type == Type.terror)
8400 exp.e2 = exp.e2.optimize(WANTvalue);
8401 if (exp.e2.op == EXP.int64 && exp.e2.toInteger() == 0)
8404 else if (sc.setUnsafe(false, exp.loc, "`@safe` function `%s` cannot index pointer `%s`", sc.func, exp.e1))
8408 exp.type = (cast(TypeNext)t1b).next;
8412 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8413 if (exp.e2.type == Type.terror)
8415 exp.type = (cast(TypeNext)t1b).next;
8420 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8421 if (exp.e2.type == Type.terror)
8423 exp.type = t1b.nextOf();
8428 TypeAArray taa = cast(TypeAArray)t1b;
8429 /* We can skip the implicit conversion if they differ only by
8431 * https://issues.dlang.org/show_bug.cgi?id=2684
8432 * see also bug https://issues.dlang.org/show_bug.cgi?id=2954 b
8434 if (!arrayTypeCompatibleWithoutCasting(exp.e2.type, taa.index))
8436 exp.e2 = exp.e2.implicitCastTo(sc, taa.index); // type checking
8437 if (exp.e2.type == Type.terror)
8441 semanticTypeInfo(sc, taa);
8442 checkNewEscape(sc, exp.e2, false);
8444 exp.type = taa.next;
8449 exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t);
8450 if (exp.e2.type == Type.terror)
8453 exp.e2 = exp.e2.ctfeInterpret();
8454 uinteger_t index = exp.e2.toUInteger();
8459 if (exp.e1.op == EXP.tuple)
8461 te = cast(TupleExp)exp.e1;
8463 length = te.exps.length;
8465 else if (exp.e1.op == EXP.type)
8468 tup = cast(TypeTuple)t1b;
8469 length = Parameter.dim(tup.arguments);
8474 if (length <= index)
8476 exp.error("array index `[%llu]` is outside array bounds `[0 .. %llu]`", index, cast(ulong)length);
8480 if (exp.e1.op == EXP.tuple)
8482 e = (*te.exps)[cast(size_t)index];
8483 e = Expression.combine(te.e0, e);
8486 e = new TypeExp(exp.e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
8491 exp.error("`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars());
8495 // We might know $ now
8496 setLengthVarIfKnown(exp.lengthVar, t1b);
8498 if (t1b.ty == Tsarray || t1b.ty == Tarray)
8500 Expression el = new ArrayLengthExp(exp.loc, exp.e1);
8501 el = el.expressionSemantic(sc);
8502 el = el.optimize(WANTvalue);
8503 if (el.op == EXP.int64)
8505 exp.e2 = exp.e2.optimize(WANTvalue);
8506 dinteger_t length = el.toInteger();
8509 auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
8510 // OR it in, because it might already be set for C array indexing
8511 exp.indexIsInBounds |= bounds.contains(getIntRange(exp.e2));
8513 else if (sc.flags & SCOPE.Cfile && t1b.ty == Tsarray)
8515 if (auto ve = exp.e1.isVarExp())
8517 /* Rewrite 0-length C array ve[exp.e2] as *(ve + exp.e2)
8519 auto vp = ve.castTo(sc, t1b.isTypeSArray().next.pointerTo());
8520 auto e = new AddExp(exp.loc, vp, exp.e2);
8521 auto pe = new PtrExp(exp.loc, e);
8522 result = pe.expressionSemantic(sc).optimize(WANTvalue);
8532 override void visit(PostExp exp)
8534 static if (LOGSEMANTIC)
8536 printf("PostExp::semantic('%s')\n", exp.toChars());
8544 if (sc.flags & SCOPE.Cfile)
8546 /* See if need to rewrite the AST because of cast/call ambiguity
8548 if (auto e = castCallAmbiguity(exp, sc))
8550 result = expressionSemantic(e, sc);
8555 if (Expression ex = binSemantic(exp, sc))
8560 Expression e1x = resolveProperties(sc, exp.e1);
8561 if (e1x.op == EXP.error)
8568 Expression e = exp.op_overload(sc);
8575 if (exp.e1.checkReadModifyWrite(exp.op))
8578 if (exp.e1.op == EXP.slice)
8580 const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement";
8581 exp.error("cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s);
8585 Type t1 = exp.e1.type.toBasetype();
8586 if (t1.ty == Tclass || t1.ty == Tstruct || exp.e1.op == EXP.arrayLength)
8588 /* Check for operator overloading,
8589 * but rewrite in terms of ++e instead of e++
8592 /* If e1 is not trivial, take a reference to it
8594 Expression de = null;
8595 if (exp.e1.op != EXP.variable && exp.e1.op != EXP.arrayLength)
8598 auto v = copyToTemp(STC.ref_, "__postref", exp.e1);
8599 de = new DeclarationExp(exp.loc, v);
8600 exp.e1 = new VarExp(exp.e1.loc, v);
8604 * auto tmp = e1; ++e1; tmp
8606 auto tmp = copyToTemp(0, "__pitmp", exp.e1);
8607 Expression ea = new DeclarationExp(exp.loc, tmp);
8609 Expression eb = exp.e1.syntaxCopy();
8610 eb = new PreExp(exp.op == EXP.plusPlus ? EXP.prePlusPlus : EXP.preMinusMinus, exp.loc, eb);
8612 Expression ec = new VarExp(exp.loc, tmp);
8614 // Combine de,ea,eb,ec
8616 ea = new CommaExp(exp.loc, de, ea);
8617 e = new CommaExp(exp.loc, ea, eb);
8618 e = new CommaExp(exp.loc, e, ec);
8619 e = e.expressionSemantic(sc);
8624 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
8625 exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true);
8628 if (exp.e1.checkScalar() ||
8629 exp.e1.checkSharedAccess(sc))
8631 if (exp.e1.checkNoBool())
8634 if (exp.e1.type.ty == Tpointer)
8635 e = scaleFactor(exp, sc);
8637 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
8638 e.type = exp.e1.type;
8642 override void visit(PreExp exp)
8644 Expression e = exp.op_overload(sc);
8645 // printf("PreExp::semantic('%s')\n", toChars());
8652 // Rewrite as e1+=1 or e1-=1
8653 if (exp.op == EXP.prePlusPlus)
8654 e = new AddAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8656 e = new MinAssignExp(exp.loc, exp.e1, IntegerExp.literal!1);
8657 result = e.expressionSemantic(sc);
8661 * Get the expression initializer for a specific struct
8664 * sd = the struct for which the expression initializer is needed
8665 * loc = the location of the initializer
8666 * sc = the scope where the expression is located
8667 * t = the type of the expression
8670 * The expression initializer or error expression if any errors occured
8672 private Expression getInitExp(StructDeclaration sd, Loc loc, Scope* sc, Type t)
8674 if (sd.zeroInit && !sd.isNested())
8676 // https://issues.dlang.org/show_bug.cgi?id=14606
8677 // Always use BlitExp for the special expression: (struct = 0)
8678 return IntegerExp.literal!0;
8683 auto sle = new StructLiteralExp(loc, sd, null, t);
8684 if (!sd.fill(loc, *sle.elements, true))
8685 return ErrorExp.get();
8686 if (checkFrameAccess(loc, sc, sd, sle.elements.length))
8687 return ErrorExp.get();
8693 return t.defaultInit(loc);
8696 override void visit(AssignExp exp)
8698 static if (LOGSEMANTIC)
8700 if (exp.op == EXP.blit) printf("BlitExp.toElem('%s')\n", exp.toChars());
8701 if (exp.op == EXP.assign) printf("AssignExp.toElem('%s')\n", exp.toChars());
8702 if (exp.op == EXP.construct) printf("ConstructExp.toElem('%s')\n", exp.toChars());
8705 void setResult(Expression e, int line = __LINE__)
8707 //printf("line %d\n", line);
8713 return setResult(exp);
8716 Expression e1old = exp.e1;
8718 if (auto e2comma = exp.e2.isCommaExp())
8720 if (!e2comma.isGenerated && !(sc.flags & SCOPE.Cfile))
8721 exp.error("using the result of a comma expression is not allowed");
8723 /* Rewrite to get rid of the comma from rvalue
8724 * e1=(e0,e2) => e0,(e1=e2)
8727 exp.e2 = Expression.extractLast(e2comma, e0);
8728 Expression e = Expression.combine(e0, exp);
8729 return setResult(e.expressionSemantic(sc));
8732 /* Look for operator overloading of a[arguments] = e2.
8733 * Do it before e1.expressionSemantic() otherwise the ArrayExp will have been
8734 * converted to unary operator overloading already.
8736 if (auto ae = exp.e1.isArrayExp())
8740 ae.e1 = ae.e1.expressionSemantic(sc);
8741 ae.e1 = resolveProperties(sc, ae.e1);
8742 Expression ae1old = ae.e1;
8744 const(bool) maybeSlice =
8745 (ae.arguments.length == 0 ||
8746 ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
8748 IntervalExp ie = null;
8749 if (maybeSlice && ae.arguments.length)
8751 assert((*ae.arguments)[0].op == EXP.interval);
8752 ie = cast(IntervalExp)(*ae.arguments)[0];
8756 if (ae.e1.op == EXP.error)
8757 return setResult(ae.e1);
8759 Expression e0 = null;
8760 Expression ae1save = ae.e1;
8761 ae.lengthVar = null;
8763 Type t1b = ae.e1.type.toBasetype();
8764 AggregateDeclaration ad = isAggregate(t1b);
8767 if (search_function(ad, Id.indexass))
8770 res = resolveOpDollar(sc, ae, &e0);
8771 if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
8773 if (res.op == EXP.error)
8774 return setResult(res);
8776 res = exp.e2.expressionSemantic(sc);
8777 if (res.op == EXP.error)
8778 return setResult(res);
8781 /* Rewrite (a[arguments] = e2) as:
8782 * a.opIndexAssign(e2, arguments)
8784 Expressions* a = ae.arguments.copy();
8785 a.insert(0, exp.e2);
8786 res = new DotIdExp(exp.loc, ae.e1, Id.indexass);
8787 res = new CallExp(exp.loc, res, a);
8788 if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
8789 res = res.trySemantic(sc);
8791 res = res.expressionSemantic(sc);
8793 return setResult(Expression.combine(e0, res));
8797 if (maybeSlice && search_function(ad, Id.sliceass))
8800 res = resolveOpDollar(sc, ae, ie, &e0);
8801 if (res.op == EXP.error)
8802 return setResult(res);
8804 res = exp.e2.expressionSemantic(sc);
8805 if (res.op == EXP.error)
8806 return setResult(res);
8810 /* Rewrite (a[i..j] = e2) as:
8811 * a.opSliceAssign(e2, i, j)
8813 auto a = new Expressions();
8820 res = new DotIdExp(exp.loc, ae.e1, Id.sliceass);
8821 res = new CallExp(exp.loc, res, a);
8822 res = res.expressionSemantic(sc);
8823 return setResult(Expression.combine(e0, res));
8826 // No operator overloading member function found yet, but
8827 // there might be an alias this to try.
8828 if (ad.aliasthis && !isRecursiveAliasThis(ae.att1, ae.e1.type))
8830 /* Rewrite (a[arguments] op e2) as:
8831 * a.aliasthis[arguments] op e2
8833 ae.e1 = resolveAliasThis(sc, ae1save, true);
8839 ae.e1 = ae1old; // recovery
8840 ae.lengthVar = null;
8843 /* Run this.e1 semantic.
8846 Expression e1x = exp.e1;
8848 /* With UFCS, e.f = value
8854 if (auto dti = e1x.isDotTemplateInstanceExp())
8856 Expression e = dti.dotTemplateSemanticProp(sc, 1);
8859 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8864 else if (sc.flags & SCOPE.Cfile && e1x.isDotIdExp())
8866 auto die = e1x.isDotIdExp();
8867 e1x = fieldLookup(die.e1, sc, die.ident);
8869 else if (auto die = e1x.isDotIdExp())
8871 Expression e = die.dotIdSemanticProp(sc, 1);
8872 if (e && isDotOpDispatch(e))
8874 /* https://issues.dlang.org/show_bug.cgi?id=19687
8876 * On this branch, e2 is semantically analyzed in resolvePropertiesX,
8877 * but that call is done with gagged errors. That is the only time when
8878 * semantic gets ran on e2, that is why the error never gets to be printed.
8879 * In order to make sure that UFCS is tried with correct parameters, e2
8880 * needs to have semantic ran on it.
8883 exp.e2 = exp.e2.expressionSemantic(sc);
8884 uint errors = global.startGagging();
8885 e = resolvePropertiesX(sc, e, exp.e2);
8886 // Any error or if 'e' is not resolved, go to UFCS
8887 if (global.endGagging(errors) || e is ode)
8888 e = null; /* fall down to UFCS */
8890 return setResult(e);
8893 return setResult(resolveUFCSProperties(sc, e1x, exp.e2));
8898 if (auto se = e1x.isSliceExp())
8901 e1x = e1x.expressionSemantic(sc);
8904 /* We have f = value.
8910 if (Expression e = resolvePropertiesX(sc, e1x, exp.e2))
8911 return setResult(e);
8913 if (e1x.checkRightThis(sc))
8918 assert(exp.e1.type);
8920 Type t1 = exp.e1.type.isTypeEnum() ? exp.e1.type : exp.e1.type.toBasetype();
8922 /* Run this.e2 semantic.
8923 * Different from other binary expressions, the analysis of e2
8924 * depends on the result of e1 in assignments.
8927 Expression e2x = inferType(exp.e2, t1.baseElemOf());
8928 e2x = e2x.expressionSemantic(sc);
8929 if (!t1.isTypeSArray())
8930 e2x = e2x.arrayFuncConv(sc);
8931 e2x = resolveProperties(sc, e2x);
8932 if (e2x.op == EXP.type)
8933 e2x = resolveAliasThis(sc, e2x); //https://issues.dlang.org/show_bug.cgi?id=17684
8934 if (e2x.op == EXP.error)
8935 return setResult(e2x);
8936 // We delay checking the value for structs/classes as these might have
8937 // an opAssign defined.
8938 if ((t1.ty != Tstruct && t1.ty != Tclass && e2x.checkValue()) ||
8939 e2x.checkSharedAccess(sc))
8942 auto etmp = checkNoreturnVarAccess(e2x);
8944 return setResult(etmp);
8949 /* Rewrite tuple assignment as a tuple of assignments.
8952 Expression e2x = exp.e2;
8955 if (exp.e1.op == EXP.tuple && e2x.op == EXP.tuple)
8957 TupleExp tup1 = cast(TupleExp)exp.e1;
8958 TupleExp tup2 = cast(TupleExp)e2x;
8959 size_t dim = tup1.exps.length;
8960 Expression e = null;
8961 if (dim != tup2.exps.length)
8963 exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
8968 e = IntegerExp.literal!0;
8969 e = new CastExp(exp.loc, e, Type.tvoid); // avoid "has no effect" error
8970 e = Expression.combine(tup1.e0, tup2.e0, e);
8974 auto exps = new Expressions(dim);
8975 for (size_t i = 0; i < dim; i++)
8977 Expression ex1 = (*tup1.exps)[i];
8978 Expression ex2 = (*tup2.exps)[i];
8979 (*exps)[i] = new AssignExp(exp.loc, ex1, ex2);
8981 e = new TupleExp(exp.loc, Expression.combine(tup1.e0, tup2.e0), exps);
8983 return setResult(e.expressionSemantic(sc));
8986 /* Look for form: e1 = e2.aliasthis.
8988 if (exp.e1.op == EXP.tuple)
8990 TupleDeclaration td = isAliasThisTuple(e2x);
8994 assert(exp.e1.type.ty == Ttuple);
8995 TypeTuple tt = cast(TypeTuple)exp.e1.type;
8998 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
9000 auto iexps = new Expressions();
9002 for (size_t u = 0; u < iexps.length; u++)
9005 Expression e = (*iexps)[u];
9007 Parameter arg = Parameter.getNth(tt.arguments, u);
9008 //printf("[%d] iexps.length = %d, ", u, iexps.length);
9009 //printf("e = (%s %s, %s), ", Token.toChars[e.op], e.toChars(), e.type.toChars());
9010 //printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
9012 if (!arg || !e.type.implicitConvTo(arg.type))
9014 // expand initializer to tuple
9015 if (expandAliasThisTuples(iexps, u) != -1)
9017 if (iexps.length <= u)
9024 e2x = new TupleExp(e2x.loc, e0, iexps);
9025 e2x = e2x.expressionSemantic(sc);
9026 if (e2x.op == EXP.error)
9031 // Do not need to overwrite this.e2
9037 /* Inside constructor, if this is the first assignment of object field,
9038 * rewrite this to initializing the field.
9040 if (exp.op == EXP.assign
9041 && exp.e1.checkModifiable(sc) == Modifiable.initialization)
9043 //printf("[%s] change to init - %s\n", exp.loc.toChars(), exp.toChars());
9045 exp = new ConstructExp(exp.loc, exp.e1, exp.e2);
9048 // https://issues.dlang.org/show_bug.cgi?id=13515
9049 // set Index::modifiable flag for complex AA element initialization
9050 if (auto ie1 = exp.e1.isIndexExp())
9052 Expression e1x = ie1.markSettingAAElem();
9053 if (e1x.op == EXP.error)
9060 else if (exp.op == EXP.construct && exp.e1.op == EXP.variable &&
9061 (cast(VarExp)exp.e1).var.storage_class & (STC.out_ | STC.ref_))
9063 exp.memset = MemorySet.referenceInit;
9066 if (exp.op == EXP.assign) // skip EXP.blit and EXP.construct, which are initializations
9068 exp.e1.checkSharedAccess(sc);
9069 checkUnsafeAccess(sc, exp.e1, false, true);
9072 checkUnsafeAccess(sc, exp.e2, true, true); // Initializer must always be checked
9074 /* If it is an assignment from a 'foreign' type,
9075 * check for operator overloading.
9077 if (exp.memset == MemorySet.referenceInit)
9079 // If this is an initialization of a reference,
9082 else if (t1.ty == Tstruct)
9086 auto sd = (cast(TypeStruct)t1).sym;
9088 if (exp.op == EXP.construct)
9090 Type t2 = e2x.type.toBasetype();
9091 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
9094 if (sd.sizeok != Sizeok.done)
9097 sd.ctor = sd.searchCtor();
9099 // https://issues.dlang.org/show_bug.cgi?id=15661
9100 // Look for the form from last of comma chain.
9101 auto e2y = lastComma(e2x);
9103 CallExp ce = (e2y.op == EXP.call) ? cast(CallExp)e2y : null;
9104 DotVarExp dve = (ce && ce.e1.op == EXP.dotVariable)
9105 ? cast(DotVarExp)ce.e1 : null;
9106 if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
9107 // https://issues.dlang.org/show_bug.cgi?id=19389
9108 dve.e1.op != EXP.dotVariable &&
9109 e2y.type.implicitConvTo(t1))
9111 /* Look for form of constructor call which is:
9112 * __ctmp.ctor(arguments...)
9115 /* Before calling the constructor, initialize
9116 * variable with a bit copy of the default
9119 Expression einit = getInitExp(sd, exp.loc, sc, t1);
9120 if (einit.op == EXP.error)
9126 auto ae = new BlitExp(exp.loc, exp.e1, einit);
9129 /* Replace __ctmp being constructed with e1.
9130 * We need to copy constructor call expression,
9131 * because it may be used in other place.
9133 auto dvx = cast(DotVarExp)dve.copy();
9135 auto cx = cast(CallExp)ce.copy();
9137 if (checkConstructorEscape(sc, cx, false))
9141 Expression.extractLast(e2x, e0);
9143 auto e = Expression.combine(e0, ae, cx);
9144 e = e.expressionSemantic(sc);
9148 // https://issues.dlang.org/show_bug.cgi?id=21586
9149 // Rewrite CondExp or e1 will miss direct construction, e.g.
9150 // e1 = a ? S(1) : ...; -> AST: e1 = a ? (S(0)).this(1) : ...;
9151 // a temporary created and an extra destructor call.
9152 // AST will be rewritten to:
9153 // a ? e1 = 0, e1.this(1) : ...; -> blitting plus construction
9154 if (e2x.op == EXP.question)
9157 * a ? e1 = b : e1 = c;
9159 CondExp econd = cast(CondExp)e2x;
9160 Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
9161 Expression ea2 = new ConstructExp(econd.e2.loc, e1x, econd.e2);
9162 Expression e = new CondExp(exp.loc, econd.econd, ea1, ea2);
9163 result = e.expressionSemantic(sc);
9166 if (sd.postblit || sd.hasCopyCtor)
9168 /* We have a copy constructor for this
9176 * e1 = init, e1.copyCtor(e2);
9178 Expression einit = new BlitExp(exp.loc, exp.e1, getInitExp(sd, exp.loc, sc, t1));
9179 einit.type = e1x.type;
9182 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9183 e = new CallExp(exp.loc, e, e2x);
9184 e = new CommaExp(exp.loc, einit, e);
9186 //printf("e: %s\n", e.toChars());
9188 result = e.expressionSemantic(sc);
9193 if (!e2x.type.implicitConvTo(e1x.type))
9195 exp.error("conversion error from `%s` to `%s`",
9196 e2x.type.toChars(), e1x.type.toChars());
9201 * (e1 = e2).postblit();
9203 * Blit assignment e1 = e2 returns a reference to the original e1,
9204 * then call the postblit on it.
9206 Expression e = e1x.copy();
9207 e.type = e.type.mutableOf();
9208 if (e.type.isShared && !sd.type.isShared)
9209 e.type = e.type.unSharedOf();
9210 e = new BlitExp(exp.loc, e, e2x);
9211 e = new DotVarExp(exp.loc, e, sd.postblit, false);
9212 e = new CallExp(exp.loc, e);
9213 result = e.expressionSemantic(sc);
9219 /* The struct value returned from the function is transferred
9220 * so should not call the destructor on it.
9222 e2x = valueNoDtor(e2x);
9226 // https://issues.dlang.org/show_bug.cgi?id=19251
9227 // if e2 cannot be converted to e1.type, maybe there is an alias this
9228 if (!e2x.implicitConvTo(t1))
9230 AggregateDeclaration ad2 = isAggregate(e2x.type);
9231 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9233 /* Rewrite (e1 op e2) as:
9234 * (e1 op e2.aliasthis)
9236 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9237 result = exp.expressionSemantic(sc);
9242 else if (!e2x.implicitConvTo(t1))
9245 if (sd.sizeok != Sizeok.done)
9248 sd.ctor = sd.searchCtor();
9252 /* Look for implicit constructor call
9254 * e1 = init, e1.ctor(e2)
9257 /* Fix Issue 5153 : https://issues.dlang.org/show_bug.cgi?id=5153
9258 * Using `new` to initialize a struct object is a common mistake, but
9259 * the error message from the compiler is not very helpful in that
9260 * case. If exp.e2 is a NewExp and the type of new is the same as
9261 * the type as exp.e1 (struct in this case), then we know for sure
9262 * that the user wants to instantiate a struct. This is done to avoid
9263 * issuing an error when the user actually wants to call a constructor
9264 * which receives a class object.
9266 * Foo f = new Foo2(0); is a valid expression if Foo has a constructor
9267 * which receives an instance of a Foo2 class
9269 if (exp.e2.op == EXP.new_)
9271 auto newExp = cast(NewExp)(exp.e2);
9272 if (newExp.newtype && newExp.newtype == t1)
9274 error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`",
9275 newExp.toChars(), newExp.type.toChars(), t1.toChars());
9276 errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?");
9281 Expression einit = new BlitExp(exp.loc, e1x, getInitExp(sd, exp.loc, sc, t1));
9282 einit.type = e1x.type;
9285 e = new DotIdExp(exp.loc, e1x, Id.ctor);
9286 e = new CallExp(exp.loc, e, e2x);
9287 e = new CommaExp(exp.loc, einit, e);
9288 e = e.expressionSemantic(sc);
9292 if (search_function(sd, Id.call))
9294 /* Look for static opCall
9295 * https://issues.dlang.org/show_bug.cgi?id=2702
9297 * e1 = typeof(e1).opCall(arguments)
9299 e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
9300 e2x = new CallExp(exp.loc, e2x, exp.e2);
9302 e2x = e2x.expressionSemantic(sc);
9303 e2x = resolveProperties(sc, e2x);
9304 if (e2x.op == EXP.error)
9309 if (e2x.checkValue() || e2x.checkSharedAccess(sc))
9313 else // https://issues.dlang.org/show_bug.cgi?id=11355
9315 AggregateDeclaration ad2 = isAggregate(e2x.type);
9316 if (ad2 && ad2.aliasthis && !isRecursiveAliasThis(exp.att2, exp.e2.type))
9318 /* Rewrite (e1 op e2) as:
9319 * (e1 op e2.aliasthis)
9321 exp.e2 = new DotIdExp(exp.e2.loc, exp.e2, ad2.aliasthis.ident);
9322 result = exp.expressionSemantic(sc);
9327 else if (exp.op == EXP.assign)
9329 if (e1x.op == EXP.index && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
9336 * ref __aakey = key;
9338 * (__aakey in __aatmp
9339 * ? __aatmp[__aakey].opAssign(__aaval)
9340 * : ConstructExp(__aatmp[__aakey], __aaval));
9342 // ensure we keep the expr modifiable
9343 Expression esetting = (cast(IndexExp)e1x).markSettingAAElem();
9344 if (esetting.op == EXP.error)
9349 assert(esetting.op == EXP.index);
9350 IndexExp ie = cast(IndexExp) esetting;
9351 Type t2 = e2x.type.toBasetype();
9353 Expression e0 = null;
9354 Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
9355 Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
9356 Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
9358 AssignExp ae = cast(AssignExp)exp.copy();
9359 ae.e1 = new IndexExp(exp.loc, ea, ek);
9360 ae.e1 = ae.e1.expressionSemantic(sc);
9361 ae.e1 = ae.e1.optimize(WANTvalue);
9363 Expression e = ae.op_overload(sc);
9366 Expression ey = null;
9367 if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
9371 else if (!ev.implicitConvTo(ie.type) && sd.ctor)
9373 // Look for implicit constructor call
9374 // Rewrite as S().ctor(e2)
9375 ey = new StructLiteralExp(exp.loc, sd, null);
9376 ey = new DotIdExp(exp.loc, ey, Id.ctor);
9377 ey = new CallExp(exp.loc, ey, ev);
9378 ey = ey.trySemantic(sc);
9383 ex = new IndexExp(exp.loc, ea, ek);
9384 ex = ex.expressionSemantic(sc);
9385 ex = ex.modifiableLvalue(sc, ex); // allocate new slot
9386 ex = ex.optimize(WANTvalue);
9388 ey = new ConstructExp(exp.loc, ex, ey);
9389 ey = ey.expressionSemantic(sc);
9390 if (ey.op == EXP.error)
9397 // https://issues.dlang.org/show_bug.cgi?id=14144
9398 // The whole expression should have the common type
9399 // of opAssign() return and assigned AA entry.
9400 // Even if there's no common type, expression should be typed as void.
9401 if (!typeMerge(sc, EXP.question, ex, ey))
9403 ex = new CastExp(ex.loc, ex, Type.tvoid);
9404 ey = new CastExp(ey.loc, ey, Type.tvoid);
9406 e = new CondExp(exp.loc, new InExp(exp.loc, ek, ea), ex, ey);
9408 e = Expression.combine(e0, e);
9409 e = e.expressionSemantic(sc);
9416 Expression e = exp.op_overload(sc);
9425 assert(exp.op == EXP.blit);
9427 if (e2x.checkValue())
9433 else if (t1.ty == Tclass)
9435 // Disallow assignment operator overloads for same type
9436 if (exp.op == EXP.assign && !exp.e2.implicitConvTo(exp.e1.type))
9438 Expression e = exp.op_overload(sc);
9445 if (exp.e2.checkValue())
9448 else if (t1.ty == Tsarray)
9450 // SliceExp cannot have static array type without context inference.
9451 assert(exp.e1.op != EXP.slice);
9452 Expression e1x = exp.e1;
9453 Expression e2x = exp.e2;
9455 /* C strings come through as static arrays. May need to adjust the size of the
9456 * string to match the size of e1.
9458 Type t2 = e2x.type.toBasetype();
9459 if (sc.flags & SCOPE.Cfile && e2x.isStringExp() && t2.isTypeSArray())
9461 uinteger_t dim1 = t1.isTypeSArray().dim.toInteger();
9462 uinteger_t dim2 = t2.isTypeSArray().dim.toInteger();
9463 if (dim1 + 1 == dim2 || dim2 < dim1)
9465 auto tsa2 = t2.isTypeSArray();
9466 auto newt = tsa2.next.sarrayOf(dim1).immutableOf();
9467 e2x = castTo(e2x, sc, newt);
9472 if (e2x.implicitConvTo(e1x.type))
9474 if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue()))
9476 if (e1x.checkPostblit(sc, t1))
9480 // e2 matches to t1 because of the implicit length match, so
9481 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
9483 // convert e1 to e1[]
9484 // e.g. e1[] = a[] + b[];
9485 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9487 e1x = sle.expressionSemantic(sc);
9491 // convert e2 to t1 later
9492 // e.g. e1 = [1, 2, 3];
9497 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCH.nomatch)
9499 uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
9500 uinteger_t dim2 = dim1;
9501 if (auto ale = e2x.isArrayLiteralExp())
9503 dim2 = ale.elements ? ale.elements.length : 0;
9505 else if (auto se = e2x.isSliceExp())
9507 Type tx = toStaticArrayType(se);
9509 dim2 = (cast(TypeSArray)tx).dim.toInteger();
9513 exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
9518 // May be block or element-wise assignment, so
9519 // convert e1 to e1[]
9520 if (exp.op != EXP.assign)
9522 // If multidimensional static array, treat as one large array
9524 // Find the appropriate array type depending on the assignment, e.g.
9525 // int[3] = int => int[3]
9526 // int[3][2] = int => int[6]
9527 // int[3][2] = int[] => int[3][2]
9528 // int[3][2][4] + int => int[24]
9529 // int[3][2][4] + int[] => int[3][8]
9530 ulong dim = t1.isTypeSArray().dim.toUInteger();
9531 auto type = t1.nextOf();
9533 for (TypeSArray tsa; (tsa = type.isTypeSArray()) !is null; )
9535 import core.checkedint : mulu;
9537 // Accumulate skipped dimensions
9538 bool overflow = false;
9539 dim = mulu(dim, tsa.dim.toUInteger(), overflow);
9540 if (overflow || dim >= uint.max)
9542 // dym exceeds maximum array size
9543 exp.error("static array `%s` size overflowed to %llu",
9544 e1x.type.toChars(), cast(ulong) dim);
9548 // Move to the element type
9549 type = tsa.nextOf().toBasetype();
9551 // Rewrite ex1 as a static array if a matching type was found
9552 if (e2x.implicitConvTo(type) > MATCH.nomatch)
9554 e1x.type = type.sarrayOf(dim);
9559 auto sle = new SliceExp(e1x.loc, e1x, null, null);
9561 e1x = sle.expressionSemantic(sc);
9563 if (e1x.op == EXP.error)
9564 return setResult(e1x);
9565 if (e2x.op == EXP.error)
9566 return setResult(e2x);
9570 t1 = e1x.type.toBasetype();
9572 /* Check the mutability of e1.
9574 if (auto ale = exp.e1.isArrayLengthExp())
9576 // e1 is not an lvalue, but we let code generator handle it
9578 auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1);
9579 if (ale1x.op == EXP.error)
9580 return setResult(ale1x);
9583 Type tn = ale.e1.type.toBasetype().nextOf();
9584 checkDefCtor(ale.loc, tn);
9586 Identifier hook = global.params.tracegc ? Id._d_arraysetlengthTTrace : Id._d_arraysetlengthT;
9587 if (!verifyHookExist(exp.loc, *sc, Id._d_arraysetlengthTImpl, "resizing arrays"))
9590 exp.e2 = exp.e2.expressionSemantic(sc);
9591 auto lc = lastComma(exp.e2);
9592 lc = lc.optimize(WANTvalue);
9593 // use slice expression when arr.length = 0 to avoid runtime call
9594 if(lc.op == EXP.int64 && lc.toInteger() == 0)
9596 Expression se = new SliceExp(ale.loc, ale.e1, lc, lc);
9597 Expression as = new AssignExp(ale.loc, ale.e1, se);
9598 as = as.expressionSemantic(sc);
9599 auto res = Expression.combine(as, exp.e2);
9600 res.type = ale.type;
9601 return setResult(res);
9604 // Lower to object._d_arraysetlengthTImpl!(typeof(e1))._d_arraysetlengthT{,Trace}(e1, e2)
9605 Expression id = new IdentifierExp(ale.loc, Id.empty);
9606 id = new DotIdExp(ale.loc, id, Id.object);
9607 auto tiargs = new Objects();
9608 tiargs.push(ale.e1.type);
9609 id = new DotTemplateInstanceExp(ale.loc, id, Id._d_arraysetlengthTImpl, tiargs);
9610 id = new DotIdExp(ale.loc, id, hook);
9611 id = id.expressionSemantic(sc);
9613 auto arguments = new Expressions();
9614 arguments.reserve(5);
9615 if (global.params.tracegc)
9617 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
9618 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
9619 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
9620 arguments.push(new StringExp(exp.loc, funcname.toDString()));
9622 arguments.push(ale.e1);
9623 arguments.push(exp.e2);
9625 Expression ce = new CallExp(ale.loc, id, arguments);
9626 auto res = ce.expressionSemantic(sc);
9627 // if (global.params.verbose)
9628 // message("lowered %s =>\n %s", exp.toChars(), res.toChars());
9629 return setResult(res);
9631 else if (auto se = exp.e1.isSliceExp())
9633 Type tn = se.type.nextOf();
9634 const fun = sc.func;
9635 if (exp.op == EXP.assign && !tn.isMutable() &&
9636 // allow modifiation in module ctor, see
9637 // https://issues.dlang.org/show_bug.cgi?id=9884
9638 (!fun || (fun && !fun.isStaticCtorDeclaration())))
9640 exp.error("slice `%s` is not mutable", se.toChars());
9644 if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable())
9646 exp.error("slice `%s` is not mutable, struct `%s` has immutable members",
9647 exp.e1.toChars(), tn.baseElemOf().toChars());
9648 result = ErrorExp.get();
9652 // For conditional operator, both branches need conversion.
9653 while (se.e1.op == EXP.slice)
9654 se = cast(SliceExp)se.e1;
9655 if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray)
9657 se.e1 = se.e1.modifiableLvalue(sc, exp.e1);
9658 if (se.e1.op == EXP.error)
9659 return setResult(se.e1);
9664 if (t1.ty == Tsarray && exp.op == EXP.assign)
9666 Type tn = exp.e1.type.nextOf();
9667 if (tn && !tn.baseElemOf().isAssignable())
9669 exp.error("array `%s` is not mutable, struct `%s` has immutable members",
9670 exp.e1.toChars(), tn.baseElemOf().toChars());
9671 result = ErrorExp.get();
9676 Expression e1x = exp.e1;
9678 // Try to do a decent error message with the expression
9679 // before it gets constant folded
9680 if (exp.op == EXP.assign)
9681 e1x = e1x.modifiableLvalue(sc, e1old);
9683 e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true);
9685 if (e1x.op == EXP.error)
9693 /* Tweak e2 based on the type of e1.
9695 Expression e2x = exp.e2;
9696 Type t2 = e2x.type.toBasetype();
9698 // If it is a array, get the element type. Note that it may be
9699 // multi-dimensional.
9701 while (telem.ty == Tarray)
9702 telem = telem.nextOf();
9704 if (exp.e1.op == EXP.slice && t1.nextOf() &&
9705 (telem.ty != Tvoid || e2x.op == EXP.null_) &&
9706 e2x.implicitConvTo(t1.nextOf()))
9708 // Check for block assignment. If it is of type void[], void[][], etc,
9709 // '= null' is the only allowable block assignment (Bug 7493)
9710 exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is
9711 e2x = e2x.implicitCastTo(sc, t1.nextOf());
9712 if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf()))
9715 else if (exp.e1.op == EXP.slice &&
9716 (t2.ty == Tarray || t2.ty == Tsarray) &&
9717 t2.nextOf().implicitConvTo(t1.nextOf()))
9719 // Check element-wise assignment.
9721 /* If assigned elements number is known at compile time,
9722 * check the mismatch.
9724 SliceExp se1 = cast(SliceExp)exp.e1;
9725 TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
9726 TypeSArray tsa2 = null;
9727 if (auto ale = e2x.isArrayLiteralExp())
9728 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.length);
9729 else if (auto se = e2x.isSliceExp())
9730 tsa2 = cast(TypeSArray)toStaticArrayType(se);
9732 tsa2 = t2.isTypeSArray();
9736 uinteger_t dim1 = tsa1.dim.toInteger();
9737 uinteger_t dim2 = tsa2.dim.toInteger();
9740 exp.error("mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars());
9745 if (exp.op != EXP.blit &&
9746 (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() ||
9747 e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() ||
9748 e2x.op != EXP.slice && e2x.isLvalue()))
9750 if (exp.e1.checkPostblit(sc, t1.nextOf()))
9754 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9755 e2x.op != EXP.slice && e2x.op != EXP.assign &&
9756 e2x.op != EXP.arrayLiteral && e2x.op != EXP.string_ &&
9757 !(e2x.op == EXP.add || e2x.op == EXP.min ||
9758 e2x.op == EXP.mul || e2x.op == EXP.div ||
9759 e2x.op == EXP.mod || e2x.op == EXP.xor ||
9760 e2x.op == EXP.and || e2x.op == EXP.or ||
9761 e2x.op == EXP.pow ||
9762 e2x.op == EXP.tilde || e2x.op == EXP.negate))
9764 const(char)* e1str = exp.e1.toChars();
9765 const(char)* e2str = e2x.toChars();
9766 exp.warning("explicit element-wise assignment `%s = (%s)[]` is better than `%s = %s`", e1str, e2str, e1str, e2str);
9769 Type t2n = t2.nextOf();
9770 Type t1n = t1.nextOf();
9772 if (t2n.equivalent(t1n) ||
9773 t1n.isBaseOf(t2n, &offset) && offset == 0)
9775 /* Allow copy of distinct qualifier elements.
9777 * char[] dst; const(char)[] src;
9780 * class C {} class D : C {}
9784 if (isArrayOpValid(e2x))
9786 // Don't add CastExp to keep AST for array operations
9788 e2x.type = exp.e1.type.constOf();
9791 e2x = e2x.castTo(sc, exp.e1.type.constOf());
9795 /* https://issues.dlang.org/show_bug.cgi?id=15778
9796 * A string literal has an array type of immutable
9797 * elements by default, and normally it cannot be convertible to
9798 * array type of mutable elements. But for element-wise assignment,
9799 * elements need to be const at best. So we should give a chance
9800 * to change code unit size for polysemous string literal.
9802 if (e2x.op == EXP.string_)
9803 e2x = e2x.implicitCastTo(sc, exp.e1.type.constOf());
9805 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9807 if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
9809 if (sc.setUnsafe(false, exp.loc, "cannot copy `void[]` to `void[]` in `@safe` code"))
9815 if (0 && global.params.warnings != DiagnosticReporting.off && !global.gag && exp.op == EXP.assign &&
9816 t1.ty == Tarray && t2.ty == Tsarray &&
9817 e2x.op != EXP.slice &&
9818 t2.implicitConvTo(t1))
9820 // Disallow ar[] = sa (Converted to ar[] = sa[])
9821 // Disallow da = sa (Converted to da = sa[])
9822 const(char)* e1str = exp.e1.toChars();
9823 const(char)* e2str = e2x.toChars();
9824 const(char)* atypestr = exp.e1.op == EXP.slice ? "element-wise" : "slice";
9825 exp.warning("explicit %s assignment `%s = (%s)[]` is better than `%s = %s`", atypestr, e1str, e2str, e1str, e2str);
9827 if (exp.op == EXP.blit)
9828 e2x = e2x.castTo(sc, exp.e1.type);
9831 e2x = e2x.implicitCastTo(sc, exp.e1.type);
9833 // Fix Issue 13435: https://issues.dlang.org/show_bug.cgi?id=13435
9835 // If the implicit cast has failed and the assign expression is
9836 // the initialization of a struct member field
9837 if (e2x.op == EXP.error && exp.op == EXP.construct && t1.ty == Tstruct)
9839 scope sd = (cast(TypeStruct)t1).sym;
9840 Dsymbol opAssign = search_function(sd, Id.assign);
9842 // and the struct defines an opAssign
9845 // offer more information about the cause of the problem
9846 errorSupplemental(exp.loc,
9847 "`%s` is the first assignment of `%s` therefore it represents its initialization",
9848 exp.toChars(), exp.e1.toChars());
9849 errorSupplemental(exp.loc,
9850 "`opAssign` methods are not used for initialization, but for subsequent assignments");
9855 if (e2x.op == EXP.error)
9861 t2 = exp.e2.type.toBasetype();
9863 /* Look for array operations
9865 if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(exp.e2))
9867 // Look for valid array operations
9868 if (exp.memset != MemorySet.blockAssign &&
9869 exp.e1.op == EXP.slice &&
9870 (isUnaArrayOp(exp.e2.op) || isBinArrayOp(exp.e2.op)))
9872 exp.type = exp.e1.type;
9873 if (exp.op == EXP.construct) // https://issues.dlang.org/show_bug.cgi?id=10282
9874 // tweak mutability of e1 element
9875 exp.e1.type = exp.e1.type.nextOf().mutableOf().arrayOf();
9876 result = arrayOp(exp, sc);
9880 // Drop invalid array operations in e2
9881 // d = a[] + b[], d = (a[] + b[])[0..2], etc
9882 if (checkNonAssignmentArrayOp(exp.e2, exp.memset != MemorySet.blockAssign && exp.op == EXP.assign))
9885 // Remains valid array assignments
9886 // d = d[], d = [1,2,3], etc
9889 /* Don't allow assignment to classes that were allocated on the stack with:
9890 * scope Class c = new Class();
9892 if (exp.e1.op == EXP.variable && exp.op == EXP.assign)
9894 VarExp ve = cast(VarExp)exp.e1;
9895 VarDeclaration vd = ve.var.isVarDeclaration();
9896 if (vd && vd.onstack)
9898 assert(t1.ty == Tclass);
9899 exp.error("cannot rebind scope variables");
9903 if (exp.e1.op == EXP.variable && (cast(VarExp)exp.e1).var.ident == Id.ctfe)
9905 exp.error("cannot modify compiler-generated variable `__ctfe`");
9908 exp.type = exp.e1.type;
9910 auto assignElem = exp.e2;
9911 auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
9912 /* https://issues.dlang.org/show_bug.cgi?id=22366
9914 * `reorderSettingAAElem` creates a tree of comma expressions, however,
9915 * `checkAssignExp` expects only AssignExps.
9917 if (res == exp) // no `AA[k] = v` rewrite was performed
9918 checkAssignEscape(sc, res, false, false);
9920 checkNewEscape(sc, assignElem, false); // assigning to AA puts it on heap
9922 if (auto ae = res.isConstructExp())
9924 Type t1b = ae.e1.type.toBasetype();
9925 if (t1b.ty != Tsarray && t1b.ty != Tarray)
9926 return setResult(res);
9928 // only non-trivial array constructions may need to be lowered (non-POD elements basically)
9929 Type t1e = t1b.nextOf();
9930 TypeStruct ts = t1e.baseElemOf().isTypeStruct();
9931 if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
9932 return setResult(res);
9934 // don't lower ref-constructions etc.
9935 if (!(t1b.ty == Tsarray || ae.e1.isSliceExp) ||
9936 (ae.e1.isVarExp && ae.e1.isVarExp.var.isVarDeclaration.isReference))
9937 return setResult(res);
9939 // Construction from an equivalent other array?
9940 // Only lower with lvalue RHS elements; let the glue layer move rvalue elements.
9941 Type t2b = ae.e2.type.toBasetype();
9942 // skip over a (possibly implicit) cast of a static array RHS to a slice
9943 Expression rhs = ae.e2;
9945 if (t2b.ty == Tarray)
9947 if (auto ce = rhs.isCastExp())
9949 auto ct = ce.e1.type.toBasetype();
9950 if (ct.ty == Tsarray)
9957 const lowerToArrayCtor =
9958 ( (rhsType.ty == Tarray && !rhs.isArrayLiteralExp) ||
9959 (rhsType.ty == Tsarray && rhs.isLvalue) ) &&
9960 t1e.equivalent(t2b.nextOf);
9962 // Construction from a single element?
9963 // If the RHS is an rvalue, then we'll need to make a temporary for it (copied multiple times).
9964 const lowerToArraySetCtor = !lowerToArrayCtor && t1e.equivalent(t2b);
9966 if (lowerToArrayCtor || lowerToArraySetCtor)
9968 auto func = lowerToArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
9969 const other = lowerToArrayCtor ? "other array" : "value";
9970 if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
9973 // Lower to object._d_array{,set}ctor(e1, e2)
9974 Expression id = new IdentifierExp(exp.loc, Id.empty);
9975 id = new DotIdExp(exp.loc, id, Id.object);
9976 id = new DotIdExp(exp.loc, id, func);
9978 auto arguments = new Expressions();
9979 arguments.push(new CastExp(ae.loc, ae.e1, t1e.arrayOf).expressionSemantic(sc));
9980 if (lowerToArrayCtor)
9982 arguments.push(new CastExp(ae.loc, rhs, t2b.nextOf.arrayOf).expressionSemantic(sc));
9983 Expression ce = new CallExp(exp.loc, id, arguments);
9984 res = ce.expressionSemantic(sc);
9989 // promote an rvalue RHS element to a temporary, it's passed by ref to _d_arraysetctor
9990 if (!ae.e2.isLvalue)
9992 auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
9993 e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
9994 arguments.push(new VarExp(vd.loc, vd).expressionSemantic(sc));
9997 arguments.push(ae.e2);
9999 Expression ce = new CallExp(exp.loc, id, arguments);
10000 res = Expression.combine(e0, ce).expressionSemantic(sc);
10003 if (global.params.verbose)
10004 message("lowered %s =>\n %s", exp.toChars(), res.toChars());
10007 else if (auto ae = res.isAssignExp())
10008 res = lowerArrayAssign(ae);
10009 else if (auto ce = res.isCommaExp())
10011 if (auto ae1 = ce.e1.isAssignExp())
10012 ce.e1 = lowerArrayAssign(ae1, true);
10013 if (auto ae2 = ce.e2.isAssignExp())
10014 ce.e2 = lowerArrayAssign(ae2, true);
10017 return setResult(res);
10020 /***************************************
10021 * Lower AssignExp to `_d_array{setassign,assign_l,assign_r}` if needed.
10024 * ae = the AssignExp to be lowered
10025 * fromCommaExp = indicates whether `ae` is part of a CommaExp or not,
10026 * so no unnecessary temporay variable is created.
10028 * a CommaExp contiaining call a to `_d_array{setassign,assign_l,assign_r}`
10029 * if needed or `ae` otherwise
10031 private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false)
10033 Type t1b = ae.e1.type.toBasetype();
10034 if (t1b.ty != Tsarray && t1b.ty != Tarray)
10037 const isArrayAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
10038 (ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) &&
10039 (ae.e1.type.nextOf() && ae.e2.type.nextOf() && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf()));
10041 const isArraySetAssign = (ae.e1.isSliceExp() || ae.e1.type.ty == Tsarray) &&
10042 (ae.e1.type.nextOf() && ae.e2.type.implicitConvTo(ae.e1.type.nextOf()));
10044 if (!isArrayAssign && !isArraySetAssign)
10047 const ts = t1b.nextOf().baseElemOf().isTypeStruct();
10048 if (!ts || (!ts.sym.postblit && !ts.sym.dtor))
10052 Identifier func = isArraySetAssign ? Id._d_arraysetassign :
10053 ae.e2.isLvalue() || ae.e2.isSliceExp() ? Id._d_arrayassign_l : Id._d_arrayassign_r;
10055 // Lower to `.object._d_array{setassign,assign_l,assign_r}(e1, e2)``
10056 Expression id = new IdentifierExp(ae.loc, Id.empty);
10057 id = new DotIdExp(ae.loc, id, Id.object);
10058 id = new DotIdExp(ae.loc, id, func);
10060 auto arguments = new Expressions();
10061 arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf)
10062 .expressionSemantic(sc));
10064 Expression eValue2, value2 = ae.e2;
10065 if (isArrayAssign && value2.isLvalue())
10066 value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf())
10067 .expressionSemantic(sc);
10068 else if (!fromCommaExp &&
10069 (isArrayAssign || (isArraySetAssign && !value2.isLvalue())))
10071 // Rvalues from CommaExps were introduced in `visit(AssignExp)`
10072 // and are temporary variables themselves. Rvalues from trivial
10073 // SliceExps are simply passed by reference without any copying.
10075 // `__assigntmp` will be destroyed together with the array `ae.e1`.
10076 // When `ae.e2` is a variadic arg array, it is also `scope`, so
10077 // `__assigntmp` may also be scope.
10078 StorageClass stc = STC.nodtor;
10080 stc |= STC.rvalue | STC.scope_;
10082 auto vd = copyToTemp(stc, "__assigntmp", ae.e2);
10083 eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
10084 value2 = new VarExp(vd.loc, vd).expressionSemantic(sc);
10086 arguments.push(value2);
10088 Expression ce = new CallExp(ae.loc, id, arguments);
10089 res = Expression.combine(eValue2, ce).expressionSemantic(sc);
10091 res = Expression.combine(res, ae.e1).expressionSemantic(sc);
10093 if (global.params.verbose)
10094 message("lowered %s =>\n %s", ae.toChars(), res.toChars());
10099 override void visit(PowAssignExp exp)
10107 Expression e = exp.op_overload(sc);
10114 if (exp.e1.checkReadModifyWrite(exp.op, exp.e2))
10117 assert(exp.e1.type && exp.e2.type);
10118 if (exp.e1.op == EXP.slice || exp.e1.type.ty == Tarray || exp.e1.type.ty == Tsarray)
10120 if (checkNonAssignmentArrayOp(exp.e1))
10124 if (exp.e2.implicitConvTo(exp.e1.type.nextOf()))
10127 exp.e2 = exp.e2.castTo(sc, exp.e1.type.nextOf());
10129 else if (Expression ex = typeCombine(exp, sc))
10135 // Check element types are arithmetic
10136 Type tb1 = exp.e1.type.nextOf().toBasetype();
10137 Type tb2 = exp.e2.type.toBasetype();
10138 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10139 tb2 = tb2.nextOf().toBasetype();
10140 if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
10142 exp.type = exp.e1.type;
10143 result = arrayOp(exp, sc);
10149 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10152 if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating()))
10154 Expression e0 = null;
10155 e = exp.reorderSettingAAElem(sc);
10156 e = Expression.extractLast(e, e0);
10159 if (exp.e1.op == EXP.variable)
10161 // Rewrite: e1 = e1 ^^ e2
10162 e = new PowExp(exp.loc, exp.e1.syntaxCopy(), exp.e2);
10163 e = new AssignExp(exp.loc, exp.e1, e);
10167 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
10168 auto v = copyToTemp(STC.ref_, "__powtmp", exp.e1);
10169 auto de = new DeclarationExp(exp.e1.loc, v);
10170 auto ve = new VarExp(exp.e1.loc, v);
10171 e = new PowExp(exp.loc, ve, exp.e2);
10172 e = new AssignExp(exp.loc, new VarExp(exp.e1.loc, v), e);
10173 e = new CommaExp(exp.loc, de, e);
10175 e = Expression.combine(e0, e);
10176 e = e.expressionSemantic(sc);
10180 result = exp.incompatibleTypes();
10183 override void visit(CatAssignExp exp)
10191 //printf("CatAssignExp::semantic() %s\n", exp.toChars());
10192 Expression e = exp.op_overload(sc);
10199 if (SliceExp se = exp.e1.isSliceExp())
10201 if (se.e1.type.toBasetype().ty == Tsarray)
10203 exp.error("cannot append to static array `%s`", se.e1.type.toChars());
10208 exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1);
10209 if (exp.e1.op == EXP.error)
10214 if (exp.e2.op == EXP.error)
10220 if (checkNonAssignmentArrayOp(exp.e2))
10223 Type tb1 = exp.e1.type.toBasetype();
10224 Type tb1next = tb1.nextOf();
10225 Type tb2 = exp.e2.type.toBasetype();
10228 * EXP.concatenateAssign: appending T[] to T[]
10229 * EXP.concatenateElemAssign: appending T to T[]
10230 * EXP.concatenateDcharAssign: appending dchar to T[]
10232 if ((tb1.ty == Tarray) &&
10233 (tb2.ty == Tarray || tb2.ty == Tsarray) &&
10234 (exp.e2.implicitConvTo(exp.e1.type) ||
10235 (tb2.nextOf().implicitConvTo(tb1next) &&
10236 (tb2.nextOf().size(Loc.initial) == tb1next.size(Loc.initial)))))
10238 // EXP.concatenateAssign
10239 assert(exp.op == EXP.concatenateAssign);
10240 if (exp.e1.checkPostblit(sc, tb1next))
10243 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
10245 else if ((tb1.ty == Tarray) && exp.e2.implicitConvTo(tb1next))
10247 /* https://issues.dlang.org/show_bug.cgi?id=19782
10249 * If e2 is implicitly convertible to tb1next, the conversion
10250 * might be done through alias this, in which case, e2 needs to
10251 * be modified accordingly (e2 => e2.aliasthis).
10253 if (tb2.ty == Tstruct && (cast(TypeStruct)tb2).implicitConvToThroughAliasThis(tb1next))
10255 if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next))
10258 if (exp.e2.checkPostblit(sc, tb2))
10261 if (checkNewEscape(sc, exp.e2, false))
10264 exp = new CatElemAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, tb1next));
10265 exp.e2 = doCopyOrMove(sc, exp.e2);
10267 else if (tb1.ty == Tarray &&
10268 (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
10269 exp.e2.type.ty != tb1next.ty &&
10270 exp.e2.implicitConvTo(Type.tdchar))
10272 // Append dchar to char[] or wchar[]
10273 exp = new CatDcharAssignExp(exp.loc, exp.type, exp.e1, exp.e2.castTo(sc, Type.tdchar));
10275 /* Do not allow appending wchar to char[] because if wchar happens
10276 * to be a surrogate pair, nothing good can result.
10281 // Try alias this on first operand
10282 static Expression tryAliasThisForLhs(BinAssignExp exp, Scope* sc)
10284 AggregateDeclaration ad1 = isAggregate(exp.e1.type);
10285 if (!ad1 || !ad1.aliasthis)
10288 /* Rewrite (e1 op e2) as:
10289 * (e1.aliasthis op e2)
10291 if (isRecursiveAliasThis(exp.att1, exp.e1.type))
10293 //printf("att %s e1 = %s\n", Token.toChars(e.op), e.e1.type.toChars());
10294 Expression e1 = new DotIdExp(exp.loc, exp.e1, ad1.aliasthis.ident);
10295 BinExp be = cast(BinExp)exp.copy();
10297 return be.trySemantic(sc);
10300 // Try alias this on second operand
10301 static Expression tryAliasThisForRhs(BinAssignExp exp, Scope* sc)
10303 AggregateDeclaration ad2 = isAggregate(exp.e2.type);
10304 if (!ad2 || !ad2.aliasthis)
10306 /* Rewrite (e1 op e2) as:
10307 * (e1 op e2.aliasthis)
10309 if (isRecursiveAliasThis(exp.att2, exp.e2.type))
10311 //printf("att %s e2 = %s\n", Token.toChars(e.op), e.e2.type.toChars());
10312 Expression e2 = new DotIdExp(exp.loc, exp.e2, ad2.aliasthis.ident);
10313 BinExp be = cast(BinExp)exp.copy();
10315 return be.trySemantic(sc);
10319 result = tryAliasThisForLhs(exp, sc);
10323 result = tryAliasThisForRhs(exp, sc);
10327 exp.error("cannot append type `%s` to type `%s`", tb2.toChars(), tb1.toChars());
10331 if (exp.e2.checkValue() || exp.e2.checkSharedAccess(sc))
10334 exp.type = exp.e1.type;
10335 auto assignElem = exp.e2;
10336 auto res = exp.reorderSettingAAElem(sc);
10337 if (res != exp) // `AA[k] = v` rewrite was performed
10338 checkNewEscape(sc, assignElem, false);
10339 else if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
10340 checkAssignEscape(sc, res, false, false);
10344 if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
10345 !(sc.flags & (SCOPE.ctfe | SCOPE.compile)))
10347 // if aa ordering is triggered, `res` will be a CommaExp
10348 // and `.e2` will be the rewritten original expression.
10350 // `output` will point to the expression that the lowering will overwrite
10351 Expression* output;
10352 if (auto comma = res.isCommaExp())
10354 output = &comma.e2;
10355 // manual cast because it could be either CatAssignExp or CatElemAssignExp
10356 exp = cast(CatAssignExp)comma.e2;
10361 exp = cast(CatAssignExp)result;
10364 if (exp.op == EXP.concatenateAssign)
10366 Identifier hook = global.params.tracegc ? Id._d_arrayappendTTrace : Id._d_arrayappendT;
10368 if (!verifyHookExist(exp.loc, *sc, hook, "appending array to arrays", Id.object))
10371 // Lower to object._d_arrayappendT{,Trace}({file, line, funcname}, e1, e2)
10372 Expression id = new IdentifierExp(exp.loc, Id.empty);
10373 id = new DotIdExp(exp.loc, id, Id.object);
10374 id = new DotIdExp(exp.loc, id, hook);
10376 auto arguments = new Expressions();
10377 arguments.reserve(5);
10378 if (global.params.tracegc)
10380 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
10381 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
10382 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
10383 arguments.push(new StringExp(exp.loc, funcname.toDString()));
10386 arguments.push(exp.e1);
10387 arguments.push(exp.e2);
10388 Expression ce = new CallExp(exp.loc, id, arguments);
10389 *output = ce.expressionSemantic(sc);
10391 else if (exp.op == EXP.concatenateElemAssign)
10393 /* Do not lower concats to the indices array returned by
10394 *`static foreach`, as this array is only used at compile-time.
10396 if (auto ve = exp.e1.isVarExp)
10398 import core.stdc.ctype : isdigit;
10399 // The name of the indices array that static foreach loops uses.
10400 // See dmd.cond.lowerNonArrayAggregate
10401 enum varName = "__res";
10402 const(char)[] id = ve.var.ident.toString;
10403 if (ve.var.storage_class & STC.temp && id.length > varName.length &&
10404 id[0 .. varName.length] == varName && id[varName.length].isdigit)
10408 Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX;
10409 if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object))
10412 // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
10413 Expression id = new IdentifierExp(exp.loc, Id.empty);
10414 id = new DotIdExp(exp.loc, id, Id.object);
10415 auto tiargs = new Objects();
10416 tiargs.push(exp.e1.type);
10417 id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs);
10418 id = new DotIdExp(exp.loc, id, hook);
10420 auto arguments = new Expressions();
10421 arguments.reserve(5);
10422 if (global.params.tracegc)
10424 auto funcname = (sc.callsc && sc.callsc.func) ? sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars();
10425 arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString()));
10426 arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32));
10427 arguments.push(new StringExp(exp.loc, funcname.toDString()));
10430 Expression eValue1;
10431 Expression value1 = extractSideEffect(sc, "__appendtmp", eValue1, exp.e1);
10433 arguments.push(value1);
10434 arguments.push(new IntegerExp(exp.loc, 1, Type.tsize_t));
10436 Expression ce = new CallExp(exp.loc, id, arguments);
10438 Expression eValue2;
10439 Expression value2 = exp.e2;
10440 if (!value2.isVarExp() && !value2.isConst())
10442 /* Before the template hook, this check was performed in e2ir.d
10443 * for expressions like `a ~= a[$-1]`. Here, $ will be modified
10444 * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in
10445 * a temporary variable.
10447 value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true);
10450 // `__appendtmp*` will be destroyed together with the array `exp.e1`.
10451 auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
10452 vd.storage_class |= STC.nodtor;
10453 // Be more explicit that this "declaration" is local to the expression
10454 vd.storage_class |= STC.exptemp;
10457 auto ale = new ArrayLengthExp(exp.loc, value1);
10458 auto elem = new IndexExp(exp.loc, value1, new MinExp(exp.loc, ale, IntegerExp.literal!1));
10459 auto ae = new ConstructExp(exp.loc, elem, value2);
10461 auto e0 = Expression.combine(ce, ae).expressionSemantic(sc);
10462 e0 = Expression.combine(e0, value1);
10463 e0 = Expression.combine(eValue1, e0);
10465 e0 = Expression.combine(eValue2, e0);
10467 *output = e0.expressionSemantic(sc);
10473 override void visit(AddExp exp)
10475 static if (LOGSEMANTIC)
10477 printf("AddExp::semantic('%s')\n", exp.toChars());
10485 if (Expression ex = binSemanticProp(exp, sc))
10490 Expression e = exp.op_overload(sc);
10497 /* ImportC: convert arrays to pointers, functions to pointers to functions
10499 exp.e1 = exp.e1.arrayFuncConv(sc);
10500 exp.e2 = exp.e2.arrayFuncConv(sc);
10502 Type tb1 = exp.e1.type.toBasetype();
10503 Type tb2 = exp.e2.type.toBasetype();
10506 if (tb1.ty == Tdelegate || tb1.isPtrToFunction())
10508 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10510 if (tb2.ty == Tdelegate || tb2.isPtrToFunction())
10512 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10517 if (tb1.ty == Tpointer && exp.e2.type.isintegral() || tb2.ty == Tpointer && exp.e1.type.isintegral())
10519 result = scaleFactor(exp, sc);
10523 if (tb1.ty == Tpointer && tb2.ty == Tpointer)
10525 result = exp.incompatibleTypes();
10529 if (Expression ex = typeCombine(exp, sc))
10535 Type tb = exp.type.toBasetype();
10536 if (tb.ty == Tarray || tb.ty == Tsarray)
10538 if (!isArrayOpValid(exp))
10540 result = arrayOpInvalidError(exp);
10547 tb1 = exp.e1.type.toBasetype();
10548 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
10550 result = exp.incompatibleTypes();
10553 if ((tb1.isreal() && exp.e2.type.isimaginary()) || (tb1.isimaginary() && exp.e2.type.isreal()))
10555 switch (exp.type.toBasetype().ty)
10559 exp.type = Type.tcomplex32;
10564 exp.type = Type.tcomplex64;
10569 exp.type = Type.tcomplex80;
10579 override void visit(MinExp exp)
10581 static if (LOGSEMANTIC)
10583 printf("MinExp::semantic('%s')\n", exp.toChars());
10591 if (Expression ex = binSemanticProp(exp, sc))
10596 Expression e = exp.op_overload(sc);
10603 /* ImportC: convert arrays to pointers, functions to pointers to functions
10605 exp.e1 = exp.e1.arrayFuncConv(sc);
10606 exp.e2 = exp.e2.arrayFuncConv(sc);
10608 Type t1 = exp.e1.type.toBasetype();
10609 Type t2 = exp.e2.type.toBasetype();
10612 if (t1.ty == Tdelegate || t1.isPtrToFunction())
10614 err |= exp.e1.checkArithmetic() || exp.e1.checkSharedAccess(sc);
10616 if (t2.ty == Tdelegate || t2.isPtrToFunction())
10618 err |= exp.e2.checkArithmetic() || exp.e2.checkSharedAccess(sc);
10623 if (t1.ty == Tpointer)
10625 if (t2.ty == Tpointer)
10627 // https://dlang.org/spec/expression.html#add_expressions
10628 // "If both operands are pointers, and the operator is -, the pointers are
10629 // subtracted and the result is divided by the size of the type pointed to
10630 // by the operands. It is an error if the pointers point to different types."
10631 Type p1 = t1.nextOf();
10632 Type p2 = t2.nextOf();
10634 if (!p1.equivalent(p2))
10636 // Deprecation to remain for at least a year, after which this should be
10637 // changed to an error
10638 // See https://github.com/dlang/dmd/pull/7332
10639 deprecation(exp.loc,
10640 "cannot subtract pointers to different types: `%s` and `%s`.",
10641 t1.toChars(), t2.toChars());
10644 // Need to divide the result by the stride
10645 // Replace (ptr - ptr) with (ptr - ptr) / stride
10648 // make sure pointer types are compatible
10649 if (Expression ex = typeCombine(exp, sc))
10655 exp.type = Type.tptrdiff_t;
10656 stride = t2.nextOf().size();
10659 e = new IntegerExp(exp.loc, 0, Type.tptrdiff_t);
10661 else if (stride == cast(long)SIZE_INVALID)
10662 e = ErrorExp.get();
10665 e = new DivExp(exp.loc, exp, new IntegerExp(Loc.initial, stride, Type.tptrdiff_t));
10666 e.type = Type.tptrdiff_t;
10669 else if (t2.isintegral())
10670 e = scaleFactor(exp, sc);
10673 exp.error("can't subtract `%s` from pointer", t2.toChars());
10674 e = ErrorExp.get();
10679 if (t2.ty == Tpointer)
10681 exp.type = exp.e2.type;
10682 exp.error("can't subtract pointer from `%s`", exp.e1.type.toChars());
10686 if (Expression ex = typeCombine(exp, sc))
10692 Type tb = exp.type.toBasetype();
10693 if (tb.ty == Tarray || tb.ty == Tsarray)
10695 if (!isArrayOpValid(exp))
10697 result = arrayOpInvalidError(exp);
10704 t1 = exp.e1.type.toBasetype();
10705 t2 = exp.e2.type.toBasetype();
10706 if (!target.isVectorOpSupported(t1, exp.op, t2))
10708 result = exp.incompatibleTypes();
10711 if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
10713 switch (exp.type.ty)
10717 exp.type = Type.tcomplex32;
10722 exp.type = Type.tcomplex64;
10727 exp.type = Type.tcomplex80;
10738 override void visit(CatExp exp)
10740 // https://dlang.org/spec/expression.html#cat_expressions
10741 //printf("CatExp.semantic() %s\n", toChars());
10748 if (Expression ex = binSemanticProp(exp, sc))
10753 Expression e = exp.op_overload(sc);
10760 Type tb1 = exp.e1.type.toBasetype();
10761 Type tb2 = exp.e2.type.toBasetype();
10763 auto f1 = checkNonAssignmentArrayOp(exp.e1);
10764 auto f2 = checkNonAssignmentArrayOp(exp.e2);
10768 Type tb1next = tb1.nextOf();
10769 Type tb2next = tb2.nextOf();
10771 // Check for: array ~ array
10772 if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCH.constant || tb2next.implicitConvTo(tb1next) >= MATCH.constant || exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2) || exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1)))
10774 /* https://issues.dlang.org/show_bug.cgi?id=9248
10775 * Here to avoid the case of:
10776 * void*[] a = [cast(void*)1];
10777 * void*[] b = [cast(void*)2];
10780 * a ~ [cast(void*)b];
10783 /* https://issues.dlang.org/show_bug.cgi?id=14682
10784 * Also to avoid the case of:
10788 * a ~ cast(int[])[];
10793 // Check for: array ~ element
10794 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
10796 if (exp.e1.op == EXP.arrayLiteral)
10798 exp.e2 = doCopyOrMove(sc, exp.e2);
10799 // https://issues.dlang.org/show_bug.cgi?id=14686
10800 // Postblit call appears in AST, and this is
10801 // finally translated to an ArrayLiteralExp in below optimize().
10803 else if (exp.e1.op == EXP.string_)
10805 // No postblit call exists on character (integer) value.
10809 if (exp.e2.checkPostblit(sc, tb2))
10811 // Postblit call will be done in runtime helper function
10814 if (exp.e1.op == EXP.arrayLiteral && exp.e1.implicitConvTo(tb2.arrayOf()))
10816 exp.e1 = exp.e1.implicitCastTo(sc, tb2.arrayOf());
10817 exp.type = tb2.arrayOf();
10820 if (exp.e2.implicitConvTo(tb1next) >= MATCH.convert)
10822 exp.e2 = exp.e2.implicitCastTo(sc, tb1next);
10823 exp.type = tb1next.arrayOf();
10825 if (tb2.ty == Tarray || tb2.ty == Tsarray)
10827 // Make e2 into [e2]
10828 exp.e2 = new ArrayLiteralExp(exp.e2.loc, exp.type, exp.e2);
10830 else if (checkNewEscape(sc, exp.e2, false))
10832 result = exp.optimize(WANTvalue);
10836 // Check for: element ~ array
10837 if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
10839 if (exp.e2.op == EXP.arrayLiteral)
10841 exp.e1 = doCopyOrMove(sc, exp.e1);
10843 else if (exp.e2.op == EXP.string_)
10848 if (exp.e1.checkPostblit(sc, tb1))
10852 if (exp.e2.op == EXP.arrayLiteral && exp.e2.implicitConvTo(tb1.arrayOf()))
10854 exp.e2 = exp.e2.implicitCastTo(sc, tb1.arrayOf());
10855 exp.type = tb1.arrayOf();
10858 if (exp.e1.implicitConvTo(tb2next) >= MATCH.convert)
10860 exp.e1 = exp.e1.implicitCastTo(sc, tb2next);
10861 exp.type = tb2next.arrayOf();
10863 if (tb1.ty == Tarray || tb1.ty == Tsarray)
10865 // Make e1 into [e1]
10866 exp.e1 = new ArrayLiteralExp(exp.e1.loc, exp.type, exp.e1);
10868 else if (checkNewEscape(sc, exp.e1, false))
10870 result = exp.optimize(WANTvalue);
10876 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
10878 Type t1 = tb1next.mutableOf().constOf().arrayOf();
10879 Type t2 = tb2next.mutableOf().constOf().arrayOf();
10880 if (exp.e1.op == EXP.string_ && !(cast(StringExp)exp.e1).committed)
10883 exp.e1 = exp.e1.castTo(sc, t1);
10884 if (exp.e2.op == EXP.string_ && !(cast(StringExp)exp.e2).committed)
10887 exp.e2 = exp.e2.castTo(sc, t2);
10890 if (Expression ex = typeCombine(exp, sc))
10895 exp.type = exp.type.toHeadMutable();
10897 Type tb = exp.type.toBasetype();
10898 if (tb.ty == Tsarray)
10899 exp.type = tb.nextOf().arrayOf();
10900 if (exp.type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
10902 exp.type = exp.type.nextOf().toHeadMutable().arrayOf();
10904 if (Type tbn = tb.nextOf())
10906 if (exp.checkPostblit(sc, tbn))
10909 Type t1 = exp.e1.type.toBasetype();
10910 Type t2 = exp.e2.type.toBasetype();
10911 if ((t1.ty == Tarray || t1.ty == Tsarray) &&
10912 (t2.ty == Tarray || t2.ty == Tsarray))
10914 // Normalize to ArrayLiteralExp or StringExp as far as possible
10915 e = exp.optimize(WANTvalue);
10919 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
10920 result = exp.incompatibleTypes();
10927 override void visit(MulExp exp)
10931 printf("MulExp::semantic() %s\n", exp.toChars());
10939 if (Expression ex = binSemanticProp(exp, sc))
10944 Expression e = exp.op_overload(sc);
10951 if (Expression ex = typeCombine(exp, sc))
10957 Type tb = exp.type.toBasetype();
10958 if (tb.ty == Tarray || tb.ty == Tsarray)
10960 if (!isArrayOpValid(exp))
10962 result = arrayOpInvalidError(exp);
10969 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
10972 if (exp.type.isfloating())
10974 Type t1 = exp.e1.type;
10975 Type t2 = exp.e2.type;
10981 else if (t2.isreal())
10985 else if (t1.isimaginary())
10987 if (t2.isimaginary())
10989 switch (t1.toBasetype().ty)
10992 exp.type = Type.tfloat32;
10996 exp.type = Type.tfloat64;
11000 exp.type = Type.tfloat80;
11008 exp.e1.type = exp.type;
11009 exp.e2.type = exp.type;
11010 e = new NegExp(exp.loc, exp);
11011 e = e.expressionSemantic(sc);
11016 exp.type = t2; // t2 is complex
11018 else if (t2.isimaginary())
11020 exp.type = t1; // t1 is complex
11023 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11025 result = exp.incompatibleTypes();
11031 override void visit(DivExp exp)
11039 if (Expression ex = binSemanticProp(exp, sc))
11044 Expression e = exp.op_overload(sc);
11051 if (Expression ex = typeCombine(exp, sc))
11057 Type tb = exp.type.toBasetype();
11058 if (tb.ty == Tarray || tb.ty == Tsarray)
11060 if (!isArrayOpValid(exp))
11062 result = arrayOpInvalidError(exp);
11069 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11072 if (exp.type.isfloating())
11074 Type t1 = exp.e1.type;
11075 Type t2 = exp.e2.type;
11080 if (t2.isimaginary())
11084 e = new NegExp(exp.loc, exp);
11085 e = e.expressionSemantic(sc);
11090 else if (t2.isreal())
11094 else if (t1.isimaginary())
11096 if (t2.isimaginary())
11098 switch (t1.toBasetype().ty)
11101 exp.type = Type.tfloat32;
11105 exp.type = Type.tfloat64;
11109 exp.type = Type.tfloat80;
11117 exp.type = t2; // t2 is complex
11119 else if (t2.isimaginary())
11121 exp.type = t1; // t1 is complex
11124 else if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11126 result = exp.incompatibleTypes();
11132 override void visit(ModExp exp)
11140 if (Expression ex = binSemanticProp(exp, sc))
11145 Expression e = exp.op_overload(sc);
11152 if (Expression ex = typeCombine(exp, sc))
11158 Type tb = exp.type.toBasetype();
11159 if (tb.ty == Tarray || tb.ty == Tsarray)
11161 if (!isArrayOpValid(exp))
11163 result = arrayOpInvalidError(exp);
11169 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11171 result = exp.incompatibleTypes();
11175 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11178 if (exp.type.isfloating())
11180 exp.type = exp.e1.type;
11181 if (exp.e2.type.iscomplex())
11183 exp.error("cannot perform modulo complex arithmetic");
11190 override void visit(PowExp exp)
11198 //printf("PowExp::semantic() %s\n", toChars());
11199 if (Expression ex = binSemanticProp(exp, sc))
11204 Expression e = exp.op_overload(sc);
11211 if (Expression ex = typeCombine(exp, sc))
11217 Type tb = exp.type.toBasetype();
11218 if (tb.ty == Tarray || tb.ty == Tsarray)
11220 if (!isArrayOpValid(exp))
11222 result = arrayOpInvalidError(exp);
11229 if (exp.checkArithmeticBin() || exp.checkSharedAccessBin(sc))
11232 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11234 result = exp.incompatibleTypes();
11238 // First, attempt to fold the expression.
11239 e = exp.optimize(WANTvalue);
11240 if (e.op != EXP.pow)
11242 e = e.expressionSemantic(sc);
11247 Module mmath = Module.loadStdMath();
11250 e.error("`%s` requires `std.math` for `^^` operators", e.toChars());
11253 e = new ScopeExp(exp.loc, mmath);
11255 if (exp.e2.op == EXP.float64 && exp.e2.toReal() == CTFloat.half)
11257 // Replace e1 ^^ 0.5 with .std.math.sqrt(e1)
11258 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._sqrt), exp.e1);
11262 // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
11263 e = new CallExp(exp.loc, new DotIdExp(exp.loc, e, Id._pow), exp.e1, exp.e2);
11265 e = e.expressionSemantic(sc);
11270 override void visit(ShlExp exp)
11272 //printf("ShlExp::semantic(), type = %p\n", type);
11279 if (Expression ex = binSemanticProp(exp, sc))
11284 Expression e = exp.op_overload(sc);
11291 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11294 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11296 result = exp.incompatibleTypes();
11299 exp.e1 = integralPromotions(exp.e1, sc);
11300 if (exp.e2.type.toBasetype().ty != Tvector)
11301 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11303 exp.type = exp.e1.type;
11307 override void visit(ShrExp exp)
11315 if (Expression ex = binSemanticProp(exp, sc))
11320 Expression e = exp.op_overload(sc);
11327 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11330 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11332 result = exp.incompatibleTypes();
11335 exp.e1 = integralPromotions(exp.e1, sc);
11336 if (exp.e2.type.toBasetype().ty != Tvector)
11337 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11339 exp.type = exp.e1.type;
11343 override void visit(UshrExp exp)
11351 if (Expression ex = binSemanticProp(exp, sc))
11356 Expression e = exp.op_overload(sc);
11363 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11366 if (!target.isVectorOpSupported(exp.e1.type.toBasetype(), exp.op, exp.e2.type.toBasetype()))
11368 result = exp.incompatibleTypes();
11371 exp.e1 = integralPromotions(exp.e1, sc);
11372 if (exp.e2.type.toBasetype().ty != Tvector)
11373 exp.e2 = exp.e2.castTo(sc, Type.tshiftcnt);
11375 exp.type = exp.e1.type;
11379 override void visit(AndExp exp)
11387 if (Expression ex = binSemanticProp(exp, sc))
11392 Expression e = exp.op_overload(sc);
11399 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11401 exp.type = exp.e1.type;
11406 if (Expression ex = typeCombine(exp, sc))
11412 Type tb = exp.type.toBasetype();
11413 if (tb.ty == Tarray || tb.ty == Tsarray)
11415 if (!isArrayOpValid(exp))
11417 result = arrayOpInvalidError(exp);
11423 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11425 result = exp.incompatibleTypes();
11428 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11434 override void visit(OrExp exp)
11442 if (Expression ex = binSemanticProp(exp, sc))
11447 Expression e = exp.op_overload(sc);
11454 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11456 exp.type = exp.e1.type;
11461 if (Expression ex = typeCombine(exp, sc))
11467 Type tb = exp.type.toBasetype();
11468 if (tb.ty == Tarray || tb.ty == Tsarray)
11470 if (!isArrayOpValid(exp))
11472 result = arrayOpInvalidError(exp);
11478 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11480 result = exp.incompatibleTypes();
11483 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11489 override void visit(XorExp exp)
11497 if (Expression ex = binSemanticProp(exp, sc))
11502 Expression e = exp.op_overload(sc);
11509 if (exp.e1.type.toBasetype().ty == Tbool && exp.e2.type.toBasetype().ty == Tbool)
11511 exp.type = exp.e1.type;
11516 if (Expression ex = typeCombine(exp, sc))
11522 Type tb = exp.type.toBasetype();
11523 if (tb.ty == Tarray || tb.ty == Tsarray)
11525 if (!isArrayOpValid(exp))
11527 result = arrayOpInvalidError(exp);
11533 if (!target.isVectorOpSupported(tb, exp.op, exp.e2.type.toBasetype()))
11535 result = exp.incompatibleTypes();
11538 if (exp.checkIntegralBin() || exp.checkSharedAccessBin(sc))
11544 override void visit(LogicalExp exp)
11546 static if (LOGSEMANTIC)
11548 printf("LogicalExp::semantic() %s\n", exp.toChars());
11557 exp.setNoderefOperands();
11559 Expression e1x = exp.e1.expressionSemantic(sc);
11561 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11562 if (e1x.op == EXP.type)
11563 e1x = resolveAliasThis(sc, e1x);
11565 e1x = resolveProperties(sc, e1x);
11566 e1x = e1x.toBoolean(sc);
11568 if (sc.flags & SCOPE.condition)
11570 /* If in static if, don't evaluate e2 if we don't have to.
11572 e1x = e1x.optimize(WANTvalue);
11573 if (e1x.toBool().hasValue(exp.op == EXP.orOr))
11575 if (sc.flags & SCOPE.Cfile)
11576 result = new IntegerExp(exp.op == EXP.orOr);
11578 result = IntegerExp.createBool(exp.op == EXP.orOr);
11583 CtorFlow ctorflow = sc.ctorflow.clone();
11584 Expression e2x = exp.e2.expressionSemantic(sc);
11585 sc.merge(exp.loc, ctorflow);
11586 ctorflow.freeFieldinit();
11588 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
11589 if (e2x.op == EXP.type)
11590 e2x = resolveAliasThis(sc, e2x);
11592 e2x = resolveProperties(sc, e2x);
11594 auto f1 = checkNonAssignmentArrayOp(e1x);
11595 auto f2 = checkNonAssignmentArrayOp(e2x);
11599 // Unless the right operand is 'void', the expression is converted to 'bool'.
11600 if (e2x.type.ty != Tvoid)
11601 e2x = e2x.toBoolean(sc);
11603 if (e2x.op == EXP.type || e2x.op == EXP.scope_)
11605 exp.error("`%s` is not an expression", exp.e2.toChars());
11608 if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn)
11613 if (e2x.op == EXP.error)
11619 // The result type is 'bool', unless the right operand has type 'void'.
11620 if (e2x.type.ty == Tvoid)
11621 exp.type = Type.tvoid;
11623 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11631 override void visit(CmpExp exp)
11633 static if (LOGSEMANTIC)
11635 printf("CmpExp::semantic('%s')\n", exp.toChars());
11643 exp.setNoderefOperands();
11645 if (Expression ex = binSemanticProp(exp, sc))
11650 Type t1 = exp.e1.type.toBasetype();
11651 Type t2 = exp.e2.type.toBasetype();
11652 if (t1.ty == Tclass && exp.e2.op == EXP.null_ || t2.ty == Tclass && exp.e1.op == EXP.null_)
11654 exp.error("do not use `null` when comparing class types");
11659 EXP cmpop = exp.op;
11660 if (auto e = exp.op_overload(sc, &cmpop))
11662 if (!e.type.isscalar() && e.type.equals(exp.e1.type))
11664 exp.error("recursive `opCmp` expansion");
11667 if (e.op == EXP.call)
11670 if (t1.ty == Tclass && t2.ty == Tclass)
11672 // Lower to object.__cmp(e1, e2)
11673 Expression cl = new IdentifierExp(exp.loc, Id.empty);
11674 cl = new DotIdExp(exp.loc, cl, Id.object);
11675 cl = new DotIdExp(exp.loc, cl, Id.__cmp);
11676 cl = cl.expressionSemantic(sc);
11678 auto arguments = new Expressions();
11679 // Check if op_overload found a better match by calling e2.opCmp(e1)
11680 // If the operands were swapped, then the result must be reversed
11681 // e1.opCmp(e2) == -e2.opCmp(e1)
11682 // cmpop takes care of this
11683 if (exp.op == cmpop)
11685 arguments.push(exp.e1);
11686 arguments.push(exp.e2);
11690 // Use better match found by op_overload
11691 arguments.push(exp.e2);
11692 arguments.push(exp.e1);
11695 cl = new CallExp(exp.loc, cl, arguments);
11696 cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
11697 result = cl.expressionSemantic(sc);
11701 e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
11702 e = e.expressionSemantic(sc);
11709 if (Expression ex = typeCombine(exp, sc))
11715 auto f1 = checkNonAssignmentArrayOp(exp.e1);
11716 auto f2 = checkNonAssignmentArrayOp(exp.e2);
11720 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
11722 // Special handling for array comparisons
11723 Expression arrayLowering = null;
11724 t1 = exp.e1.type.toBasetype();
11725 t2 = exp.e2.type.toBasetype();
11726 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
11728 Type t1next = t1.nextOf();
11729 Type t2next = t2.nextOf();
11730 if (t1next.implicitConvTo(t2next) < MATCH.constant && t2next.implicitConvTo(t1next) < MATCH.constant && (t1next.ty != Tvoid && t2next.ty != Tvoid))
11732 exp.error("array comparison type mismatch, `%s` vs `%s`", t1next.toChars(), t2next.toChars());
11735 if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
11737 if (!verifyHookExist(exp.loc, *sc, Id.__cmp, "comparing arrays"))
11740 // Lower to object.__cmp(e1, e2)
11741 Expression al = new IdentifierExp(exp.loc, Id.empty);
11742 al = new DotIdExp(exp.loc, al, Id.object);
11743 al = new DotIdExp(exp.loc, al, Id.__cmp);
11744 al = al.expressionSemantic(sc);
11746 auto arguments = new Expressions(2);
11747 (*arguments)[0] = exp.e1;
11748 (*arguments)[1] = exp.e2;
11750 al = new CallExp(exp.loc, al, arguments);
11751 al = new CmpExp(exp.op, exp.loc, al, IntegerExp.literal!0);
11753 arrayLowering = al;
11756 else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
11758 if (t2.ty == Tstruct)
11759 exp.error("need member function `opCmp()` for %s `%s` to compare", t2.toDsymbol(sc).kind(), t2.toChars());
11761 exp.error("need member function `opCmp()` for %s `%s` to compare", t1.toDsymbol(sc).kind(), t1.toChars());
11764 else if (t1.iscomplex() || t2.iscomplex())
11766 exp.error("compare not defined for complex operands");
11769 else if (t1.ty == Taarray || t2.ty == Taarray)
11771 exp.error("`%s` is not defined for associative arrays", EXPtoString(exp.op).ptr);
11774 else if (!target.isVectorOpSupported(t1, exp.op, t2))
11776 result = exp.incompatibleTypes();
11781 bool r1 = exp.e1.checkValue() || exp.e1.checkSharedAccess(sc);
11782 bool r2 = exp.e2.checkValue() || exp.e2.checkSharedAccess(sc);
11787 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
11790 arrayLowering = arrayLowering.expressionSemantic(sc);
11791 result = arrayLowering;
11795 if (auto tv = t1.isTypeVector())
11796 exp.type = tv.toBooleanVector();
11802 override void visit(InExp exp)
11810 if (Expression ex = binSemanticProp(exp, sc))
11815 Expression e = exp.op_overload(sc);
11822 Type t2b = exp.e2.type.toBasetype();
11827 TypeAArray ta = cast(TypeAArray)t2b;
11829 // Special handling for array keys
11830 if (!arrayTypeCompatibleWithoutCasting(exp.e1.type, ta.index))
11832 // Convert key to type of key
11833 exp.e1 = exp.e1.implicitCastTo(sc, ta.index);
11836 semanticTypeInfo(sc, ta.index);
11838 // Return type is pointer to value
11839 exp.type = ta.nextOf().pointerTo();
11846 case Tarray, Tsarray:
11847 result = exp.incompatibleTypes();
11848 exp.errorSupplemental("`in` is only allowed on associative arrays");
11849 const(char)* slice = (t2b.ty == Tsarray) ? "[]" : "";
11850 exp.errorSupplemental("perhaps use `std.algorithm.find(%s, %s%s)` instead",
11851 exp.e1.toChars(), exp.e2.toChars(), slice);
11855 result = exp.incompatibleTypes();
11861 override void visit(RemoveExp e)
11863 if (Expression ex = binSemantic(e, sc))
11871 override void visit(EqualExp exp)
11873 //printf("EqualExp::semantic('%s')\n", exp.toChars());
11880 exp.setNoderefOperands();
11882 if (auto e = binSemanticProp(exp, sc))
11887 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
11889 /* https://issues.dlang.org/show_bug.cgi?id=12520
11890 * empty tuples are represented as types so special cases are added
11891 * so that they can be compared for equality with tuples of values.
11893 static auto extractTypeTupAndExpTup(Expression e)
11895 static struct Result { bool ttEmpty; bool te; }
11896 auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
11897 return Result(tt && (!tt.arguments || !tt.arguments.length), e.isTupleExp() !is null);
11899 auto tups1 = extractTypeTupAndExpTup(exp.e1);
11900 auto tups2 = extractTypeTupAndExpTup(exp.e2);
11901 // AliasSeq!() == AliasSeq!(<at least a value>)
11902 if (tups1.ttEmpty && tups2.te)
11904 result = IntegerExp.createBool(exp.op != EXP.equal);
11907 // AliasSeq!(<at least a value>) == AliasSeq!()
11908 else if (tups1.te && tups2.ttEmpty)
11910 result = IntegerExp.createBool(exp.op != EXP.equal);
11913 // AliasSeq!() == AliasSeq!()
11914 else if (tups1.ttEmpty && tups2.ttEmpty)
11916 result = IntegerExp.createBool(exp.op == EXP.equal);
11919 // otherwise, two types are really not comparable
11920 result = exp.incompatibleTypes();
11925 auto t1 = exp.e1.type;
11926 auto t2 = exp.e2.type;
11927 if (t1.ty == Tenum && t2.ty == Tenum && !t1.equivalent(t2))
11928 exp.error("comparison between different enumeration types `%s` and `%s`; If this behavior is intended consider using `std.conv.asOriginalType`",
11929 t1.toChars(), t2.toChars());
11932 /* Before checking for operator overloading, check to see if we're
11933 * comparing the addresses of two statics. If so, we can just see
11934 * if they are the same symbol.
11936 if (exp.e1.op == EXP.address && exp.e2.op == EXP.address)
11938 AddrExp ae1 = cast(AddrExp)exp.e1;
11939 AddrExp ae2 = cast(AddrExp)exp.e2;
11940 if (ae1.e1.op == EXP.variable && ae2.e1.op == EXP.variable)
11942 VarExp ve1 = cast(VarExp)ae1.e1;
11943 VarExp ve2 = cast(VarExp)ae2.e1;
11944 if (ve1.var == ve2.var)
11946 // They are the same, result is 'true' for ==, 'false' for !=
11947 result = IntegerExp.createBool(exp.op == EXP.equal);
11953 Type t1 = exp.e1.type.toBasetype();
11954 Type t2 = exp.e2.type.toBasetype();
11956 // Indicates whether the comparison of the 2 specified array types
11957 // requires an object.__equals() lowering.
11958 static bool needsDirectEq(Type t1, Type t2, Scope* sc)
11960 Type t1n = t1.nextOf().toBasetype();
11961 Type t2n = t2.nextOf().toBasetype();
11962 if ((t1n.ty.isSomeChar && t2n.ty.isSomeChar) ||
11963 (t1n.ty == Tvoid || t2n.ty == Tvoid))
11967 if (t1n.constOf() != t2n.constOf())
11971 while (t.toBasetype().nextOf())
11972 t = t.nextOf().toBasetype();
11973 if (auto ts = t.isTypeStruct())
11975 // semanticTypeInfo() makes sure hasIdentityEquals has been computed
11976 if (global.params.useTypeInfo && Type.dtypeinfo)
11977 semanticTypeInfo(sc, ts);
11979 return ts.sym.hasIdentityEquals; // has custom opEquals
11985 if (auto e = exp.op_overload(sc))
11992 const isArrayComparison = (t1.ty == Tarray || t1.ty == Tsarray) &&
11993 (t2.ty == Tarray || t2.ty == Tsarray);
11994 const needsArrayLowering = isArrayComparison && needsDirectEq(t1, t2, sc);
11996 if (!needsArrayLowering)
11998 if (auto e = typeCombine(exp, sc))
12005 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12006 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12010 exp.type = (sc && sc.flags & SCOPE.Cfile) ? Type.tint32 : Type.tbool;
12012 if (!isArrayComparison)
12014 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
12016 // Cast both to complex
12017 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
12018 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
12022 // lower some array comparisons to object.__equals(e1, e2)
12023 if (needsArrayLowering || (t1.ty == Tarray && t2.ty == Tarray))
12025 //printf("Lowering to __equals %s %s\n", exp.e1.toChars(), exp.e2.toChars());
12027 // https://issues.dlang.org/show_bug.cgi?id=22390
12028 // Equality comparison between array of noreturns simply lowers to length equality comparison
12029 if (t1.nextOf.isTypeNoreturn() && t2.nextOf.isTypeNoreturn())
12031 Expression exp_l1 = new DotIdExp(exp.e1.loc, exp.e1, Id.length);
12032 Expression exp_l2 = new DotIdExp(exp.e2.loc, exp.e2, Id.length);
12033 auto e = new EqualExp(EXP.equal, exp.loc, exp_l1, exp_l2);
12034 result = e.expressionSemantic(sc);
12038 if (!verifyHookExist(exp.loc, *sc, Id.__equals, "equal checks on arrays"))
12041 Expression __equals = new IdentifierExp(exp.loc, Id.empty);
12042 Identifier id = Identifier.idPool("__equals");
12043 __equals = new DotIdExp(exp.loc, __equals, Id.object);
12044 __equals = new DotIdExp(exp.loc, __equals, id);
12046 auto arguments = new Expressions(2);
12047 (*arguments)[0] = exp.e1;
12048 (*arguments)[1] = exp.e2;
12050 __equals = new CallExp(exp.loc, __equals, arguments);
12051 if (exp.op == EXP.notEqual)
12053 __equals = new NotExp(exp.loc, __equals);
12055 __equals = __equals.trySemantic(sc); // for better error message
12058 exp.error("incompatible types for array comparison: `%s` and `%s`",
12059 exp.e1.type.toChars(), exp.e2.type.toChars());
12060 __equals = ErrorExp.get();
12067 if (exp.e1.type.toBasetype().ty == Taarray)
12068 semanticTypeInfo(sc, exp.e1.type.toBasetype());
12071 if (!target.isVectorOpSupported(t1, exp.op, t2))
12073 result = exp.incompatibleTypes();
12077 if (auto tv = t1.isTypeVector())
12078 exp.type = tv.toBooleanVector();
12083 override void visit(IdentityExp exp)
12091 exp.setNoderefOperands();
12093 if (auto e = binSemanticProp(exp, sc))
12099 if (auto e = typeCombine(exp, sc))
12105 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12106 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12110 if (exp.e1.op == EXP.type || exp.e2.op == EXP.type)
12112 result = exp.incompatibleTypes();
12116 exp.type = Type.tbool;
12118 if (exp.e1.type != exp.e2.type && exp.e1.type.isfloating() && exp.e2.type.isfloating())
12120 // Cast both to complex
12121 exp.e1 = exp.e1.castTo(sc, Type.tcomplex80);
12122 exp.e2 = exp.e2.castTo(sc, Type.tcomplex80);
12125 auto tb1 = exp.e1.type.toBasetype();
12126 auto tb2 = exp.e2.type.toBasetype();
12127 if (!target.isVectorOpSupported(tb1, exp.op, tb2))
12129 result = exp.incompatibleTypes();
12133 if (exp.e1.op == EXP.call)
12134 exp.e1 = (cast(CallExp)exp.e1).addDtorHook(sc);
12135 if (exp.e2.op == EXP.call)
12136 exp.e2 = (cast(CallExp)exp.e2).addDtorHook(sc);
12138 if (exp.e1.type.toBasetype().ty == Tsarray ||
12139 exp.e2.type.toBasetype().ty == Tsarray)
12140 exp.deprecation("identity comparison of static arrays "
12141 ~ "implicitly coerces them to slices, "
12142 ~ "which are compared by reference");
12147 override void visit(CondExp exp)
12149 static if (LOGSEMANTIC)
12151 printf("CondExp::semantic('%s')\n", exp.toChars());
12159 if (auto die = exp.econd.isDotIdExp())
12160 die.noderef = true;
12162 Expression ec = exp.econd.expressionSemantic(sc);
12163 ec = resolveProperties(sc, ec);
12164 ec = ec.toBoolean(sc);
12166 CtorFlow ctorflow_root = sc.ctorflow.clone();
12167 Expression e1x = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
12168 e1x = resolveProperties(sc, e1x);
12170 CtorFlow ctorflow1 = sc.ctorflow;
12171 sc.ctorflow = ctorflow_root;
12172 Expression e2x = exp.e2.expressionSemantic(sc).arrayFuncConv(sc);
12173 e2x = resolveProperties(sc, e2x);
12175 sc.merge(exp.loc, ctorflow1);
12176 ctorflow1.freeFieldinit();
12178 if (ec.op == EXP.error)
12183 if (ec.type == Type.terror)
12187 if (e1x.op == EXP.error)
12192 if (e1x.type == Type.terror)
12196 if (e2x.op == EXP.error)
12201 if (e2x.type == Type.terror)
12205 auto f0 = checkNonAssignmentArrayOp(exp.econd);
12206 auto f1 = checkNonAssignmentArrayOp(exp.e1);
12207 auto f2 = checkNonAssignmentArrayOp(exp.e2);
12208 if (f0 || f1 || f2)
12211 Type t1 = exp.e1.type;
12212 Type t2 = exp.e2.type;
12213 if (t1.ty == Tnoreturn)
12216 exp.e1 = specialNoreturnCast(exp.e1, exp.type);
12218 else if (t2.ty == Tnoreturn)
12221 exp.e2 = specialNoreturnCast(exp.e2, exp.type);
12223 // If either operand is void the result is void, we have to cast both
12224 // the expression to void so that we explicitly discard the expression
12226 // https://issues.dlang.org/show_bug.cgi?id=16598
12227 else if (t1.ty == Tvoid || t2.ty == Tvoid)
12229 exp.type = Type.tvoid;
12230 exp.e1 = exp.e1.castTo(sc, exp.type);
12231 exp.e2 = exp.e2.castTo(sc, exp.type);
12237 if (Expression ex = typeCombine(exp, sc))
12243 switch (exp.e1.type.toBasetype().ty)
12248 exp.e2 = exp.e2.castTo(sc, exp.e1.type);
12253 switch (exp.e2.type.toBasetype().ty)
12258 exp.e1 = exp.e1.castTo(sc, exp.e2.type);
12263 if (exp.type.toBasetype().ty == Tarray)
12265 exp.e1 = exp.e1.castTo(sc, exp.type);
12266 exp.e2 = exp.e2.castTo(sc, exp.type);
12269 exp.type = exp.type.merge2();
12272 printf("res: %s\n", exp.type.toChars());
12273 printf("e1 : %s\n", exp.e1.type.toChars());
12274 printf("e2 : %s\n", exp.e2.type.toChars());
12277 /* https://issues.dlang.org/show_bug.cgi?id=14696
12278 * If either e1 or e2 contain temporaries which need dtor,
12279 * make them conditional.
12281 * cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
12283 * (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
12284 * and replace edtors of __tmp1 and __tmp2 with:
12285 * __tmp1.edtor --> __cond && __tmp1.dtor()
12286 * __tmp2.edtor --> __cond || __tmp2.dtor()
12293 override void visit(GenericExp exp)
12295 static if (LOGSEMANTIC)
12297 printf("GenericExp::semantic('%s')\n", exp.toChars());
12299 // C11 6.5.1.1 Generic Selection
12301 auto ec = exp.cntlExp.expressionSemantic(sc).arrayFuncConv(sc);
12302 bool errors = ec.isErrorExp() !is null;
12305 auto types = (*exp.types)[];
12306 foreach (i, ref t; types)
12309 continue; // `default:` case
12310 t = t.typeSemantic(ec.loc, sc);
12311 if (t.isTypeError())
12317 /* C11 6.5.1-2 duplicate check
12319 /* C11 distinguishes int, long, and long long. But D doesn't, so depending on the
12320 * C target, a long may have the same type as `int` in the D type system.
12321 * So, skip checks when this may be the case. Later pick the first match
12324 (t.ty == Tint32 || t.ty == Tuns32) && target.c.longsize == 4 ||
12325 (t.ty == Tint64 || t.ty == Tuns64) && target.c.longsize == 8 ||
12326 (t.ty == Tfloat64 || t.ty == Timaginary64 || t.ty == Tcomplex64) && target.c.long_doublesize == 8
12330 foreach (t2; types[0 .. i])
12332 if (t2 && t2.equals(t))
12334 error(ec.loc, "generic association type `%s` can only appear once", t.toChars());
12341 auto exps = (*exp.exps)[];
12342 foreach (ref e; exps)
12344 e = e.expressionSemantic(sc);
12345 if (e.isErrorExp())
12352 enum size_t None = ~0;
12353 size_t imatch = None;
12354 size_t idefault = None;
12355 foreach (const i, t; types)
12359 /* if tc is compatible with t, it's a match
12360 * C11 6.2.7 defines a compatible type as being the same type, including qualifiers
12364 assert(imatch == None);
12366 break; // pick first match
12370 idefault = i; // multiple defaults are not allowed, and are caught by cparse
12373 if (imatch == None)
12375 if (imatch == None)
12377 error(exp.loc, "no compatible generic association type for controlling expression type `%s`", tc.toChars());
12381 result = exps[imatch];
12384 override void visit(FileInitExp e)
12386 //printf("FileInitExp::semantic()\n");
12387 e.type = Type.tstring;
12391 override void visit(LineInitExp e)
12393 e.type = Type.tint32;
12397 override void visit(ModuleInitExp e)
12399 //printf("ModuleInitExp::semantic()\n");
12400 e.type = Type.tstring;
12404 override void visit(FuncInitExp e)
12406 //printf("FuncInitExp::semantic()\n");
12407 e.type = Type.tstring;
12410 result = e.resolveLoc(Loc.initial, sc);
12416 override void visit(PrettyFuncInitExp e)
12418 //printf("PrettyFuncInitExp::semantic()\n");
12419 e.type = Type.tstring;
12422 result = e.resolveLoc(Loc.initial, sc);
12430 /**********************************
12431 * Try to run semantic routines.
12432 * If they fail, return NULL.
12434 Expression trySemantic(Expression exp, Scope* sc)
12436 //printf("+trySemantic(%s)\n", exp.toChars());
12437 uint errors = global.startGagging();
12438 Expression e = expressionSemantic(exp, sc);
12439 if (global.endGagging(errors))
12443 //printf("-trySemantic(%s)\n", exp.toChars());
12447 /**************************
12448 * Helper function for easy error propagation.
12449 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12451 Expression unaSemantic(UnaExp e, Scope* sc)
12453 static if (LOGSEMANTIC)
12455 printf("UnaExp::semantic('%s')\n", e.toChars());
12457 Expression e1x = e.e1.expressionSemantic(sc);
12458 if (e1x.op == EXP.error)
12464 /**************************
12465 * Helper function for easy error propagation.
12466 * If error occurs, returns ErrorExp. Otherwise returns NULL.
12468 Expression binSemantic(BinExp e, Scope* sc)
12470 static if (LOGSEMANTIC)
12472 printf("BinExp::semantic('%s')\n", e.toChars());
12474 Expression e1x = e.e1.expressionSemantic(sc);
12475 Expression e2x = e.e2.expressionSemantic(sc);
12477 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
12478 if (e1x.op == EXP.type)
12479 e1x = resolveAliasThis(sc, e1x);
12480 if (e2x.op == EXP.type)
12481 e2x = resolveAliasThis(sc, e2x);
12483 if (e1x.op == EXP.error)
12485 if (e2x.op == EXP.error)
12492 Expression binSemanticProp(BinExp e, Scope* sc)
12494 if (Expression ex = binSemantic(e, sc))
12496 Expression e1x = resolveProperties(sc, e.e1);
12497 Expression e2x = resolveProperties(sc, e.e2);
12498 if (e1x.op == EXP.error)
12500 if (e2x.op == EXP.error)
12507 // entrypoint for semantic ExpressionSemanticVisitor
12508 extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
12510 scope v = new ExpressionSemanticVisitor(sc);
12515 private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc)
12517 //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
12518 if (Expression ex = unaSemantic(exp, sc))
12521 if (!(sc.flags & SCOPE.Cfile) && exp.ident == Id._mangleof)
12525 // return mangleof as an Expression
12526 static Expression dotMangleof(const ref Loc loc, Scope* sc, Dsymbol ds)
12529 if (auto f = ds.isFuncDeclaration())
12531 if (f.checkForwardRef(loc))
12532 return ErrorExp.get();
12534 if (f.purityInprocess || f.safetyInprocess || f.nothrowInprocess || f.nogcInprocess)
12536 f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
12537 return ErrorExp.get();
12541 mangleToBuffer(ds, &buf);
12542 Expression e = new StringExp(loc, buf.extractSlice());
12543 return e.expressionSemantic(sc);
12549 case EXP.scope_: return dotMangleof(exp.loc, sc, exp.e1.isScopeExp().sds);
12550 case EXP.variable: return dotMangleof(exp.loc, sc, exp.e1.isVarExp().var);
12551 case EXP.dotVariable: return dotMangleof(exp.loc, sc, exp.e1.isDotVarExp().var);
12552 case EXP.overloadSet: return dotMangleof(exp.loc, sc, exp.e1.isOverExp().vars);
12553 case EXP.template_:
12555 TemplateExp te = exp.e1.isTemplateExp();
12556 return dotMangleof(exp.loc, sc, ds = te.fd ? te.fd.isDsymbol() : te.td);
12564 if (exp.e1.isVarExp() && exp.e1.type.toBasetype().isTypeSArray() && exp.ident == Id.length)
12566 // bypass checkPurity
12567 return exp.e1.type.dotExp(sc, exp.e1, exp.ident, exp.noderef ? DotExpFlag.noDeref : 0);
12570 if (!exp.e1.isDotExp())
12572 exp.e1 = resolvePropertiesX(sc, exp.e1);
12575 if (auto te = exp.e1.isTupleExp())
12577 if (exp.ident == Id.offsetof)
12579 /* 'distribute' the .offsetof to each of the tuple elements.
12581 auto exps = new Expressions(te.exps.length);
12582 foreach (i, e; (*te.exps)[])
12584 (*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
12586 // Don't evaluate te.e0 in runtime
12587 Expression e = new TupleExp(exp.loc, null, exps);
12588 e = e.expressionSemantic(sc);
12591 if (exp.ident == Id.length)
12593 // Don't evaluate te.e0 in runtime
12594 return new IntegerExp(exp.loc, te.exps.length, Type.tsize_t);
12598 // https://issues.dlang.org/show_bug.cgi?id=14416
12599 // Template has no built-in properties except for 'stringof'.
12600 if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof)
12602 exp.error("template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12603 return ErrorExp.get();
12607 exp.error("expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars());
12608 return ErrorExp.get();
12614 /******************************
12615 * Resolve properties, i.e. `e1.ident`, without seeing UFCS.
12617 * exp = expression to resolve
12619 * flag = if 1 then do not emit error messages, just return null
12621 * resolved expression, null if error
12623 Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, int flag)
12625 //printf("DotIdExp::semanticY(this = %p, '%s')\n", exp, exp.toChars());
12627 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
12629 const cfile = (sc.flags & SCOPE.Cfile) != 0;
12631 /* Special case: rewrite this.id and super.id
12632 * to be classtype.id and baseclasstype.id
12633 * if we have no this pointer.
12635 if ((exp.e1.isThisExp() || exp.e1.isSuperExp()) && !hasThis(sc))
12637 if (AggregateDeclaration ad = sc.getStructClassScope())
12639 if (exp.e1.isThisExp())
12641 exp.e1 = new TypeExp(exp.e1.loc, ad.type);
12645 if (auto cd = ad.isClassDeclaration())
12648 exp.e1 = new TypeExp(exp.e1.loc, cd.baseClass.type);
12655 Expression e = dotIdSemanticPropX(exp, sc);
12662 if (auto de = exp.e1.isDotExp())
12673 Type t1b = exp.e1.type.toBasetype();
12675 if (auto ie = eright.isScopeExp()) // also used for template alias's
12677 auto flags = SearchLocalsOnly;
12678 /* Disable access to another module's private imports.
12679 * The check for 'is sds our current module' is because
12680 * the current module should have access to its own imports.
12682 if (ie.sds.isModule() && ie.sds != sc._module)
12683 flags |= IgnorePrivateImports;
12684 if (sc.flags & SCOPE.ignoresymbolvisibility)
12685 flags |= IgnoreSymbolVisibility;
12686 Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags);
12687 /* Check for visibility before resolving aliases because public
12688 * aliases to private symbols are public.
12690 if (s && !(sc.flags & SCOPE.ignoresymbolvisibility) && !symbolIsVisible(sc._module, s))
12696 auto p = s.isPackage();
12697 if (p && checkAccess(sc, p))
12704 // if 's' is a tuple variable, the tuple is returned.
12707 exp.checkDeprecated(sc, s);
12708 exp.checkDisabled(sc, s);
12710 if (auto em = s.isEnumMember())
12712 return em.getVarExp(exp.loc, sc);
12714 if (auto v = s.isVarDeclaration())
12716 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
12718 !v.type.deco && v.inuse)
12721 exp.error("circular reference to %s `%s`", v.kind(), v.toPrettyChars());
12723 exp.error("forward reference to %s `%s`", v.kind(), v.toPrettyChars());
12724 return ErrorExp.get();
12726 if (v.type.isTypeError())
12727 return ErrorExp.get();
12729 if ((v.storage_class & STC.manifest) && v._init && !exp.wantsym)
12731 /* Normally, the replacement of a symbol with its initializer is supposed to be in semantic2().
12732 * Introduced by https://github.com/dlang/dmd/pull/5588 which should probably
12733 * be reverted. `wantsym` is the hack to work around the problem.
12737 error(exp.loc, "circular initialization of %s `%s`", v.kind(), v.toPrettyChars());
12738 return ErrorExp.get();
12740 auto e = v.expandInitializer(exp.loc);
12742 e = e.expressionSemantic(sc);
12751 eleft = new ThisExp(exp.loc);
12752 e = new DotVarExp(exp.loc, eleft, v);
12753 e = e.expressionSemantic(sc);
12757 e = new VarExp(exp.loc, v);
12760 e = new CommaExp(exp.loc, eleft, e);
12765 return e.expressionSemantic(sc);
12768 if (auto f = s.isFuncDeclaration())
12770 //printf("it's a function\n");
12771 if (!f.functionSemantic())
12772 return ErrorExp.get();
12777 eleft = new ThisExp(exp.loc);
12778 e = new DotVarExp(exp.loc, eleft, f, true);
12779 e = e.expressionSemantic(sc);
12783 e = new VarExp(exp.loc, f, true);
12786 e = new CommaExp(exp.loc, eleft, e);
12792 if (auto td = s.isTemplateDeclaration())
12796 e = new DotTemplateExp(exp.loc, eleft, td);
12798 e = new TemplateExp(exp.loc, td);
12799 e = e.expressionSemantic(sc);
12802 if (OverDeclaration od = s.isOverDeclaration())
12804 Expression e = new VarExp(exp.loc, od, true);
12807 e = new CommaExp(exp.loc, eleft, e);
12808 e.type = Type.tvoid; // ambiguous type?
12810 return e.expressionSemantic(sc);
12812 if (auto o = s.isOverloadSet())
12814 //printf("'%s' is an overload set\n", o.toChars());
12815 return new OverExp(exp.loc, o);
12818 if (auto t = s.getType())
12820 return (new TypeExp(exp.loc, t)).expressionSemantic(sc);
12823 if (auto tup = s.isTupleDeclaration())
12827 Expression e = new DotVarExp(exp.loc, eleft, tup);
12828 e = e.expressionSemantic(sc);
12831 Expression e = new TupleExp(exp.loc, tup);
12832 e = e.expressionSemantic(sc);
12836 if (auto sds = s.isScopeDsymbol())
12838 //printf("it's a ScopeDsymbol %s\n", ident.toChars());
12839 Expression e = new ScopeExp(exp.loc, sds);
12840 e = e.expressionSemantic(sc);
12842 e = new DotExp(exp.loc, eleft, e);
12846 if (auto imp = s.isImport())
12848 Expression se = new ScopeExp(exp.loc, imp.pkg);
12849 return se.expressionSemantic(sc);
12851 // BUG: handle other cases like in IdentifierExp::semantic()
12854 printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
12858 else if (exp.ident == Id.stringof)
12860 Expression e = new StringExp(exp.loc, ie.toString());
12861 e = e.expressionSemantic(sc);
12864 if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
12870 s = ie.sds.search_correct(exp.ident);
12871 if (s && symbolIsVisible(sc, s))
12874 exp.error("undefined identifier `%s` in %s `%s`, perhaps add `static import %s;`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.toPrettyChars());
12876 exp.error("undefined identifier `%s` in %s `%s`, did you mean %s `%s`?", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars());
12879 exp.error("undefined identifier `%s` in %s `%s`", exp.ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
12880 return ErrorExp.get();
12882 else if (t1b.ty == Tpointer && exp.e1.type.ty != Tenum &&
12884 exp.ident == Id.__sizeof ||
12885 exp.ident == Id.__xalignof ||
12887 (exp.ident == Id._mangleof ||
12888 exp.ident == Id.offsetof ||
12889 exp.ident == Id._init ||
12890 exp.ident == Id.stringof)
12893 Type t1bn = t1b.nextOf();
12896 if (AggregateDeclaration ad = isAggregate(t1bn))
12898 if (!ad.members) // https://issues.dlang.org/show_bug.cgi?id=11312
12908 if (flag && t1bn.ty == Tvoid)
12910 Expression e = new PtrExp(exp.loc, exp.e1);
12911 e = e.expressionSemantic(sc);
12912 return e.type.dotExp(sc, e, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12914 else if (exp.ident == Id.__xalignof &&
12915 exp.e1.isVarExp() &&
12916 exp.e1.isVarExp().var.isVarDeclaration() &&
12917 !exp.e1.isVarExp().var.isVarDeclaration().alignment.isUnknown())
12919 // For `x.alignof` get the alignment of the variable, not the alignment of its type
12920 const explicitAlignment = exp.e1.isVarExp().var.isVarDeclaration().alignment;
12921 const naturalAlignment = exp.e1.type.alignsize();
12922 const actualAlignment = explicitAlignment.isDefault() ? naturalAlignment : explicitAlignment.get();
12923 Expression e = new IntegerExp(exp.loc, actualAlignment, Type.tsize_t);
12926 else if ((exp.ident == Id.max || exp.ident == Id.min) &&
12927 exp.e1.isVarExp() &&
12928 exp.e1.isVarExp().var.isBitFieldDeclaration())
12930 // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
12931 auto bf = exp.e1.isVarExp().var.isBitFieldDeclaration();
12932 return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
12934 else if ((exp.ident == Id.max || exp.ident == Id.min) &&
12935 exp.e1.isDotVarExp() &&
12936 exp.e1.isDotVarExp().var.isBitFieldDeclaration())
12938 // For `x.max` and `x.min` get the max/min of the bitfield, not the max/min of its type
12939 auto bf = exp.e1.isDotVarExp().var.isBitFieldDeclaration();
12940 return new IntegerExp(exp.loc, bf.getMinMax(exp.ident), bf.type);
12944 if (exp.e1.isTypeExp() || exp.e1.isTemplateExp())
12946 Expression e = exp.e1.type.dotExp(sc, exp.e1, exp.ident, flag | (exp.noderef ? DotExpFlag.noDeref : 0));
12949 e = e.expressionSemantic(sc);
12955 // Resolve e1.ident!tiargs without seeing UFCS.
12956 // If flag == 1, stop "not a property" error and return NULL.
12957 Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, int flag)
12959 static if (LOGSEMANTIC)
12961 printf("DotTemplateInstanceExpY::semantic('%s')\n", exp.toChars());
12964 static Expression errorExp()
12966 return ErrorExp.get();
12969 Expression e1 = exp.e1;
12971 if (exp.ti.tempdecl && exp.ti.tempdecl.parent && exp.ti.tempdecl.parent.isTemplateMixin())
12973 // if 'ti.tempdecl' happens to be found in a mixin template don't lose that info
12974 // and do the symbol search in that context (Issue: 19476)
12975 auto tm = cast(TemplateMixin)exp.ti.tempdecl.parent;
12976 e1 = new DotExp(exp.e1.loc, exp.e1, new ScopeExp(tm.loc, tm));
12979 auto die = new DotIdExp(exp.loc, e1, exp.ti.name);
12981 Expression e = die.dotIdSemanticPropX(sc);
12984 exp.e1 = die.e1; // take back
12985 Type t1b = exp.e1.type.toBasetype();
12986 if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
12988 /* No built-in type has templatized properties, so do shortcut.
12989 * It is necessary in: 1024.max!"a < b"
12994 e = die.dotIdSemanticProp(sc, flag);
12998 isDotOpDispatch(e))
13000 /* opDispatch!tiargs would be a function template that needs IFTI,
13001 * so it's not a template
13009 if (e.op == EXP.error)
13011 if (DotVarExp dve = e.isDotVarExp())
13013 if (FuncDeclaration fd = dve.var.isFuncDeclaration())
13015 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
13017 e = new DotTemplateExp(dve.loc, dve.e1, td);
13018 e = e.expressionSemantic(sc);
13021 else if (OverDeclaration od = dve.var.isOverDeclaration())
13023 exp.e1 = dve.e1; // pull semantic() result
13025 if (!exp.findTempDecl(sc))
13027 if (exp.ti.needsTypeInference(sc))
13029 exp.ti.dsymbolSemantic(sc);
13030 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13033 if (Declaration v = exp.ti.toAlias().isDeclaration())
13035 if (v.type && !v.type.deco)
13036 v.type = v.type.typeSemantic(v.loc, sc);
13037 return new DotVarExp(exp.loc, exp.e1, v)
13038 .expressionSemantic(sc);
13040 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13041 .expressionSemantic(sc);
13044 else if (e.op == EXP.variable)
13046 VarExp ve = cast(VarExp)e;
13047 if (FuncDeclaration fd = ve.var.isFuncDeclaration())
13049 if (TemplateDeclaration td = fd.findTemplateDeclRoot())
13051 e = new TemplateExp(ve.loc, td)
13052 .expressionSemantic(sc);
13055 else if (OverDeclaration od = ve.var.isOverDeclaration())
13057 exp.ti.tempdecl = od;
13058 return new ScopeExp(exp.loc, exp.ti)
13059 .expressionSemantic(sc);
13063 if (DotTemplateExp dte = e.isDotTemplateExp())
13065 exp.e1 = dte.e1; // pull semantic() result
13067 exp.ti.tempdecl = dte.td;
13068 if (!exp.ti.semanticTiargs(sc))
13070 if (exp.ti.needsTypeInference(sc))
13072 exp.ti.dsymbolSemantic(sc);
13073 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13076 if (Declaration v = exp.ti.toAlias().isDeclaration())
13078 return new DotVarExp(exp.loc, exp.e1, v)
13079 .expressionSemantic(sc);
13081 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13082 .expressionSemantic(sc);
13084 else if (e.op == EXP.template_)
13086 exp.ti.tempdecl = (cast(TemplateExp)e).td;
13087 return new ScopeExp(exp.loc, exp.ti)
13088 .expressionSemantic(sc);
13090 else if (DotExp de = e.isDotExp())
13092 if (de.e2.op == EXP.overloadSet)
13094 if (!exp.findTempDecl(sc) || !exp.ti.semanticTiargs(sc))
13098 if (exp.ti.needsTypeInference(sc))
13100 exp.ti.dsymbolSemantic(sc);
13101 if (!exp.ti.inst || exp.ti.errors) // if template failed to expand
13104 if (Declaration v = exp.ti.toAlias().isDeclaration())
13106 if (v.type && !v.type.deco)
13107 v.type = v.type.typeSemantic(v.loc, sc);
13108 return new DotVarExp(exp.loc, exp.e1, v)
13109 .expressionSemantic(sc);
13111 return new DotExp(exp.loc, exp.e1, new ScopeExp(exp.loc, exp.ti))
13112 .expressionSemantic(sc);
13115 else if (OverExp oe = e.isOverExp())
13117 exp.ti.tempdecl = oe.vars;
13118 return new ScopeExp(exp.loc, exp.ti)
13119 .expressionSemantic(sc);
13123 exp.error("`%s` isn't a template", e.toChars());
13127 /***************************************
13128 * If expression is shared, check that we can access it.
13129 * Give error message if not.
13132 * e = expression to check
13134 * returnRef = Whether this expression is for a `return` statement
13135 * off a `ref` function, in which case a single level
13136 * of dereference is allowed (e.g. `shared(int)*`).
13140 bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
13142 if (global.params.noSharedAccess != FeatureState.enabled ||
13145 sc.flags & SCOPE.ctfe)
13150 //printf("checkSharedAccess() `%s` returnRef: %d\n", e.toChars(), returnRef);
13152 /* In case we don't know which expression triggered it,
13153 * e.g. for `visit(Type)` overload
13155 Expression original = e;
13157 bool check(Expression e, bool allowRef)
13159 bool sharedError(Expression e)
13161 // https://dlang.org/phobos/core_atomic.html
13162 e.error("direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars());
13166 // Error by default
13167 bool visit(Expression e)
13169 if (e.type.isShared())
13170 return sharedError(e);
13174 bool visitNew(NewExp e)
13177 check(e.thisexp, false);
13178 // Note: This handles things like `new shared(Throwable).msg`,
13179 // where accessing `msg` would violate `shared`.
13180 if (e.newtype.isShared())
13181 return sharedError(original);
13185 bool visitVar(VarExp e)
13187 // https://issues.dlang.org/show_bug.cgi?id=22626
13188 // Synchronized functions don't need to use core.atomic
13189 // when accessing `this`.
13190 if (sc.func && sc.func.isSynchronized())
13192 if (e.var.isThisDeclaration())
13195 return sharedError(e);
13197 else if (!allowRef && e.var.type.isShared())
13198 return sharedError(e);
13203 bool visitAddr(AddrExp e)
13205 return check(e.e1, true);
13208 bool visitPtr(PtrExp e)
13210 if (!allowRef && e.type.isShared())
13211 return sharedError(e);
13213 if (e.e1.type.isShared())
13214 return sharedError(e);
13216 return check(e.e1, false);
13219 bool visitThis(ThisExp e)
13221 if (sc.func && sc.func.isSynchronized())
13224 if (!allowRef && e.type.isShared())
13225 return sharedError(e);
13230 bool visitDotVar(DotVarExp e)
13232 //printf("dotvarexp = %s\n", e.toChars());
13233 auto fd = e.var.isFuncDeclaration();
13234 const sharedFunc = fd && fd.type.isShared;
13235 // Allow using `DotVarExp` within value types
13236 if (!allowRef && e.type.isShared() && !sharedFunc && !(sc.func && sc.func.isSynchronized()))
13237 return sharedError(e);
13238 if (e.e1.type.isTypeSArray() || e.e1.type.isTypeStruct())
13239 return check(e.e1, allowRef);
13241 // If we end up with a single `VarExp`, it might be a `ref` param
13242 // `shared ref T` param == `shared(T)*`.
13243 if (auto ve = e.e1.isVarExp())
13245 return check(e.e1, allowRef && (ve.var.storage_class & STC.ref_));
13248 return check(e.e1, false);
13251 bool visitIndex(IndexExp e)
13253 if (!allowRef && e.type.isShared())
13254 return sharedError(e);
13256 if (e.e1.type.isShared())
13257 return sharedError(e);
13259 return check(e.e1, false);
13262 bool visitComma(CommaExp e)
13264 // Cannot be `return ref` since we can't use the return,
13265 // but it's better to show that error than an unrelated `shared` one
13266 return check(e.e2, true);
13271 default: return visit(e);
13273 // Those have no indirections / can be ignored
13276 case EXP.complex80:
13278 case EXP.null_: return false;
13280 case EXP.variable: return visitVar(e.isVarExp());
13281 case EXP.new_: return visitNew(e.isNewExp());
13282 case EXP.address: return visitAddr(e.isAddrExp());
13283 case EXP.star: return visitPtr(e.isPtrExp());
13284 case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
13285 case EXP.index: return visitIndex(e.isIndexExp());
13286 case EXP.this_: return visitThis(e.isThisExp());
13290 return check(e, returnRef);
13295 /****************************************************
13296 * Determine if `exp`, which gets its address taken, can do so safely.
13299 * exp = expression having its address taken
13300 * v = the variable getting its address taken
13302 * `true` if ok, `false` for error
13304 bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v)
13306 //printf("checkAddressVar(exp: %s, v: %s)\n", exp.toChars(), v.toChars());
13310 if (!v.canTakeAddressOf())
13312 exp.error("cannot take address of `%s`", exp.toChars());
13315 if (sc.func && !sc.intypeof && !v.isDataseg())
13317 if (global.params.useDIP1000 != FeatureState.enabled &&
13318 !(v.storage_class & STC.temp) &&
13319 sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func))
13327 /**************************************
13328 * This check ensures that the object in `exp` can have its address taken, or
13329 * issue a diagnostic error.
13331 * e = expression to check
13334 * true if the expression is addressable
13336 bool checkAddressable(Expression e, Scope* sc)
13343 case EXP.dotVariable:
13344 // https://issues.dlang.org/show_bug.cgi?id=22749
13345 // Error about taking address of any bit-field, regardless of
13346 // whether SCOPE.Cfile is set.
13347 if (auto bf = ex.isDotVarExp().var.isBitFieldDeclaration())
13349 e.error("cannot take address of bit-field `%s`", bf.toChars());
13352 goto case EXP.cast_;
13355 ex = ex.isBinExp().e1;
13361 ex = ex.isUnaExp().e1;
13365 if (sc.flags & SCOPE.Cfile)
13367 // C11 6.5.3.2: A variable that has its address taken cannot be
13368 // stored in a register.
13369 // C11 6.3.2.1: An array that has its address computed with `[]`
13370 // or cast to an lvalue pointer cannot be stored in a register.
13371 if (ex.isVarExp().var.storage_class & STC.register)
13373 if (e.isIndexExp())
13374 e.error("cannot index through register variable `%s`", ex.toChars());
13376 e.error("cannot take address of register variable `%s`", ex.toChars());
13391 /*******************************
13392 * Checks the attributes of a function.
13393 * Purity (`pure`), safety (`@safe`), no GC allocations(`@nogc`)
13394 * and usage of `deprecated` and `@disabled`-ed symbols are checked.
13397 * exp = expression to check attributes for
13398 * sc = scope of the function
13399 * f = function to be checked
13400 * Returns: `true` if error occur.
13402 private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f)
13406 bool error = checkDisabled(sc, f);
13407 error |= checkDeprecated(sc, f);
13408 error |= checkPurity(sc, f);
13409 error |= checkSafety(sc, f);
13410 error |= checkNogc(sc, f);
13415 /*******************************
13416 * Helper function for `getRightThis()`.
13417 * Gets `this` of the next outer aggregate.
13419 * loc = location to use for error messages
13421 * s = the parent symbol of the existing `this`
13422 * ad = struct or class we need the correct `this` for
13423 * e1 = existing `this`
13424 * t = type of the existing `this`
13425 * var = the specific member of ad we're accessing
13426 * flag = if true, return `null` instead of throwing an error
13428 * Expression representing the `this` for the var
13430 Expression getThisSkipNestedFuncs(const ref Loc loc, Scope* sc, Dsymbol s, AggregateDeclaration ad, Expression e1, Type t, Dsymbol var, bool flag = false)
13433 while (s && s.isFuncDeclaration())
13435 FuncDeclaration f = s.isFuncDeclaration();
13439 e1 = new VarExp(loc, f.vthis);
13440 if (f.hasDualContext())
13444 e1 = e1.expressionSemantic(sc);
13445 e1 = new PtrExp(loc, e1);
13446 uint i = f.followInstantiationContext(ad);
13447 e1 = new IndexExp(loc, e1, new IntegerExp(i));
13448 s = f.toParentP(ad);
13456 e1.error("need `this` of type `%s` to access member `%s` from static function `%s`", ad.toChars(), var.toChars(), f.toChars());
13457 e1 = ErrorExp.get();
13462 if (n > 1 || e1.op == EXP.index)
13463 e1 = e1.expressionSemantic(sc);
13464 if (s && e1.type.equivalent(Type.tvoidptr))
13466 if (auto sad = s.isAggregateDeclaration())
13468 Type ta = sad.handleType();
13469 if (ta.ty == Tstruct)
13470 ta = ta.pointerTo();
13474 e1.type = e1.type.addMod(t.mod);
13478 /*******************************
13479 * Make a dual-context container for use as a `this` argument.
13481 * loc = location to use for error messages
13482 * sc = current scope
13483 * fd = target function that will take the `this` argument
13485 * Temporary closure variable.
13487 * The function `fd` is added to the nested references of the
13488 * newly created variable such that a closure is made for the variable when
13489 * the address of `fd` is taken.
13491 VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration fd)
13493 Type tthis2 = Type.tvoidptr.sarrayOf(2);
13494 VarDeclaration vthis2 = new VarDeclaration(loc, tthis2, Identifier.generateId("__this"), null);
13495 vthis2.storage_class |= STC.temp;
13496 vthis2.dsymbolSemantic(sc);
13497 vthis2.parent = sc.parent;
13498 // make it a closure var
13500 sc.func.closureVars.push(vthis2);
13501 // add `fd` to the nested refs
13502 vthis2.nestedrefs.push(fd);
13506 /*******************************
13507 * Make sure that the runtime hook `id` exists.
13509 * loc = location to use for error messages
13510 * sc = current scope
13511 * id = the hook identifier
13512 * description = what the hook does
13513 * module_ = what module the hook is located in
13515 * a `bool` indicating if the hook is present.
13517 bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object)
13519 auto rootSymbol = sc.search(loc, Id.empty, null);
13520 if (auto moduleSymbol = rootSymbol.search(loc, module_))
13521 if (moduleSymbol.search(loc, id))
13523 error(loc, "`%s.%s` not found. The current runtime does not support %.*s, or the runtime is corrupt.", module_.toChars(), id.toChars(), cast(int)description.length, description.ptr);
13527 /***************************************
13528 * Fit elements[] to the corresponding types of the `sd`'s fields.
13531 * sd = the struct declaration
13532 * loc = location to use for error messages
13534 * elements = explicit arguments used to construct object
13535 * stype = the constructed object type.
13537 * false if any errors occur,
13538 * otherwise true and elements[] are rewritten for the output.
13540 private bool fit(StructDeclaration sd, const ref Loc loc, Scope* sc, Expressions* elements, Type stype)
13545 const nfields = sd.nonHiddenFields();
13547 for (size_t i = 0; i < elements.length; i++)
13549 Expression e = (*elements)[i];
13553 e = resolveProperties(sc, e);
13556 if (i < sd.fields.length && e.op == EXP.null_)
13558 // CTFE sometimes creates null as hidden pointer; we'll allow this.
13561 .error(loc, "more initializers than fields (%llu) of `%s`", cast(ulong)nfields, sd.toChars());
13564 VarDeclaration v = sd.fields[i];
13565 if (v.offset < offset)
13567 .error(loc, "overlapping initialization for `%s`", v.toChars());
13568 if (!sd.isUnionDeclaration())
13570 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
13571 " must initialize only the first member of a `union`. All subsequent" ~
13572 " non-overlapping fields are default initialized";
13573 .errorSupplemental(loc, errorMsg);
13577 const vsize = v.type.size();
13578 if (vsize == SIZE_INVALID)
13580 offset = cast(uint)(v.offset + vsize);
13584 t = t.addMod(stype.mod);
13586 Type tb = t.toBasetype();
13588 const hasPointers = tb.hasPointers();
13591 if ((!stype.alignment.isDefault() && stype.alignment.get() < target.ptrsize ||
13592 (v.offset & (target.ptrsize - 1))) &&
13593 (sc.setUnsafe(false, loc,
13594 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, v)))
13600 /* Look for case of initializing a static array with a too-short
13601 * string literal, such as:
13602 * char[5] foo = "abc";
13603 * Allow this by doing an explicit cast, which will lengthen the string
13606 if (e.op == EXP.string_ && tb.ty == Tsarray)
13608 StringExp se = cast(StringExp)e;
13609 Type typeb = se.type.toBasetype();
13610 TY tynto = tb.nextOf().ty;
13611 if (!se.committed &&
13612 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
13613 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
13615 e = se.castTo(sc, t);
13620 while (!e.implicitConvTo(t) && tb.ty == Tsarray)
13622 /* Static array initialization, as in:
13626 tb = t.toBasetype();
13628 if (!e.implicitConvTo(t))
13629 t = origType; // restore type for better diagnostic
13631 e = e.implicitCastTo(sc, t);
13633 if (e.op == EXP.error)
13636 (*elements)[i] = doCopyOrMove(sc, e);
13643 * Returns `em` as a VariableExp
13645 * em = the EnumMember to wrap
13646 * loc = location of use of em
13647 * sc = scope of use of em
13649 * VarExp referenceing `em` or ErrorExp if `em` if disabled/deprecated
13651 Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
13653 dsymbolSemantic(em, sc);
13655 return ErrorExp.get();
13656 em.checkDisabled(loc, sc);
13658 if (em.depdecl && !em.depdecl._scope)
13659 em.depdecl._scope = sc;
13660 em.checkDeprecated(loc, sc);
13663 return ErrorExp.get();
13664 Expression e = new VarExp(loc, em);
13665 e = e.expressionSemantic(sc);
13666 if (!(sc.flags & SCOPE.Cfile) && em.isCsymbol())
13668 /* C11 types them as int. But if in D file,
13669 * type qualified names as the enum
13671 e.type = em.parent.isEnumDeclaration().type;
13678 /*****************************
13679 * Try to treat `exp` as a boolean,
13681 * exp = the expression
13682 * sc = scope to evalute `exp` in
13684 * Modified expression on success, ErrorExp on error
13686 Expression toBoolean(Expression exp, Scope* sc)
13691 exp.error("`delete` does not give a boolean result");
13692 return ErrorExp.get();
13695 auto ce = exp.isCommaExp();
13696 auto ex2 = ce.e2.toBoolean(sc);
13697 if (ex2.op == EXP.error)
13700 ce.type = ce.e2.type;
13704 case EXP.construct:
13706 if (sc.flags & SCOPE.Cfile)
13710 // are usually mistakes.
13711 exp.error("assignment cannot be used as a condition, perhaps `==` was meant?");
13712 return ErrorExp.get();
13717 auto le = exp.isLogicalExp();
13718 auto ex2 = le.e2.toBoolean(sc);
13719 if (ex2.op == EXP.error)
13725 auto ce = exp.isCondExp();
13726 auto ex1 = ce.e1.toBoolean(sc);
13727 auto ex2 = ce.e2.toBoolean(sc);
13728 if (ex1.op == EXP.error)
13730 if (ex2.op == EXP.error)
13738 // Default is 'yes' - do nothing
13739 Expression e = arrayFuncConv(exp, sc);
13741 Type tb = t.toBasetype();
13746 // Structs can be converted to bool using opCast(bool)()
13747 if (auto ts = tb.isTypeStruct())
13749 AggregateDeclaration ad = ts.sym;
13750 /* Don't really need to check for opCast first, but by doing so we
13751 * get better error messages if it isn't there.
13753 if (Dsymbol fd = search_function(ad, Id._cast))
13755 e = new CastExp(exp.loc, e, Type.tbool);
13756 e = e.expressionSemantic(sc);
13760 // Forward to aliasthis.
13761 if (ad.aliasthis && !isRecursiveAliasThis(att, tb))
13763 e = resolveAliasThis(sc, e);
13765 tb = e.type.toBasetype();
13772 if (!t.isBoolean())
13774 if (tb != Type.terror)
13775 exp.error("expression `%s` of type `%s` does not have a boolean value",
13776 exp.toChars(), t.toChars());
13777 return ErrorExp.get();