Пример #1
0
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
{
    //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
    Dsymbol *s = toAlias();
    Dsymbol *sm;

    if (Declaration *d = s->isDeclaration())
    {
        if (d->inuse)
        {
            ::error(loc, "circular reference to '%s'", d->toPrettyChars());
            return NULL;
        }
    }

    switch (id->dyncast())
    {
        case DYNCAST_IDENTIFIER:
            sm = s->search(loc, (Identifier *)id);
            break;

        case DYNCAST_DSYMBOL:
        {
            // It's a template instance
            //printf("\ttemplate instance id\n");
            Dsymbol *st = (Dsymbol *)id;
            TemplateInstance *ti = st->isTemplateInstance();
            sm = s->search(loc, ti->name);
            if (!sm)
            {
                sm = s->search_correct(ti->name);
                if (sm)
                    error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
                          ti->name->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
                else
                    error("template identifier '%s' is not a member of '%s %s'",
                          ti->name->toChars(), s->kind(), s->toChars());
                return NULL;
            }
            sm = sm->toAlias();
            TemplateDeclaration *td = sm->isTemplateDeclaration();
            if (!td)
            {
                error("%s is not a template, it is a %s", ti->name->toChars(), sm->kind());
                return NULL;
            }
            ti->tempdecl = td;
            if (!ti->semanticRun)
                ti->semantic(sc);
            sm = ti->toAlias();
            break;
        }

        default:
            assert(0);
    }
    return sm;
}
Пример #2
0
void AnonDeclaration::semantic(Scope *sc)
{
    //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);

    assert(sc->parent);

    Dsymbol *p = sc->parent->pastMixin();
    AggregateDeclaration *ad = p->isAggregateDeclaration();
    if (!ad)
    {
        ::error(loc, "%s can only be a part of an aggregate, not %s %s",
            kind(), p->kind(), p->toChars());
        return;
    }

    alignment = sc->structalign;
    if (decl)
    {
        sc = sc->push();
        sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
        sc->inunion = isunion;
        sc->flags = 0;

        for (size_t i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = (*decl)[i];
            s->semantic(sc);
        }
        sc = sc->pop();
    }
}
Пример #3
0
void Nspace::semantic2(Scope *sc)
{
    if (semanticRun >= PASSsemantic2)
        return;
    semanticRun = PASSsemantic2;
#if LOG
    printf("+Nspace::semantic2('%s')\n", toChars());
#endif
    if (members)
    {
        assert(sc);
        sc = sc->push(this);
        sc->linkage = LINKcpp;
        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
#if LOG
            printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
#endif
            s->semantic2(sc);
        }
        sc->pop();
    }
#if LOG
    printf("-Nspace::semantic2('%s')\n", toChars());
#endif
}
Пример #4
0
void AliasThis::semantic(Scope *sc)
{
    Dsymbol *p = sc->parent->pastMixin();
    AggregateDeclaration *ad = p->isAggregateDeclaration();
    if (!ad)
    {
        ::error(loc, "alias this can only be a member of aggregate, not %s %s",
            p->kind(), p->toChars());
        return;
    }

    assert(ad->members);
    Dsymbol *s = ad->search(loc, ident);
    if (!s)
    {
        s = sc->search(loc, ident, NULL);
        if (s)
            ::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
        else
            ::error(loc, "undefined identifier %s", ident->toChars());
        return;
    }
    else if (ad->aliasthis && s != ad->aliasthis)
    {
        ::error(loc, "there can be only one alias this");
        return;
    }

    if (ad->type->ty == Tstruct && ((TypeStruct *)ad->type)->sym != ad)
    {
        AggregateDeclaration *ad2 = ((TypeStruct *)ad->type)->sym;
        assert(ad2->type == Type::terror);
        ad->aliasthis = ad2->aliasthis;
        return;
    }

    /* disable the alias this conversion so the implicit conversion check
     * doesn't use it.
     */
    ad->aliasthis = NULL;

    Dsymbol *sx = s;
    if (sx->isAliasDeclaration())
        sx = sx->toAlias();
    Declaration *d = sx->isDeclaration();
    if (d && !d->isTupleDeclaration())
    {
        Type *t = d->type;
        assert(t);
        if (ad->type->implicitConvTo(t) > MATCHnomatch)
        {
            ::error(loc, "alias this is not reachable as %s already converts to %s", ad->toChars(), t->toChars());
        }
    }

    ad->aliasthis = s;
}
Пример #5
0
Файл: dsymbol.c Проект: olgk/ldc
Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
{
    //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
    Dsymbol *s = toAlias();
    Dsymbol *sm;

    switch (id->dyncast())
    {
        case DYNCAST_IDENTIFIER:
            sm = s->search(loc, id, 0);
            break;

        case DYNCAST_DSYMBOL:
        {   // It's a template instance
            //printf("\ttemplate instance id\n");
            Dsymbol *st = (Dsymbol *)id;
            TemplateInstance *ti = st->isTemplateInstance();
            id = ti->name;
            sm = s->search(loc, id, 0);
            if (!sm)
            {   error("template identifier %s is not a member of %s %s",
                    id->toChars(), s->kind(), s->toChars());
                return NULL;
            }
            sm = sm->toAlias();
            TemplateDeclaration *td = sm->isTemplateDeclaration();
            if (!td)
            {
                error("%s is not a template, it is a %s", id->toChars(), sm->kind());
                return NULL;
            }
            ti->tempdecl = td;
            if (!ti->semanticRun)
                ti->semantic(sc);
            sm = ti->toAlias();
            break;
        }

        default:
            assert(0);
    }
    return sm;
}
Пример #6
0
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
{
    int errors = 0;

    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
    vars.setDim(field.dim);
    t = t->toBasetype();
    if (t->ty == Tstruct)
    {
        unsigned fieldi = 0;

        TypeStruct *ts = (TypeStruct *)t;
        ad = ts->sym;
        if (ad->ctor)
            error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
                ad->kind(), ad->toChars(), ad->toChars());
        StructDeclaration *sd = ad->isStructDeclaration();
        assert(sd);
        sd->size(loc);
        if (sd->sizeok != SIZEOKdone)
        {
            error(loc, "struct %s is forward referenced", sd->toChars());
            errors = 1;
            goto Lerror;
        }
        size_t nfields = sd->fields.dim;
        if (sd->isnested)
            nfields--;
        for (size_t i = 0; i < field.dim; i++)
        {
            Identifier *id = field[i];
            Initializer *val = value[i];
            Dsymbol *s;
            VarDeclaration *v;

            if (id == NULL)
            {
                if (fieldi >= nfields)
                {   error(loc, "too many initializers for %s", ad->toChars());
                    errors = 1;
                    field.remove(i);
                    i--;
                    continue;
                }
                else
                {
                    s = ad->fields[fieldi];
                }
            }
            else
            {
                //s = ad->symtab->lookup(id);
                s = ad->search(loc, id, 0);
                if (!s)
                {
                    s = ad->search_correct(id);
                    if (s)
                        error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                              id->toChars(), t->toChars(), s->kind(), s->toChars());
                    else
                        error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
                    errors = 1;
                    continue;
                }
                s = s->toAlias();

                // Find out which field index it is
                for (fieldi = 0; 1; fieldi++)
                {
                    if (fieldi >= nfields)
                    {
                        error(loc, "%s.%s is not a per-instance initializable field",
                            t->toChars(), s->toChars());
                        errors = 1;
                        break;
                    }
                    if (s == ad->fields[fieldi])
                        break;
                }
            }
            if (s && (v = s->isVarDeclaration()) != NULL)
            {
                val = val->semantic(sc, v->type, needInterpret);
                value[i] = val;
                vars[i] = v;
            }
            else
            {   error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
                errors = 1;
            }
            fieldi++;
        }
    }
    else if (t->ty == Tdelegate && value.dim == 0)
    {   /* Rewrite as empty delegate literal { }
         */
        Parameters *arguments = new Parameters;
        Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
        FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
        fd->fbody = new CompoundStatement(loc, new Statements());
        fd->endloc = loc;
        Expression *e = new FuncExp(loc, fd);
        ExpInitializer *ie = new ExpInitializer(loc, e);
        return ie->semantic(sc, t, needInterpret);
    }
    else
    {
        error(loc, "a struct is not a valid initializer for a %s", t->toChars());
        errors = 1;
    }
