www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 16455] New: Wrong code when calling a struct delegate

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

          Issue ID: 16455
           Summary: Wrong code when calling a struct delegate
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Windows
            Status: NEW
          Severity: critical
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: apz28 hotmail.com

Created attachment 1612
  --> https://issues.dlang.org/attachment.cgi?id=1612&action=edit
Test case

module Test;

import std.stdio : writeln;

class Node(S)
{
    Node!S parent;
    Node!S first;
    Node!S next;
    S text;

    this()
    {
    }

    this(S aText)
    {
        text = aText;
    }

    NodeRange!S children()
    {
        return NodeRange!S(this);
    }

    Node!S push(Node!S aNode)
    {
        assert(aNode.next is null);

        aNode.parent = this;
        if (first is null)
            first = aNode;
        else
        {
            aNode.next = first;
            first = aNode;
        }
        return aNode;
    }
}

struct NodeRange(S)
{
private:
    Node!S parent;
    Node!S current;
    void delegate() doPopFront;

    void doMove()
    {
        writeln("doMove()");
        assert(current !is null);

        current = current.next;
    }

public:
    this(Node!S aParent)
    {
        writeln("aParent.text: ", aParent.text);

        parent = aParent;
        current = aParent.first;
        doPopFront = &doMove;
    }

    void popFront()
    {
    writeln("popFront()");
        assert(current !is null);

        // work if straight call
        //doMove(); 

        // access violation when calling delegate
        // or current is not set correctly
        doPopFront();  
    }

     property 
    {
        bool empty()
        {
            return (current is null);
        }

        Node!S front()
        {
            return current;
        }
    }
}

void main()
{
    Node!string tree = new Node!string();
    Node!string first = tree.push(new Node!string("first"));
    first.push(new Node!string("firstChild"));

    NodeRange!string r = tree.first.children();

    assert(!r.empty);
    writeln("r.front.text: ", r.front.text);
    assert(r.front.text == "firstChild");
    r.popFront();

    writeln("r.empty: ", r.empty);
    assert(r.empty);
}

--
Aug 31 2016