From 76ff9a450d4336f138328db24d62440da603afc6 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 15 Sep 2017 01:28:40 -0700 Subject: [PATCH] fix Issue 17795 - [scope] Scope errors not detected in ~= operation --- src/ddmd/escape.d | 6 +++--- src/ddmd/expressionsem.d | 16 +++++++++++++--- test/fail_compilation/retscope6.d | 23 +++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 test/fail_compilation/retscope6.d diff --git a/src/ddmd/escape.d b/src/ddmd/escape.d index 6cd2ea57a295..7b44d05fb88f 100644 --- a/src/ddmd/escape.d +++ b/src/ddmd/escape.d @@ -169,7 +169,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier par, Ex * to eliminate the error. * Params: * sc = used to determine current function and module - * ae = AssignExp to check for any pointers to the stack + * e = AssignExp or CatAssignExp to check for any pointers to the stack * gag = do not print error messages * Returns: * true if pointers to the stack can escape via assignment @@ -178,9 +178,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag) { enum log = false; if (log) printf("checkAssignEscape(e: %s)\n", e.toChars()); - if (e.op != TOKassign && e.op != TOKblit && e.op != TOKconstruct) + if (e.op != TOKassign && e.op != TOKblit && e.op != TOKconstruct && e.op != TOKcatass) return false; - auto ae = cast(AssignExp)e; + auto ae = cast(BinExp)e; Expression e1 = ae.e1; Expression e2 = ae.e2; //printf("type = %s, %d\n", e1.type.toChars(), e1.type.hasPointers()); diff --git a/src/ddmd/expressionsem.d b/src/ddmd/expressionsem.d index 8a01a4805d39..eb68e6fa565d 100644 --- a/src/ddmd/expressionsem.d +++ b/src/ddmd/expressionsem.d @@ -6731,7 +6731,7 @@ extern (C++) final class ExpressionSemanticVisitor : Visitor return; } - //printf("CatAssignExp::semantic() %s\n", toChars()); + //printf("CatAssignExp::semantic() %s\n", exp.toChars()); Expression e = exp.op_overload(sc); if (e) { @@ -6772,13 +6772,20 @@ extern (C++) final class ExpressionSemanticVisitor : Visitor Type tb1next = tb1.nextOf(); Type tb2 = exp.e2.type.toBasetype(); + /* Two possibilities: + * 1. appending T[] to T[] + * 2. appending T to T[] + */ + bool appendArray = false; // assume case 2 + if ((tb1.ty == Tarray) && (tb2.ty == Tarray || tb2.ty == Tsarray) && (exp.e2.implicitConvTo(exp.e1.type) || (tb2.nextOf().implicitConvTo(tb1next) && (tb2.nextOf().size(Loc()) == tb1next.size(Loc()))))) { - // Append array + // case 1: append array + appendArray = true; if (exp.e1.checkPostblit(sc, tb1next)) { result = new ErrorExp(); @@ -6822,7 +6829,10 @@ extern (C++) final class ExpressionSemanticVisitor : Visitor } exp.type = exp.e1.type; - result = exp.reorderSettingAAElem(sc); + auto res = exp.reorderSettingAAElem(sc); + if (!appendArray && global.params.vsafe) + checkAssignEscape(sc, res, false); + result = res; } override void visit(AddExp exp) diff --git a/test/fail_compilation/retscope6.d b/test/fail_compilation/retscope6.d new file mode 100644 index 000000000000..0510b68b0aa0 --- /dev/null +++ b/test/fail_compilation/retscope6.d @@ -0,0 +1,23 @@ +/* +REQUIRED_ARGS: -dip1000 +PERMUTE_ARGS: +*/ + +/* +TEST_OUTPUT: +--- +fail_compilation/retscope6.d(6007): Error: reference to local variable `i` assigned to non-scope `arr[0]` +--- +*/ + +#line 6000 + +// https://issues.dlang.org/show_bug.cgi?id=17795 + +int* test() @safe +{ + int i; + int*[][] arr = new int*[][](1); + arr[0] ~= &i; + return arr[0][0]; +}