Skip to content

Commit

Permalink
Merge pull request #4687 from 9rnsr/fix9279
Browse files Browse the repository at this point in the history
[REG2.055/2.063] Issue 9279 - Static array return value implicitly converted to immutable dynamic array
  • Loading branch information
WalterBright committed Jun 7, 2015
2 parents f79d860 + 6138de4 commit 6d3fc41
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 64 deletions.
25 changes: 10 additions & 15 deletions src/escape.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,9 @@ bool checkEscape(Scope *sc, Expression *e, bool gag)
{
Type *tb = e->type->toBasetype();
if (tb->ty == Tarray &&
e->e1->op == TOKvar &&
e->e1->type->toBasetype()->ty == Tsarray)
{
VarExp *ve = (VarExp *)e->e1;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v && v->toParent2() == sc->func)
{
if (!v->isDataseg() && !v->isParameter())
error(e->loc, "escaping reference to local %s", v);
}
result |= checkEscapeRef(sc, e->e1, gag);
}
}

Expand Down Expand Up @@ -252,10 +245,10 @@ bool checkEscapeRef(Scope *sc, Expression *e, bool gag)
{
}

void error(Loc loc, const char *format, Dsymbol *s)
void error(Loc loc, const char *format, RootObject *o)
{
if (!gag)
::error(loc, format, s->toChars());
::error(loc, format, o->toChars());
result = true;
}

Expand Down Expand Up @@ -399,15 +392,12 @@ bool checkEscapeRef(Scope *sc, Expression *e, bool gag)
Type *t1 = e->e1->type->toBasetype();
TypeFunction *tf;
if (t1->ty == Tdelegate)
{
tf = (TypeFunction *)((TypeDelegate *)t1)->next;
assert(tf->ty == Tfunction);
}
else if (t1->ty == Tfunction)
tf = (TypeFunction *)t1;
else
tf = NULL;
if (tf && tf->isref)
return;
if (tf->isref)
{
if (e->arguments && e->arguments->dim)
{
Expand Down Expand Up @@ -436,6 +426,11 @@ bool checkEscapeRef(Scope *sc, Expression *e, bool gag)
dve->e1->accept(this);
}
}
else
{
error(e->loc, "escaping reference to stack allocated value returned by %s", e);
return;
}
}
};
EscapeRefVisitor v(sc, gag);
Expand Down
1 change: 1 addition & 0 deletions src/magicport.json
Original file line number Diff line number Diff line change
Expand Up @@ -3166,6 +3166,7 @@
"declaration",
"func",
"mtype",
"root.rootobject",
"tokens",
"errors",
"init"
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail1313a.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail1313a.d(13): Error: escaping reference to local a
fail_compilation/fail1313a.d(13): Error: escaping reference to local variable a
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail1313b.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail1313b.d(13): Error: escaping reference to local a
fail_compilation/fail1313b.d(13): Error: escaping reference to local variable a
---
*/