Lerror:
    if (errors)
    {
        field.setDim(0);
        value.setDim(0);
        vars.setDim(0);
    }
    return this;
}
Пример #7
0
        void visit(ClassDeclaration *cd)
        {
            //printf("ClassDeclaration::toObjFile('%s')\n", cd->toChars());

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

            if (!cd->members)
                return;

            if (multiobj && !cd->hasStaticCtorOrDtor())
            {
                obj_append(cd);
                return;
            }

            if (global.params.symdebug)
                toDebug(cd);

            assert(!cd->scope);     // semantic() should have been run to completion

            enum_SC scclass = SCglobal;
            if (cd->isInstantiated())
                scclass = SCcomdat;

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

            // Generate C symbols
            toSymbol(cd);
            toVtblSymbol(cd);
            Symbol *sinit = toInitializer(cd);

            //////////////////////////////////////////////

            // Generate static initializer
            sinit->Sclass = scclass;
            sinit->Sfl = FLdata;
            ClassDeclaration_toDt(cd, &sinit->Sdt);
            out_readonly(sinit);
            outdata(sinit);

            //////////////////////////////////////////////

            // Put out the TypeInfo
            genTypeInfo(cd->type, NULL);
            //toObjFile(cd->type->vtinfo, multiobj);

            //////////////////////////////////////////////

            // Put out the ClassInfo
            cd->csym->Sclass = scclass;
            cd->csym->Sfl = FLdata;

            /* The layout is:
               {
                    void **vptr;
                    monitor_t monitor;
                    byte[] initializer;         // static initialization data
                    char[] name;                // class name
                    void *[] vtbl;
                    Interface[] interfaces;
                    ClassInfo *base;            // base class
                    void *destructor;
                    void *invariant;            // class invariant
                    ClassFlags flags;
                    void *deallocator;
                    OffsetTypeInfo[] offTi;
                    void *defaultConstructor;
                    //const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
                    void *xgetRTInfo;
                    //TypeInfo typeinfo;
               }
             */
            dt_t *dt = NULL;
            unsigned offset = Target::classinfosize;    // must be ClassInfo.size
            if (Type::typeinfoclass)
            {
                if (Type::typeinfoclass->structsize != Target::classinfosize)
                {
        #ifdef DEBUG
                    printf("Target::classinfosize = x%x, Type::typeinfoclass->structsize = x%x\n", offset, Type::typeinfoclass->structsize);
        #endif
                    cd->error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
                    fatal();
                }
            }

            if (Type::typeinfoclass)
                dtxoff(&dt, toVtblSymbol(Type::typeinfoclass), 0, TYnptr); // vtbl for ClassInfo
            else
                dtsize_t(&dt, 0);                // BUG: should be an assert()
            dtsize_t(&dt, 0);                    // monitor

            // initializer[]
            assert(cd->structsize >= 8 || (cd->cpp && cd->structsize >= 4));
            dtsize_t(&dt, cd->structsize);           // size
            dtxoff(&dt, sinit, 0, TYnptr);      // initializer

            // name[]
            const char *name = cd->ident->toChars();
            size_t namelen = strlen(name);
            if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
            {
                name = cd->toPrettyChars();
                namelen = strlen(name);
            }
            dtsize_t(&dt, namelen);
            dtabytes(&dt, TYnptr, 0, namelen + 1, name);

            // vtbl[]
            dtsize_t(&dt, cd->vtbl.dim);
            dtxoff(&dt, cd->vtblsym, 0, TYnptr);

            // interfaces[]
            dtsize_t(&dt, cd->vtblInterfaces->dim);
            if (cd->vtblInterfaces->dim)
                dtxoff(&dt, cd->csym, offset, TYnptr);      // (*)
            else
                dtsize_t(&dt, 0);

            // base
            if (cd->baseClass)
                dtxoff(&dt, toSymbol(cd->baseClass), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // destructor
            if (cd->dtor)
                dtxoff(&dt, toSymbol(cd->dtor), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // invariant
            if (cd->inv)
                dtxoff(&dt, toSymbol(cd->inv), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // flags
            ClassFlags::Type flags = ClassFlags::hasOffTi;
            if (cd->isCOMclass()) flags |= ClassFlags::isCOMclass;
            if (cd->isCPPclass()) flags |= ClassFlags::isCPPclass;
            flags |= ClassFlags::hasGetMembers;
            flags |= ClassFlags::hasTypeInfo;
            if (cd->ctor)
                flags |= ClassFlags::hasCtor;
            for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
            {
                if (pc->dtor)
                {
                    flags |= ClassFlags::hasDtor;
                    break;
                }
            }
            if (cd->isabstract)
                flags |= ClassFlags::isAbstract;
            for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
            {
                if (pc->members)
                {
                    for (size_t i = 0; i < pc->members->dim; i++)
                    {
                        Dsymbol *sm = (*pc->members)[i];
                        //printf("sm = %s %s\n", sm->kind(), sm->toChars());
                        if (sm->hasPointers())
                            goto L2;
                    }
                }
            }
            flags |= ClassFlags::noPointers;
          L2:
            dtsize_t(&dt, flags);


            // deallocator
            if (cd->aggDelete)
                dtxoff(&dt, toSymbol(cd->aggDelete), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // offTi[]
            dtsize_t(&dt, 0);
            dtsize_t(&dt, 0);            // null for now, fix later

            // defaultConstructor
            if (cd->defaultCtor && !(cd->defaultCtor->storage_class & STCdisable))
                dtxoff(&dt, toSymbol(cd->defaultCtor), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // xgetRTInfo
            if (cd->getRTInfo)
                Expression_toDt(cd->getRTInfo, &dt);
            else if (flags & ClassFlags::noPointers)
                dtsize_t(&dt, 0);
            else
                dtsize_t(&dt, 1);

            //dtxoff(&dt, toSymbol(type->vtinfo), 0, TYnptr); // typeinfo

            //////////////////////////////////////////////

            // Put out (*vtblInterfaces)[]. Must immediately follow csym, because
            // of the fixup (*)

            offset += cd->vtblInterfaces->dim * (4 * Target::ptrsize);
            for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
            {
                BaseClass *b = (*cd->vtblInterfaces)[i];
                ClassDeclaration *id = b->sym;

                /* The layout is:
                 *  struct Interface
                 *  {
                 *      ClassInfo *interface;
                 *      void *[] vtbl;
                 *      size_t offset;
                 *  }
                 */

                // Fill in vtbl[]
                b->fillVtbl(cd, &b->vtbl, 1);

                dtxoff(&dt, toSymbol(id), 0, TYnptr);         // ClassInfo

                // vtbl[]
                dtsize_t(&dt, id->vtbl.dim);
                dtxoff(&dt, cd->csym, offset, TYnptr);

                dtsize_t(&dt, b->offset);                        // this offset

                offset += id->vtbl.dim * Target::ptrsize;
            }

            // Put out the (*vtblInterfaces)[].vtbl[]
            // This must be mirrored with ClassDeclaration::baseVtblOffset()
            //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars());
            for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
            {
                BaseClass *b = (*cd->vtblInterfaces)[i];
                ClassDeclaration *id = b->sym;

                //printf("    interface[%d] is '%s'\n", i, id->toChars());
                size_t j = 0;
                if (id->vtblOffset())
                {
                    // First entry is ClassInfo reference
                    //dtxoff(&dt, toSymbol(id), 0, TYnptr);

                    // First entry is struct Interface reference
                    dtxoff(&dt, cd->csym, Target::classinfosize + i * (4 * Target::ptrsize), TYnptr);
                    j = 1;
                }
                assert(id->vtbl.dim == b->vtbl.dim);
                for (; j < id->vtbl.dim; j++)
                {
                    assert(j < b->vtbl.dim);
        #if 0
                    RootObject *o = b->vtbl[j];
                    if (o)
                    {
                        printf("o = %p\n", o);
                        assert(o->dyncast() == DYNCAST_DSYMBOL);
                        Dsymbol *s = (Dsymbol *)o;
                        printf("s->kind() = '%s'\n", s->kind());
                    }
        #endif
                    FuncDeclaration *fd = b->vtbl[j];
                    if (fd)
                        dtxoff(&dt, toThunkSymbol(fd, b->offset), 0, TYnptr);
                    else
                        dtsize_t(&dt, 0);
                }
            }

            // Put out the overriding interface vtbl[]s.
            // This must be mirrored with ClassDeclaration::baseVtblOffset()
            //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
            ClassDeclaration *pc;
            for (pc = cd->baseClass; pc; pc = pc->baseClass)
            {
                for (size_t k = 0; k < pc->vtblInterfaces->dim; k++)
                {
                    BaseClass *bs = (*pc->vtblInterfaces)[k];
                    FuncDeclarations bvtbl;
                    if (bs->fillVtbl(cd, &bvtbl, 0))
                    {
                        //printf("\toverriding vtbl[] for %s\n", bs->sym->toChars());
                        ClassDeclaration *id = bs->sym;

                        size_t j = 0;
                        if (id->vtblOffset())
                        {
                            // First entry is ClassInfo reference
                            //dtxoff(&dt, toSymbol(id), 0, TYnptr);

                            // First entry is struct Interface reference
                            dtxoff(&dt, toSymbol(pc), Target::classinfosize + k * (4 * Target::ptrsize), TYnptr);
                            j = 1;
                        }

                        for (; j < id->vtbl.dim; j++)
                        {
                            assert(j < bvtbl.dim);
                            FuncDeclaration *fd = bvtbl[j];
                            if (fd)
                                dtxoff(&dt, toThunkSymbol(fd, bs->offset), 0, TYnptr);
                            else
                                dtsize_t(&dt, 0);
                        }
                    }
                }
            }

            cd->csym->Sdt = dt;
            // ClassInfo cannot be const data, because we use the monitor on it
            outdata(cd->csym);
            if (cd->isExport())
                objmod->export_symbol(cd->csym, 0);

            //////////////////////////////////////////////

            // Put out the vtbl[]
            //printf("putting out %s.vtbl[]\n", toChars());
            dt = NULL;
            if (cd->vtblOffset())
                dtxoff(&dt, cd->csym, 0, TYnptr);           // first entry is ClassInfo reference
            for (size_t i = cd->vtblOffset(); i < cd->vtbl.dim; i++)
            {
                FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration();

                //printf("\tvtbl[%d] = %p\n", i, fd);
                if (fd && (fd->fbody || !cd->isAbstract()))
                {
                    // Ensure function has a return value (Bugzilla 4869)
                    fd->functionSemantic();

                    Symbol *s = toSymbol(fd);

                    if (cd->isFuncHidden(fd))
                    {
                        /* fd is hidden from the view of this class.
                         * If fd overlaps with any function in the vtbl[], then
                         * issue 'hidden' error.
                         */
                        for (size_t j = 1; j < cd->vtbl.dim; j++)
                        {
                            if (j == i)
                                continue;
                            FuncDeclaration *fd2 = cd->vtbl[j]->isFuncDeclaration();
                            if (!fd2->ident->equals(fd->ident))
                                continue;
                            if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
                            {
                                TypeFunction *tf = (TypeFunction *)fd->type;
                                if (tf->ty == Tfunction)
                                    cd->error("use of %s%s is hidden by %s; use 'alias %s = %s.%s;' to introduce base class overload set",
                                        fd->toPrettyChars(),
                                        parametersTypeToChars(tf->parameters, tf->varargs),
                                        cd->toChars(),

                                        fd->toChars(),
                                        fd->parent->toChars(),
                                        fd->toChars());
                                else
                                    cd->error("use of %s is hidden by %s", fd->toPrettyChars(), cd->toChars());
                                break;
                            }
                        }
                    }

                    dtxoff(&dt, s, 0, TYnptr);
                }
                else
                    dtsize_t(&dt, 0);
            }
            cd->vtblsym->Sdt = dt;
            cd->vtblsym->Sclass = scclass;
            cd->vtblsym->Sfl = FLdata;
            out_readonly(cd->vtblsym);
            outdata(cd->vtblsym);
            if (cd->isExport())
                objmod->export_symbol(cd->vtblsym,0);
        }
Пример #8
0
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{
    //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;

    // Look in symbols declared in this module
    Dsymbol *s1 = symtab ? symtab->lookup(ident) : NULL;
    //printf("\ts1 = %p, imports = %p, %d\n", s1, imports, imports ? imports->dim : 0);
    if (s1)
    {
        //printf("\ts = '%s.%s'\n",toChars(),s1->toChars());
        return s1;
    }
    else if (!imports)
        return NULL;
    else
    {
        Dsymbol *s = NULL;
        OverloadSet *a = NULL;

        // Look in imported modules
        for (size_t i = 0; i < imports->dim; i++)
        {
            // If private import, don't search it
            if (flags & 1 && prots[i] == PROTprivate)
                continue;

            Dsymbol *ss = (*imports)[i];

            //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
            /* Don't find private members if ss is a module
             */
            Dsymbol *s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
            if (!s)
                s = s2;
            else if (s2 && s != s2)
            {
                if (s->toAlias() == s2->toAlias() ||
                    s->getType() == s2->getType() && s->getType())
                {
                    /* After following aliases, we found the same
                     * symbol, so it's not an ambiguity.  But if one
                     * alias is deprecated or less accessible, prefer
                     * the other.
                     */
                    if (s->isDeprecated() ||
                        s2->prot() > s->prot() && s2->prot() != PROTnone)
                        s = s2;
                }
                else
                {
                    /* Two imports of the same module should be regarded as
                     * the same.
                     */
                    Import *i1 = s->isImport();
                    Import *i2 = s2->isImport();
                    if (!(i1 && i2 &&
                          (i1->mod == i2->mod ||
                           (!i1->parent->isImport() && !i2->parent->isImport() &&
                            i1->ident->equals(i2->ident))
                          )
                         )
                       )
                    {
                        /* Bugzilla 8668:
                         * Public selective import adds AliasDeclaration in module.
                         * To make an overload set, resolve aliases in here and
                         * get actual overload roots which accessible via s and s2.
                         */
                        s = s->toAlias();
                        s2 = s2->toAlias();

                        /* If both s2 and s are overloadable (though we only
                         * need to check s once)
                         */
                        if (s2->isOverloadable() && (a || s->isOverloadable()))
                        {   if (!a)
                            {
                                a = new OverloadSet(s->ident);
                                a->parent = this;
                            }
                            /* Don't add to a[] if s2 is alias of previous sym
                             */
                            for (size_t j = 0; j < a->a.dim; j++)
                            {   Dsymbol *s3 = a->a[j];
                                if (s2->toAlias() == s3->toAlias())
                                {
                                    if (s3->isDeprecated() ||
                                        s2->prot() > s3->prot() && s2->prot() != PROTnone)
                                        a->a[j] = s2;
                                    goto Lcontinue;
                                }
                            }
                            a->push(s2);
                        Lcontinue:
                            continue;
                        }
                        if (flags & 4)          // if return NULL on ambiguity
                            return NULL;
                        if (!(flags & 2))
                            ScopeDsymbol::multiplyDefined(loc, s, s2);
                        break;
                    }
                }
            }
        }

        /* Build special symbol if we had multiple finds
         */
        if (a)
        {   assert(s);
            a->push(s);
            s = a;
        }

        if (s)
        {
            if (!(flags & 2) && s->prot() == PROTprivate && !s->parent->isTemplateMixin())
            {
                if (!s->isImport())
                    error(loc, "%s %s is private", s->kind(), s->toPrettyChars());
            }
        }
        return s;
    }
}
Пример #9
0
Expression *semanticTraits(TraitsExp *e, Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", e->toChars());
#endif
    if (e->ident != Id::compiles && e->ident != Id::isSame &&
        e->ident != Id::identifier && e->ident != Id::getProtection)
    {
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1))
            return new ErrorExp();
    }
    size_t dim = e->args ? e->args->dim : 0;

    if (e->ident == Id::isArithmetic)
    {
        return isTypeX(e, &isTypeArithmetic);
    }
    else if (e->ident == Id::isFloating)
    {
        return isTypeX(e, &isTypeFloating);
    }
    else if (e->ident == Id::isIntegral)
    {
        return isTypeX(e, &isTypeIntegral);
    }
    else if (e->ident == Id::isScalar)
    {
        return isTypeX(e, &isTypeScalar);
    }
    else if (e->ident == Id::isUnsigned)
    {
        return isTypeX(e, &isTypeUnsigned);
    }
    else if (e->ident == Id::isAssociativeArray)
    {
        return isTypeX(e, &isTypeAssociativeArray);
    }
    else if (e->ident == Id::isStaticArray)
    {
        return isTypeX(e, &isTypeStaticArray);
    }
    else if (e->ident == Id::isAbstractClass)
    {
        return isTypeX(e, &isTypeAbstractClass);
    }
    else if (e->ident == Id::isFinalClass)
    {
        return isTypeX(e, &isTypeFinalClass);
    }
    else if (e->ident == Id::isPOD)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Type *t = isType(o);
        StructDeclaration *sd;
        if (!t)
        {
            e->error("type expected as second argument of __traits %s instead of %s", e->ident->toChars(), o->toChars());
            goto Lfalse;
        }
        Type *tb = t->baseElemOf();
        if (tb->ty == Tstruct
            && ((sd = (StructDeclaration *)(((TypeStruct *)tb)->sym)) != NULL))
        {
            if (sd->isPOD())
                goto Ltrue;
            else
                goto Lfalse;
        }
        goto Ltrue;
    }
    else if (e->ident == Id::isNested)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        AggregateDeclaration *a;
        FuncDeclaration *f;

        if (!s) { }
        else if ((a = s->isAggregateDeclaration()) != NULL)
        {
            if (a->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }
        else if ((f = s->isFuncDeclaration()) != NULL)
        {
            if (f->isNested())
                goto Ltrue;
            else
                goto Lfalse;
        }

        e->error("aggregate or function expected instead of '%s'", o->toChars());
        goto Lfalse;
    }
    else if (e->ident == Id::isAbstractFunction)
    {
        return isFuncX(e, &isFuncAbstractFunction);
    }
    else if (e->ident == Id::isVirtualFunction)
    {
        return isFuncX(e, &isFuncVirtualFunction);
    }
    else if (e->ident == Id::isVirtualMethod)
    {
        return isFuncX(e, &isFuncVirtualMethod);
    }
    else if (e->ident == Id::isFinalFunction)
    {
        return isFuncX(e, &isFuncFinalFunction);
    }
    else if (e->ident == Id::isOverrideFunction)
    {
        return isFuncX(e, &isFuncOverrideFunction);
    }
    else if (e->ident == Id::isStaticFunction)
    {
        return isFuncX(e, &isFuncStaticFunction);
    }
    else if (e->ident == Id::isRef)
    {
        return isDeclX(e, &isDeclRef);
    }
    else if (e->ident == Id::isOut)
    {
        return isDeclX(e, &isDeclOut);
    }
    else if (e->ident == Id::isLazy)
    {
        return isDeclX(e, &isDeclLazy);
    }
    else if (e->ident == Id::identifier)
    {
        // Get identifier for symbol as a string literal
        /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that
         * a symbol should not be folded to a constant.
         * Bit 1 means don't convert Parameter to Type if Parameter has an identifier
         */
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2))
            return new ErrorExp();

        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Parameter *po = isParameter(o);
        Identifier *id;
        if (po)
        {
            id = po->ident;
            assert(id);
        }
        else
        {
            Dsymbol *s = getDsymbol(o);
            if (!s || !s->ident)
            {
                e->error("argument %s has no identifier", o->toChars());
                goto Lfalse;
            }
            id = s->ident;
        }
        StringExp *se = new StringExp(e->loc, id->toChars());
        return se->semantic(sc);
    }
    else if (e->ident == Id::getProtection)
    {
        if (dim != 1)
            goto Ldimerror;

        Scope *sc2 = sc->push();
        sc2->flags = sc->flags | SCOPEnoaccesscheck;
        bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1);
        sc2->pop();

        if (!ok)
            return new ErrorExp();

        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
            if (!isError(o))
                e->error("argument %s has no protection", o->toChars());
            goto Lfalse;
        }
        if (s->scope)
            s->semantic(s->scope);
        PROT protection = s->prot();

        const char *protName = Pprotectionnames[protection];

        assert(protName);
        StringExp *se = new StringExp(e->loc, (char *) protName);
        return se->semantic(sc);
    }
    else if (e->ident == Id::parent)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (s)
        {
            if (FuncDeclaration *fd = s->isFuncDeclaration())   // Bugzilla 8943
                s = fd->toAliasFunc();
            if (!s->isImport())  // Bugzilla 8922
                s = s->toParent();
        }
        if (!s || s->isImport())
        {
            e->error("argument %s has no parent", o->toChars());
            goto Lfalse;
        }

        if (FuncDeclaration *f = s->isFuncDeclaration())
        {
            if (TemplateDeclaration *td = getFuncTemplateDecl(f))
            {
                if (td->overroot)       // if not start of overloaded list of TemplateDeclaration's
                    td = td->overroot;  // then get the start
                Expression *ex = new TemplateExp(e->loc, td, f);
                ex = ex->semantic(sc);
                return ex;
            }

            if (FuncLiteralDeclaration *fld = f->isFuncLiteralDeclaration())
            {
                // Directly translate to VarExp instead of FuncExp
                Expression *ex = new VarExp(e->loc, fld, 1);
                return ex->semantic(sc);
            }
        }

        return (new DsymbolExp(e->loc, s))->semantic(sc);
    }
    else if (e->ident == Id::hasMember ||
             e->ident == Id::getMember ||
             e->ident == Id::getOverloads ||
             e->ident == Id::getVirtualMethods ||
             e->ident == Id::getVirtualFunctions)
    {
        if (dim != 2)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Expression *ex = isExpression((*e->args)[1]);
        if (!ex)
        {
            e->error("expression expected as second argument of __traits %s", e->ident->toChars());
            goto Lfalse;
        }
        ex = ex->ctfeInterpret();
        StringExp *se = ex->toStringExp();
        if (!se || se->length() == 0)
        {
            e->error("string expected as second argument of __traits %s instead of %s", e->ident->toChars(), ex->toChars());
            goto Lfalse;
        }
        se = se->toUTF8(sc);
        if (se->sz != 1)
        {
            e->error("string must be chars");
            goto Lfalse;
        }
        Identifier *id = Lexer::idPool((char *)se->string);

        /* Prefer dsymbol, because it might need some runtime contexts.
         */
        Dsymbol *sym = getDsymbol(o);
        if (sym)
        {
            ex = new DsymbolExp(e->loc, sym);
            ex = new DotIdExp(e->loc, ex, id);
        }
        else if (Type *t = isType(o))
            ex = typeDotIdExp(e->loc, t, id);
        else if (Expression *ex2 = isExpression(o))
            ex = new DotIdExp(e->loc, ex2, id);
        else
        {
            e->error("invalid first argument");
            goto Lfalse;
        }

        if (e->ident == Id::hasMember)
        {
            if (sym)
            {
                Dsymbol *sm = sym->search(e->loc, id);
                if (sm)
                    goto Ltrue;
            }

            /* Take any errors as meaning it wasn't found
             */
            Scope *sc2 = sc->push();
            ex = ex->trySemantic(sc2);
            sc2->pop();
            if (!ex)
                goto Lfalse;
            else
                goto Ltrue;
        }
        else if (e->ident == Id::getMember)
        {
            ex = ex->semantic(sc);
            return ex;
        }
        else if (e->ident == Id::getVirtualFunctions ||
                 e->ident == Id::getVirtualMethods ||
                 e->ident == Id::getOverloads)
        {
            unsigned errors = global.errors;
            Expression *eorig = ex;
            ex = ex->semantic(sc);
            if (errors < global.errors)
                e->error("%s cannot be resolved", eorig->toChars());

            /* Create tuple of functions of ex
             */
            //ex->print();
            Expressions *exps = new Expressions();
            FuncDeclaration *f;
            if (ex->op == TOKvar)
            {
                VarExp *ve = (VarExp *)ex;
                f = ve->var->isFuncDeclaration();
                ex = NULL;
            }
            else if (ex->op == TOKdotvar)
            {
                DotVarExp *dve = (DotVarExp *)ex;
                f = dve->var->isFuncDeclaration();
                if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis)
                    ex = NULL;
                else
                    ex = dve->e1;
            }
            else
                f = NULL;
            Ptrait p;
            p.exps = exps;
            p.e1 = ex;
            p.ident = e->ident;
            overloadApply(f, &p, &fptraits);

            TupleExp *tup = new TupleExp(e->loc, exps);
            return tup->semantic(sc);
        }
        else
            assert(0);
    }
    else if (e->ident == Id::classInstanceSize)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        ClassDeclaration *cd;
        if (!s || (cd = s->isClassDeclaration()) == NULL)
        {
            e->error("first argument is not a class");
            goto Lfalse;
        }
        if (cd->sizeok == SIZEOKnone)
        {
            if (cd->scope)
                cd->semantic(cd->scope);
        }
        if (cd->sizeok != SIZEOKdone)
        {
            e->error("%s %s is forward referenced", cd->kind(), cd->toChars());
            goto Lfalse;
        }
        return new IntegerExp(e->loc, cd->structsize, Type::tsize_t);
    }
    else if (e->ident == Id::getAliasThis)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        AggregateDeclaration *ad;
        if (!s || (ad = s->isAggregateDeclaration()) == NULL)
        {
            e->error("argument is not an aggregate type");
            goto Lfalse;
        }

        Expressions *exps = new Expressions();
        if (ad->aliasthis)
            exps->push(new StringExp(e->loc, ad->aliasthis->ident->toChars()));

        Expression *ex = new TupleExp(e->loc, exps);
        ex = ex->semantic(sc);
        return ex;
    }
    else if (e->ident == Id::getAttributes)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
        #if 0
            Expression *x = isExpression(o);
            Type *t = isType(o);
            if (x) printf("e = %s %s\n", Token::toChars(x->op), x->toChars());
            if (t) printf("t = %d %s\n", t->ty, t->toChars());
        #endif
            e->error("first argument is not a symbol");
            goto Lfalse;
        }
        //printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttributes, s->userAttributesScope);
        UserAttributeDeclaration *udad = s->userAttribDecl;
        TupleExp *tup = new TupleExp(e->loc, udad ? udad->getAttributes() : new Expressions());
        return tup->semantic(sc);
    }
    else if (e->ident == Id::getFunctionAttributes)
    {
        /// extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs.

        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        Type *t = isType(o);
        TypeFunction *tf = NULL;

        if (s)
        {
            if (FuncDeclaration *f = s->isFuncDeclaration())
                t = f->type;
            else if (VarDeclaration *v = s->isVarDeclaration())
                t = v->type;
        }
        if (t)
        {
            if (t->ty == Tfunction)
                tf = (TypeFunction *)t;
            else if (t->ty == Tdelegate)
                tf = (TypeFunction *)t->nextOf();
            else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction)
                tf = (TypeFunction *)t->nextOf();
        }
        if (!tf)
        {
            e->error("first argument is not a function");
            goto Lfalse;
        }

        Expressions *mods = new Expressions();

        PushAttributes pa;
        pa.mods = mods;

        tf->modifiersApply(&pa, &PushAttributes::fp);
        tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem);

        TupleExp *tup = new TupleExp(e->loc, mods);
        return tup->semantic(sc);
    }
    else if (e->ident == Id::allMembers || e->ident == Id::derivedMembers)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        ScopeDsymbol *sds;
        if (!s)
        {
            e->error("argument has no members");
            goto Lfalse;
        }
        Import *import;
        if ((import = s->isImport()) != NULL)
        {
            // Bugzilla 9692
            sds = import->mod;
        }
        else if ((sds = s->isScopeDsymbol()) == NULL)
        {
            e->error("%s %s has no members", s->kind(), s->toChars());
            goto Lfalse;
        }

        // use a struct as local function
        struct PushIdentsDg
        {
            static int dg(void *ctx, size_t n, Dsymbol *sm)
            {
                if (!sm)
                    return 1;
                //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                if (sm->ident)
                {
                    if (sm->ident != Id::ctor &&
                        sm->ident != Id::dtor &&
                        sm->ident != Id::_postblit &&
                        memcmp(sm->ident->string, "__", 2) == 0)
                    {
                        return 0;
                    }

                    //printf("\t%s\n", sm->ident->toChars());
                    Identifiers *idents = (Identifiers *)ctx;

                    /* Skip if already present in idents[]
                     */
                    for (size_t j = 0; j < idents->dim; j++)
                    {   Identifier *id = (*idents)[j];
                        if (id == sm->ident)
                            return 0;
#ifdef DEBUG
                        // Avoid using strcmp in the first place due to the performance impact in an O(N^2) loop.
                        assert(strcmp(id->toChars(), sm->ident->toChars()) != 0);
#endif
                    }

                    idents->push(sm->ident);
                }
                else
                {
                    EnumDeclaration *ed = sm->isEnumDeclaration();
                    if (ed)
                    {
                        ScopeDsymbol::foreach(NULL, ed->members, &PushIdentsDg::dg, (Identifiers *)ctx);
                    }
                }
                return 0;
            }
        };

        Identifiers *idents = new Identifiers;

        ScopeDsymbol::foreach(sc, sds->members, &PushIdentsDg::dg, idents);

        ClassDeclaration *cd = sds->isClassDeclaration();
        if (cd && e->ident == Id::allMembers)
        {
            struct PushBaseMembers
            {
                static void dg(ClassDeclaration *cd, Identifiers *idents)
                {
                    for (size_t i = 0; i < cd->baseclasses->dim; i++)
                    {
                        ClassDeclaration *cb = (*cd->baseclasses)[i]->base;
                        ScopeDsymbol::foreach(NULL, cb->members, &PushIdentsDg::dg, idents);
                        if (cb->baseclasses->dim)
                            dg(cb, idents);
                    }
                }
            };
            PushBaseMembers::dg(cd, idents);
        }

        // Turn Identifiers into StringExps reusing the allocated array
        assert(sizeof(Expressions) == sizeof(Identifiers));
        Expressions *exps = (Expressions *)idents;
        for (size_t i = 0; i < idents->dim; i++)
        {
            Identifier *id = (*idents)[i];
            StringExp *se = new StringExp(e->loc, id->toChars());
            (*exps)[i] = se;
        }

        /* Making this a tuple is more flexible, as it can be statically unrolled.
         * To make an array literal, enclose __traits in [ ]:
         *   [ __traits(allMembers, ...) ]
         */
        Expression *ex = new TupleExp(e->loc, exps);
        ex = ex->semantic(sc);
        return ex;
    }
    else if (e->ident == Id::compiles)
    {
        /* Determine if all the objects - types, expressions, or symbols -
         * compile without error
         */
        if (!dim)
            goto Lfalse;

        for (size_t i = 0; i < dim; i++)
        {
            unsigned errors = global.startGagging();
            unsigned oldspec = global.speculativeGag;
            global.speculativeGag = global.gag;
            Scope *sc2 = sc->push();
            sc2->speculative = true;
            sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile;
            bool err = false;

            RootObject *o = (*e->args)[i];
            Type *t = isType(o);
            Expression *ex = t ? t->toExpression() : isExpression(o);
            if (!ex && t)
            {
                Dsymbol *s;
                t->resolve(e->loc, sc2, &ex, &t, &s);
                if (t)
                {
                    t->semantic(e->loc, sc2);
                    if (t->ty == Terror)
                        err = true;
                }
                else if (s && s->errors)
                    err = true;
            }
            if (ex)
            {
                ex = ex->semantic(sc2);
                ex = resolvePropertiesOnly(sc2, ex);
                ex = ex->optimize(WANTvalue);
                ex = checkGC(sc2, ex);
                if (ex->op == TOKerror)
                    err = true;
            }

            sc2->pop();
            global.speculativeGag = oldspec;
            if (global.endGagging(errors) || err)
            {
                goto Lfalse;
            }
        }
        goto Ltrue;
    }
    else if (e->ident == Id::isSame)
    {
        /* Determine if two symbols are the same
         */
        if (dim != 2)
            goto Ldimerror;
        if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0))
            return new ErrorExp();
        RootObject *o1 = (*e->args)[0];
        RootObject *o2 = (*e->args)[1];
        Dsymbol *s1 = getDsymbol(o1);
        Dsymbol *s2 = getDsymbol(o2);

        //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
