diff options
Diffstat (limited to 'gcc/d/dmd/expressionsem.d')
-rw-r--r-- | gcc/d/dmd/expressionsem.d | 95 |
1 files changed, 88 insertions, 7 deletions
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 30baabd..3114100 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -2044,7 +2044,8 @@ private bool functionParameters(const ref Loc loc, Scope* sc, /* Argument value can escape from the called function. * Check arg to see if it matters. */ - err |= checkParamArgumentEscape(sc, fd, p, cast(STC) pStc, arg, false, false); + VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null; + err |= checkParamArgumentEscape(sc, fd, p, vPar, cast(STC) pStc, arg, false, false); } // Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference @@ -4726,7 +4727,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tthis = ue.e1.type; if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual)) { - if (checkParamArgumentEscape(sc, exp.f, null, STC.undefined_, ethis, false, false)) + if (checkParamArgumentEscape(sc, exp.f, null, null, STC.undefined_, ethis, false, false)) return setError(); } } @@ -6388,7 +6389,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.msg = resolveProperties(sc, exp.msg); exp.msg = exp.msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf()); exp.msg = exp.msg.optimize(WANTvalue); - checkParamArgumentEscape(sc, null, null, STC.undefined_, exp.msg, true, false); + checkParamArgumentEscape(sc, null, null, null, STC.undefined_, exp.msg, true, false); } if (exp.msg && exp.msg.op == EXP.error) @@ -9934,7 +9935,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (isArrayCtor || isArraySetCtor) { const ts = t1b.nextOf().baseElemOf().isTypeStruct(); - if (!ts || (!ts.sym.postblit && !ts.sym.dtor)) + if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor)) return setResult(res); auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor; @@ -9976,10 +9977,89 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor message("lowered %s =>\n %s", exp.toChars(), res.toChars()); } } + else if (auto ae = res.isAssignExp()) + res = lowerArrayAssign(ae); + else if (auto ce = res.isCommaExp()) + { + if (auto ae1 = ce.e1.isAssignExp()) + ce.e1 = lowerArrayAssign(ae1, true); + if (auto ae2 = ce.e2.isAssignExp()) + ce.e2 = lowerArrayAssign(ae2, true); + } return setResult(res); } + /*************************************** + * Lower AssignExp to `_d_arrayassign_{l,r}` if needed. + * + * Params: + * ae = the AssignExp to be lowered + * fromCommaExp = indicates whether `ae` is part of a CommaExp or not, + * so no unnecessary temporay variable is created. + * Returns: + * a CommaExp contiaining call a to `_d_arrayassign_{l,r}` if needed or + * `ae` otherwise + */ + private Expression lowerArrayAssign(AssignExp ae, bool fromCommaExp = false) + { + Type t1b = ae.e1.type.toBasetype(); + if (t1b.ty != Tsarray && t1b.ty != Tarray) + return ae; + + const isArrayAssign = + (ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) && + (ae.e2.type.ty == Tsarray || ae.e2.type.ty == Tarray) && + (ae.e1.type.nextOf && ae.e2.type.nextOf && ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf)); + + if (!isArrayAssign) + return ae; + + const ts = t1b.nextOf().baseElemOf().isTypeStruct(); + if (!ts || (!ts.sym.postblit && !ts.sym.dtor)) + return ae; + + Expression res; + auto func = ae.e2.isLvalue || ae.e2.isSliceExp ? Id._d_arrayassign_l : Id._d_arrayassign_r; + + // Lower to `.object._d_arrayassign_l{r}(e1, e2)`` + Expression id = new IdentifierExp(ae.loc, Id.empty); + id = new DotIdExp(ae.loc, id, Id.object); + id = new DotIdExp(ae.loc, id, func); + + auto arguments = new Expressions(); + arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf) + .expressionSemantic(sc)); + + Expression eValue2, value2 = ae.e2; + if (ae.e2.isLvalue) + value2 = new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf) + .expressionSemantic(sc); + else if (!fromCommaExp) + { + // Rvalues from CommaExps were introduced in `visit(AssignExp)` + // and are temporary variables themselves. Rvalues from trivial + // SliceExps are simply passed by reference without any copying. + + // `__assigntmp` will be destroyed together with the array `ae.e1`. + // When `ae.e2` is a variadic arg array, it is also `scope`, so + // `__assigntmp` may also be scope. + auto vd = copyToTemp(STC.rvalue | STC.nodtor | STC.scope_, "__assigntmp", ae.e2); + eValue2 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc); + value2 = new VarExp(vd.loc, vd).expressionSemantic(sc); + } + arguments.push(value2); + + Expression ce = new CallExp(ae.loc, id, arguments); + res = Expression.combine(eValue2, ce).expressionSemantic(sc); + res = Expression.combine(res, ae.e1).expressionSemantic(sc); + + if (global.params.verbose) + message("lowered %s =>\n %s", ae.toChars(), res.toChars()); + + return res; + } + override void visit(PowAssignExp exp) { if (exp.type) @@ -13092,7 +13172,10 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) if (sc.func && sc.func.isSynchronized()) return false; - return sharedError(e); + if (!allowRef && e.type.isShared()) + return sharedError(e); + + return false; } bool visitDotVar(DotVarExp e) @@ -13182,8 +13265,6 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) } if (sc.func && !sc.intypeof && !v.isDataseg()) { - v.storage_class &= ~STC.maybescope; - v.doNotInferScope = true; if (global.params.useDIP1000 != FeatureState.enabled && !(v.storage_class & STC.temp) && sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func)) |