@@ -6992,8 +6992,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
69926992
69936993 if (!global.params.useGC && sc.needsCodegen())
69946994 {
6995- error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-%s`", exp.toErrMsg(), SwitchVariadic.ptr);
6996- return setError();
6995+ if (sc.func)
6996+ {
6997+ sc.func.skipCodegen = true; // same net result as calling checkGC
6998+ goto LskipNewArrayLowering; // not checked in sc.needsCodegen() !?
6999+ }
69977000 }
69987001
69997002 if (!sc.needsCodegen())
@@ -8516,7 +8519,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
85168519 {
85178520 exp.type = tf.next;
85188521 auto casted_exp = exp.castTo(sc, t);
8519- if (auto cex = casted_exp.isCastExp())
8522+ if (auto cex = lastComma( casted_exp) .isCastExp())
85208523 {
85218524 lowerCastExp(cex, sc);
85228525 }
@@ -10933,7 +10936,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1093310936 }
1093410937 }
1093510938
10936- if (auto cex = ex .isCastExp())
10939+ if (auto cex = lastComma(ex) .isCastExp())
1093710940 {
1093810941 lowerCastExp(cex, sc);
1093910942 }
@@ -15079,12 +15082,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
1507915082 return;
1508015083 }
1508115084
15082- // When array comparison is not lowered to `__equals`, `memcmp` is used, but
15083- // GC checks occur before the expression is lowered to `memcmp` in e2ir.d.
15084- // Thus, we will consider the literal arrays as on-stack arrays to avoid issues
15085- // during GC checks.
15085+ // Remaining array comparisons are trivially memcmp-able.
15086+ // Allocate array-literal operands on the stack, since they don't
15087+ // escape during the comparison; enabling @nogc for these.
1508615088 if (isArrayComparison)
1508715089 {
15090+ exp.e1 = exp.e1.optimize(WANTvalue);
15091+ exp.e2 = exp.e2.optimize(WANTvalue);
15092+
1508815093 if (auto ale1 = exp.e1.isArrayLiteralExp())
1508915094 {
1509015095 ale1.onstack = true;
@@ -19745,12 +19750,12 @@ private Expression buildAAIndexRValueX(Type t, Expression eaa, Expression ekey,
1974519750 auto call = new CallExp(loc, func, arguments);
1974619751 e0 = Expression.combine(e0, call);
1974719752
19748- if (arrayBoundsCheck(sc.func))
19753+ if (sc.func && arrayBoundsCheck(sc.func))
1974919754 {
1975019755 // __aaget = _d_aaGetRvalueX(aa, key), __aaget ? __aaget : onRangeError(__FILE__, __LINE__)
1975119756 auto ei = new ExpInitializer(loc, e0);
19752- auto vartmp = Identifier.generateId("__aaget");
19753- auto vardecl = new VarDeclaration(loc, null, vartmp , ei, STC.exptemp);
19757+ auto id = Identifier.generateId("__aaget");
19758+ auto vardecl = new VarDeclaration(loc, null, id , ei, STC.exptemp);
1975419759 auto declexp = new DeclarationExp(loc, vardecl);
1975519760
1975619761 //Expression idrange = new IdentifierExp(loc, Identifier.idPool("_d_arraybounds"));
@@ -19760,9 +19765,9 @@ private Expression buildAAIndexRValueX(Type t, Expression eaa, Expression ekey,
1976019765 auto locargs = new Expressions(new FileInitExp(loc, EXP.file), new LineInitExp(loc));
1976119766 auto ex = new CallExp(loc, idrange, locargs);
1976219767
19763- auto idvar1 = new IdentifierExp (loc, vartmp );
19764- auto idvar2 = new IdentifierExp (loc, vartmp );
19765- auto cond = new CondExp(loc, idvar1, idvar2 , ex);
19768+ auto ve1 = new VarExp (loc, vardecl );
19769+ auto ve2 = new VarExp (loc, vardecl );
19770+ auto cond = new CondExp(loc, ve1, ve2 , ex);
1976619771 auto comma = new CommaExp(loc, declexp, cond);
1976719772 return comma;
1976819773 }
@@ -19795,6 +19800,26 @@ Expression revertIndexAssignToRvalues(IndexExp ie, Scope* sc)
1979519800 return lowerAAIndexRead(ie, sc);
1979619801}
1979719802
19803+ // Ditto, but traverses DotVarExp from `alias this` rewrites.
19804+ private Expression revertModifiableAAIndexReads(Expression e, Scope* sc)
19805+ {
19806+ // Recurse through dot-accesses (alias this produces DotVarExp on an inner IndexExp)
19807+ if (auto dve = e.isDotVarExp())
19808+ {
19809+ dve.e1 = revertModifiableAAIndexReads(dve.e1, sc);
19810+ return e;
19811+ }
19812+ if (auto ie = e.isIndexExp())
19813+ {
19814+ // Recurse first to handle deeper nesting
19815+ ie.e1 = revertModifiableAAIndexReads(ie.e1, sc);
19816+ // Lower a modifiable AA IndexExp to an rvalue read
19817+ if (ie.modifiable && ie.e1.type.isTypeAArray())
19818+ return lowerAAIndexRead(ie, sc);
19819+ }
19820+ return e;
19821+ }
19822+
1979819823// helper for rewriteAAIndexAssign
1979919824private Expression implicitConvertToStruct(Expression ev, StructDeclaration sd, Scope* sc)
1980019825{
@@ -19845,6 +19870,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias
1984519870 // find the AA of multi dimensional access
1984619871 for (auto ieaa = ie.e1.isIndexExp(); ieaa && ieaa.e1.type.isTypeAArray(); ieaa = ieaa.e1.isIndexExp())
1984719872 eaa = ieaa.e1;
19873+ eaa = revertModifiableAAIndexReads(eaa, sc);
1984819874 eaa = extractSideEffect(sc, "__aatmp", e0, eaa);
1984919875 // collect all keys of multi dimensional access
1985019876 Expressions ekeys;
@@ -19883,7 +19909,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias
1988319909 auto tiargs = new Objects(taa.index, taa.next);
1988419910 func = new DotTemplateInstanceExp(loc, func, hook, tiargs);
1988519911
19886- auto arguments = new Expressions(eaa, ekeys[i-1], new IdentifierExp (loc, idfound ));
19912+ auto arguments = new Expressions(eaa, ekeys[i-1], new VarExp (loc, varfound ));
1988719913 eaa = new CallExp(loc, func, arguments);
1988819914 if (i > 1)
1988919915 {
@@ -19940,7 +19966,7 @@ private Expression rewriteAAIndexAssign(BinExp exp, Scope* sc, ref Type[2] alias
1994019966 ex = new CastExp(ex.loc, ex, Type.tvoid);
1994119967 ey = new CastExp(ey.loc, ey, Type.tvoid);
1994219968 }
19943- Expression condfound = new IdentifierExp (loc, idfound );
19969+ Expression condfound = new VarExp (loc, varfound );
1994419970 ex = new CondExp(loc, condfound, ex, ey);
1994519971 ex = Expression.combine(e0, ex);
1994619972 ex.isCommaExp().originalExp = exp;
0 commit comments