#if 0
        printf("o1: %p\n", o1);
        printf("o2: %p\n", o2);
        if (!s1)
        {
            Expression *ea = isExpression(o1);
            if (ea)
                printf("%s\n", ea->toChars());
            Type *ta = isType(o1);
            if (ta)
                printf("%s\n", ta->toChars());
            goto Lfalse;
        }
        else
            printf("%s %s\n", s1->kind(), s1->toChars());
#endif
        if (!s1 && !s2)
        {
            Expression *ea1 = isExpression(o1);
            Expression *ea2 = isExpression(o2);
            if (ea1 && ea2)
            {
                if (ea1->equals(ea2))
                    goto Ltrue;
            }
        }

        if (!s1 || !s2)
            goto Lfalse;

        s1 = s1->toAlias();
        s2 = s2->toAlias();

        if (s1->isFuncAliasDeclaration())
            s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc();
        if (s2->isFuncAliasDeclaration())
            s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc();

        if (s1 == s2)
            goto Ltrue;
        else
            goto Lfalse;
    }
    else if (e->ident == Id::getUnitTests)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        if (!s)
        {
            e->error("argument %s to __traits(getUnitTests) must be a module or aggregate", o->toChars());
            goto Lfalse;
        }

        Import *imp = s->isImport();
        if (imp)  // Bugzilla 10990
            s = imp->mod;

        ScopeDsymbol* scope = s->isScopeDsymbol();

        if (!scope)
        {
            e->error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s", s->toChars(), s->kind());
            goto Lfalse;
        }

        Expressions* unitTests = new Expressions();
        Dsymbols* symbols = scope->members;

        if (global.params.useUnitTests && symbols)
        {
            // Should actually be a set
            AA* uniqueUnitTests = NULL;
            collectUnitTests(symbols, uniqueUnitTests, unitTests);
        }

        TupleExp *tup = new TupleExp(e->loc, unitTests);
        return tup->semantic(sc);
    }
    else if(e->ident == Id::getVirtualIndex)
    {
        if (dim != 1)
            goto Ldimerror;
        RootObject *o = (*e->args)[0];
        Dsymbol *s = getDsymbol(o);
        FuncDeclaration *fd;
        if (!s || (fd = s->isFuncDeclaration()) == NULL)
        {
            e->error("first argument to __traits(getVirtualIndex) must be a function");
            goto Lfalse;
        }
        fd = fd->toAliasFunc(); // Neccessary to support multiple overloads.
        return new IntegerExp(e->loc, fd->vtblIndex, Type::tptrdiff_t);
    }
    else
    {
        if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars))
            e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub);
        else
            e->error("unrecognized trait '%s'", e->ident->toChars());

        goto Lfalse;
    }

    return NULL;

