A CTFE Segfault (with explanation, but I'm not sure what the fix is).

Brad Roberts braddr at puremagic.com
Sun Nov 21 14:18:38 PST 2010


On 11/21/2010 2:11 PM, Gareth Charnock wrote:
> This code makes the DMD compiler segfault
> 
> struct LeafType {
>     string Compile_not_ovloaded() {
>         return "expression";
>     }
> };
> 
> struct MatrixASTNode {
>     LeafType Right;
> 
>     string Compile() {
>         return  Right.Compile_not_ovloaded();
>     }
> };
> 
> void main() {
>     enum AST = MatrixASTNode();
>     enum s=AST.Compile();
> }
> 
> I'm not sure if it's valid D, but MatrixASTNode.Compile seems like it should be
> evaluable at compile time. segfaults are bad anyway. A search with the keyword
> "segfault" didn't seem to turn up any existing bugs with promising titles, so I
> assume this is a new bug (I'll put it in bugzilla if nobody can think of an
> existing bug).
> 
> I've tried compiling a debug version of svn dmd and I traced the bug down to
> what appears to be a stack overflow. These two functions in interpret.c seem to
> call each other repeatedly.
> 
> Expression *ThisExp::interpret(InterState *istate)
> {
>     if (istate && istate->localThis)
>         return istate->localThis->interpret(istate);
>     error("value of 'this' is not known at compile time");
>     return EXP_CANT_INTERPRET;
> }
> 
> Expression *DotVarExp::interpret(InterState *istate)
> {   Expression *e = EXP_CANT_INTERPRET;
> 
> #if LOG
>     printf("DotVarExp::interpret() %s\n", toChars());
> #endif
> 
>     Expression *ex = e1->interpret(istate); // <- we never get past here
>     if (ex != EXP_CANT_INTERPRET)
>     {
>         if (ex->op == TOKstructliteral)
>         {   StructLiteralExp *se = (StructLiteralExp *)ex;
>             VarDeclaration *v = var->isVarDeclaration();
>             if (v)
>             {   e = se->getField(type, v->offset);
>                 if (!e)
>                 {
>                     error("couldn't find field %s in %s", v->toChars(),
> type->toChars());
>                     e = EXP_CANT_INTERPRET;
>                 }
>                 return e;
>             }
>         }
>         else
>             error("%s.%s is not yet implemented at compile time", e1->toChars(),
> var->toChars());
>     }
> 
> 
> If you turn logging on for the file you get this:
> 
> CallExp::interpret() MatrixASTNode(LeafType()).Compile()
> 
> ********
> FuncDeclaration::interpret(istate = (nil)) Compile
> cantInterpret = 0, semanticRun = 5
> StructLiteralExp::interpret() MatrixASTNode(LeafType())
> StructLiteralExp::interpret() LeafType()
> CompoundStatement::interpret()
> ExpStatement::interpret(assert(&this,"null this"))
> AssertExp::interpret() assert(&this,"null this")
> StructLiteralExp::interpret() MatrixASTNode(LeafType())
> StructLiteralExp::interpret() LeafType()
> ReturnStatement::interpret(this.Right.Compile_not_ovloaded())
> CallExp::interpret() this.Right.Compile_not_ovloaded()
> 
> ********
> FuncDeclaration::interpret(istate = 0xbfe685a0) Compile_not_ovloaded
> cantInterpret = 0, semanticRun = 5
> DotVarExp::interpret() this.Right
> StructLiteralExp::interpret() MatrixASTNode(LeafType())
> StructLiteralExp::interpret() LeafType()
> CompoundStatement::interpret()
> ExpStatement::interpret(assert(&this,"null this"))
> AssertExp::interpret() assert(&this,"null this")
> DotVarExp::interpret() this.Right
> DotVarExp::interpret() this.Right
> DotVarExp::interpret() this.Right
> DotVarExp::interpret() this.Right
> ...an so on until stack overflow
> 
> 
> The reason for the recursion happens is that in the contect of
> DotVarExp::interpret istate->localThis == this so in ThisExp::interpret the
> statement
> 
> istate->localThis->interpret(istate);
> 
> goes right back to DotVarExp::interpret again.
> 
> Unfortunately I don't really know enough about the internals of dmd so say what
> the fix is, but I hope this information is helpful.

Please file a bug report:  http://d.puremagic.com/issues/




More information about the Digitalmars-d mailing list