www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 17764] New: [scope][DIP1000] Escape checker defeated by

https://issues.dlang.org/show_bug.cgi?id=17764

          Issue ID: 17764
           Summary: [scope][DIP1000] Escape checker defeated by
                    composition transformations
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: petar.p.kirov gmail.com

At first I was about to name this issue "The compiler treats 'scope ref T' and
'scope ref T[1]' differently" (see `use0x3()` and `use0x4()`), but then I
decided to dig a little more, so here's what I've found so far:

$ cat > scope_bug.d << DBUG
 safe:
struct Context0x0 { char[]       str; }

struct Parent0x1 { Context0x0      c; }
struct Parent0x2 { Context0x0[1] csa; }
struct Parent0x3 { Context0x0[]  csl; }
struct Parent0x4 { Context0x0*    cp; }

struct Parent0x5 { Parent0x1      p1; }
struct Parent0x6 { Parent0x5      p5; }
struct Parent0x7 { Parent0x6      p6; }

struct Parent0x8 { Parent0x2[1]*  p2; }
struct Parent0x9 { Parent0x8[1]   p8; }
struct Parent0xA { Parent0x9[1]   p9; }

struct Parent0xB { Parent0x4*     p4; }
struct Parent0xC { Parent0xB*     pb; }
struct Parent0xD { Parent0xC*     pc; }

void main()
{
    char[16] buf;
    use0x0(buf);

    char[] charSlice = buf;
    use0x1(charSlice);

    // use0x2(&charSlice); // NG - rejects valid

    Context0x0[1] c = Context0x0(charSlice);

    use0x3(c[0]);
    use0x4(c);
    use0x5(c);

    auto p1 = Parent0x1(c[0]);
    use0x6(p1);

    auto p2 = Parent0x2(c);
    use0x7(p2);

    Context0x0[] contextSlice = c[];
    auto p3 = Parent0x3(contextSlice);
    use0x8(p3);

    auto p4 = Parent0x4(&c[0]);
    use0x9(p4);

    auto p5 = Parent0x7(Parent0x6(Parent0x5(p1)));
    use0xA(p5);

    Parent0x2[1] p2sa = Parent0x2(c);
    Parent0xA p6 = Parent0xA(Parent0x9(Parent0x8(&p2sa)));
    use0xB(p6);

    // auto pbAttemp1 = Parent0xB(&p4); // NG - rejects valid
    Parent0x4[1] p4WorkAround = Parent0x4(&c[0]);
    Parent0xB[1] pb = Parent0xB(&p4WorkAround[0]);
    Parent0xC[1] pc = Parent0xC(&pb[0]);
    Parent0xD[1] pd = Parent0xD(&pc[0]);
    use0xC(pd[0]);
}

char[] global;

void use0x0(scope char[] arr)
{
    // global = arr; // OK - this does not compile
}

void use0x1(scope ref char[] arr)
{
    // global = arr; // OK - this does not compile
}

void use0x2(scope char[]* arr)
{
    global = *arr; // NG - accepts invalid
}

void use0x3(scope ref Context0x0 c)
{
    // global = c.str; // OK - this does not compile
}

void use0x4(scope ref Context0x0[1] c)
{
    global = c[0].str; // NG - accepts invalid
}

void use0x5(scope Context0x0[] c)
{
    global = c[0].str; // NG - accepts invalid
}

void use0x6(scope ref Parent0x1 p)
{
    // global = p.c.str; // OK - this does not compile
}

void use0x7(scope ref Parent0x2 p)
{
    global = p.csa[0].str; // NG - accepts invalid
}

void use0x8(scope ref Parent0x3 p)
{
    global = p.csl[0].str; // NG - accepts invalid
}

void use0x9(scope ref Parent0x4 p)
{
    global = p.cp.str; // NG - accepts invalid
}

void use0xA(scope ref Parent0x7 p)
{
    // global = p.p6.p5.p1.c.str; // OK - this does not compile
}

void use0xB(scope ref Parent0xA p)
{
    global = (*p.p9[0].p8[0].p2)[0].csa[0].str; // NG - accepts invalid
}

void use0xC(scope ref Parent0xD p)
{
    global = p.pc.pb.p4.cp.str; // NG - accepts invalid
}
DBUG

$ dmd -dip1000 scope_bug.d
scope_bug.d(11): Error: cannot take address of scope local c in  safe function
main

$ dmd --version
DMD64 D Compiler v2.076.0-b1-master-32bb4ed

--
Aug 19 2017