Ldimerror:
    e->error("wrong number of arguments %d", (int)dim);
    goto Lfalse;


Lfalse:
    return new IntegerExp(e->loc, 0, Type::tbool);

Ltrue:
    return new IntegerExp(e->loc, 1, Type::tbool);
}
Пример #10
0
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    //printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars());
    assert(t->ty == Tstruct);
    StructDeclaration *sd = ((TypeStruct *)t)->sym;
    sd->size(loc);
    if (sd->sizeok != SIZEOKdone)
        return new ErrorExp();
    size_t nfields = sd->fields.dim - sd->isNested();

    Expressions *elements = new Expressions();
    elements->setDim(nfields);
    for (size_t i = 0; i < elements->dim; i++)
        (*elements)[i] = NULL;

    // Run semantic for explicitly given initializers
    bool errors = false;
    for (size_t fieldi = 0, i = 0; i < field.dim; i++)
    {
        if (Identifier *id = field[i])
        {
            Dsymbol *s = sd->search(loc, id, 0);
            if (!s)
            {
                s = sd->search_correct(id);
                if (s)
                    error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                          id->toChars(), sd->toChars(), s->kind(), s->toChars());
                else
                    error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
                return new ErrorExp();
            }
            s = s->toAlias();

            // Find out which field index it is
            for (fieldi = 0; 1; fieldi++)
            {
                if (fieldi >= nfields)
                {
                    error(loc, "%s.%s is not a per-instance initializable field",
                        sd->toChars(), s->toChars());
                    return new ErrorExp();
                }
                if (s == sd->fields[fieldi])
                    break;
            }
        }
        else if (fieldi >= nfields)
        {
            error(loc, "too many initializers for %s", sd->toChars());
            return new ErrorExp();
        }

        VarDeclaration *vd = sd->fields[fieldi];
        if ((*elements)[fieldi])
        {
            error(loc, "duplicate initializer for field '%s'", vd->toChars());
            errors = true;
            continue;
        }
        for (size_t j = 0; j < nfields; j++)
        {
            VarDeclaration *v2 = sd->fields[j];
            bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                            v2->offset < vd->offset + vd->type->size());
            if (overlap && (*elements)[j])
            {
                error(loc, "overlapping initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
                errors = true;
                continue;
            }
        }

        assert(sc);
        Initializer *iz = value[i];
        iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
        Expression *ex = iz->toExpression();
        if (ex->op == TOKerror)
        {
            errors = true;
            continue;
        }
        value[i] = iz;
        (*elements)[fieldi] = ex;
        ++fieldi;
    }
    if (errors)
        return new ErrorExp();

    // Fill in missing any elements with default initializers
    for (size_t i = 0; i < elements->dim; i++)
    {
        if ((*elements)[i])
            continue;
        VarDeclaration *vd = sd->fields[i];
        VarDeclaration *vx = vd;
        if (vd->init && vd->init->isVoidInitializer())
            vx = NULL;
        // Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
        size_t fieldi = i;
        for (size_t j = 0; j < nfields; j++)
        {
            if (i == j)
                continue;
            VarDeclaration *v2 = sd->fields[j];
            if (v2->init && v2->init->isVoidInitializer())
                continue;

            bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                            v2->offset < vd->offset + vd->type->size());
            if (!overlap)
                continue;

            if ((*elements)[j])
            {
                vx = NULL;
                break;
            }

    #if 1
            /* Prefer first found non-void-initialized field
             * union U { int a; int b = 2; }
             * U u;    // Error: overlapping initialization for field a and b
             */
            if (!vx)
                vx = v2, fieldi = j;
            else if (v2->init)
            {
                error(loc, "overlapping initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
            }
    #else   // fix Bugzilla 1432
            /* Prefer explicitly initialized field
             * union U { int a; int b = 2; }
             * U u;    // OK (u.b == 2)
             */
            if (!vx || !vx->init && v2->init)
                vx = v2, fieldi = j;
            else if (vx->init && v2->init)
            {
                error(loc, "overlapping default initialization for field %s and %s",
                    v2->toChars(), vd->toChars());
            }
            else
                assert(vx->init || !vx->init && !v2->init);
    #endif
        }
        if (vx)
        {
            if (vx->init)
            {
                assert(!vx->init->isVoidInitializer());
                if (vx->scope)
                {
                    // Do deferred semantic analysis
                    Initializer *i2 = vx->init->syntaxCopy();
                    i2 = i2->semantic(vx->scope, vx->type, INITinterpret);
                    (*elements)[fieldi] = i2->toExpression();
                    if (!global.gag)
                    {
                        vx->scope = NULL;
                        vx->init = i2;  // save result
                    }
                }
                else
                    (*elements)[fieldi] = vx->init->toExpression();
            }
            else
                (*elements)[fieldi] = vx->type->defaultInit();
        }
    }

    for (size_t i = 0; i < elements->dim; i++)
    {
        Expression *e = (*elements)[i];
        if (e && e->op == TOKerror)
            return e;
    }

    Expression *e = new StructLiteralExp(loc, sd, elements, t);
    if (sc)
        e = e->semantic(sc);
    else
        e->type = sd->type; // from glue layer
    return e;
}
Пример #11
0
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", toChars());
#endif
    if (ident != Id::compiles && ident != Id::isSame)
        TemplateInstance::semanticTiargs(loc, sc, args, 1);
    size_t dim = args ? args->dim : 0;
    Object *o;
    FuncDeclaration *f;

