示例#1
0
文件: class.c 项目: olgk/dmd
void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
    if (!isAnonymous())
    {
        buf->printf("%s ", kind());
        buf->writestring(toChars());
        if (baseclasses->dim)
            buf->writestring(" : ");
    }
    for (size_t i = 0; i < baseclasses->dim; i++)
    {
        BaseClass *b = (*baseclasses)[i];

        if (i)
            buf->writeByte(',');
        //buf->writestring(b->base->ident->toChars());
        b->type->toCBuffer(buf, NULL, hgs);
    }
    if (members)
    {
        buf->writenl();
        buf->writeByte('{');
        buf->writenl();
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];

            buf->writestring("    ");
            s->toCBuffer(buf, hgs);
        }
        buf->writestring("}");
    }
    else
        buf->writeByte(';');
    buf->writenl();
}
示例#2
0
文件: struct.c 项目: denis-sh/dmd
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
    buf->printf("%s ", kind());
    if (!isAnonymous())
        buf->writestring(toChars());
    if (!members)
    {
        buf->writeByte(';');
        buf->writenl();
        return;
    }
    buf->writenl();
    buf->writeByte('{');
    buf->writenl();
    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *s = (*members)[i];

        buf->writestring("    ");
        s->toCBuffer(buf, hgs);
    }
    buf->writeByte('}');
    buf->writenl();
}
示例#3
0
文件: enum.c 项目: JenkinsDev/dmd
Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
{
    Type *t = NULL;
    if (memtype)
        t = memtype->syntaxCopy();

    EnumDeclaration *ed;
    if (s)
    {   ed = (EnumDeclaration *)s;
        ed->memtype = t;
    }
    else
        ed = new EnumDeclaration(loc, ident, t);
    ScopeDsymbol::syntaxCopy(ed);
    if (isAnonymous())
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            EnumMember *em = (*members)[i]->isEnumMember();
            em->ed = ed;
        }
    }
    return ed;
}
示例#4
0
void StructDeclaration::toDebug()
{
    idx_t typidx = 0;

    //printf("StructDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
        return /*0*/;

    if (typidx)                 // if reference already generated
        return /*typidx*/;      // use already existing reference

    targ_size_t size;
    unsigned property = 0;
    if (!members)
    {   size = 0;
        property |= 0x80;               // forward reference
    }
    else
        size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
        property |= 8;
//    if (st->Sctor || st->Sdtor)
//      property |= 2;          // class has ctors and/or dtors
//    if (st->Sopoverload)
//      property |= 4;          // class has overloaded operators
//    if (st->Scastoverload)
//      property |= 0x40;               // class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//      property |= 0x20;               // class has overloaded assignment

    const char *id = toPrettyChars();

    unsigned leaf = isUnionDeclaration() ? LF_UNION : LF_STRUCTURE;
    if (config.fulltypes == CV8)
        leaf = leaf == LF_UNION ? LF_UNION_V3 : LF_STRUCTURE_V3;

    unsigned numidx;
    switch (leaf)
    {
        case LF_UNION:        numidx = 8;       break;
        case LF_UNION_V3:     numidx = 10;      break;
        case LF_STRUCTURE:    numidx = 12;      break;
        case LF_STRUCTURE_V3: numidx = 18;      break;
    }

    unsigned len = numidx + cv4_numericbytes(size);
    debtyp_t *d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    if (leaf == LF_STRUCTURE)
    {
        TOWORD(d->data + 8,0);          // dList
        TOWORD(d->data + 10,0);         // vshape is 0 (no virtual functions)
    }
    else if (leaf == LF_STRUCTURE_V3)
    {
        TOLONG(d->data + 10,0);         // dList
        TOLONG(d->data + 14,0);         // vshape is 0 (no virtual functions)
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    unsigned length_save = d->length;
    d->length = 0;                      // so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = length_save;            // restore length

    if (!members)                       // if reference only
    {
        if (config.fulltypes == CV8)
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOLONG(d->data + 6,0);          // field list is 0
            TOWORD(d->data + 4,property);
        }
        else
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOWORD(d->data + 4,0);          // field list is 0
            TOWORD(d->data + 6,property);
        }
        return /*typidx*/;
    }

    // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen)
    CvMemberCount mc;
    mc.nfields = 0;
    mc.fnamelen = 2;
    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_count, &mc);
    }
    unsigned nfields = mc.nfields;
    unsigned fnamelen = mc.fnamelen;

    int count = nfields;                  // COUNT field in LF_CLASS

    // Generate fieldlist type record
    debtyp_t *dt = debtyp_alloc(fnamelen);
    unsigned char *p = dt->data;

    // And fill it in
    TOWORD(p,config.fulltypes == CV8 ? LF_FIELDLIST_V2 : LF_FIELDLIST);
    p += 2;
    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_p, &p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    idx_t fieldlist = cv_debtyp(dt);

    TOWORD(d->data + 2,count);
    if (config.fulltypes == CV8)
    {
        TOWORD(d->data + 4,property);
        TOLONG(d->data + 6,fieldlist);
    }
    else
    {
        TOWORD(d->data + 4,fieldlist);
        TOWORD(d->data + 6,property);
    }

//    cv4_outsym(s);

    if (config.fulltypes == CV8)
        cv8_udt(id, typidx);
    else
    {
        size_t idlen = strlen(id);
        unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + idlen);

        // Output a 'user-defined type' for the tag name
        TOWORD(debsym + 2,S_UDT);
        TOIDX(debsym + 4,typidx);
        unsigned length = 2 + 2 + cgcv.sz_idx;
        length += cv_namestring(debsym + length,id);
        TOWORD(debsym,length - 2);

        assert(length <= 40 + idlen);
        objmod->write_bytes(SegData[DEBSYM],length,debsym);
    }

