The following code crashes both DMD 2.048 and 2.049 beta on Windows:
// Module a.d
class Base {
auto fun() { return 1; }
}
// Module b.d
import a;
class Derived : Base {}
// Command
dmd -c b.d
Any of the following will prevent this bug from being reproduced:
1. Changing the return type of fun from auto to int.
2. Passing both modules to DMD at once.
3. Putting both classes in the same module.
Comment #1 by clugdbug — 2010-09-14T20:52:39Z
Not a regression. This fails on 2.026 and later.
Comment #2 by clugdbug — 2010-09-14T21:02:06Z
The segfault should be turned into an ICE with this code: toctype.c, line 254
TypeFunction::toCtype()
if (varargs != 1)
t->Tflags |= TFfixed;
ctype = t;
+ assert(next);
t->Tnext = next->toCtype();
Comment #3 by clugdbug — 2010-09-14T23:57:45Z
This is happening because semantic3() isn't run on the base class function.
Bug 3602 has a similar root cause.
A workaround is to use the function in module b.d. This forces semantic3 to be run on 'fun'.
void workaround(Derived d)
{
auto k = d.fun();
}
Mitigation patch (turns it into rejects-valid):
---------
tocsym.c, line 349, FuncDeclaration::toSymbol()
s = symbol_calloc(id);
slist_add(s);
+ // Ensure function has a return value
+ if (type->ty == Tfunction && !((TypeFunction *)type)->next)
+ {
+ error("Internal Compiler Error. See Bugzilla 4869.");
+ // Prevent a later crash
+ ((TypeFunction *)type)->next = Type::tint32;
+ }
{
s->prettyIdent = toPrettyChars();
s->Sclass = SCglobal;
symbol_func(s);
Comment #4 by clugdbug — 2010-09-15T05:06:45Z
Proper patch. The assert in comment 2 should still be added.
toobj.c line 790. ClassDeclaration::toObjFile(). Ensure each function has had
semantic3 run on it, if the return type is still unknown. (Ideally, this should
happen earlier on, but better late than never).
for (; i < vtbl.dim; i++)
{
FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
//printf("\tvtbl[%d] = %p\n", i, fd);
if (fd && (fd->fbody || !isAbstract()))
{
+ // Ensure function has a return value (Bugzilla 4869)
+ if (fd->type->ty == Tfunction && !((TypeFunction *)fd->type)->next)
+ {
+ assert(fd->scope);
+ fd->semantic3(fd->scope);
+ }
Symbol *s = fd->toSymbol();