digitalmars.D - A CTFE Segfault (with explanation, but I'm not sure what the fix
- Gareth Charnock (92/92) Nov 21 2010 This code makes the DMD compiler segfault
- Brad Roberts (2/114) Nov 21 2010 Please file a bug report: http://d.puremagic.com/issues/
- Gareth Charnock (4/118) Nov 21 2010 Done.
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.
Nov 21 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/
Nov 21 2010
Done. http://d.puremagic.com/issues/show_bug.cgi?id=5248 I'm sorry if I'm a bit over-cautious before submitting bugs. On 21/11/10 22:18, Brad Roberts wrote: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/
Nov 21 2010