//    return typidx;
}
示例#5
0
void InheritanceBuilder::tackOnto(MatchFinder &MF) {
  MF.addMatcher(cxxRecordDecl(isDefinition(),
                              unless(hasAncestor(namespaceDecl(isAnonymous()))))
                    .bind("class"),
                this);
}
示例#6
0
文件: struct.c 项目: hariomrana/dmd
void StructDeclaration::semantic(Scope *sc)
{
    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    if (semanticRun >= PASSsemanticdone)
        return;
    unsigned dprogress_save = Module::dprogress;
    int errors = global.errors;

    Scope *scx = NULL;
    if (scope)
    {
        sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }

    if (!parent)
    {
        assert(sc->parent && sc->func);
        parent = sc->parent;
    }
    assert(parent && !isAnonymous());
    type = type->semantic(loc, sc);

    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        TemplateInstance *ti = ((TypeStruct *)type)->sym->isInstantiated();
        if (ti && isError(ti))
            ((TypeStruct *)type)->sym = this;
    }

    // Ungag errors when not speculative
    Ungag ungag = ungagSpeculative();

    if (semanticRun == PASSinit)
    {
        protection = sc->protection;

        alignment = sc->structalign;

        storage_class |= sc->stc;
        if (storage_class & STCdeprecated)
            isdeprecated = true;
        if (storage_class & STCabstract)
            error("structs, unions cannot be abstract");
        userAttribDecl = sc->userAttribDecl;
    }
    else if (symtab)
    {
        if (sizeok == SIZEOKdone || !scx)
        {
            semanticRun = PASSsemanticdone;
            return;
        }
    }
    semanticRun = PASSsemantic;

    if (!members)               // if opaque declaration
    {
        semanticRun = PASSsemanticdone;
        return;
    }
    if (!symtab)
        symtab = new DsymbolTable();

    if (sizeok == SIZEOKnone)            // if not already done the addMember step
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
        }
    }

    sizeok = SIZEOKnone;
    Scope *sc2 = sc->push(this);
    sc2->stc &= STCsafe | STCtrusted | STCsystem;
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = Prot(PROTpublic);
    sc2->explicitProtection = 0;
    sc2->structalign = STRUCTALIGN_DEFAULT;
    sc2->userAttribDecl = NULL;

    /* 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("struct: setScope %s %s\n", s->kind(), s->toChars());
        s->setScope(sc2);
    }

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

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

        /* If this is the last member, see if we can finish setting the size.
         * This could be much better - finish setting the size after the last
         * field was processed. The problem is the chicken-and-egg determination
         * of when that is. See Bugzilla 7426 for more info.
         */
        if (i + 1 == members->dim)
        {
            if (sizeok == SIZEOKnone && s->isAliasDeclaration())
                finalizeSize(sc2);
        }
        s->semantic(sc2);
    }
    finalizeSize(sc2);

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

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

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    Module::dprogress++;
    semanticRun = PASSsemanticdone;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (size_t i = 0; i < fields.dim; i++)
    {
        VarDeclaration *vd = fields[i];
        if (!vd->isDataseg())
        {
            if (vd->init)
            {
                // Should examine init to see if it is really all 0's
                zeroInit = 0;
                break;
            }
            else
            {
                if (!vd->type->isZeroInit(loc))
                {
                    zeroInit = 0;
                    break;
                }
            }
        }
    }

    dtor = buildDtor(this, sc2);
    postblit = buildPostBlit(this, sc2);
    cpctor = buildCpCtor(this, sc2);

    buildOpAssign(this, sc2);
    buildOpEquals(this, sc2);

    xeq = buildXopEquals(this, sc2);
    xcmp = buildXopCmp(this, sc2);
    xhash = buildXtoHash(this, sc2);

    /* Even if the struct is merely imported and its semantic3 is not run,
     * the TypeInfo object would be speculatively stored in each object
     * files. To set correct function pointer, run semantic3 for xeq and xcmp.
     */
    //if ((xeq && xeq != xerreq || xcmp && xcmp != xerrcmp) && isImportedSym(this))
    //    Module::addDeferredSemantic3(this);
    /* Defer requesting semantic3 until TypeInfo generation is actually invoked.
     * See semanticTypeInfo().
     */
    inv = buildInv(this, sc2);

    sc2->pop();

    /* Look for special member functions.
     */
    ctor = searchCtor();
    aggNew =       (NewDeclaration *)search(Loc(), Id::classNew);
    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);

    if (ctor)
    {
        Dsymbol *scall = search(Loc(), Id::call);
        if (scall)
        {
            unsigned xerrors = global.startGagging();
            sc = sc->push();
            sc->speculative = true;
            FuncDeclaration *fcall = resolveFuncCall(loc, sc, scall, NULL, NULL, NULL, 1);
            sc = sc->pop();
            global.endGagging(xerrors);

            if (fcall && fcall->isStatic())
            {
                error(fcall->loc, "static opCall is hidden by constructors and can never be called");
                errorSupplemental(fcall->loc, "Please use a factory method instead, or replace all constructors with static opCall.");
            }
        }
    }

    TypeTuple *tup = toArgTypes(type);
    size_t dim = tup->arguments->dim;
    if (dim >= 1)
    {
        assert(dim <= 2);
        arg1type = (*tup->arguments)[0]->type;
        if (dim == 2)
            arg2type = (*tup->arguments)[1]->type;
    }

    if (sc->func)
        semantic2(sc);

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

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

#if 0
    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        printf("this = %p %s\n", this, this->toChars());
        printf("type = %d sym = %p\n", type->ty, ((TypeStruct *)type)->sym);
    }
