Esempio n. 1
0
void VisitorNodeTyper::visit(ExprOP2 *n){
    n->getLeft()->accept(*this);
    TypeClass* tc = dynamic_cast<TypeClass*>(n->getLeft()->getType());
    Class* old_cur_class = this->cur_class;
    this->cur_class = tc ? tc->getClass() : 0;
    n->getRight()->accept(*this);
    // Type of binary operator is type of operands (with promotion), except for comparison operators
    if (   n->getOperator() == ExprOP2::LT || n->getOperator() == ExprOP2::LTE
        || n->getOperator() == ExprOP2::GT || n->getOperator() == ExprOP2::GTE
        || n->getOperator() == ExprOP2::EQ || n->getOperator() == ExprOP2::NEQ
    )
    {
        n->setType(TypePrimary::getBool());
    }
    else if (n->getOperator() == ExprOP2::DOT)
    {
        if (!tc)
            throw __FILE__ "(" QUOTE(__LINE__) "): Left hand side of . operator must be an object / class.";
        n->setType(n->getRight()->getType());
    }
    else if (n->getOperator() == ExprOP2::ARRAY)
    {
        // TODO Check rhs type
        TypeArray* ta = dynamic_cast<TypeArray*>(n->getLeft()->getType());
        if (!ta)
            throw __FILE__ "(" QUOTE(__LINE__) "): Left hand side of [] operator must be an array.";
        n->setType(ta->getType());
    }
    else    // All other operators
    {
        n->setType(n->getLeft()->getType());
    }
    this->cur_class = old_cur_class;
}
Esempio n. 2
0
void ClassDeclaration::semantic(Scope *sc)
{
    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
    //printf("sc->stc = %x\n", sc->stc);

    //{ static int n;  if (++n == 20) *(char*)0=0; }

    if (!ident)         // if anonymous class
    {   const char *id = "__anonclass";

        ident = Identifier::generateId(id);
    }

    if (!sc)
        sc = scope;
    if (!parent && sc->parent && !sc->parent->isModule())
        parent = sc->parent;

    type = type->semantic(loc, sc);

    if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
    {
        TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
        if (ti && ti->errors)
            ((TypeClass *)type)->sym = this;
    }

    if (!members)               // if opaque declaration
    {   //printf("\tclass '%s' is forward referenced\n", toChars());
        return;
    }
    if (symtab)
    {   if (sizeok == SIZEOKdone || !scope)
        {   //printf("\tsemantic for '%s' is already completed\n", toChars());
            return;             // semantic() already completed
        }
    }
    else
        symtab = new DsymbolTable();

    Scope *scx = NULL;
    if (scope)
    {
        sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }
    unsigned dprogress_save = Module::dprogress;
    int errors = global.errors;

    if (sc->stc & STCdeprecated)
    {
        isdeprecated = true;
    }
    userAttribDecl = sc->userAttribDecl;

    if (sc->linkage == LINKcpp)
        cpp = 1;

    // Expand any tuples in baseclasses[]
    for (size_t i = 0; i < baseclasses->dim; )
    {
        // Ungag errors when not speculative
        Ungag ungag = ungagSpeculative();

        BaseClass *b = (*baseclasses)[i];
        b->type = b->type->semantic(loc, sc);

        Type *tb = b->type->toBasetype();
        if (tb->ty == Ttuple)
        {   TypeTuple *tup = (TypeTuple *)tb;
            PROT protection = b->protection;
            baseclasses->remove(i);
            size_t dim = Parameter::dim(tup->arguments);
            for (size_t j = 0; j < dim; j++)
            {   Parameter *arg = Parameter::getNth(tup->arguments, j);
                b = new BaseClass(arg->type, protection);
                baseclasses->insert(i + j, b);
            }
        }
        else
            i++;
    }

    // See if there's a base class as first in baseclasses[]
    if (baseclasses->dim)
    {
        // Ungag errors when not speculative
        Ungag ungag = ungagSpeculative();

        BaseClass *b = (*baseclasses)[0];
        //b->type = b->type->semantic(loc, sc);

        Type *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
        {
            TypeClass *tc = (TypeClass *)(tb);

            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = true;

                    tc->checkDeprecated(loc, sc);
                }
            }

            if (tc->sym->isInterfaceDeclaration())
                ;
            else
            {
                for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
                {
                    if (cdb == this)
                    {
                        error("circular inheritance");
                        baseclasses->remove(0);
                        goto L7;
                    }
                }
                if (tc->sym->scope)
                {
                    // Try to resolve forward reference
                    tc->sym->semantic(NULL);
                }

                if (tc->sym->symtab && tc->sym->scope == NULL)
                {
                    /* Bugzilla 11034: Essentailly, class inheritance hierarchy
                     * and instance size of each classes are orthogonal information.
                     * Therefore, even if tc->sym->sizeof == SIZEOKnone,
                     * we need to set baseClass field for class covariance check.
                     */
                    baseClass = tc->sym;
                    b->base = baseClass;
                }
                if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
                {
                    //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
                    //error("forward reference of base class %s", baseClass->toChars());
                    // Forward reference of base class, try again later
                    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
                    scope = scx ? scx : sc->copy();
                    scope->setNoFree();
                    if (tc->sym->scope)
                        tc->sym->scope->module->addDeferredSemantic(tc->sym);
                    scope->module->addDeferredSemantic(this);
                    return;
                }
             L7: ;
            }
        }
    }

    // Treat the remaining entries in baseclasses as interfaces
    // Check for errors, handle forward references
    for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
    {
        // Ungag errors when not speculative
        Ungag ungag = ungagSpeculative();

        BaseClass *b = (*baseclasses)[i];
        b->type = b->type->semantic(loc, sc);

        Type *tb = b->type->toBasetype();
        TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
        if (!tc || !tc->sym->isInterfaceDeclaration())
        {
            if (b->type != Type::terror)
                error("base type must be interface, not %s", b->type->toChars());
            baseclasses->remove(i);
            continue;
        }
        else
        {
            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = true;

                    tc->checkDeprecated(loc, sc);
                }
            }

            // Check for duplicate interfaces
            for (size_t j = (baseClass ? 1 : 0); j < i; j++)
            {
                BaseClass *b2 = (*baseclasses)[j];
                if (b2->base == tc->sym)
                    error("inherits from duplicate interface %s", b2->base->toChars());
            }

            if (tc->sym->scope)
            {
                // Try to resolve forward reference
                tc->sym->semantic(NULL);
            }

            b->base = tc->sym;
            if (!b->base->symtab || b->base->scope)
            {
                //error("forward reference of base class %s", baseClass->toChars());
                // Forward reference of base, try again later
                //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
                scope = scx ? scx : sc->copy();
                scope->setNoFree();
                if (tc->sym->scope)
                    tc->sym->scope->module->addDeferredSemantic(tc->sym);
                scope->module->addDeferredSemantic(this);
                return;
            }
        }
        i++;
    }
    if (doAncestorsSemantic == SemanticIn)
        doAncestorsSemantic = SemanticDone;


    if (sizeok == SIZEOKnone)
    {
        // If no base class, and this is not an Object, use Object as base class
        if (!baseClass && ident != Id::Object && !cpp)
        {
            if (!object)
            {
                error("missing or corrupt object.d");
                fatal();
            }

            Type *t = object->type;
            t = t->semantic(loc, sc)->toBasetype();
            assert(t->ty == Tclass);
            TypeClass *tc = (TypeClass *)t;

            BaseClass *b = new BaseClass(tc, PROTpublic);
            baseclasses->shift(b);

            baseClass = tc->sym;
            assert(!baseClass->isInterfaceDeclaration());
            b->base = baseClass;
        }

        interfaces_dim = baseclasses->dim;
        interfaces = baseclasses->tdata();

        if (baseClass)
        {
            if (baseClass->storage_class & STCfinal)
                error("cannot inherit from final class %s", baseClass->toChars());

            interfaces_dim--;
            interfaces++;

            // Copy vtbl[] from base class
            vtbl.setDim(baseClass->vtbl.dim);
            memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);

            // Inherit properties from base class
            com = baseClass->isCOMclass();
            if (baseClass->isCPPclass())
                cpp = 1;
            isscope = baseClass->isscope;
            vthis = baseClass->vthis;
            enclosing = baseClass->enclosing;
            storage_class |= baseClass->storage_class & STC_TYPECTOR;
        }
        else
        {
            // No base class, so this is the root of the class hierarchy
            vtbl.setDim(0);
            if (vtblOffset())
                vtbl.push(this);            // leave room for classinfo as first member
        }

        protection = sc->protection;
        storage_class |= sc->stc;

        interfaceSemantic(sc);

        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            s->addMember(sc, this, 1);
        }

        /* If this is a nested class, add the hidden 'this'
         * member which is a pointer to the enclosing scope.
         */
        if (vthis)              // if inheriting from nested class
        {
            // Use the base class's 'this' member
            if (storage_class & STCstatic)
                error("static class cannot inherit from nested class %s", baseClass->toChars());
            if (toParent2() != baseClass->toParent2() &&
                (!toParent2() ||
                 !baseClass->toParent2()->getType() ||
                 !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
            {
                if (toParent2())
                {
                    error("is nested within %s, but super class %s is nested within %s",
                        toParent2()->toChars(),
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                else
                {
                    error("is not nested, but super class %s is nested within %s",
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                enclosing = NULL;
            }
        }
        else
            makeNested();

        if (storage_class & STCauto)
            error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
        if (storage_class & STCscope)
            isscope = true;
        if (storage_class & STCabstract)
            isabstract = 1;
    }

    sc = sc->push(this);
    //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
    //sc->stc |= storage_class & STC_TYPECTOR;
    sc->stc &= STCsafe | STCtrusted | STCsystem;
    sc->parent = this;
    sc->inunion = 0;
    if (isCOMclass())
    {
        if (global.params.isWindows)
            sc->linkage = LINKwindows;
        else
            /* This enables us to use COM objects under Linux and
             * work with things like XPCOM
             */
            sc->linkage = LINKc;
    }
    sc->protection = PROTpublic;
    sc->explicitProtection = 0;
    sc->structalign = STRUCTALIGN_DEFAULT;
    if (baseClass)
    {
        sc->offset = baseClass->structsize;
        alignsize = baseClass->alignsize;
        sc->offset = (sc->offset + alignsize - 1) & ~(alignsize - 1);
//      if (enclosing)
//          sc->offset += Target::ptrsize;      // room for uplevel context pointer
    }
    else
    {
        if (cpp)
            sc->offset = Target::ptrsize;       // allow room for __vptr
        else
            sc->offset = Target::ptrsize * 2;   // allow room for __vptr and __monitor
        alignsize = Target::ptrsize;
    }
    sc->userAttribDecl = NULL;
    structsize = sc->offset;
    Scope scsave = *sc;
    size_t members_dim = members->dim;
    sizeok = SIZEOKnone;

    /* Set scope so if there are forward references, we still might be able to
     * resolve individual members like enums.
     */
    for (size_t i = 0; i < members_dim; i++)
    {
        Dsymbol *s = (*members)[i];
        //printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc);
        s->setScope(sc);
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];
        s->importAll(sc);
    }

    for (size_t i = 0; i < members_dim; i++)
    {
        Dsymbol *s = (*members)[i];

        // Ungag errors when not speculative
        Ungag ungag = ungagSpeculative();
        s->semantic(sc);
    }

    // Set the offsets of the fields and determine the size of the class

    unsigned offset = structsize;
    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];
        s->setFieldOffset(this, &offset, false);
    }
    sc->offset = structsize;

    if (global.errors != errors)
    {
        // The type is no good.
        type = Type::terror;
    }

    if (sizeok == SIZEOKfwd)            // failed due to forward references
    {
        // semantic() failed due to forward references
        // Unwind what we did, and defer it for later
        for (size_t i = 0; i < fields.dim; i++)
        {
            VarDeclaration *v = fields[i];
            v->offset = 0;
        }
        fields.setDim(0);
        structsize = 0;
        alignsize = 0;
//        structalign = 0;

        sc = sc->pop();

        scope = scx ? scx : sc->copy();
        scope->setNoFree();
        scope->module->addDeferredSemantic(this);

        Module::dprogress = dprogress_save;

        //printf("\tsemantic('%s') failed due to forward references\n", toChars());
        return;
    }

    //printf("\tsemantic('%s') successful\n", toChars());

    //members->print();

    /* Look for special member functions.
     * They must be in this class, not in a base class.
     */
    searchCtor();
    if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration())))
        ctor = NULL;    // search() looks through ancestor classes
    if (!ctor && noDefaultCtor)
    {
        // A class object is always created by constructor, so this check is legitimate.
        for (size_t i = 0; i < fields.dim; i++)
        {
            VarDeclaration *v = fields[i];
            if (v->storage_class & STCnodefaultctor)
                ::error(v->loc, "field %s must be initialized in constructor", v->toChars());
        }
    }

    inv = buildInv(this, sc);

    // Can be in base class
    aggNew    =    (NewDeclaration *)search(Loc(), Id::classNew);
    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);

    // If this class has no constructor, but base class has a default
    // ctor, create a constructor:
    //    this() { }
    if (!ctor && baseClass && baseClass->ctor)
    {
        FuncDeclaration *fd = resolveFuncCall(loc, sc, baseClass->ctor, NULL, NULL, NULL, 1);
        if (fd && !fd->errors)
        {
            //printf("Creating default this(){} for class %s\n", toChars());
            TypeFunction *btf = (TypeFunction *)fd->type;
            TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
            tf->purity = btf->purity;
            tf->isnothrow = btf->isnothrow;
            tf->trust = btf->trust;
            CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
            ctor->fbody = new CompoundStatement(Loc(), new Statements());
            members->push(ctor);
            ctor->addMember(sc, this, 1);
            *sc = scsave;   // why? What about sc->nofree?
            ctor->semantic(sc);
            this->ctor = ctor;
            defaultCtor = ctor;
        }
        else
        {
            error("Cannot implicitly generate a default ctor when base class %s is missing a default ctor", baseClass->toPrettyChars());
        }
    }