#define ISTYPE(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Type *t = getType((Object *)args->data[i]); \
            if (!t)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;

#define ISDSYMBOL(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Dsymbol *s = getDsymbol((Object *)args->data[i]);   \
            if (!s)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;



    if (ident == Id::isArithmetic)
    {
        ISTYPE(t->isintegral() || t->isfloating())
    }
    else if (ident == Id::isFloating)
    {
        ISTYPE(t->isfloating())
    }
    else if (ident == Id::isIntegral)
    {
        ISTYPE(t->isintegral())
    }
    else if (ident == Id::isScalar)
    {
        ISTYPE(t->isscalar())
    }
    else if (ident == Id::isUnsigned)
    {
        ISTYPE(t->isunsigned())
    }
    else if (ident == Id::isAssociativeArray)
    {
        ISTYPE(t->toBasetype()->ty == Taarray)
    }
    else if (ident == Id::isStaticArray)
    {
        ISTYPE(t->toBasetype()->ty == Tsarray)
    }
    else if (ident == Id::isAbstractClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
    }
    else if (ident == Id::isFinalClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
    }
    else if (ident == Id::isAbstractFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
    }
    else if (ident == Id::isVirtualFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
    }
    else if (ident == Id::isFinalFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
    }
    else if (ident == Id::hasMember ||
             ident == Id::getMember ||
             ident == Id::getVirtualFunctions)
    {
        if (dim != 2)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Expression *e = isExpression((Object *)args->data[1]);
        if (!e)
        {   error("expression expected as second argument of __traits %s", ident->toChars());
            goto Lfalse;
        }
        e = e->optimize(WANTvalue | WANTinterpret);
        if (e->op != TOKstring)
        {   error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
            goto Lfalse;
        }
        StringExp *se = (StringExp *)e;
        se = se->toUTF8(sc);
        if (se->sz != 1)
        {   error("string must be chars");
            goto Lfalse;
        }
        Identifier *id = Lexer::idPool((char *)se->string);

        Type *t = isType(o);
        e = isExpression(o);
        Dsymbol *s = isDsymbol(o);
        if (t)
            e = typeDotIdExp(loc, t, id);
        else if (e)
            e = new DotIdExp(loc, e, id);
        else if (s)
        {   e = new DsymbolExp(loc, s);
            e = new DotIdExp(loc, e, id);
        }
        else
        {   error("invalid first argument");
            goto Lfalse;
        }

        if (ident == Id::hasMember)
        {   /* Take any errors as meaning it wasn't found
             */
            unsigned errors = global.errors;
            global.gag++;
            e = e->semantic(sc);
            global.gag--;
            if (errors != global.errors)
            {   if (global.gag == 0)
                    global.errors = errors;
                goto Lfalse;
            }
            else
                goto Ltrue;
        }
        else if (ident == Id::getMember)
        {
            e = e->semantic(sc);
            return e;
        }
        else if (ident == Id::getVirtualFunctions)
        {
            unsigned errors = global.errors;
            Expression *ex = e;
            e = e->semantic(sc);
            if (errors < global.errors)
                error("%s cannot be resolved", ex->toChars());

            /* Create tuple of virtual function overloads of e
             */
            //e->dump(0);
            Expressions *exps = new Expressions();
            FuncDeclaration *f;
            if (e->op == TOKvar)
            {   VarExp *ve = (VarExp *)e;
                f = ve->var->isFuncDeclaration();
            }
            else if (e->op == TOKdotvar)
            {   DotVarExp *dve = (DotVarExp *)e;
                f = dve->var->isFuncDeclaration();
            }
            else
                f = NULL;
            Pvirtuals p;
            p.exps = exps;
            p.e1 = e;
            overloadApply(f, fpvirtuals, &p);

            TupleExp *tup = new TupleExp(loc, exps);
            return tup->semantic(sc);
        }
        else
            assert(0);
    }
    else if (ident == Id::classInstanceSize)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ClassDeclaration *cd;
        if (!s || (cd = s->isClassDeclaration()) == NULL)
        {
            error("first argument is not a class");
            goto Lfalse;
        }
        return new IntegerExp(loc, cd->structsize, Type::tsize_t);
    }
    else if (ident == Id::allMembers || ident == Id::derivedMembers)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ScopeDsymbol *sd;
        if (!s)
        {
            error("argument has no members");
            goto Lfalse;
        }
        if ((sd = s->isScopeDsymbol()) == NULL)
        {
            error("%s %s has no members", s->kind(), s->toChars());
            goto Lfalse;
        }
        Expressions *exps = new Expressions;
        while (1)
        {   size_t dim = ScopeDsymbol::dim(sd->members);
            for (size_t i = 0; i < dim; i++)
            {
                Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i);
                //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                if (sm->ident)
                {
                    //printf("\t%s\n", sm->ident->toChars());
                    char *str = sm->ident->toChars();

                    /* Skip if already present in exps[]
                     */
                    for (size_t j = 0; j < exps->dim; j++)
                    {   StringExp *se2 = (StringExp *)exps->data[j];
                        if (strcmp(str, (char *)se2->string) == 0)
                            goto Lnext;
                    }

                    StringExp *se = new StringExp(loc, str);
                    exps->push(se);
                }
            Lnext:
                ;
            }
            ClassDeclaration *cd = sd->isClassDeclaration();
            if (cd && cd->baseClass && ident == Id::allMembers)
                sd = cd->baseClass;     // do again with base class
            else
                break;
        }
        Expression *e = new ArrayLiteralExp(loc, exps);
        e = e->semantic(sc);
        return e;
    }
    else if (ident == Id::compiles)
    {
        /* Determine if all the objects - types, expressions, or symbols -
         * compile without error
         */
        if (!dim)
            goto Lfalse;

        for (size_t i = 0; i < dim; i++)
        {   Object *o = (Object *)args->data[i];
            Type *t;
            Expression *e;
            Dsymbol *s;

            unsigned errors = global.errors;
            global.gag++;

            t = isType(o);
            if (t)
            {   t->resolve(loc, sc, &e, &t, &s);
                if (t)
                    t->semantic(loc, sc);
                else if (e)
                    e->semantic(sc);
            }
            else
            {   e = isExpression(o);
                if (e)
                    e->semantic(sc);
            }

            global.gag--;
            if (errors != global.errors)
            {
                global.errors = errors;
                goto Lfalse;
            }
        }
        goto Ltrue;
    }
    else if (ident == Id::isSame)
    {   /* Determine if two symbols are the same
         */
        if (dim != 2)
            goto Ldimerror;
        TemplateInstance::semanticTiargs(loc, sc, args, 0);
        Object *o1 = (Object *)args->data[0];
        Object *o2 = (Object *)args->data[1];
        Dsymbol *s1 = getDsymbol(o1);
        Dsymbol *s2 = getDsymbol(o2);

#if 0
        printf("o1: %p\n", o1);
        printf("o2: %p\n", o2);
        if (!s1)
        {   Expression *ea = isExpression(o1);
            if (ea)
                printf("%s\n", ea->toChars());
            Type *ta = isType(o1);
            if (ta)
                printf("%s\n", ta->toChars());
            goto Lfalse;
        }
        else
            printf("%s %s\n", s1->kind(), s1->toChars());
#endif
        if (!s1 && !s2)
        {   Expression *ea1 = isExpression(o1);
            Expression *ea2 = isExpression(o2);
            if (ea1 && ea2 && ea1->equals(ea2))
                goto Ltrue;
        }

        if (!s1 || !s2)
            goto Lfalse;

        s1 = s1->toAlias();
        s2 = s2->toAlias();

        if (s1 == s2)
            goto Ltrue;
        else
            goto Lfalse;
    }
    else
    {   error("unrecognized trait %s", ident->toChars());
        goto Lfalse;
    }

    return NULL;