#endif
    assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
}
示例#7
0
文件: enum.c 项目: rbanderton/dmd
void EnumDeclaration::semantic(Scope *sc)
{
    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
    //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
    if (semanticRun >= PASSsemanticdone)
        return;             // semantic() already completed
    if (semanticRun == PASSsemantic)
    {
        assert(memtype);
        ::error(loc, "circular reference to enum base type %s", memtype->toChars());
        errors = true;
        semanticRun = PASSsemanticdone;
        return;
    }
    unsigned dprogress_save = Module::dprogress;

    Scope *scx = NULL;
    if (scope)
    {
        sc = scope;
        scx = scope;            // save so we don't make redundant copies
        scope = NULL;
    }

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

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

    semanticRun = PASSsemantic;

    if (!members && !memtype)               // enum ident;
    {
        semanticRun = PASSsemanticdone;
        return;
    }

    if (!symtab)
        symtab = new DsymbolTable();

    /* The separate, and distinct, cases are:
     *  1. enum { ... }
     *  2. enum : memtype { ... }
     *  3. enum ident { ... }
     *  4. enum ident : memtype { ... }
     *  5. enum ident : memtype;
     *  6. enum ident;
     */

    if (memtype)
    {
        memtype = memtype->semantic(loc, sc);

        /* Check to see if memtype is forward referenced
         */
        if (memtype->ty == Tenum)
        {
            EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
            if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
            {
                // memtype is forward referenced, so try again later
                scope = scx ? scx : sc->copy();
                scope->setNoFree();
                scope->module->addDeferredSemantic(this);
                Module::dprogress = dprogress_save;
                //printf("\tdeferring %s\n", toChars());
                semanticRun = PASSinit;
                return;
            }
        }
        if (memtype->ty == Tvoid)
        {
            error("base type must not be void");
            memtype = Type::terror;
        }
        if (memtype->ty == Terror)
        {
            errors = true;
            if (members)
            {
                for (size_t i = 0; i < members->dim; i++)
                {
                    Dsymbol *s = (*members)[i];
                    s->errors = true;               // poison all the members
                }
            }
            semanticRun = PASSsemanticdone;
            return;
        }
    }

    semanticRun = PASSsemanticdone;

    if (!members)               // enum ident : memtype;
        return;

    if (members->dim == 0)
    {
        error("enum %s must have at least one member", toChars());
        errors = true;
        return;
    }

    Module::dprogress++;

    Scope *sce;
    if (isAnonymous())
        sce = sc;
    else
    {
        sce = sc->push(this);
        sce->parent = this;
    }
    sce = sce->startCTFE();
    sce->setNoFree();                   // needed for getMaxMinValue()

    /* Each enum member gets the sce scope
     */
    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (em)
            em->scope = sce;
    }

    if (!added)
    {
        /* addMember() is not called when the EnumDeclaration appears as a function statement,
         * so we have to do what addMember() does and install the enum members in the right symbol
         * table
         */
        ScopeDsymbol *scopesym = NULL;
        if (isAnonymous())
        {
            /* Anonymous enum members get added to enclosing scope.
             */
            for (Scope *sct = sce; 1; sct = sct->enclosing)
            {
                assert(sct);
                if (sct->scopesym)
                {
                    scopesym = sct->scopesym;
                    if (!sct->scopesym->symtab)
                        sct->scopesym->symtab = new DsymbolTable();
                    break;
                }
            }
        }
        else
        {
            // Otherwise enum members are in the EnumDeclaration's symbol table
            scopesym = this;
        }

        for (size_t i = 0; i < members->dim; i++)
        {
            EnumMember *em = (*members)[i]->isEnumMember();
            if (em)
            {
                em->ed = this;
                em->addMember(sc, scopesym, 1);
            }
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (em)
            em->semantic(em->scope);
    }
    //printf("defaultval = %lld\n", defaultval);

    //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
    //printf("members = %s\n", members->toChars());
}
示例#8
0
文件: tocvdebug.c 项目: Geod24/dnet
void ClassDeclaration::toDebug()
{
    unsigned leaf;
    unsigned property;
    unsigned nfields;
    unsigned fnamelen;
    const char *id;
    targ_size_t size;
    unsigned numidx;
    debtyp_t *d,*dt;
    unsigned len;
    int i;
    int count;			// COUNT field in LF_CLASS
    unsigned char *p;
    idx_t typidx = 0;

    //printf("ClassDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
	return /*0*/;

    if (typidx)			// if reference already generated
	return /*typidx*/;	// use already existing reference

    property = 0;
    if (!members)
    {	size = 0;
	property |= 0x80;		// forward reference
    }
    else
	size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
	property |= 8;
    if (ctor || dtors.dim)
	property |= 2;		// class has ctors and/or dtors
//    if (st->Sopoverload)
//	property |= 4;		// class has overloaded operators
//    if (st->Scastoverload)
//	property |= 0x40;		// class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//	property |= 0x20;		// class has overloaded assignment

    id = toPrettyChars();
    numidx = isUnionDeclaration() ? 8 : 12;
    len = numidx + cv4_numericbytes(size);
    d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    leaf = LF_CLASS;
    TOWORD(d->data + 8,0);		// dList

    if (1)
    {   debtyp_t *vshape;
	unsigned n;
	unsigned char descriptor;

	n = vtbl.dim;			// number of virtual functions
	if (n == 0)
	{
	    TOWORD(d->data + 10,0);             // vshape is 0
	}
	else
	{   int i;

	    vshape = debtyp_alloc(4 + (n + 1) / 2);
	    TOWORD(vshape->data,LF_VTSHAPE);
	    TOWORD(vshape->data + 2,1);

	    n = 0;
	    descriptor = 0;
	    for (i = 0; i < vtbl.dim; i++)
	    {   FuncDeclaration *fd = (FuncDeclaration *)vtbl.data[i];
		tym_t ty;

		//if (intsize == 4)
		    descriptor |= 5;
		vshape->data[4 + n / 2] = descriptor;
		descriptor <<= 4;
		n++;
	    }
	    TOWORD(d->data + 10,cv_debtyp(vshape));     // vshape
	}
    }
    else
	TOWORD(d->data + 10,0);		// vshape is 0 (no virtual functions)

    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    d->length = 0;			// so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = len;		// restore length

    if (!members)			// if reference only
    {
	TOWORD(d->data + 2,0);		// count: number of fields is 0
	TOWORD(d->data + 4,0);		// field list is 0
	TOWORD(d->data + 6,property);
	return /*typidx*/;
    }

    // Compute the number of fields, and the length of the fieldlist record
    nfields = 0;
    fnamelen = 2;

    // Add in base classes
    for (i = 0; i < baseclasses.dim; i++)
    {	BaseClass *bc = (BaseClass *)baseclasses.data[i];

	nfields++;
	fnamelen += 6 + cv4_numericbytes(bc->offset);
    }

    count = nfields;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];
	int nwritten;

	nwritten = s->cvMember(NULL);
	if (nwritten)
	{
	    fnamelen += nwritten;
	    nfields++;
	    count++;
	}
    }

    TOWORD(d->data + 2,count);
    TOWORD(d->data + 6,property);

    // Generate fieldlist type record
    dt = debtyp_alloc(fnamelen);
    p = dt->data;

    // And fill it in
    TOWORD(p,LF_FIELDLIST);
    p += 2;

    // Add in base classes
    for (i = 0; i < baseclasses.dim; i++)
    {	BaseClass *bc = (BaseClass *)baseclasses.data[i];
	idx_t typidx;
	unsigned attribute;

        typidx = cv4_typidx(bc->base->type->toCtype()->Tnext);

	attribute = PROTtoATTR(bc->protection);

        TOWORD(p,LF_BCLASS);
	TOWORD(p + 2,typidx);
	TOWORD(p + 4,attribute);
	p += 6;

        cv4_storenumeric(p, bc->offset);
        p += cv4_numericbytes(bc->offset);
    }



    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];

	p += s->cvMember(p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    TOWORD(d->data + 4,cv_debtyp(dt));

//    cv4_outsym(s);

    unsigned char *debsym;
    unsigned length;

    len = strlen(id);
    debsym = (unsigned char *) alloca(39 + IDOHD + len);

    // Output a 'user-defined type' for the tag name
    TOWORD(debsym + 2,S_UDT);
    TOIDX(debsym + 4,typidx);
    length = 2 + 2 + cgcv.sz_idx;
    length += cv_namestring(debsym + length,id);
    TOWORD(debsym,length - 2);

    assert(length <= 40 + len);
    obj_write_bytes(SegData[DEBSYM],length,debsym);

//    return typidx;
}
示例#9
0
文件: enum.c 项目: alekseysidorov/ldc
void EnumDeclaration::semantic(Scope *sc)
{
    uinteger_t number;
    Type *t;
    Scope *sce;

    //printf("EnumDeclaration::semantic(sd = %p, '%s')\n", sc->scopesym, sc->scopesym->toChars());
    if (!memtype)
        memtype = Type::tint32;

    if (symtab)                 // if already done
    {   if (isdone || !scope)
            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;

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

    parent = sc->scopesym;
    memtype = memtype->semantic(loc, sc);

    /* Check to see if memtype is forward referenced
     */
    if (memtype->ty == Tenum)
    {   EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
        if (!sym->memtype)
        {
            error("base enum %s is forward referenced", sym->toChars());
            memtype = Type::tint32;
        }
    }

    if (!memtype->isintegral())
    {   error("base type must be of integral type, not %s", memtype->toChars());
        memtype = Type::tint32;
    }

    isdone = 1;
    Module::dprogress++;

    t = isAnonymous() ? memtype : type;
    symtab = new DsymbolTable();
    sce = sc->push(this);
    sce->parent = this;
    number = 0;
    if (!members)               // enum ident;
        return;
    if (members->dim == 0)
        error("enum %s must have at least one member", toChars());
    int first = 1;
    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
        Expression *e;

        if (!em)
            /* The e->semantic(sce) can insert other symbols, such as
             * template instances and function literals.
             */
            continue;

        //printf("Enum member '%s'\n",em->toChars());
        e = em->value;
        if (e)
        {
            assert(e->dyncast() == DYNCAST_EXPRESSION);
            e = e->semantic(sce);
            e = e->optimize(WANTvalue);
            // Need to copy it because we're going to change the type
            e = e->copy();
            e = e->implicitCastTo(sc, memtype);
            e = e->optimize(WANTvalue);
            number = e->toInteger();
            e->type = t;
        }
        else
        {   // Default is the previous number plus 1

            // Check for overflow
            if (!first)
            {
                switch (t->toBasetype()->ty)
                {
                    case Tbool:
                        if (number == 2)        goto Loverflow;
                        break;

                    case Tint8:
                        if (number == 128) goto Loverflow;
                        break;

                    case Tchar:
                    case Tuns8:
                        if (number == 256) goto Loverflow;
                        break;

                    case Tint16:
                        if (number == 0x8000) goto Loverflow;
                        break;

                    case Twchar:
                    case Tuns16:
                        if (number == 0x10000) goto Loverflow;
                        break;

                    case Tint32:
                        if (number == 0x80000000) goto Loverflow;
                        break;

                    case Tdchar:
                    case Tuns32:
                        if (number == 0x100000000LL) goto Loverflow;
                        break;

                    case Tint64:
                        if (number == 0x8000000000000000LL) goto Loverflow;
                        break;

                    case Tuns64:
                        if (number == 0) goto Loverflow;
                        break;

                    Loverflow:
                        error("overflow of enum value");
                        break;

                    default:
                        assert(0);
                }
            }
            e = new IntegerExp(em->loc, number, t);
        }
        em->value = e;

        // Add to symbol table only after evaluating 'value'
        if (isAnonymous())
        {
            //sce->enclosing->insert(em);
            for (Scope *sct = sce->enclosing; sct; sct = sct->enclosing)
            {
                if (sct->scopesym)
                {
                    if (!sct->scopesym->symtab)
                        sct->scopesym->symtab = new DsymbolTable();
                    em->addMember(sce, sct->scopesym, 1);
                    break;
                }
            }
        }
        else
            em->addMember(sc, this, 1);

        if (first)
        {   first = 0;
            defaultval = number;
            minval = number;
            maxval = number;
        }
        else if (memtype->isunsigned())
        {
            if (number < minval)
                minval = number;
            if (number > maxval)
                maxval = number;
        }
        else
        {
            if ((sinteger_t)number < (sinteger_t)minval)
                minval = number;
            if ((sinteger_t)number > (sinteger_t)maxval)
                maxval = number;
        }

        number++;
    }
    //printf("defaultval = %lld\n", defaultval);

    sce->pop();
    //members->print();
}
示例#10
0
void StructDeclaration::semantic(Scope *sc)
{
    Scope *sc2;

    //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    assert(type);
    if (!members)                       // if forward reference
        return;

    if (symtab)
    {   if (sizeok == 1 || !scope)
        {   //printf("already completed\n");
            scope = NULL;
            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
    methods.setDim(0);
#endif

    parent = sc->parent;
    type = type->semantic(loc, sc);
#if STRUCTTHISREF
    handle = type;
#else
    handle = type->pointerTo();
#endif
    structalign = sc->structalign;
    protection = sc->protection;
    if (sc->stc & STCdeprecated)
        isdeprecated = 1;
    assert(!isAnonymous());
    if (sc->stc & STCabstract)
        error("structs, unions cannot be abstract");
#if DMDV2
    if (storage_class & STCimmutable)
        type = type->invariantOf();
    else if (storage_class & STCconst)
        type = type->constOf();
#endif
#if IN_GCC
    if (attributes)
        attributes->append(sc->attributes);
    else
        attributes = sc->attributes;
#endif

    if (sizeok == 0)            // if not already done the addMember step
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (Dsymbol *)members->data[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
        }
    }

    sizeok = 0;
    sc2 = sc->push(this);
    sc2->stc = 0;
#if IN_GCC
    sc2->attributes = NULL;
#endif
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = PROTpublic;
    sc2->explicitProtection = 0;

    size_t members_dim = members->dim;

    /* 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(sc2);
        }
    }

    for (size_t i = 0; i < members_dim; i++)
    {
        Dsymbol *s = (Dsymbol *)members->data[i];
        s->semantic(sc2);
#if 0
        if (sizeok == 2)
        {   //printf("forward reference\n");
            break;
        }
#endif
    }

#if DMDV1
    /* This doesn't work for DMDV2 because (ref S) and (S) parameter
     * lists will overload the same.
     */
    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
     * a parameter that is a pointer to the struct. But if there
     * isn't one, but is an opEquals or opCmp with a value, write
     * another that is a shell around the value:
     *  int opCmp(struct *p) { return opCmp(*p); }
     */

    TypeFunction *tfeqptr;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, handle, Id::p, NULL);

        arguments->push(arg);
        tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
    }

    TypeFunction *tfeq;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, type, NULL, NULL);

        arguments->push(arg);
        tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeq = (TypeFunction *)tfeq->semantic(0, sc);
    }

    Identifier *id = Id::eq;
    for (int i = 0; i < 2; i++)
    {
        Dsymbol *s = search_function(this, id);
        FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
        if (fdx)
        {   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
            if (!fd)
            {   fd = fdx->overloadExactMatch(tfeq);
                if (fd)
                {   // Create the thunk, fdptr
                    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
                    Expression *e = new IdentifierExp(loc, Id::p);
                    e = new PtrExp(loc, e);
                    Expressions *args = new Expressions();
                    args->push(e);
                    e = new IdentifierExp(loc, id);
                    e = new CallExp(loc, e, args);
                    fdptr->fbody = new ReturnStatement(loc, e);
                    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
                    assert(s);
                    s->members->push(fdptr);
                    fdptr->addMember(sc, s, 1);
                    fdptr->semantic(sc2);
                }
            }
        }

        id = Id::cmp;
    }
