www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A CTFE Segfault (with explanation, but I'm not sure what the fix

reply Gareth Charnock <gareth.charnock gmail.com> writes:
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
next sibling parent Gareth Charnock <gareth.charnock gmail.com> writes:
Sorry, wrong mailing list. This should have gone to d.D
Nov 21 2010
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Gareth Charnock:

 struct LeafType {
 	string Compile_not_ovloaded() {
 		return "expression";
 	}
 };
Note that D structs don't require the ending semicolon, so in practice it is not used. And in D method names start with a lower case. Bye, bearophile
Nov 21 2010
next sibling parent reply =?ISO-8859-1?Q?Per_=C5ngstr=F6m?= <d-news autark.se> writes:
On 2010-11-21 23:39, bearophile wrote:
 Gareth Charnock:

 	string Compile_not_ovloaded() {
 		return "expression";
 	}
Note that [...] in D method names start with a lower case.
Surely this must be more of a convention than a rule. Unless you are writing a standard library I think you should be able to use whatever capitalization standard you find appropriate. -- Cheers, Per Å.
Nov 22 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Per Ångström:

 Surely this must be more of a convention than a rule. Unless you are 
 writing a standard library I think you should be able to use whatever 
 capitalization standard you find appropriate.
If you live in a cave and there is zero probability that I will see and use the D code you write, then you are free to write D code as you like. Otherwise if you want to contribute the D community with your code, then you are supposed to follow basic language conventions, like using struct/class names that start with upper case, function/method names that start with lower case, and no underscores inside them. Bye, bearophile
Nov 22 2010
parent reply =?ISO-8859-1?Q?Per_=C5ngstr=F6m?= <d-news autark.se> writes:
On 2010-11-22 13:20, bearophile wrote:
 Per Ångström:

 Surely this must be more of a convention than a rule. Unless you are
 writing a standard library I think you should be able to use whatever
 capitalization standard you find appropriate.
If you live in a cave and there is zero probability that I will see and use the D code you write, then you are free to write D code as you like. Otherwise if you want to contribute the D community with your code, then you are supposed to follow basic language conventions, like using struct/class names that start with upper case, function/method names that start with lower case, and no underscores inside them. Bye, bearophile
I haven't yet found the official document describing the naming standard for D, so seeing such an assertive statement from you just had to trigger a reaction in me. Actually, I tend to use the same basic convention as you, but there are other conventions that are equally valid, in my view. I see you have now started a thread in d.D about this. That will be interesting. -- Cheers, Per Å.
Nov 22 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
Per Ångström:

 I haven't yet found the official document describing the naming standard 
 for D,
http://www.digitalmars.com/d/2.0/dstyle.html
 but there are other conventions that are equally valid, in my view.
I agree. But the point of a standard is to use just one. Bye, bearophile
Nov 22 2010
parent Don <nospam nospam.com> writes:
bearophile wrote:
 Per Ångström:
 
 I haven't yet found the official document describing the naming standard 
 for D,
http://www.digitalmars.com/d/2.0/dstyle.html
That's not really authoritative. That was written by Walter, without any consultation with anybody else. Consider it to be a draft, rather than a ratified standard.
 but there are other conventions that are equally valid, in my view.
I agree. But the point of a standard is to use just one. Bye, bearophile
Nov 22 2010
prev sibling parent Gareth Charnock <gareth.charnock gmail.com> writes:
On 21/11/10 22:39, bearophile wrote:
 Gareth Charnock:

 struct LeafType {
 	string Compile_not_ovloaded() {
 		return "expression";
 	}
 };
Note that D structs don't require the ending semicolon, so in practice it is not used. And in D method names start with a lower case. Bye, bearophile
Okay, but this was completely experimental code unlikely to see the light of day. I like to put the semicolon after the struct to keep in the habit (otherwise when I use C++ I start forgetting). The "_not_ovloaded" bit was to check the bug wasn't anything to do with overloading (it wasn't).
Dec 08 2010