Expand Down
100 changes: 75 additions & 25 deletions test/fail_compilation/fail13902.d
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,64 @@ int* testEscape3(
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(151): Error: escaping reference to local variable x
fail_compilation/fail13902.d(152): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(156): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(150): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(151): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(152): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(155): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(156): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(157): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(158): Error: escaping reference to local variable x
fail_compilation/fail13902.d(159): Error: escaping reference to local variable x
fail_compilation/fail13902.d(160): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(161): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(161): Error: escaping reference to local variable s
fail_compilation/fail13902.d(162): Error: escaping reference to local variable s
fail_compilation/fail13902.d(163): Error: escaping reference to local variable s
fail_compilation/fail13902.d(166): Error: escaping reference to stack allocated value returned by makeSA()
fail_compilation/fail13902.d(167): Error: escaping reference to stack allocated value returned by makeSA()
fail_compilation/fail13902.d(168): Error: escaping reference to stack allocated value returned by makeSA()
fail_compilation/fail13902.d(171): Error: escaping reference to stack allocated value returned by makeS()
fail_compilation/fail13902.d(172): Error: escaping reference to stack allocated value returned by makeS()
fail_compilation/fail13902.d(173): Error: escaping reference to stack allocated value returned by makeS()
---
*/
int[] testEscape4(int[3] sa1) // Bugzilla 9279
{
if (0) return sa1; // error <- no error
if (0) return cast(int[])sa1; // error <- no error
if (0) return sa1[]; // error

int[3] sa2;
if (0) return sa2; // error
if (0) return cast(int[])sa2; // error
if (0) return sa2[]; // error

struct S { int[3] sa; }
S s;
if (0) return s.sa; // error <- no error
if (0) return cast(int[])s.sa; // error <- no error
if (0) return s.sa[]; // error

int[3] makeSA() { int[3] ret; return ret; }
if (0) return makeSA(); // error <- no error
if (0) return cast(int[])makeSA(); // error <- no error
if (0) return makeSA()[]; // error <- no error

S makeS() { S s; return s; }
if (0) return makeS().sa; // error <- no error
if (0) return cast(int[])makeS().sa; // error <- no error
if (0) return makeS().sa[]; // error <- no error

return null;
}

/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(201): Error: escaping reference to local variable x
fail_compilation/fail13902.d(202): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(206): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(207): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(208): Error: escaping reference to local variable x
fail_compilation/fail13902.d(209): Error: escaping reference to local variable x
fail_compilation/fail13902.d(210): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(211): Error: escaping reference to local variable s1
---
*/
ref int testEscapeRef1()
Expand Down Expand Up @@ -167,14 +217,14 @@ ref int testEscapeRef1()
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(190): Error: escaping reference to local variable x
fail_compilation/fail13902.d(191): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(195): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(196): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(197): Error: escaping reference to local variable x
fail_compilation/fail13902.d(198): Error: escaping reference to local variable x
fail_compilation/fail13902.d(199): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(200): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(240): Error: escaping reference to local variable x
fail_compilation/fail13902.d(241): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(245): Error: escaping reference to local variable sa1
fail_compilation/fail13902.d(246): Error: escaping reference to local variable sa2
fail_compilation/fail13902.d(247): Error: escaping reference to local variable x
fail_compilation/fail13902.d(248): Error: escaping reference to local variable x
fail_compilation/fail13902.d(249): Error: escaping reference to local variable s1
fail_compilation/fail13902.d(250): Error: escaping reference to local variable s1
---
*/
ref int testEscapeRef2(
Expand Down Expand Up @@ -237,8 +287,8 @@ ref int testEscapeRef2(
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(244): Error: escaping reference to local x
fail_compilation/fail13902.d(245): Error: escaping reference to local x
fail_compilation/fail13902.d(294): Error: escaping reference to local x
fail_compilation/fail13902.d(295): Error: escaping reference to local x
---
*/
int*[] testArrayLiteral1() { int x; return [&x]; }
Expand All @@ -247,8 +297,8 @@ int*[1] testArrayLiteral2() { int x; return [&x]; }
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(254): Error: escaping reference to local x
fail_compilation/fail13902.d(255): Error: escaping reference to local x
fail_compilation/fail13902.d(304): Error: escaping reference to local x
fail_compilation/fail13902.d(305): Error: escaping reference to local x
---
*/
S2 testStructLiteral1() { int x; return S2(&x); }
Expand All @@ -257,8 +307,8 @@ S2* testStructLiteral2() { int x; return new S2(&x); }
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(264): Error: escaping reference to local variable sa
fail_compilation/fail13902.d(265): Error: escaping reference to local variable sa
fail_compilation/fail13902.d(314): Error: escaping reference to local variable sa
fail_compilation/fail13902.d(315): Error: escaping reference to local variable sa
---
*/
int[] testSlice1() { int[3] sa; return sa[]; }
Expand All @@ -267,8 +317,8 @@ int[] testSlice2() { int[3] sa; int n; return sa[n..2][1..2]; }
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(274): Error: escaping reference to the payload of variadic parameter vda
fail_compilation/fail13902.d(275): Error: escaping reference to the payload of variadic parameter vda
fail_compilation/fail13902.d(324): Error: escaping reference to the payload of variadic parameter vda
fail_compilation/fail13902.d(325): Error: escaping reference to the payload of variadic parameter vda
---
*/
ref int testDynamicArrayVariadic1(int[] vda...) { return vda[0]; }
Expand All @@ -278,8 +328,8 @@ int[3] testDynamicArrayVariadic3(int[] vda...) { return vda[0..3]; } // no er
/*
TEST_OUTPUT:
---
fail_compilation/fail13902.d(285): Error: escaping reference to the payload of variadic parameter vsa
fail_compilation/fail13902.d(286): Error: escaping reference to the payload of variadic parameter vsa
fail_compilation/fail13902.d(335): Error: escaping reference to the payload of variadic parameter vsa
fail_compilation/fail13902.d(336): Error: escaping reference to the payload of variadic parameter vsa
---
*/
ref int testStaticArrayVariadic1(int[3] vsa...) { return vsa[0]; }
Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail140.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail140.d(11): Error: escaping reference to local string
fail_compilation/fail140.d(11): Error: escaping reference to local variable string
---
*/

Expand Down
13 changes: 13 additions & 0 deletions test/fail_compilation/fail9279.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail9279.d(10): Error: escaping reference to stack allocated value returned by b()
fail_compilation/fail9279.d(13): Error: escaping reference to stack allocated value returned by getArr()
---
*/

char[2] b()() { char[2] ret; return ret; }
string a() { return b(); }

char[12] getArr() { return "Hello World!"; }
string getString() { return getArr(); }
33 changes: 12 additions & 21 deletions test/runnable/test34.d
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ struct Struct
{
int langID;
long _force_nrvo;
}
}

Struct[1] table;

Expand Down Expand Up @@ -107,11 +107,11 @@ void test4()
/************************************************/

int status5;

struct MyStruct5
{
}

void rec5(int i, MyStruct5 s)
{
if( i > 0 )
Expand All @@ -120,7 +120,7 @@ void rec5(int i, MyStruct5 s)
rec5(i-1, s);
}
}

void test5()
{
assert(status5==0);
Expand Down Expand Up @@ -379,7 +379,7 @@ void test17()
S17!(int).iterator i;
auto x = insert17(a, i);
assert(x == 3);
}
}