#endif
#if DMDV2
    /* Try to find the opEquals function. Build it if necessary.
     */
    TypeFunction *tfeqptr;
    {   // bool opEquals(const T*) const;
        Parameters *parameters = new Parameters;
#if STRUCTTHISREF
        // bool opEquals(ref const T) const;
        Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL);
#else
        // bool opEquals(const T*) const;
        Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL);
#endif

        parameters->push(param);
        tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
        tfeqptr->mod = MODconst;
        tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2);

        Dsymbol *s = search_function(this, Id::eq);
        FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
        if (fdx)
        {
            eq = fdx->overloadExactMatch(tfeqptr);
            if (!eq)
                fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars());
        }

        TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL;
        // BUG: should also check that td is a function template, not just a template

        if (!eq && !td)
            eq = buildOpEquals(sc2);
    }

    dtor = buildDtor(sc2);
    postblit = buildPostBlit(sc2);
    cpctor = buildCpCtor(sc2);
    buildOpAssign(sc2);
#endif

    sc2->pop();

    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;

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

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    // 0 sized struct's are set to 1 byte
    if (structsize == 0)
    {
        structsize = 1;
        alignsize = 1;
    }

    // Round struct size up to next alignsize boundary.
    // This will ensure that arrays of structs will get their internals
    // aligned properly.
    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);

    sizeok = 1;
    Module::dprogress++;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (size_t i = 0; i < fields.dim; i++)
    {
        Dsymbol *s = (Dsymbol *)fields.data[i];
        VarDeclaration *vd = s->isVarDeclaration();
        if (vd && !vd->isDataseg())
        {
            if (vd->init)
            {
                // Should examine init to see if it is really all 0's
                zeroInit = 0;
                break;
            }
            else
            {
                if (!vd->type->isZeroInit(loc))
                {
                    zeroInit = 0;
                    break;
                }
            }
        }
    }

    /* Look for special member functions.
     */
#if DMDV2
    ctor = search(0, Id::ctor, 0);
