Bug 12603 – [CTFE] goto does not correctly call dtors
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2014-04-20T13:52:00Z
Last change time
2015-10-04T18:19:56Z
Assigned to
nobody
Creator
dmitry.olsh
Comments
Comment #0 by dmitry.olsh — 2014-04-20T13:52:44Z
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
}