www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 12603] New: [CTFE] Unknown bug with goto case.

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

          Issue ID: 12603
           Summary: [CTFE] Unknown bug with goto case.
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Windows
            Status: NEW
          Severity: normal
          Priority: P1
         Component: DMD
          Assignee: nobody puremagic.com
          Reporter: dmitry.olsh gmail.com

Not yet reduced, but is very curious. Found in CTFE code of std.regex.

import std.uni, std.array, std.typetuple, std.range, std.exception;


struct Parser(R)
{
    dchar _current;
    bool empty;
    R pat, origin;
    CodepointSet charset;  //

     trusted this(S)(R pattern, S flags)
    {
        pat = origin = pattern;
        next();
        next();
        auto a = parseCharTerm();
        auto b = parseCharTerm();
        a.set |= b.set;
        charset = a.set;
    }

     property dchar current(){ return _current; }

    bool next()
    {
        if(pat.empty)
        {
            empty = true;
            return false;
        }
        _current = pat[0];
        pat = pat[1..$];
        return true;
    }
    static struct AB{ 
        CodepointSet set;
    }

    enum Operator { None, Union, Difference, SymDifference, Intersection };
    //parse unit of CodepointSet spec, most notably escape sequences and char
ranges
    //also fetches next set operation
    AB parseCharTerm()
    {
        enum State{ Start, Char, Escape, CharDash, CharDashEscape,
            PotentialTwinSymbolOperator }
        Operator op = Operator.None;
        dchar last;
        CodepointSet set;
        State state = State.Start;

        static void addWithFlags(ref CodepointSet set, uint ch)
        {
            set |= ch;
        }

        L_CharTermLoop:
        for(;;)
        {
            final switch(state)
            {
            case State.Start:
                switch(current)
                {
                case ']':
                    break L_CharTermLoop;
                default:
                    state = State.Char;
                    last = current;
                }
                break;
            case State.Char:
                // xxx last current xxx
                switch(current)
                {
                case '|':
                case '~':
                case '&':
                    state = State.PotentialTwinSymbolOperator;
                    addWithFlags(set, last);
                    last = current;
                    break;
                case ']':
                    set |= last;
                    break L_CharTermLoop;
                default:
                    addWithFlags(set, last);
                    last = current;
                }
                break;
            case State.PotentialTwinSymbolOperator:
                //Uncomment the following to get matching results at C-T and
R-T
                //BASICALLY A COPY OF State.Char code above
                /*switch(current)
                {
                case ']':
                    set |= last;
                    break L_CharTermLoop;
                default:
                    addWithFlags(set, last);
                    last = current;
                }
                break;*/
                goto case State.Char;
            case State.Escape:
            case State.CharDash:
            case State.CharDashEscape:
            //xxx last - \ current xxx
               assert(0);
            }
            bool r = next();
            assert(r);

        }
        return AB(set);
    }

}


auto getIt()
{
    auto p = Parser!(string)("[A~]", "");
    assert(p.cnt == 2);
    return p.charset;
}

import std.stdio;

 system void main()
{

    auto r1 = getIt();
    writeln(r1);
    static r2 = getIt();
    writeln(r2);
    assert(r1 == r2); //fails
}

--
Apr 20 2014