#endif
    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);

    if (sc->func)
    {
        semantic2(sc);
        semantic3(sc);
    }
}
示例#11
0
void StructDeclaration::semantic(Scope *sc)
{   int i;
    Scope *sc2;

    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    //static int count; if (++count == 20) *(char*)0=0;

    assert(type);
    if (!members)			// if forward reference
	return;

    if (symtab)
    {   if (!scope)
            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;
    }

    parent = sc->parent;
    handle = type->pointerTo();
    structalign = sc->structalign;
    protection = sc->protection;
    storage_class |= sc->stc;
    assert(!isAnonymous());
    if (sc->stc & STCabstract)
	error("structs, unions cannot be abstract");
    if (storage_class & STCinvariant)
        type = type->invariantOf();
    else if (storage_class & STCconst)
        type = type->constOf();

    if (sizeok == 0)		// if not already done the addMember step
    {
	for (i = 0; i < members->dim; i++)
	{
	    Dsymbol *s = (Dsymbol *)members->data[i];
	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
	    s->addMember(sc, this, 1);
	}
    }

    sizeok = 0;
    sc2 = sc->push(this);
    sc2->stc &= storage_class & (STCconst | STCinvariant);
    sc2->parent = this;
    if (isUnionDeclaration())
	sc2->inunion = 1;
    sc2->protection = PROTpublic;
    sc2->explicitProtection = 0;

    int members_dim = members->dim;
    for (i = 0; i < members_dim; i++)
    {
	Dsymbol *s = (Dsymbol *)members->data[i];
	s->semantic(sc2);
	if (isUnionDeclaration())
	    sc2->offset = 0;
#if 0
	if (sizeok == 2)
	{   //printf("forward reference\n");
	    break;
	}
#endif
    }

    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
     * a parameter that is a pointer to the struct. But if there
     * isn't one, but is an opEquals or opCmp with a value, write
     * another that is a shell around the value:
     *	int opCmp(struct *p) { return opCmp(*p); }
     */

    TypeFunction *tfeqptr;
    {
	Arguments *arguments = new Arguments;
	Argument *arg = new Argument(STCin, handle, Id::p, NULL);

	arguments->push(arg);
	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
    }

    TypeFunction *tfeq;
    {
	Arguments *arguments = new Arguments;
	Argument *arg = new Argument(STCin, type, NULL, NULL);

	arguments->push(arg);
	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
    }

    Identifier *id = Id::eq;
    for (int i = 0; i < 2; i++)
    {
	Dsymbol *s = search_function(this, id);
	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
	if (fdx)
	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
	    if (!fd)
	    {	fd = fdx->overloadExactMatch(tfeq);
		if (fd)
		{   // Create the thunk, fdptr
		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
		    Expression *e = new IdentifierExp(loc, Id::p);
		    e = new PtrExp(loc, e);
		    Expressions *args = new Expressions();
		    args->push(e);
		    e = new IdentifierExp(loc, id);
		    e = new CallExp(loc, e, args);
		    fdptr->fbody = new ReturnStatement(loc, e);
		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
		    assert(s);
		    s->members->push(fdptr);
		    fdptr->addMember(sc, s, 1);
		    fdptr->semantic(sc2);
		}
	    }
	}

	id = Id::cmp;
    }

    dtor = buildDtor(sc2);
    postblit = buildPostBlit(sc2);
    cpctor = buildCpCtor(sc2);
    buildOpAssign(sc2);

    sc2->pop();

    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;

	scope = scx ? scx : new Scope(*sc);
	scope->setNoFree();
	scope->module->addDeferredSemantic(this);
	//printf("\tdeferring %s\n", toChars());
	return;
    }

    // 0 sized struct's are set to 1 byte
    if (structsize == 0)
    {
	structsize = 1;
	alignsize = 1;
    }

    // Round struct size up to next alignsize boundary.
    // This will ensure that arrays of structs will get their internals
    // aligned properly.
    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);

    sizeok = 1;
    Module::dprogress++;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (i = 0; i < fields.dim; i++)
    {
	Dsymbol *s = (Dsymbol *)fields.data[i];
	VarDeclaration *vd = s->isVarDeclaration();
	if (vd && !vd->isDataseg())
	{
	    if (vd->init)
	    {
		// Should examine init to see if it is really all 0's
		zeroInit = 0;
		break;
	    }
	    else
	    {
		if (!vd->type->isZeroInit())
		{
		    zeroInit = 0;
		    break;
		}
	    }
	}
    }

    /* Look for special member functions.
     */
    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);

    if (sc->func)
    {
	semantic2(sc);
	semantic3(sc);
    }
}
示例#12
0
文件: struct.c 项目: rainers/dmd
void StructDeclaration::semantic(Scope *sc)
{
    Scope *sc2;

    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    assert(type);
    if (!members)               // if opaque declaration
    {
        return;
    }

    if (symtab)
    {   if (sizeok == SIZEOKdone || !scope)
        {   //printf("already completed\n");
            scope = NULL;
            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;

    parent = sc->parent;
    type = type->semantic(loc, sc);
    handle = type;
    protection = sc->protection;
    alignment = sc->structalign;
    storage_class |= sc->stc;
    if (sc->stc & STCdeprecated)
        isdeprecated = true;
    assert(!isAnonymous());
    if (sc->stc & STCabstract)
        error("structs, unions cannot be abstract");
    userAttributes = sc->userAttributes;

    if (sizeok == SIZEOKnone)            // if not already done the addMember step
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
        }
    }

    sizeok = SIZEOKnone;
    sc2 = sc->push(this);
    sc2->stc &= STCsafe | STCtrusted | STCsystem;
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = PROTpublic;
    sc2->explicitProtection = 0;
    sc2->structalign = STRUCTALIGN_DEFAULT;
    sc2->userAttributes = NULL;

    /* 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("struct: setScope %s %s\n", s->kind(), s->toChars());
        s->setScope(sc2);
    }

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

        /* If this is the last member, see if we can finish setting the size.
         * This could be much better - finish setting the size after the last
         * field was processed. The problem is the chicken-and-egg determination
         * of when that is. See Bugzilla 7426 for more info.
         */
        if (i + 1 == members->dim)
        {
            if (sizeok == SIZEOKnone && s->isAliasDeclaration())
                finalizeSize(sc2);
        }

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

    if (sizeok == SIZEOKfwd)
    {   // semantic() failed because of 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;

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

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    Module::dprogress++;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = calcZeroInit();

    dtor = buildDtor(sc2);
    postblit = buildPostBlit(sc2);
    cpctor = buildCpCtor(sc2);

    buildOpAssign(sc2);
    buildOpEquals(sc2);

    xeq = buildXopEquals(sc2);
    xcmp = buildXopCmp(sc2);

    /* Even if the struct is merely imported and its semantic3 is not run,
     * the TypeInfo object would be speculatively stored in each object
     * files. To set correct function pointer, run semantic3 for xeq and xcmp.
     */
    //if ((xeq && xeq != xerreq || xcmp && xcmp != xerrcmp) && isImportedSym(this))
    //    Module::addDeferredSemantic3(this);
    /* Defer requesting semantic3 until TypeInfo generation is actually invoked.
     * See Type::getTypeInfo().
     */
    inv = buildInv(sc2);

    sc2->pop();

    /* Look for special member functions.
     */
    searchCtor();
    aggNew =       (NewDeclaration *)search(Loc(), Id::classNew,       0);
    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete,    0);

    TypeTuple *tup = type->toArgTypes();
    size_t dim = tup->arguments->dim;
    if (dim >= 1)
    {   assert(dim <= 2);
        arg1type = (*tup->arguments)[0]->type;
        if (dim == 2)
            arg2type = (*tup->arguments)[1]->type;
    }

    if (sc->func)
    {
        semantic2(sc);
        semantic3(sc);
    }

#if 1
    {
        // build a literal now to initialize vtinfo of element types
        StructLiteralExp *sle = new StructLiteralExp(loc, this, NULL);
        Expression *e = sle->fill(true);
    }
#endif

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

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

    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        error("failed semantic analysis");
        this->errors = true;
        type = Type::terror;
    }
}
void UnnamedNamespaceInHeaderCheck::registerMatchers(
    ast_matchers::MatchFinder *Finder) {
  Finder->addMatcher(namespaceDecl(isAnonymous()).bind("anonymousNamespace"),
                     this);
}
示例#14
0
文件: toobj.c 项目: Orvid/dmd
void StructDeclaration::toObjFile(bool multiobj)
{
    //printf("StructDeclaration::toObjFile('%s')\n", toChars());

    if (type->ty == Terror)
    {
        error("had semantic errors when compiling");
        return;
    }

    if (multiobj && !hasStaticCtorOrDtor())
    {
        obj_append(this);
        return;
    }

    // Anonymous structs/unions only exist as part of others,
    // do not output forward referenced structs's
    if (!isAnonymous() && members)
    {
        if (global.params.symdebug)
            toDebug(this);

        type->genTypeInfo(NULL);

        if (1)
        {
            // Generate static initializer
            toInitializer();
            if (isInstantiated())
            {
                sinit->Sclass = SCcomdat;
            }
            else
            {
                sinit->Sclass = SCglobal;
            }

            sinit->Sfl = FLdata;
            StructDeclaration_toDt(this, &sinit->Sdt);
            dt_optimize(sinit->Sdt);
            out_readonly(sinit);    // put in read-only segment
            outdata(sinit);
        }

        // Put out the members
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *member = (*members)[i];
            /* There might be static ctors in the members, and they cannot
             * be put in separate obj files.
             */
            member->toObjFile(multiobj);
        }

        if (xeq && xeq != xerreq)
            xeq->toObjFile(multiobj);
        if (xcmp && xcmp != xerrcmp)
            xcmp->toObjFile(multiobj);
        if (xhash)
            xhash->toObjFile(multiobj);
    }
}
示例#15
0
void ClassDeclaration::toDebug()
{
    idx_t typidx = 0;

    //printf("ClassDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
        return /*0*/;

    if (typidx)                 // if reference already generated
        return /*typidx*/;      // use already existing reference

    targ_size_t size;
    unsigned property = 0;
    if (!members)
    {   size = 0;
        property |= 0x80;               // forward reference
    }
    else
        size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
        property |= 8;
    if (ctor || dtors.dim)
        property |= 2;          // class has ctors and/or dtors
//    if (st->Sopoverload)
//      property |= 4;          // class has overloaded operators
//    if (st->Scastoverload)
//      property |= 0x40;               // class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//      property |= 0x20;               // class has overloaded assignment

#if DMDV1
    const char *id = toPrettyChars();
#else
    const char *id = isCPPinterface() ? ident->toChars() : toPrettyChars();
#endif
    unsigned leaf = config.fulltypes == CV8 ? LF_CLASS_V3 : LF_CLASS;

    unsigned numidx = (leaf == LF_CLASS_V3) ? 18 : 12;
    unsigned len = numidx + cv4_numericbytes(size);
    debtyp_t *d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    idx_t vshapeidx = 0;
    if (1)
    {
        size_t n = vtbl.dim;                   // number of virtual functions
        if (n)
        {   // 4 bits per descriptor
            debtyp_t *vshape = debtyp_alloc(4 + (n + 1) / 2);
            TOWORD(vshape->data,LF_VTSHAPE);
            TOWORD(vshape->data + 2,n);

            n = 0;
            unsigned char descriptor = 0;
            for (size_t i = 0; i < vtbl.dim; i++)
            {   FuncDeclaration *fd = (FuncDeclaration *)vtbl[i];

                //if (intsize == 4)
                    descriptor |= 5;
                vshape->data[4 + n / 2] = descriptor;
                descriptor <<= 4;
                n++;
            }
            vshapeidx = cv_debtyp(vshape);
        }
    }
    if (leaf == LF_CLASS)
    {
        TOWORD(d->data + 8,0);          // dList
        TOWORD(d->data + 10,vshapeidx);
    }
    else if (leaf == LF_CLASS_V3)
    {
        TOLONG(d->data + 10,0);         // dList
        TOLONG(d->data + 14,vshapeidx);
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    unsigned length_save = d->length;
    d->length = 0;                      // so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = length_save;            // restore length

    if (!members)                       // if reference only
    {
        if (leaf == LF_CLASS_V3)
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOLONG(d->data + 6,0);          // field list is 0
            TOWORD(d->data + 4,property);
        }
        else
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOWORD(d->data + 4,0);          // field list is 0
            TOWORD(d->data + 6,property);
        }
        return /*typidx*/;
    }

    // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen)
    CvMemberCount mc;
    mc.nfields = 0;
    mc.fnamelen = 2;

    /* Adding in the base classes causes VS 2010 debugger to refuse to display any
     * of the fields. I have not been able to determine why.
     * (Could it be because the base class is "forward referenced"?)
     * It does work with VS 2012.
     */
    bool addInBaseClasses = true;
    if (addInBaseClasses)
    {
        // Add in base classes
        for (size_t i = 0; i < baseclasses->dim; i++)
        {   BaseClass *bc = (*baseclasses)[i];

            mc.nfields++;
            unsigned elementlen = 4 + cgcv.sz_idx + cv4_numericbytes(bc->offset);
            elementlen = cv_align(NULL, elementlen);
            mc.fnamelen += elementlen;
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_count, &mc);
    }
    unsigned nfields = mc.nfields;
    unsigned fnamelen = mc.fnamelen;

    int count = nfields;
    TOWORD(d->data + 2,count);

    // Generate fieldlist type record
    debtyp_t *dt = debtyp_alloc(fnamelen);
    unsigned char *p = dt->data;

    // And fill it in
    TOWORD(p,config.fulltypes == CV8 ? LF_FIELDLIST_V2 : LF_FIELDLIST);
    p += 2;

    if (addInBaseClasses)
    {
        // Add in base classes
        for (size_t i = 0; i < baseclasses->dim; i++)
        {   BaseClass *bc = (*baseclasses)[i];

            idx_t typidx = cv4_typidx(bc->base->type->toCtype()->Tnext);
            unsigned attribute = PROTtoATTR(bc->protection);

            unsigned elementlen;
            switch (config.fulltypes)
            {
                case CV8:
                    TOWORD(p, LF_BCLASS_V2);
                    TOWORD(p + 2,attribute);
                    TOLONG(p + 4,typidx);
                    elementlen = 8;
                    break;

                case CV4:
                    TOWORD(p, LF_BCLASS);
                    TOWORD(p + 2,typidx);
                    TOWORD(p + 4,attribute);
                    elementlen = 6;
                    break;
            }

            cv4_storenumeric(p + elementlen, bc->offset);
            elementlen += cv4_numericbytes(bc->offset);
            elementlen = cv_align(p + elementlen, elementlen);
            p += elementlen;
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_p, &p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    idx_t fieldlist = cv_debtyp(dt);

    TOWORD(d->data + 2,count);
    if (config.fulltypes == CV8)
    {
        TOWORD(d->data + 4,property);
        TOLONG(d->data + 6,fieldlist);
    }
    else
    {
        TOWORD(d->data + 4,fieldlist);
        TOWORD(d->data + 6,property);
    }

//    cv4_outsym(s);

    if (config.fulltypes == CV8)
        cv8_udt(id, typidx);
    else
    {
        size_t idlen = strlen(id);
        unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + idlen);

        // Output a 'user-defined type' for the tag name
        TOWORD(debsym + 2,S_UDT);
        TOIDX(debsym + 4,typidx);
        unsigned length = 2 + 2 + cgcv.sz_idx;
        length += cv_namestring(debsym + length,id);
        TOWORD(debsym,length - 2);

        assert(length <= 40 + idlen);
        objmod->write_bytes(SegData[DEBSYM],length,debsym);
    }

//    return typidx;
}
示例#16
0
文件: tocvdebug.c 项目: Geod24/dnet
void StructDeclaration::toDebug()
{
    unsigned leaf;
    unsigned property;
    unsigned nfields;
    unsigned fnamelen;
    const char *id;
    targ_size_t size;
    unsigned numidx;
    debtyp_t *d,*dt;
    unsigned len;
    int i;
    int count;			// COUNT field in LF_CLASS
    unsigned char *p;
    idx_t typidx = 0;

    //printf("StructDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
	return /*0*/;

    if (typidx)			// if reference already generated
	return /*typidx*/;	// use already existing reference

    property = 0;
    if (!members)
    {	size = 0;
	property |= 0x80;		// forward reference
    }
    else
	size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
	property |= 8;
//    if (st->Sctor || st->Sdtor)
//	property |= 2;		// class has ctors and/or dtors
//    if (st->Sopoverload)
//	property |= 4;		// class has overloaded operators
//    if (st->Scastoverload)
//	property |= 0x40;		// class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//	property |= 0x20;		// class has overloaded assignment

    id = toPrettyChars();
    numidx = isUnionDeclaration() ? 8 : 12;
    len = numidx + cv4_numericbytes(size);
    d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    leaf = isUnionDeclaration() ? LF_UNION : LF_STRUCTURE;
    if (!isUnionDeclaration())
    {
	TOWORD(d->data + 8,0);		// dList
	TOWORD(d->data + 10,0);		// vshape is 0 (no virtual functions)
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    d->length = 0;			// so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = len;		// restore length

    if (!members)			// if reference only
    {
	TOWORD(d->data + 2,0);		// count: number of fields is 0
	TOWORD(d->data + 4,0);		// field list is 0
	TOWORD(d->data + 6,property);
	return /*typidx*/;
    }

    // Compute the number of fields, and the length of the fieldlist record
    nfields = 0;
    fnamelen = 2;

    count = nfields;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];
	int nwritten;

	nwritten = s->cvMember(NULL);
	if (nwritten)
	{
	    fnamelen += nwritten;
	    nfields++;
	    count++;
	}
    }

    TOWORD(d->data + 2,count);
    TOWORD(d->data + 6,property);

    // Generate fieldlist type record
    dt = debtyp_alloc(fnamelen);
    p = dt->data;

    // And fill it in
    TOWORD(p,LF_FIELDLIST);
    p += 2;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];

	p += s->cvMember(p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    TOWORD(d->data + 4,cv_debtyp(dt));

//    cv4_outsym(s);

    unsigned char *debsym;
    unsigned length;

    len = strlen(id);
    debsym = (unsigned char *) alloca(39 + IDOHD + len);

    // Output a 'user-defined type' for the tag name
    TOWORD(debsym + 2,S_UDT);
    TOIDX(debsym + 4,typidx);
    length = 2 + 2 + cgcv.sz_idx;
    length += cv_namestring(debsym + length,id);
    TOWORD(debsym,length - 2);

    assert(length <= 40 + len);
    obj_write_bytes(SegData[DEBSYM],length,debsym);

//    return typidx;
}
示例#17
0
文件: enum.c 项目: Geod24/dnet
int EnumDeclaration::oneMember(Dsymbol **ps)
{
    if (isAnonymous())
	return Dsymbol::oneMembers(members, ps);
    return Dsymbol::oneMember(ps);
}
示例#18
0
文件: enum.c 项目: rbanderton/dmd
bool EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
    if (isAnonymous())
        return Dsymbol::oneMembers(members, ps, ident);
    return Dsymbol::oneMember(ps, ident);
}
示例#19
0
文件: enum.c 项目: Geod24/dnet
void EnumDeclaration::semantic(Scope *sc)
{
    Type *t;
    Scope *sce;

    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
    //printf("EnumDeclaration::semantic() %s\n", toChars());
    if (!members)		// enum ident;
	return;

    if (!memtype && !isAnonymous())
    {	// Set memtype if we can to reduce fwd reference errors
	memtype = Type::tint32;	// case 1)  enum ident { ... }
    }

    if (symtab)			// if already done
    {	if (!scope)
	    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;
    }

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

    parent = sc->parent;

    /* The separate, and distinct, cases are:
     *  1. enum { ... }
     *  2. enum : memtype { ... }
     *  3. enum ident { ... }
     *  4. enum ident : memtype { ... }
     */

    if (memtype)
    {
	memtype = memtype->semantic(loc, sc);

	/* Check to see if memtype is forward referenced
	 */
	if (memtype->ty == Tenum)
	{   EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
	    if (!sym->memtype || !sym->members || !sym->symtab || sym->scope)
	    {	// memtype is forward referenced, so try again later
		scope = scx ? scx : new Scope(*sc);
		scope->setNoFree();
		scope->module->addDeferredSemantic(this);
		printf("\tdeferring %s\n", toChars());
		return;
	    }
	}
#if 0	// Decided to abandon this restriction for D 2.0
	if (!memtype->isintegral())
	{   error("base type must be of integral type, not %s", memtype->toChars());
	    memtype = Type::tint32;
	}
#endif
    }

    type = type->semantic(loc, sc);
    if (isAnonymous())
    	sce = sc;
    else
    {	sce = sc->push(this);
	sce->parent = this;
    }
    if (members->dim == 0)
	error("enum %s must have at least one member", toChars());
    int first = 1;
    Expression *elast = NULL;
    for (int i = 0; i < members->dim; i++)
    {
	EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember();
	Expression *e;

	if (!em)
	    /* The e->semantic(sce) can insert other symbols, such as
	     * template instances and function literals.
	     */
	    continue;

	//printf("  Enum member '%s'\n",em->toChars());
	if (em->type)
	    em->type = em->type->semantic(em->loc, sce);
	e = em->value;
	if (e)
	{
	    assert(e->dyncast() == DYNCAST_EXPRESSION);
	    e = e->semantic(sce);
	    e = e->optimize(WANTvalue | WANTinterpret);
	    if (memtype)
	    {
		e = e->implicitCastTo(sce, memtype);
		e = e->optimize(WANTvalue | WANTinterpret);
		if (!isAnonymous())
		    e = e->castTo(sce, type);
		t = memtype;
	    }
	    else if (em->type)
	    {
		e = e->implicitCastTo(sce, em->type);
		e = e->optimize(WANTvalue | WANTinterpret);
		assert(isAnonymous());
		t = e->type;
	    }
	    else
		t = e->type;
	}
	else if (first)
	{
	    if (memtype)
		t = memtype;
	    else if (em->type)
		t = em->type;
	    else
		t = Type::tint32;
	    e = new IntegerExp(em->loc, 0, Type::tint32);
	    e = e->implicitCastTo(sce, t);
	    e = e->optimize(WANTvalue | WANTinterpret);
	    if (!isAnonymous())
		e = e->castTo(sce, type);
	}
	else
	{
	    // Set value to (elast + 1).
	    // But first check that (elast != t.max)
	    assert(elast);
	    e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
	    e = e->semantic(sce);
	    e = e->optimize(WANTvalue | WANTinterpret);
	    if (e->toInteger())
		error("overflow of enum value %s", elast->toChars());

	    // Now set e to (elast + 1)
	    e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32));
	    e = e->semantic(sce);
	    e = e->castTo(sce, elast->type);
	    e = e->optimize(WANTvalue | WANTinterpret);
	}
	elast = e;
	em->value = e;

	// Add to symbol table only after evaluating 'value'
	if (isAnonymous())
	{
	    /* Anonymous enum members get added to enclosing scope.
	     */
	    for (Scope *scx = sce; scx; scx = scx->enclosing)
	    {
		if (scx->scopesym)
		{
		    if (!scx->scopesym->symtab)
			scx->scopesym->symtab = new DsymbolTable();
		    em->addMember(sce, scx->scopesym, 1);
		    break;
		}
	    }
	}
	else
	    em->addMember(sc, this, 1);

	/* Compute .min, .max and .default values.
	 * If enum doesn't have a name, we can never identify the enum type,
	 * so there is no purpose for a .min, .max or .default
	 */
	if (!isAnonymous())
	{
	    if (first)
	    {	defaultval = e;
		minval = e;
		maxval = e;
	    }
	    else
	    {	Expression *ec;

		/* In order to work successfully with UDTs,
		 * build expressions to do the comparisons,
		 * and let the semantic analyzer and constant
		 * folder give us the result.
		 */

		// Compute if(e < minval)
		ec = new CmpExp(TOKlt, em->loc, e, minval);
		ec = ec->semantic(sce);
		ec = ec->optimize(WANTvalue | WANTinterpret);
		if (ec->toInteger())
		    minval = e;

		ec = new CmpExp(TOKgt, em->loc, e, maxval);
		ec = ec->semantic(sce);
		ec = ec->optimize(WANTvalue | WANTinterpret);
		if (ec->toInteger())
		    maxval = e;
	    }
	}
	first = 0;
    }
    //printf("defaultval = %lld\n", defaultval);

    //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
    if (sc != sce)
	sce->pop();
    //members->print();
}
示例#20
0
文件: struct.c 项目: duralog/ldc
void StructDeclaration::semantic(Scope *sc)
{
    Scope *sc2;

    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    assert(type);
    if (!members)               // if opaque declaration
    {
        return;
    }

    if (symtab)
    {   if (sizeok == SIZEOKdone || !scope)
        {   //printf("already completed\n");
            scope = NULL;
            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;
    }

    int errors = global.errors;

    unsigned dprogress_save = Module::dprogress;

    parent = sc->parent;
    type = type->semantic(loc, sc);
    handle = type;
    protection = sc->protection;
    alignment = sc->structalign;
    storage_class |= sc->stc;
    if (sc->stc & STCdeprecated)
        isdeprecated = true;
    assert(!isAnonymous());
    if (sc->stc & STCabstract)
        error("structs, unions cannot be abstract");
    userAttributes = sc->userAttributes;

    if (sizeok == SIZEOKnone)            // if not already done the addMember step
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
        }
    }

    sizeok = SIZEOKnone;
    sc2 = sc->push(this);
    sc2->stc &= STCsafe | STCtrusted | STCsystem;
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = PROTpublic;
    sc2->explicitProtection = 0;
    sc2->structalign = STRUCTALIGN_DEFAULT;
    sc2->userAttributes = NULL;

    /* 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))
        {
            //printf("struct: setScope %s %s\n", s->kind(), s->toChars());
            s->setScope(sc2);
        }
    }

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

        /* If this is the last member, see if we can finish setting the size.
         * This could be much better - finish setting the size after the last
         * field was processed. The problem is the chicken-and-egg determination
         * of when that is. See Bugzilla 7426 for more info.
         */
        if (i + 1 == members->dim)
        {
            if (sizeok == SIZEOKnone && s->isAliasDeclaration())
                finalizeSize(sc2);
        }
        // Ungag errors when not speculative
        unsigned oldgag = global.gag;
        if (global.isSpeculativeGagging() && !isSpeculative())
        {
            global.gag = 0;
        }
        s->semantic(sc2);
        global.gag = oldgag;
    }
    finalizeSize(sc2);

    if (sizeok == SIZEOKfwd)
    {   // semantic() failed because of 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;

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

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    Module::dprogress++;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (size_t i = 0; i < fields.dim; i++)
    {
        Dsymbol *s = fields[i];
        VarDeclaration *vd = s->isVarDeclaration();
        if (vd && !vd->isDataseg())
        {
            if (vd->init)
            {
                // Should examine init to see if it is really all 0's
                zeroInit = 0;
                break;
            }
            else
            {
                if (!vd->type->isZeroInit(loc))
                {
                    zeroInit = 0;
                    break;
                }
            }
        }
    }

#if DMDV1
    /* This doesn't work for DMDV2 because (ref S) and (S) parameter
     * lists will overload the same.
     */
    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
     * a parameter that is a pointer to the struct. But if there
     * isn't one, but is an opEquals or opCmp with a value, write
     * another that is a shell around the value:
     *  int opCmp(struct *p) { return opCmp(*p); }
     */

    TypeFunction *tfeqptr;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, handle, Id::p, NULL);

        arguments->push(arg);
        tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), sc);
    }

    TypeFunction *tfeq;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, type, NULL, NULL);

        arguments->push(arg);
        tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeq = (TypeFunction *)tfeq->semantic(Loc(), sc);
    }

    Identifier *id = Id::eq;
    for (int i = 0; i < 2; i++)
    {
        Dsymbol *s = search_function(this, id);
        FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
        if (fdx)
        {   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
            if (!fd)
            {   fd = fdx->overloadExactMatch(tfeq);
                if (fd)
                {   // Create the thunk, fdptr
                    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
                    Expression *e = new IdentifierExp(loc, Id::p);
                    e = new PtrExp(loc, e);
                    Expressions *args = new Expressions();
                    args->push(e);
                    e = new IdentifierExp(loc, id);
                    e = new CallExp(loc, e, args);
                    fdptr->fbody = new ReturnStatement(loc, e);
                    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
                    assert(s);
                    s->members->push(fdptr);
                    fdptr->addMember(sc, s, 1);
                    fdptr->semantic(sc2);
                }
            }
        }

        id = Id::cmp;
    }