Lnottype:
    error("%s is not a type", o->toChars());
    goto Lfalse;

Ldimerror:
    error("wrong number of arguments %d", dim);
    goto Lfalse;


Lfalse:
    return new IntegerExp(loc, 0, Type::tbool);

Ltrue:
    return new IntegerExp(loc, 1, Type::tbool);
}
Пример #12
0
void Nspace::semantic(Scope *sc)
{
    if (semanticRun >= PASSsemantic)
        return;
    semanticRun = PASSsemantic;
#if LOG
    printf("+Nspace::semantic('%s')\n", toChars());
#endif
    if (scope)
    {
        sc = scope;
        scope = NULL;
    }
    parent = sc->parent;
    if (members)
    {
        if (!symtab)
            symtab = new DsymbolTable();

        // The namespace becomes 'imported' into the enclosing scope
        for (Scope *sce = sc; 1; sce = sce->enclosing)
        {
            ScopeDsymbol *sds = (ScopeDsymbol *)sce->scopesym;
            if (sds)
            {
                sds->importScope(this, Prot(PROTpublic));
                break;
            }
        }

        assert(sc);
        sc = sc->push(this);
        sc->linkage = LINKcpp;          // note that namespaces imply C++ linkage
        sc->parent = this;

        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            //printf("add %s to scope %s\n", s->toChars(), toChars());
            s->addMember(sc, this);
        }

        for (size_t i = 0; i < members->dim; i++)
        {
            Dsymbol *s = (*members)[i];
            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];
#if LOG
            printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
#endif
            s->semantic(sc);
        }
        sc->pop();
    }