#if 0
    if (baseClass)
    {   if (!aggDelete)
            aggDelete = baseClass->aggDelete;
        if (!aggNew)
            aggNew = baseClass->aggNew;
    }
#endif

    // Allocate instance of each new interface
    sc->offset = structsize;
    for (size_t i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (*vtblInterfaces)[i];
        unsigned thissize = Target::ptrsize;

        alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset);
        assert(b->offset == 0);
        b->offset = sc->offset;

        // Take care of single inheritance offsets
        while (b->baseInterfaces_dim)
        {
            b = &b->baseInterfaces[0];
            b->offset = sc->offset;
        }

        sc->offset += thissize;
        if (alignsize < thissize)
            alignsize = thissize;
    }
    structsize = sc->offset;
    sizeok = SIZEOKdone;
    Module::dprogress++;

    dtor = buildDtor(this, sc);
    if (FuncDeclaration *f = hasIdentityOpAssign(this, sc))
    {
        if (!(f->storage_class & STCdisable))
            error(f->loc, "identity assignment operator overload is illegal");
    }
    sc->pop();

#if 0 // Do not call until toObjfile() because of forward references
    // Fill in base class vtbl[]s
    for (i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (*vtblInterfaces)[i];

        //b->fillVtbl(this, &b->vtbl, 1);
    }