#endif
#if DMDV2
    dtor = buildDtor(sc2);
    postblit = buildPostBlit(sc2);
    cpctor = buildCpCtor(sc2);

    buildOpAssign(sc2);
    buildOpEquals(sc2);
#endif
    inv = buildInv(sc2);

    sc2->pop();

    /* Look for special member functions.
     */
#if DMDV2
    ctor = search(Loc(), Id::ctor, 0);
#endif
    aggNew =       (NewDeclaration *)search(Loc(), Id::classNew,       0);
    aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete,    0);

    TypeTuple *tup = type->toArgTypes();
    size_t dim = tup->arguments->dim;
    if (dim >= 1)
    {   assert(dim <= 2);
        arg1type = (*tup->arguments)[0]->type;
        if (dim == 2)
            arg2type = (*tup->arguments)[1]->type;
    }

    if (sc->func)
    {
        semantic2(sc);
        semantic3(sc);
    }

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

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

#if 0
    if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this)
    {
        printf("this = %p %s\n", this, this->toChars());
        printf("type = %d sym = %p\n", type->ty, ((TypeStruct *)type)->sym);
    }
#endif
    assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this);
}
示例#21
0
文件: struct.c 项目: kryptonX/dmd
void StructDeclaration::semantic(Scope *sc)
{
    Scope *sc2;

    //printf("+StructDeclaration::semantic(this=%p, %s '%s', sizeok = %d)\n", this, parent->toChars(), toChars(), sizeok);

    //static int count; if (++count == 20) halt();

    assert(type);
    if (!members)                       // if forward reference
        return;

    if (symtab)
    {   if (sizeok == 1 || !scope)
        {   //printf("already completed\n");
            scope = NULL;
            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;
    }

    int errors = global.gaggedErrors;

    unsigned dprogress_save = Module::dprogress;

    parent = sc->parent;
    type = type->semantic(loc, sc);
#if STRUCTTHISREF
    handle = type;
#else
    handle = type->pointerTo();
#endif
    structalign = sc->structalign;
    protection = sc->protection;
    storage_class |= sc->stc;
    if (sc->stc & STCdeprecated)
        isdeprecated = true;
    assert(!isAnonymous());
    if (sc->stc & STCabstract)
        error("structs, unions cannot be abstract");
#if DMDV2
    if (storage_class & STCimmutable)
        type = type->addMod(MODimmutable);
    if (storage_class & STCconst)
        type = type->addMod(MODconst);
    if (storage_class & STCshared)
        type = type->addMod(MODshared);
#endif

    if (sizeok == 0)            // if not already done the addMember step
    {
        int hasfunctions = 0;
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = members->tdata()[i];
            //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
            s->addMember(sc, this, 1);
            if (s->isFuncDeclaration())
                hasfunctions = 1;
        }

        // If nested struct, add in hidden 'this' pointer to outer scope
        if (hasfunctions && !(storage_class & STCstatic))
        {   Dsymbol *s = toParent2();
            if (s)
            {
                AggregateDeclaration *ad = s->isAggregateDeclaration();
                FuncDeclaration *fd = s->isFuncDeclaration();

                TemplateInstance *ti;
                if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd)
                {   isnested = 1;
                    Type *t;
                    if (ad)
                        t = ad->handle;
                    else if (fd)
                    {   AggregateDeclaration *ad = fd->isMember2();
                        if (ad)
                            t = ad->handle;
                        else
                            t = Type::tvoidptr;
                    }
                    else
                        assert(0);
                    if (t->ty == Tstruct)
                        t = Type::tvoidptr;     // t should not be a ref type
                    assert(!vthis);
                    vthis = new ThisDeclaration(loc, t);
                    //vthis->storage_class |= STCref;
                    members->push(vthis);
                }
            }
        }
    }

    sizeok = 0;
    sc2 = sc->push(this);
    sc2->stc &= STCsafe | STCtrusted | STCsystem;
    sc2->parent = this;
    if (isUnionDeclaration())
        sc2->inunion = 1;
    sc2->protection = PROTpublic;
    sc2->explicitProtection = 0;

    size_t members_dim = members->dim;

    /* 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))
        {
            //printf("setScope %s %s\n", s->kind(), s->toChars());
            s->setScope(sc2);
        }
    }

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

        /* If this is the last member, see if we can finish setting the size.
         * This could be much better - finish setting the size after the last
         * field was processed. The problem is the chicken-and-egg determination
         * of when that is. See Bugzilla 7426 for more info.
         */
        if (i + 1 == members_dim)
        {
            if (sizeok == 0 && s->isAliasDeclaration())
                finalizeSize();
        }
        // Ungag errors when not speculative
        unsigned oldgag = global.gag;
        if (global.isSpeculativeGagging() && !isSpeculative())
            global.gag = 0;
        s->semantic(sc2);
        global.gag = oldgag;
    }

    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;

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

        Module::dprogress = dprogress_save;
        //printf("\tdeferring %s\n", toChars());
        return;
    }

    finalizeSize();
    Module::dprogress++;

    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());

    // Determine if struct is all zeros or not
    zeroInit = 1;
    for (size_t i = 0; i < fields.dim; i++)
    {
        Dsymbol *s = fields.tdata()[i];
        VarDeclaration *vd = s->isVarDeclaration();
        if (vd && !vd->isDataseg())
        {
            if (vd->init)
            {
                // Should examine init to see if it is really all 0's
                zeroInit = 0;
                break;
            }
            else
            {
                if (!vd->type->isZeroInit(loc))
                {
                    zeroInit = 0;
                    break;
                }
            }
        }
    }

