aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/expressionsem.d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d/dmd/expressionsem.d')
-rw-r--r--gcc/d/dmd/expressionsem.d95
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))