#if LOG
    printf("-Nspace::semantic('%s')\n", toChars());
#endif
}
Пример #13
0
void Import::semantic(Scope *sc)
{
    //printf("Import::semantic('%s')\n", toPrettyChars());

    if (scope)
    {
        sc = scope;
        scope = NULL;
    }

    // Load if not already done so
    if (!mod)
    {
        load(sc);
        if (mod)
            mod->importAll(NULL);
    }

    if (mod)
    {
        // Modules need a list of each imported module
        //printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
        sc->module->aimports.push(mod);

        if (!isstatic && !aliasId && !names.dim)
        {
            if (sc->explicitProtection)
                protection = sc->protection;
            for (Scope *scd = sc; scd; scd = scd->enclosing)
            {
                if (scd->scopesym)
                {
                    scd->scopesym->importScope(mod, protection);
                    break;
                }
            }
        }

        mod->semantic();

        if (mod->needmoduleinfo)
        {
            //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars());
            sc->module->needmoduleinfo = 1;
        }

        sc = sc->push(mod);
        /* BUG: Protection checks can't be enabled yet. The issue is
         * that Dsymbol::search errors before overload resolution.
         */
#if 0
        sc->protection = protection;
#else
        sc->protection = PROTpublic;
#endif
        for (size_t i = 0; i < aliasdecls.dim; i++)
        {
            AliasDeclaration *ad = aliasdecls[i];
            //printf("\tImport alias semantic('%s')\n", ad->toChars());
            if (mod->search(loc, names[i]))
            {
                ad->semantic(sc);
            }
            else
            {
                Dsymbol *s = mod->search_correct(names[i]);
                if (s)
                    mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars());
                else
                    mod->error(loc, "import '%s' not found", names[i]->toChars());
                ad->type = Type::terror;
            }
        }
        sc = sc->pop();
    }

    // object self-imports itself, so skip that (Bugzilla 7547)
    // don't list pseudo modules __entrypoint.d, __main.d (Bugzilla 11117, 11164)
    if (global.params.moduleDeps != NULL &&
        !(id == Id::object && sc->module->ident == Id::object) &&
        sc->module->ident != Id::entrypoint &&
        strcmp(sc->module->ident->string, "__main") != 0)
    {
        /* The grammar of the file is:
         *      ImportDeclaration
         *          ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
         *      ModuleAliasIdentifier ] "\n"
         *
         *      BasicImportDeclaration
         *          ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection|"string"
         *              " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
         *
         *      FilePath
         *          - any string with '(', ')' and '\' escaped with the '\' character
         */

        OutBuffer *ob = global.params.moduleDeps;
        Module* imod = sc->instantiatingModule();
        if (!global.params.moduleDepsFile)
            ob->writestring("depsImport ");
        ob->writestring(imod->toPrettyChars());
        ob->writestring(" (");
        escapePath(ob,  imod->srcfile->toChars());
        ob->writestring(") : ");

        // use protection instead of sc->protection because it couldn't be
        // resolved yet, see the comment above
        protectionToBuffer(ob, protection);
        ob->writeByte(' ');
        if (isstatic)
            StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
        ob->writestring(": ");

        if (packages)
        {
            for (size_t i = 0; i < packages->dim; i++)
            {
                Identifier *pid = (*packages)[i];
                ob->printf("%s.", pid->toChars());
            }
        }

        ob->writestring(id->toChars());
        ob->writestring(" (");
        if (mod)
            escapePath(ob, mod->srcfile->toChars());
        else
            ob->writestring("???");
        ob->writeByte(')');

        for (size_t i = 0; i < names.dim; i++)
        {
            if (i == 0)
                ob->writeByte(':');
            else
                ob->writeByte(',');

            Identifier *name = names[i];
            Identifier *alias = aliases[i];

            if (!alias)
            {
                ob->printf("%s", name->toChars());
                alias = name;
            }
            else
                ob->printf("%s=%s", alias->toChars(), name->toChars());
        }

        if (aliasId)
                ob->printf(" -> %s", aliasId->toChars());

        ob->writenl();
    }

    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
Пример #14
0
void Import::load(Scope *sc)
{
    //printf("Import::load('%s') %p\n", toPrettyChars(), this);

    // See if existing module
    DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
#if 0
    if (pkg && pkg->isModule())
    {
        ::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
             pkg->toChars(), pkg->toPrettyChars(), id->toChars());
        mod = pkg->isModule(); // Error recovery - treat as import of that module
        return;
    }
