http://d.puremagic.com/issues/show_bug.cgi?id=8466



--- Comment #1 from Chad Joan <chadj...@gmail.com> 2012-08-05 11:52:49 PDT ---
I've been trying to fix this one.  I'm probably going to give up.

In class.c I added this code:
Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
{
    // Search bases classes in depth-first, left to right order

    for (size_t i = 0; i < baseclasses->dim; i++)
    {
        BaseClass *b = (*baseclasses)[i];
        Dsymbol *cdb = b->type->isClassHandle();
+       if (cdb == NULL)
+           return NULL;
        if (cdb->ident->equals(ident))
            return cdb;
        cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident);
        if (cdb)
            return cdb;
    }
    return NULL;
}

This eliminates the segfault and allows dmd to throw error messages closer to
the source of the problem.

With that in hand I returned to dustmite with the code that I reduced into the
first test case I posted, and then instead reduced it into this:


I created a new test case:

class SpaceSeq(Expr) {
}

class ZeroOrMore(Expr) {
    dstring ruleName = Expr.ruleName;
}

class PatternExpressions : ZeroOrMore!PatternExpression{
}

class PatternExpression : BinaryExpression
{
    dstring ruleName = "PatternExpression";
}

class BlockExpression : SpaceSeq!(PatternExpression)
{
}

Invalid code for a couple reasons: BinaryExpression is undefined and
Expr.ruleName is not compile-time evaluatable.  It instead gives me this odd
error message:
pml.d(17): Error: SpaceSeq!(_error_) is used as a type

I found out that it should be erroring around line 340 of class.c in the "void
ClassDeclaration::semantic(Scope *sc)" method because of the non-existant
"BinaryExpression" base class in the test.  This is the code that should do it:
        b = (*baseclasses)[0];
        //b->type = b->type->semantic(loc, sc);
        tb = b->type->toBasetype();
        if (tb->ty != Tclass)
        {   if (b->type != Type::terror)
                error("base type must be class or interface, not %s",
b->type->toChars());
            baseclasses->remove(0);
        }
        else

However, the call to error(...) was completely silent.  Even the earlier call
that should have said "undefined identifier BinaryExpression" gets silenced.  

I dig around a lot.  I'm told on IRC that there is a global.gag variable that
can cause this.  Who would have guessed?  More digging leads me to around line
1500 in declaration.c where I find this code:

            /* Because we may need the results of a const declaration in a
             * subsequent type, such as an array dimension, before semantic2()
             * gets ordinarily run, try to run semantic2() now.
             * Ignore failure.
             */

            if (!global.errors && !inferred)
            {
                unsigned errors = global.startGagging();
                Expression *e;
                Initializer *i2 = init;
                inuse++;

So it seems that in "void VarDeclaration::semantic(Scope *sc)" it attempts to
do some semantic analysis that calls ClassDeclaration::semantic().  It's the
semantic analysis for PatternExpression's declaration in the test case.  It
/should/ error but the calling code gagged it.  It's OK because the calling
code has a reason.  However, later on the same semantic analysis for
PatternExpression is called, but it returns success that time because semantic
analysis has already been run!  This all means that it is possible to run
semantic analysis on stuff without actually having done so!  I'm sure that
somewhere in this contradiction a NULL value was introduced that caused the
later segfault.

I'm not inclined to try and change the code in VarDeclaration because I'm not
sure what it is trying to do.  I'm even less inclined to try and engineer it a
way to attempt semantic analysis without causing unintended side-effects. 
There's no way I have time for it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------

Reply via email to