/************************************************/

Expand Down Expand Up @@ -619,7 +619,7 @@ class RangeCoder
}

void encode(uint symbol) {
uint total = cumCount[$ - 1];
uint total = cumCount[$ - 1];
// "Error: Access Violation" in following line
upper = lower + cast(uint)((cumCount[symbol+1] * range) / total) - 1;
lower = lower + cast(uint)((cumCount[symbol] * range) / total);
Expand Down Expand Up @@ -687,7 +687,7 @@ class Foo34
}

void test34()
{
{
Foo34 f = new Foo34();
f.foo();
}
Expand Down Expand Up @@ -797,7 +797,7 @@ void test39()

/************************************************/

void test40()
void test40()
{
int[char] x;
x['b'] = 123;
Expand Down Expand Up @@ -1003,14 +1003,6 @@ void test49()

/************************************************/

int[] foo50(int[2] x) { return x; }

void test50()
{
}

/************************************************/

struct S51
{
int i = 3;
Expand All @@ -1026,12 +1018,12 @@ void test51()

void test52()
{
struct Foo {
struct Foo {
alias int Y;
}
}
with (Foo) {
Y y;
}
Y y;
}
}

/************************************************/
Expand Down Expand Up @@ -1284,7 +1276,6 @@ void main()
test47();
test48();
test49();
test50();
test51();
test52();
test53();
Expand Down

0 comments on commit 6d3fc41

Please sign in to comment.