#endif
    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);

    if (deferred && !global.gag)
    {
        deferred->semantic2(sc);
        deferred->semantic3(sc);
    }

#if 0
    if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
    {
        printf("this = %p %s\n", this, this->toChars());
        printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym);
      }
#endif
    assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
}
Esempio n. 3
0
LLType* DtoType(Type* t)
{
    t = stripModifiers( t );

    if (t->ctype)
    {
        return t->ctype->getLLType();
    }

    IF_LOG Logger::println("Building type: %s", t->toChars());
    LOG_SCOPE;

    assert(t);
    switch (t->ty)
    {
    // basic types
    case Tvoid:
    case Tint8:
    case Tuns8:
    case Tint16:
    case Tuns16:
    case Tint32:
    case Tuns32:
    case Tint64:
    case Tuns64:
    case Tint128:
    case Tuns128:
    case Tfloat32:
    case Tfloat64:
    case Tfloat80:
    case Timaginary32:
    case Timaginary64:
    case Timaginary80:
    case Tcomplex32:
    case Tcomplex64:
    case Tcomplex80:
    //case Tbit:
    case Tbool:
    case Tchar:
    case Twchar:
    case Tdchar:
    {
        return IrTypeBasic::get(t)->getLLType();
    }

    // pointers
    case Tnull:
    case Tpointer:
    {
        return IrTypePointer::get(t)->getLLType();
    }

    // arrays
    case Tarray:
    {
        return IrTypeArray::get(t)->getLLType();
    }

    case Tsarray:
    {
        return IrTypeSArray::get(t)->getLLType();
    }

    // aggregates
    case Tstruct:
    {
        TypeStruct* ts = static_cast<TypeStruct*>(t);
        if (ts->sym->type->ctype)
        {
            // This should not happen, but the frontend seems to be buggy. Not
            // sure if this is the best way to handle the situation, but we
            // certainly don't want to override ts->sym->type->ctype.
            IF_LOG Logger::cout() << "Struct with multiple Types detected: " <<
                ts->toChars() << " (" << ts->sym->locToChars() << ")" << std::endl;
            return ts->sym->type->ctype->getLLType();
        }
        return IrTypeStruct::get(ts->sym)->getLLType();
    }
    case Tclass:
    {
        TypeClass* tc = static_cast<TypeClass*>(t);
        if (tc->sym->type->ctype)
        {
            // See Tstruct case.
            IF_LOG Logger::cout() << "Class with multiple Types detected: " <<
                tc->toChars() << " (" << tc->sym->locToChars() << ")" << std::endl;
            return tc->sym->type->ctype->getLLType();
        }
        return IrTypeClass::get(tc->sym)->getLLType();
    }

    // functions
    case Tfunction:
    {
        return IrTypeFunction::get(t)->getLLType();
    }

    // delegates
    case Tdelegate:
    {
        return IrTypeDelegate::get(t)->getLLType();
    }

    // typedefs
    // enum

    // FIXME: maybe just call toBasetype first ?
    case Tenum:
    {
        Type* bt = t->toBasetype();
        assert(bt);
        return DtoType(bt);
    }

    // associative arrays
    case Taarray:
        return getVoidPtrType();

    case Tvector:
    {
        return IrTypeVector::get(t)->getLLType();
    }

/*
    Not needed atm as VarDecls for tuples are rewritten as a string of
    VarDecls for the fields (u -> _u_field_0, ...)

    case Ttuple:
    {
        TypeTuple* ttupl = static_cast<TypeTuple*>(t);
        return DtoStructTypeFromArguments(ttupl->arguments);
    }
*/

    default:
        llvm_unreachable("Unknown class of D Type!");
    }
    return 0;
}
Esempio n. 4
0
File: class.c Progetto: OpenFlex/ldc
void ClassDeclaration::semantic(Scope *sc)
{
    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
    //printf("sc->stc = %x\n", sc->stc);

    //{ static int n;  if (++n == 20) *(char*)0=0; }

    if (!ident)         // if anonymous class
    {   const char *id = "__anonclass";

        ident = Identifier::generateId(id);
    }

    if (!sc)
        sc = scope;
    if (!parent && sc->parent && !sc->parent->isModule())
        parent = sc->parent;

    type = type->semantic(loc, sc);
    handle = type;

    if (!members)                       // if forward reference
    {   //printf("\tclass '%s' is forward referenced\n", toChars());
        return;
    }
    if (symtab)
    {   if (sizeok == SIZEOKdone || !scope)
        {   //printf("\tsemantic for '%s' is already completed\n", toChars());
            return;             // semantic() already completed
        }
    }
    else
        symtab = new DsymbolTable();

    Scope *scx = NULL;
    if (scope)
    {   sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }
    unsigned dprogress_save = Module::dprogress;
    int errors = global.gaggedErrors;

    if (sc->stc & STCdeprecated)
    {
        isdeprecated = true;
    }
    userAttributes = sc->userAttributes;

    if (sc->linkage == LINKcpp)
        error("cannot create C++ classes");

    // Expand any tuples in baseclasses[]
    for (size_t i = 0; i < baseclasses->dim; )
    {   BaseClass *b = (*baseclasses)[i];
        b->type = b->type->semantic(loc, sc);
        Type *tb = b->type->toBasetype();

        if (tb->ty == Ttuple)
        {   TypeTuple *tup = (TypeTuple *)tb;
            enum PROT protection = b->protection;
            baseclasses->remove(i);
            size_t dim = Parameter::dim(tup->arguments);
            for (size_t j = 0; j < dim; j++)
            {   Parameter *arg = Parameter::getNth(tup->arguments, j);
                b = new BaseClass(arg->type, protection);
                baseclasses->insert(i + j, b);
            }
        }
        else
            i++;
    }

    // See if there's a base class as first in baseclasses[]
    if (baseclasses->dim)
    {   TypeClass *tc;
        BaseClass *b;
        Type *tb;

        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
        {
            tc = (TypeClass *)(tb);

            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = true;

                    tc->checkDeprecated(loc, sc);
                }
            }

            if (tc->sym->isInterfaceDeclaration())
                ;
            else
            {
                for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
                {
                    if (cdb == this)
                    {
                        error("circular inheritance");
                        baseclasses->remove(0);
                        goto L7;
                    }
                }
                if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
                {   // Try to resolve forward reference
                    if (/*sc->mustsemantic &&*/ tc->sym->scope)
                        tc->sym->semantic(NULL);
                }
                if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
                {
                    //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
                    //error("forward reference of base class %s", baseClass->toChars());
                    // Forward reference of base class, try again later
                    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
                    scope = scx ? scx : new Scope(*sc);
                    scope->setNoFree();
                    if (tc->sym->scope)
                        tc->sym->scope->module->addDeferredSemantic(tc->sym);
                    scope->module->addDeferredSemantic(this);
                    return;
                }
                else
                {   baseClass = tc->sym;
                    b->base = baseClass;
                }
             L7: ;
            }
        }
    }

    // Treat the remaining entries in baseclasses as interfaces
    // Check for errors, handle forward references
    for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
    {   TypeClass *tc;
        BaseClass *b;
        Type *tb;

        b = (*baseclasses)[i];
        b->type = b->type->semantic(loc, sc);
        tb = b->type->toBasetype();
        if (tb->ty == Tclass)
            tc = (TypeClass *)tb;
        else
            tc = NULL;
        if (!tc || !tc->sym->isInterfaceDeclaration())
        {   if (b->type != Type::terror)
                error("base type must be interface, not %s", b->type->toChars());
            baseclasses->remove(i);
            continue;
        }
        else
        {
            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = true;

                    tc->checkDeprecated(loc, sc);
                }
            }

            // Check for duplicate interfaces
            for (size_t j = (baseClass ? 1 : 0); j < i; j++)
            {
                BaseClass *b2 = (*baseclasses)[j];
                if (b2->base == tc->sym)
                    error("inherits from duplicate interface %s", b2->base->toChars());
            }

            if (!tc->sym->symtab)
            {   // Try to resolve forward reference
                if (/*sc->mustsemantic &&*/ tc->sym->scope)
                    tc->sym->semantic(NULL);
            }

            b->base = tc->sym;
            if (!b->base->symtab || b->base->scope)
            {
                //error("forward reference of base class %s", baseClass->toChars());
                // Forward reference of base, try again later
                //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
                scope = scx ? scx : new Scope(*sc);
                scope->setNoFree();
                if (tc->sym->scope)
                    tc->sym->scope->module->addDeferredSemantic(tc->sym);
                scope->module->addDeferredSemantic(this);
                return;
            }
        }
        i++;
    }


    // If no base class, and this is not an Object, use Object as base class
    if (!baseClass && ident != Id::Object)
    {
        if (!object)
        {
            error("missing or corrupt object.d");
            fatal();
        }

        Type *t = object->type;
        t = t->semantic(loc, sc)->toBasetype();
        assert(t->ty == Tclass);
        TypeClass *tc = (TypeClass *)t;

        BaseClass *b = new BaseClass(tc, PROTpublic);
        baseclasses->shift(b);

        baseClass = tc->sym;
        assert(!baseClass->isInterfaceDeclaration());
        b->base = baseClass;
    }

    interfaces_dim = baseclasses->dim;
    interfaces = baseclasses->tdata();


    if (baseClass)
    {
        if (baseClass->storage_class & STCfinal)
            error("cannot inherit from final class %s", baseClass->toChars());

        interfaces_dim--;
        interfaces++;

        // Copy vtbl[] from base class
        vtbl.setDim(baseClass->vtbl.dim);
        memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);

        // Inherit properties from base class
        com = baseClass->isCOMclass();
        isscope = baseClass->isscope;
        vthis = baseClass->vthis;
        storage_class |= baseClass->storage_class & STC_TYPECTOR;
    }
    else
    {
        // No base class, so this is the root of the class hierarchy
        vtbl.setDim(0);
        vtbl.push(this);                // leave room for classinfo as first member
    }

    protection = sc->protection;
    storage_class |= sc->stc;

    if (sizeok == SIZEOKnone)
    {
        interfaceSemantic(sc);

        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            s->addMember(sc, this, 1);
        }

        /* If this is a nested class, add the hidden 'this'
         * member which is a pointer to the enclosing scope.
         */
        if (vthis)              // if inheriting from nested class
        {   // Use the base class's 'this' member
            isnested = true;
            if (storage_class & STCstatic)
                error("static class cannot inherit from nested class %s", baseClass->toChars());
            if (toParent2() != baseClass->toParent2() &&
                (!toParent2() ||
                 !baseClass->toParent2()->getType() ||
                 !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
            {
                if (toParent2())
                {
                    error("is nested within %s, but super class %s is nested within %s",
                        toParent2()->toChars(),
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                else
                {
                    error("is not nested, but super class %s is nested within %s",
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                isnested = false;
            }
        }
        else if (!(storage_class & STCstatic))
        {   Dsymbol *s = toParent2();
            if (s)
            {
                AggregateDeclaration *ad = s->isClassDeclaration();
                FuncDeclaration *fd = s->isFuncDeclaration();


                if (ad || fd)
                {   isnested = true;
                    Type *t;
                    if (ad)
                        t = ad->handle;
                    else if (fd)
                    {   AggregateDeclaration *ad2 = fd->isMember2();
                        if (ad2)
                            t = ad2->handle;
                        else
                        {
                            t = Type::tvoidptr;
                        }
                    }
                    else
                        assert(0);
                    if (t->ty == Tstruct)       // ref to struct
                        t = Type::tvoidptr;
                    assert(!vthis);
                    vthis = new ThisDeclaration(loc, t);
                    members->push(vthis);
                }
            }
        }
    }

    if (storage_class & STCauto)
        error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
    if (storage_class & STCscope)
        isscope = 1;
    if (storage_class & STCabstract)
        isabstract = 1;

    sc = sc->push(this);
    //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
    //sc->stc |= storage_class & STC_TYPECTOR;
    sc->stc &= STCsafe | STCtrusted | STCsystem;
    sc->parent = this;
    sc->inunion = 0;

    if (isCOMclass())
    {
#if IN_LLVM
        if (global.params.targetTriple.isOSWindows())
#else
        if (global.params.isWindows)
#endif
            sc->linkage = LINKwindows;
        else
            /* This enables us to use COM objects under Linux and
             * work with things like XPCOM
             */
            sc->linkage = LINKc;
    }
    sc->protection = PROTpublic;
    sc->explicitProtection = 0;
    sc->structalign = STRUCTALIGN_DEFAULT;
    if (baseClass)
    {   sc->offset = baseClass->structsize;
        alignsize = baseClass->alignsize;
//      if (isnested)
//          sc->offset += PTRSIZE;      // room for uplevel context pointer
    }
    else
    {   sc->offset = PTRSIZE * 2;       // allow room for __vptr and __monitor
        alignsize = PTRSIZE;
    }
    sc->userAttributes = NULL;
    structsize = sc->offset;
    Scope scsave = *sc;
    size_t members_dim = members->dim;
    sizeok = SIZEOKnone;

    /* Set scope so if there are forward references, we still might be able to
     * resolve individual members like enums.
     */
    for (size_t i = 0; i < members_dim; i++)
    {   Dsymbol *s = (*members)[i];
        /* There are problems doing this in the general case because
         * Scope keeps track of things like 'offset'
         */
        if (s->isEnumDeclaration() ||
            (s->isAggregateDeclaration() && s->ident) ||
            s->isTemplateMixin() ||
            s->isAttribDeclaration() ||
            s->isAliasDeclaration())
        {
            //printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc);
            s->setScope(sc);
        }
    }

    for (size_t i = 0; i < members_dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->semantic(sc);
    }

    // Set the offsets of the fields and determine the size of the class

    unsigned offset = structsize;
    bool isunion = isUnionDeclaration() != NULL;
    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->setFieldOffset(this, &offset, false);
    }
    sc->offset = structsize;

    if (global.gag && global.gaggedErrors != errors)
    {   // The type is no good, yet the error messages were gagged.
        type = Type::terror;
    }

    if (sizeok == SIZEOKfwd)            // failed due to forward references
    {   // semantic() failed due to forward references
        // Unwind what we did, and defer it for later

        for (size_t i = 0; i < fields.dim; i++)
        {   Dsymbol *s = fields[i];
            VarDeclaration *vd = s->isVarDeclaration();
            if (vd)
                vd->offset = 0;
        }
        fields.setDim(0);
        structsize = 0;
        alignsize = 0;
//        structalign = 0;

        sc = sc->pop();

        scope = scx ? scx : new Scope(*sc);
        scope->setNoFree();
        scope->module->addDeferredSemantic(this);

        Module::dprogress = dprogress_save;

        //printf("\tsemantic('%s') failed due to forward references\n", toChars());
        return;
    }

    //printf("\tsemantic('%s') successful\n", toChars());

    //members->print();

    /* Look for special member functions.
     * They must be in this class, not in a base class.
     */
    ctor = search(0, Id::ctor, 0);
#if DMDV1
    if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
        ctor = NULL;
#else
    if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration())))
        ctor = NULL;    // search() looks through ancestor classes
#endif

//    dtor = (DtorDeclaration *)search(Id::dtor, 0);
//    if (dtor && dtor->toParent() != this)
//      dtor = NULL;

//    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
//    if (inv && inv->toParent() != this)
//      inv = NULL;

    // Can be in base class
    aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);

    // If this class has no constructor, but base class does, create
    // a constructor:
    //    this() { }
    if (!ctor && baseClass && baseClass->ctor)
    {
        //printf("Creating default this(){} for class %s\n", toChars());
        Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
        CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf);
        ctor->isImplicit = true;
        ctor->fbody = new CompoundStatement(0, new Statements());
        members->push(ctor);
        ctor->addMember(sc, this, 1);
        *sc = scsave;   // why? What about sc->nofree?
        ctor->semantic(sc);
        this->ctor = ctor;
        defaultCtor = ctor;
    }