#endif
    Dsymbol *s = dst->lookup(id);
    if (s)
    {
        if (s->isModule())
            mod = (Module *)s;
        else
        {
            if (s->isAliasDeclaration())
            {
                ::error(loc, "%s %s conflicts with %s", s->kind(), s->toPrettyChars(), id->toChars());
            }
            else if (Package *p = s->isPackage())
            {
                if (p->isPkgMod == PKGunknown)
                {
                    mod = Module::load(loc, packages, id);
                    if (!mod)
                        p->isPkgMod = PKGpackage;
                    else
                        assert(p->isPkgMod == PKGmodule);
                }
                else
                {
                    mod = p->isPackageMod();
                }
                if (!mod)
                {
                    ::error(loc, "can only import from a module, not from package %s.%s",
                        p->toPrettyChars(), id->toChars());
                }
            }
            else if (pkg)
            {
                ::error(loc, "can only import from a module, not from package %s.%s",
                    pkg->toPrettyChars(), id->toChars());
            }
            else
            {
                ::error(loc, "can only import from a module, not from package %s",
                    id->toChars());
            }
        }
    }

    if (!mod)
    {
        // Load module
        mod = Module::load(loc, packages, id);
        if (mod)
        {
            dst->insert(id, mod);           // id may be different from mod->ident,
                                            // if so then insert alias
        }
    }
    if (mod && !mod->importedFrom)
        mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
    if (!pkg)
        pkg = mod;

    //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
}
Пример #15
0
void Import::semantic(Scope *sc)
{
    //printf("Import::semantic('%s')\n", toChars());

    // Load if not already done so
    if (!mod)
    {   load(sc);
        if (mod)
            mod->importAll(0);
    }

    if (mod)
    {
#if 0
        if (mod->loc.linnum != 0)
        {   /* If the line number is not 0, then this is not
             * a 'root' module, i.e. it was not specified on the command line.
             */
            mod->importedFrom = sc->module->importedFrom;
            assert(mod->importedFrom);
        }
#endif

        // Modules need a list of each imported module
        //printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
        sc->module->aimports.push(mod);

        if (!isstatic && !aliasId && !names.dim)
        {
            if (sc->explicitProtection)
                protection = sc->protection;
            for (Scope *scd = sc; scd; scd = scd->enclosing)
            {
                if (scd->scopesym)
                {
                    scd->scopesym->importScope(mod, protection);
                    break;
                }
            }
        }

        mod->semantic();

        if (mod->needmoduleinfo)
        {   //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars());
            sc->module->needmoduleinfo = 1;
        }

        sc = sc->push(mod);
        /* BUG: Protection checks can't be enabled yet. The issue is
         * that Dsymbol::search errors before overload resolution.
         */
#if 0
        sc->protection = protection;
#else
        sc->protection = PROTpublic;
#endif
        for (size_t i = 0; i < aliasdecls.dim; i++)
        {   Dsymbol *s = aliasdecls[i];

            //printf("\tImport alias semantic('%s')\n", s->toChars());
            if (mod->search(loc, names[i], 0))
                s->semantic(sc);
            else
            {
                s = mod->search_correct(names[i]);
                if (s)
                    mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars());
                else
                    mod->error(loc, "import '%s' not found", names[i]->toChars());
            }
        }
        sc = sc->pop();
    }

    if (global.params.moduleDeps != NULL &&
        // object self-imports itself, so skip that (Bugzilla 7547)
        !(id == Id::object && sc->module->ident == Id::object))
    {
        /* The grammar of the file is:
         *      ImportDeclaration
         *          ::= BasicImportDeclaration [ " : " ImportBindList ] [ " -> "
         *      ModuleAliasIdentifier ] "\n"
         *
         *      BasicImportDeclaration
         *          ::= ModuleFullyQualifiedName " (" FilePath ") : " Protection
         *              " [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
         *
         *      FilePath
         *          - any string with '(', ')' and '\' escaped with the '\' character
         */

        OutBuffer *ob = global.params.moduleDeps;

        ob->writestring(sc->module->toPrettyChars());
        ob->writestring(" (");
        escapePath(ob, sc->module->srcfile->toChars());
        ob->writestring(") : ");

        // use protection instead of sc->protection because it couldn't be
        // resolved yet, see the comment above
        ProtDeclaration::protectionToCBuffer(ob, protection);
        if (isstatic)
            StorageClassDeclaration::stcToCBuffer(ob, STCstatic);
        ob->writestring(": ");

        if (packages)
        {
            for (size_t i = 0; i < packages->dim; i++)
            {
                Identifier *pid = (*packages)[i];
                ob->printf("%s.", pid->toChars());
            }
        }

        ob->writestring(id->toChars());
        ob->writestring(" (");
        if (mod)
            escapePath(ob, mod->srcfile->toChars());
        else
            ob->writestring("???");
        ob->writebyte(')');

        for (size_t i = 0; i < names.dim; i++)
        {
            if (i == 0)
                ob->writebyte(':');
            else
                ob->writebyte(',');

            Identifier *name = names[i];
            Identifier *alias = aliases[i];

            if (!alias)
            {
                ob->printf("%s", name->toChars());
                alias = name;
            }
            else
                ob->printf("%s=%s", alias->toChars(), name->toChars());
        }

        if (aliasId)
                ob->printf(" -> %s", aliasId->toChars());

        ob->writenl();
    }

    //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
}
Пример #16
0
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
    t = t->toBasetype();
    if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct)
        t = t->nextOf()->toBasetype();
    if (t->ty == Tstruct)
    {
        StructDeclaration *sd = ((TypeStruct *)t)->sym;
        if (sd->ctor)
        {
            error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
                sd->kind(), sd->toChars(), sd->toChars());
            return new ErrorInitializer();
        }
        sd->size(loc);
        if (sd->sizeok != SIZEOKdone)
            return new ErrorInitializer();
        size_t nfields = sd->fields.dim - sd->isNested();

        //expandTuples for non-identity arguments?

        Expressions *elements = new Expressions();
        elements->setDim(nfields);
        for (size_t i = 0; i < elements->dim; i++)
            (*elements)[i] = NULL;

        // Run semantic for explicitly given initializers
        // TODO: this part is slightly different from StructLiteralExp::semantic.
        bool errors = false;
        for (size_t fieldi = 0, i = 0; i < field.dim; i++)
        {
            if (Identifier *id = field[i])
            {
                Dsymbol *s = sd->search(loc, id);
                if (!s)
                {
                    s = sd->search_correct(id);
                    if (s)
                        error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                              id->toChars(), sd->toChars(), s->kind(), s->toChars());
                    else
                        error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
                    return new ErrorInitializer();
                }
                s = s->toAlias();

                // Find out which field index it is
                for (fieldi = 0; 1; fieldi++)
                {
                    if (fieldi >= nfields)
                    {
                        error(loc, "%s.%s is not a per-instance initializable field",
                            sd->toChars(), s->toChars());
                        return new ErrorInitializer();
                    }
                    if (s == sd->fields[fieldi])
                        break;
                }
            }
            else if (fieldi >= nfields)
            {
                error(loc, "too many initializers for %s", sd->toChars());
                return new ErrorInitializer();
            }

            VarDeclaration *vd = sd->fields[fieldi];
            if ((*elements)[fieldi])
            {
                error(loc, "duplicate initializer for field '%s'", vd->toChars());
                errors = true;
                continue;
            }
            for (size_t j = 0; j < nfields; j++)
            {
                VarDeclaration *v2 = sd->fields[j];
                bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                                v2->offset < vd->offset + vd->type->size());
                if (overlap && (*elements)[j])
                {
                    error(loc, "overlapping initialization for field %s and %s",
                        v2->toChars(), vd->toChars());
                    errors = true;
                    continue;
                }
            }

            assert(sc);
            Initializer *iz = value[i];
            iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret);
            Expression *ex = iz->toExpression();
            if (ex->op == TOKerror)
            {
                errors = true;
                continue;
            }
            value[i] = iz;
            (*elements)[fieldi] = ex;
            ++fieldi;
        }
        if (errors)
            return new ErrorInitializer();

        StructLiteralExp *sle = new StructLiteralExp(loc, sd, elements, t);
        if (!sd->fill(loc, elements, false))
            return new ErrorInitializer();
        sle->type = t;

        ExpInitializer *ie = new ExpInitializer(loc, sle);
        return ie->semantic(sc, t, needInterpret);
    }
    else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0)
    {
        TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction;
        /* Rewrite as empty delegate literal { }
         */
        Parameters *arguments = new Parameters;
        Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
        FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, NULL);
        fd->fbody = new CompoundStatement(loc, new Statements());
        fd->endloc = loc;
        Expression *e = new FuncExp(loc, fd);
        ExpInitializer *ie = new ExpInitializer(loc, e);
        return ie->semantic(sc, t, needInterpret);
    }

    error(loc, "a struct is not a valid initializer for a %s", t->toChars());
    return new ErrorInitializer();
}
Пример #17
0
/*******************************************
 * Look for constructor declaration.
 */
Dsymbol *AggregateDeclaration::searchCtor()
{
    Dsymbol *s = search(Loc(), Id::ctor);
    if (s)
    {
        if (!(s->isCtorDeclaration() ||
              s->isTemplateDeclaration() ||
              s->isOverloadSet()))
        {
            error("%s %s is not a constructor; identifiers starting with __ are reserved for the implementation", s->kind(), s->toChars());
            errors = true;
            s = NULL;
        }
    }
    return s;
}