Thread overview
A CTFE Segfault (with explanation, but I'm not sure what the fix is).
Nov 21, 2010
Gareth Charnock
Nov 21, 2010
Gareth Charnock
Re: A CTFE Segfault (with explanation, but I'm not sure what the fix
Nov 21, 2010
bearophile
Nov 22, 2010
Per Ångström
Re: A CTFE Segfault (with explanation, but I'm not sure what the
Nov 22, 2010
bearophile
Nov 22, 2010
Per Ångström
Nov 22, 2010
bearophile
Nov 23, 2010
Don
Dec 08, 2010
Gareth Charnock
November 21, 2010
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.


November 21, 2010
Sorry, wrong mailing list. This should have gone to d.D
November 21, 2010
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
November 22, 2010
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 Å.
November 22, 2010
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
November 22, 2010
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 Å.
November 22, 2010
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
November 23, 2010
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
December 08, 2010
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).