#if 0
    if (baseClass)
    {   if (!aggDelete)
            aggDelete = baseClass->aggDelete;
        if (!aggNew)
            aggNew = baseClass->aggNew;
    }
#endif

    // Allocate instance of each new interface
    sc->offset = structsize;
    for (size_t i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (*vtblInterfaces)[i];
        unsigned thissize = PTRSIZE;

        alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset);
        assert(b->offset == 0);
        b->offset = sc->offset;

        // Take care of single inheritance offsets
        while (b->baseInterfaces_dim)
        {
            b = &b->baseInterfaces[0];
            b->offset = sc->offset;
        }

        sc->offset += thissize;
        if (alignsize < thissize)
            alignsize = thissize;
    }
    structsize = sc->offset;
#if IN_LLVM
    if (sc->structalign == STRUCTALIGN_DEFAULT)
        structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
    else
        structsize = (structsize + sc->structalign - 1) & ~(sc->structalign - 1);
#endif

    sizeok = SIZEOKdone;
    Module::dprogress++;

    dtor = buildDtor(sc);
    if (Dsymbol *assign = search_function(this, Id::assign))
    {
        if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign))
        {
            if (!(f->storage_class & STCdisable))
                error("identity assignment operator overload is illegal");
        }
    }
    sc->pop();