#if DMDV1
    /* This doesn't work for DMDV2 because (ref S) and (S) parameter
     * lists will overload the same.
     */
    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
     * a parameter that is a pointer to the struct. But if there
     * isn't one, but is an opEquals or opCmp with a value, write
     * another that is a shell around the value:
     *  int opCmp(struct *p) { return opCmp(*p); }
     */

    TypeFunction *tfeqptr;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, handle, Id::p, NULL);

        arguments->push(arg);
        tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
    }

    TypeFunction *tfeq;
    {
        Parameters *arguments = new Parameters;
        Parameter *arg = new Parameter(STCin, type, NULL, NULL);

        arguments->push(arg);
        tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
        tfeq = (TypeFunction *)tfeq->semantic(0, sc);
    }

    Identifier *id = Id::eq;
    for (int i = 0; i < 2; i++)
    {
        Dsymbol *s = search_function(this, id);
        FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
        if (fdx)
        {   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr);
            if (!fd)
            {   fd = fdx->overloadExactMatch(tfeq);
                if (fd)
                {   // Create the thunk, fdptr
                    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
                    Expression *e = new IdentifierExp(loc, Id::p);
                    e = new PtrExp(loc, e);
                    Expressions *args = new Expressions();
                    args->push(e);
                    e = new IdentifierExp(loc, id);
                    e = new CallExp(loc, e, args);
                    fdptr->fbody = new ReturnStatement(loc, e);
                    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
                    assert(s);
                    s->members->push(fdptr);
                    fdptr->addMember(sc, s, 1);
                    fdptr->semantic(sc2);
                }
            }
        }

        id = Id::cmp;
    }
#endif
#if DMDV2
    dtor = buildDtor(sc2);
    postblit = buildPostBlit(sc2);
    cpctor = buildCpCtor(sc2);

    buildOpAssign(sc2);
    hasIdentityEquals = (buildOpEquals(sc2) != NULL);

    xeq = buildXopEquals(sc2);
#endif

    sc2->pop();

    /* Look for special member functions.
     */
#if DMDV2
    ctor = search(0, Id::ctor, 0);
#endif
    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);

    if (sc->func)
    {
        semantic2(sc);
        semantic3(sc);
    }

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

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