#if 0 // Do not call until toObjfile() because of forward references
    // Fill in base class vtbl[]s
    for (i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (*vtblInterfaces)[i];

        //b->fillVtbl(this, &b->vtbl, 1);
    }
#endif
    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);

    if (deferred && !global.gag)
    {
        deferred->semantic2(sc);
        deferred->semantic3(sc);
    }
}
Esempio n. 5
0
LLType *DtoType(Type *t) {
  t = stripModifiers(t);

  if (t->ctype) {
    return t->ctype->getLLType();
  }

  IF_LOG Logger::println("Building type: %s", t->toChars());
  LOG_SCOPE;

  assert(t);
  switch (t->ty) {
  // basic types
  case Tvoid:
  case Tint8:
  case Tuns8:
  case Tint16:
  case Tuns16:
  case Tint32:
  case Tuns32:
  case Tint64:
  case Tuns64:
  case Tint128:
  case Tuns128:
  case Tfloat32:
  case Tfloat64:
  case Tfloat80:
  case Timaginary32:
  case Timaginary64:
  case Timaginary80:
  case Tcomplex32:
  case Tcomplex64:
  case Tcomplex80:
  // case Tbit:
  case Tbool:
  case Tchar:
  case Twchar:
  case Tdchar: {
    return IrTypeBasic::get(t)->getLLType();
  }

  // pointers
  case Tnull:
  case Tpointer:
  case Treference: { // CALYPSO
    return IrTypePointer::get(t)->getLLType();
  }

  // arrays
  case Tarray: {
    return IrTypeArray::get(t)->getLLType();
  }

  case Tsarray: {
    return IrTypeSArray::get(t)->getLLType();
  }

  // aggregates
  case Tstruct: {
    TypeStruct *ts = static_cast<TypeStruct *>(t);
    if (ts->sym->type->ctype) {
      // This should not happen, but the frontend seems to be buggy. Not
      // sure if this is the best way to handle the situation, but we
      // certainly don't want to override ts->sym->type->ctype.
      IF_LOG Logger::cout()
          << "Struct with multiple Types detected: " << ts->toChars() << " ("
          << ts->sym->locToChars() << ")" << std::endl;
      return ts->sym->type->ctype->getLLType();
    }
    return IrTypeStruct::get(ts->sym)->getLLType();
  }
  case Tclass: {
    TypeClass *tc = static_cast<TypeClass *>(t);
    if (tc->sym->type->ctype) {
      // See Tstruct case.
      IF_LOG Logger::cout()
          << "Class with multiple Types detected: " << tc->toChars() << " ("
          << tc->sym->locToChars() << ")" << std::endl;
      return tc->sym->type->ctype->getLLType();
    }
    return IrTypeClass::get(tc->sym)->getLLType();
  }

  // functions
  case Tfunction: {
    return IrTypeFunction::get(t)->getLLType();
  }

  // delegates
  case Tdelegate: {
    return IrTypeDelegate::get(t)->getLLType();
  }

  // typedefs
  // enum

  // FIXME: maybe just call toBasetype first ?
  case Tenum: {
    Type *bt = t->toBasetype();
    assert(bt);
    if (t == bt) {
      // This is an enum forward reference that is only legal when referenced
      // through an indirection (e.g. "enum E; void foo(E* p);"). For lack of a
      // better choice, make the outer indirection a void pointer.
      return getVoidPtrType()->getContainedType(0);
    }
    return DtoType(bt);
  }

  // associative arrays
  case Taarray:
    return getVoidPtrType();

  case Tvector: {
    return IrTypeVector::get(t)->getLLType();
  }

  default:
    llvm_unreachable("Unknown class of D Type!");
  }
  return nullptr;
}
Esempio n. 6
0
void VisitorNodeTyper::visit(ExprClass *n){
    TypeClass* tc = new TypeClass(n->getClass());
    tc->setStatic(true);
    n->setType(tc);
}
Esempio n. 7
0
void ClassDeclaration::semantic(Scope *sc)
{
    //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
    //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
    //printf("sc->stc = %x\n", sc->stc);

    //{ static int n;  if (++n == 20) *(char*)0=0; }

    if (!ident)         // if anonymous class
    {   const char *id = "__anonclass";

        ident = Identifier::generateId(id);
    }

    if (!sc)
        sc = scope;
    if (!parent && sc->parent && !sc->parent->isModule())
        parent = sc->parent;

    type = type->semantic(loc, sc);
    handle = type;

    if (!members)                       // if forward reference
    {   //printf("\tclass '%s' is forward referenced\n", toChars());
        return;
    }
    if (symtab)
    {   if (sizeok == 1 || !scope)
        {   //printf("\tsemantic for '%s' is already completed\n", toChars());
            return;             // semantic() already completed
        }
    }
    else
        symtab = new DsymbolTable();

    Scope *scx = NULL;
    if (scope)
    {   sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }
    unsigned dprogress_save = Module::dprogress;
#ifdef IN_GCC
    if (attributes)
        attributes->append(sc->attributes);
    else
        attributes = sc->attributes;

    methods.setDim(0);
#endif

    if (sc->stc & STCdeprecated)
    {
        isdeprecated = 1;
    }

    // Expand any tuples in baseclasses[]
    for (size_t i = 0; i < baseclasses->dim; )
    {   BaseClass *b = (BaseClass *)baseclasses->data[i];
        b->type = b->type->semantic(loc, sc);
        Type *tb = b->type->toBasetype();

        if (tb->ty == Ttuple)
        {   TypeTuple *tup = (TypeTuple *)tb;
            enum PROT protection = b->protection;
            baseclasses->remove(i);
            size_t dim = Parameter::dim(tup->arguments);
            for (size_t j = 0; j < dim; j++)
            {   Parameter *arg = Parameter::getNth(tup->arguments, j);
                b = new BaseClass(arg->type, protection);
                baseclasses->insert(i + j, b);
            }
        }
        else
            i++;
    }

    // See if there's a base class as first in baseclasses[]
    if (baseclasses->dim)
    {   TypeClass *tc;
        BaseClass *b;
        Type *tb;

        b = (BaseClass *)baseclasses->data[0];
        //b->type = b->type->semantic(loc, sc);
        tb = b->type->toBasetype();
        if (tb->ty != Tclass)
        {   error("base type must be class or interface, not %s", b->type->toChars());
            baseclasses->remove(0);
        }
        else
        {
            tc = (TypeClass *)(tb);

            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = 1;

                    tc->checkDeprecated(loc, sc);
                }
            }

            if (tc->sym->isInterfaceDeclaration())
                ;
            else
            {
                for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
                {
                    if (cdb == this)
                    {
                        error("circular inheritance");
                        baseclasses->remove(0);
                        goto L7;
                    }
                }
                if (!tc->sym->symtab || tc->sym->sizeok == 0)
                {   // Try to resolve forward reference
                    if (/*sc->mustsemantic &&*/ tc->sym->scope)
                        tc->sym->semantic(NULL);
                }
                if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
                {
                    //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
                    //error("forward reference of base class %s", baseClass->toChars());
                    // Forward reference of base class, try again later
                    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
                    scope = scx ? scx : new Scope(*sc);
                    scope->setNoFree();
                    if (tc->sym->scope)
                        tc->sym->scope->module->addDeferredSemantic(tc->sym);
                    scope->module->addDeferredSemantic(this);
                    return;
                }
                else
                {   baseClass = tc->sym;
                    b->base = baseClass;
                }
             L7: ;
            }
        }
    }

    // Treat the remaining entries in baseclasses as interfaces
    // Check for errors, handle forward references
    for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
    {   TypeClass *tc;
        BaseClass *b;
        Type *tb;

        b = (BaseClass *)baseclasses->data[i];
        b->type = b->type->semantic(loc, sc);
        tb = b->type->toBasetype();
        if (tb->ty == Tclass)
            tc = (TypeClass *)tb;
        else
            tc = NULL;
        if (!tc || !tc->sym->isInterfaceDeclaration())
        {
            error("base type must be interface, not %s", b->type->toChars());
            baseclasses->remove(i);
            continue;
        }
        else
        {
            if (tc->sym->isDeprecated())
            {
                if (!isDeprecated())
                {
                    // Deriving from deprecated class makes this one deprecated too
                    isdeprecated = 1;

                    tc->checkDeprecated(loc, sc);
                }
            }

            // Check for duplicate interfaces
            for (size_t j = (baseClass ? 1 : 0); j < i; j++)
            {
                BaseClass *b2 = (BaseClass *)baseclasses->data[j];
                if (b2->base == tc->sym)
                    error("inherits from duplicate interface %s", b2->base->toChars());
            }

            if (!tc->sym->symtab)
            {   // Try to resolve forward reference
                if (/*sc->mustsemantic &&*/ tc->sym->scope)
                    tc->sym->semantic(NULL);
            }

            b->base = tc->sym;
            if (!b->base->symtab || b->base->scope)
            {
                //error("forward reference of base class %s", baseClass->toChars());
                // Forward reference of base, try again later
                //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
                scope = scx ? scx : new Scope(*sc);
                scope->setNoFree();
                if (tc->sym->scope)
                    tc->sym->scope->module->addDeferredSemantic(tc->sym);
                scope->module->addDeferredSemantic(this);
                return;
            }
        }
        i++;
    }


    // If no base class, and this is not an Object, use Object as base class
    if (!baseClass && ident != Id::Object)
    {
        // BUG: what if Object is redefined in an inner scope?
        Type *tbase = new TypeIdentifier(0, Id::Object);
        BaseClass *b;
        TypeClass *tc;
        Type *bt;

        if (!object)
        {
            error("missing or corrupt object.d");
            fatal();
        }
        bt = tbase->semantic(loc, sc)->toBasetype();
        b = new BaseClass(bt, PROTpublic);
        baseclasses->shift(b);
        assert(b->type->ty == Tclass);
        tc = (TypeClass *)(b->type);
        baseClass = tc->sym;
        assert(!baseClass->isInterfaceDeclaration());
        b->base = baseClass;
    }

    interfaces_dim = baseclasses->dim;
    interfaces = (BaseClass **)baseclasses->data;


    if (baseClass)
    {
        if (baseClass->storage_class & STCfinal)
            error("cannot inherit from final class %s", baseClass->toChars());

        interfaces_dim--;
        interfaces++;

        // Copy vtbl[] from base class
        vtbl.setDim(baseClass->vtbl.dim);
        memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);

        // Inherit properties from base class
        com = baseClass->isCOMclass();
        isscope = baseClass->isscope;
        vthis = baseClass->vthis;
    }
    else
    {
        // No base class, so this is the root of the class hierarchy
        vtbl.setDim(0);
        vtbl.push(this);                // leave room for classinfo as first member
    }

    protection = sc->protection;
    storage_class |= sc->stc;

    if (sizeok == 0)
    {
        interfaceSemantic(sc);

        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (Dsymbol *)members->data[i];
            s->addMember(sc, this, 1);
        }

        /* If this is a nested class, add the hidden 'this'
         * member which is a pointer to the enclosing scope.
         */
        if (vthis)              // if inheriting from nested class
        {   // Use the base class's 'this' member
            isnested = 1;
            if (storage_class & STCstatic)
                error("static class cannot inherit from nested class %s", baseClass->toChars());
            if (toParent2() != baseClass->toParent2())
            {
                if (toParent2())
                {
                    error("is nested within %s, but super class %s is nested within %s",
                        toParent2()->toChars(),
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                else
                {
                    error("is not nested, but super class %s is nested within %s",
                        baseClass->toChars(),
                        baseClass->toParent2()->toChars());
                }
                isnested = 0;
            }
        }
        else if (!(storage_class & STCstatic))
        {   Dsymbol *s = toParent2();
            if (s)
            {
                AggregateDeclaration *ad = s->isClassDeclaration();
                FuncDeclaration *fd = s->isFuncDeclaration();


                if (ad || fd)
                {   isnested = 1;
                    Type *t;
                    if (ad)
                        t = ad->handle;
                    else if (fd)
                    {   AggregateDeclaration *ad2 = fd->isMember2();
                        if (ad2)
                            t = ad2->handle;
                        else
                        {
                            t = new TypePointer(Type::tvoid);
                            t = t->semantic(0, sc);
                        }
                    }
                    else
                        assert(0);
                    assert(!vthis);
                    vthis = new ThisDeclaration(loc, t);
                    members->push(vthis);
                }
            }
        }
    }

    if (storage_class & STCauto)
        error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
    if (storage_class & STCscope)
        isscope = 1;
    if (storage_class & STCabstract)
        isabstract = 1;

    sc = sc->push(this);
    sc->stc &= STCsafe | STCtrusted | STCsystem;
#if IN_GCC
    sc->attributes = NULL;
#endif
    sc->parent = this;
    sc->inunion = 0;

    if (isCOMclass())
    {
#if _WIN32
        sc->linkage = LINKwindows;
#else
        /* This enables us to use COM objects under Linux and
         * work with things like XPCOM
         */
        sc->linkage = LINKc;
#endif
    }
    sc->protection = PROTpublic;
    sc->explicitProtection = 0;
    sc->structalign = 8;
    structalign = sc->structalign;
    if (baseClass)
    {   sc->offset = baseClass->structsize;
        alignsize = baseClass->alignsize;
//      if (isnested)
//          sc->offset += PTRSIZE;      // room for uplevel context pointer
    }
    else
    {   sc->offset = PTRSIZE * 2;       // allow room for __vptr and __monitor
        alignsize = PTRSIZE;
    }
    structsize = sc->offset;
    Scope scsave = *sc;
    size_t members_dim = members->dim;
    sizeok = 0;

    /* Set scope so if there are forward references, we still might be able to
     * resolve individual members like enums.
     */
    for (size_t i = 0; i < members_dim; i++)
    {   Dsymbol *s = (Dsymbol *)members->data[i];
        /* There are problems doing this in the general case because
         * Scope keeps track of things like 'offset'
         */
        if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
        {
            //printf("setScope %s %s\n", s->kind(), s->toChars());
            s->setScope(sc);
        }
    }

    for (size_t i = 0; i < members_dim; i++)
    {   Dsymbol *s = (Dsymbol *)members->data[i];
        s->semantic(sc);
    }

    if (sizeok == 2)
    {   // semantic() failed because of forward references.
        // Unwind what we did, and defer it for later
        fields.setDim(0);
        structsize = 0;
        alignsize = 0;
        structalign = 0;

        sc = sc->pop();

        scope = scx ? scx : new Scope(*sc);
        scope->setNoFree();
        scope->module->addDeferredSemantic(this);

        Module::dprogress = dprogress_save;

        //printf("\tsemantic('%s') failed due to forward references\n", toChars());
        return;
    }

    //printf("\tsemantic('%s') successful\n", toChars());

    structsize = sc->offset;
    //members->print();

    /* Look for special member functions.
     * They must be in this class, not in a base class.
     */
    ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
    if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
        ctor = NULL;

//    dtor = (DtorDeclaration *)search(Id::dtor, 0);
//    if (dtor && dtor->toParent() != this)
//      dtor = NULL;

//    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
//    if (inv && inv->toParent() != this)
//      inv = NULL;

    // Can be in base class
    aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);

    // If this class has no constructor, but base class does, create
    // a constructor:
    //    this() { }
    if (!ctor && baseClass && baseClass->ctor)
    {
        //printf("Creating default this(){} for class %s\n", toChars());
        CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0);
        ctor->fbody = new CompoundStatement(0, new Statements());
        members->push(ctor);
        ctor->addMember(sc, this, 1);
        *sc = scsave;   // why? What about sc->nofree?
        sc->offset = structsize;
        ctor->semantic(sc);
        this->ctor = ctor;
        defaultCtor = ctor;
    }

#if 0
    if (baseClass)
    {   if (!aggDelete)
            aggDelete = baseClass->aggDelete;
        if (!aggNew)
            aggNew = baseClass->aggNew;
    }
#endif

    // Allocate instance of each new interface
    for (size_t i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
        unsigned thissize = PTRSIZE;

        alignmember(structalign, thissize, &sc->offset);
        assert(b->offset == 0);
        b->offset = sc->offset;

        // Take care of single inheritance offsets
        while (b->baseInterfaces_dim)
        {
            b = &b->baseInterfaces[0];
            b->offset = sc->offset;
        }

        sc->offset += thissize;
        if (alignsize < thissize)
            alignsize = thissize;
    }
    structsize = sc->offset;
    sizeok = 1;
    Module::dprogress++;

    dtor = buildDtor(sc);

    sc->pop();

#if 0 // Do not call until toObjfile() because of forward references
    // Fill in base class vtbl[]s
    for (i = 0; i < vtblInterfaces->dim; i++)
    {
        BaseClass *b = (BaseClass *)vtblInterfaces->data[i];

        //b->fillVtbl(this, &b->vtbl, 1);
    }
#endif
    //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
}
void ClassSpecifierAst::walk()
{
    if (checkIsNotWalking()) {
        return ;
    }

    switch (nodeType){
        case T_CCLASSSF_CLASS_ID_CLASSDECTIONLIST:{
            //std::cout << "walk in T_CCLASSSF_CLASS_ID_CLASSDECTIONLIST" << endl;
            LogiMsg::logi("walk in T_CCLASSSF_CLASS_ID_CLASSDECTIONLIST", getLineno());

            childs.at(0)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            //Scope *tmpScope = new Scope();
            if (Scope::resolveScope(s_context->tmpIdenName, Scope::SCOPE_CLASS))
            {
                /*std::cout << "error in T_CCLASSSF_CLASS_ID_CLASSDECTIONLIST: " << s_context->tmpIdenName
                << " has been defined at line " << getLineno() << std::endl;*/
                string errorStr = "error in T_CCLASSSF_CLASS_ID_CLASSDECTIONLIST: "
                + s_context->tmpIdenName + " has been defined";
                LogiMsg::logi(errorStr, getLineno());
                stopWalk();
                return ;
            }

            Scope *tmpScope = new Scope();
            tmpScope->setTotalByteSize(0);
            tmpScope->setTotalFuncByteSize(0);

            tmpScope->initClassScope(s_context->tmpIdenName);
            Scope::pushScope(Scope::s_curScope,tmpScope);
            Scope::setCurScope(tmpScope);

            childs.at(1)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            Scope::setCurScope(Scope::encloseScope(Scope::s_curScope));
            //std::cout<<"safsadfafasfsafasf"<<Scope::s_curScope->scopeName<<std::endl;

            TypeClass tmp;
            //tmp.scopeType = tmpScope;
            tmp.setScopeType(tmpScope);
            tmp.typeSfType = TypeClass::SF_INT;
            s_context->clearContext();
            s_context->tmpDeclType.clone(&tmp);
            break;
        }
        case T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST:{
            //std::cout << "walk in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST" << endl;
            LogiMsg::logi("walk in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST", getLineno());


            childs.at(0)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            //Scope *tmpScope = new Scope();
            if (Scope::resolveScope(s_context->tmpIdenName, Scope::SCOPE_CLASS))
            {
                /*std::cout << "error in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: "
                << s_context->tmpIdenName << " has been defined at line " << getLineno() << std::endl;*/
                string errorStr = "error in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: "
                + s_context->tmpIdenName + " has been defined";
                LogiMsg::logi(errorStr, getLineno());

                stopWalk();
                return ;
            }

            //tmpScope->initClassScope(s_context->tmpIdenName);

            if (childs.at(1)->nodeType!=T_CTERMINATE_CIDLIST_ID)
            {
                /*std::cout << "sorry in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: our compiler do not support multiple inheritance at line "
                << getLineno() << std::endl;*/
                LogiMsg::logi("sorry in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: our compiler do not support multiple inheritance",
                getLineno());
                stopWalk();
                return ;
            }

            Scope *tmpScope = new Scope();

            tmpScope->initClassScope(s_context->tmpIdenName);

            childs.at(1)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            Scope *superScope = Scope::resolveScope(s_context->tmpIdenName, Scope::SCOPE_CLASS);

            if (!superScope)
            {
                /*std::cout<<"error in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: the super class "
                << s_context->tmpIdenName << " does not exit at line " << getLineno() << std::endl;*/
                string errorStr = "error in T_CCLASSSF_CLASS_ID_IDLIST_CLASSDECTIONLIST: the super class "
                + s_context->tmpIdenName + " does not exit";
                LogiMsg::logi(errorStr, getLineno());
                delete tmpScope;

                stopWalk();
                return ;
            }

            tmpScope->setSuperClass(superScope);
            tmpScope->setTotalByteSize(tmpScope->getSuperClass()->getTotalByteSize());
            tmpScope->setTotalFuncByteSize(tmpScope->getSuperClass()->getTotalFuncByteSize());
            Scope::pushScope(Scope::s_curScope,tmpScope);
            Scope::setCurScope(tmpScope);

            childs.at(2)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            Scope::setCurScope(Scope::encloseScope(Scope::s_curScope));

            TypeClass tmp;
            //tmp.scopeType = tmpScope;
            tmp.setScopeType(tmpScope);
            tmp.typeSfType = TypeClass::SF_INT;
            s_context->clearContext();
            s_context->tmpDeclType.clone(&tmp);
            break;
        }
        case T_CCLASSSF_CLASS_ID:{
            //std::cout << "walk in T_CCLASSSF_CLASS_ID" << endl;
            LogiMsg::logi("walk in T_CCLASSSF_CLASS_ID", getLineno());

            childs.at(0)->walk();
            if (checkIsNotWalking()) {
                return ;
            }

            Scope *tmpScope = Scope::resolveScope(s_context->tmpIdenName,Scope::SCOPE_CLASS);
            if (!tmpScope)
            {
                /*std::cout<<"error in T_CCLASSSF_CLASS_ID: the super class "
                << s_context->tmpIdenName << " does not exit at line "<<getLineno()<<std::endl;*/
                string errorStr = "error in T_CCLASSSF_CLASS_ID: the super class "
                + s_context->tmpIdenName + " does not exit";
                LogiMsg::logi(errorStr, getLineno());
                stopWalk();
                return ;
            }

            TypeClass tmp;
            //tmp.scopeType = tmpScope;
            tmp.setScopeType(tmpScope);
            tmp.typeSfType = TypeClass::SF_INT;
            s_context->clearContext();
            s_context->tmpDeclType.clone(&tmp);
            break;
        }
        default:{
            //std::cout << "error in ClassSpecifierAst: nodeType is invalid" << std::endl;
            LogiMsg::logi("error in ClassSpecifierAst: nodeType is invalid", getLineno());
            stopWalk();
            return ;
            break;
        }
    }

}