Beispiel #1
0
void AliasDeclaration::semantic(Scope *sc)
{
    //printf("AliasDeclaration::semantic() %s\n", toChars());
    if (aliassym)
    {
        if (aliassym->isTemplateInstance())
            aliassym->semantic(sc);
        return;
    }
    this->inSemantic = 1;

#if DMDV1   // don't really know why this is here
    if (storage_class & STCconst)
        error("cannot be const");
#endif

    storage_class |= sc->stc & STCdeprecated;

    // Given:
    //  alias foo.bar.abc def;
    // it is not knowable from the syntax whether this is an alias
    // for a type or an alias for a symbol. It is up to the semantic()
    // pass to distinguish.
    // If it is a type, then type is set and getType() will return that
    // type. If it is a symbol, then aliassym is set and type is NULL -
    // toAlias() will return aliasssym.

    Dsymbol *s;
    Type *t;
    Expression *e;

    /* This section is needed because resolve() will:
     *   const x = 3;
     *   alias x y;
     * try to alias y to 3.
     */
    s = type->toDsymbol(sc);
    if (s
#if DMDV2
`       && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())
#endif
        )
        goto L2;                        // it's a symbolic alias

#if DMDV2
    type = type->addStorageClass(storage_class);
    if (storage_class & (STCref | STCnothrow | STCpure | STCdisable))
    {   // For 'ref' to be attached to function types, and picked
        // up by Type::resolve(), it has to go into sc.
        sc = sc->push();
        sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable);
        type->resolve(loc, sc, &e, &t, &s);
        sc = sc->pop();
    }
    else
#endif
        type->resolve(loc, sc, &e, &t, &s);
    if (s)
    {
        goto L2;
    }
    else if (e)
    {
        // Try to convert Expression to Dsymbol
        if (e->op == TOKvar)
        {   s = ((VarExp *)e)->var;
            goto L2;
        }
        else if (e->op == TOKfunction)
        {   s = ((FuncExp *)e)->fd;
            goto L2;
        }
        else
        {   error("cannot alias an expression %s", e->toChars());
            t = e->type;
        }
    }
    else if (t)
    {
        type = t;
    }
    if (overnext)
        ScopeDsymbol::multiplyDefined(0, this, overnext);
    this->inSemantic = 0;
    return;

  L2:
    //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
    type = NULL;
    VarDeclaration *v = s->isVarDeclaration();
    if (0 && v && v->linkage == LINKdefault)
    {
        error("forward reference of %s", v->toChars());
        s = NULL;
    }
    else
    {
        FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
        if (f)
        {
            if (overnext)
            {
                FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
                fa->importprot = importprot;
                if (!fa->overloadInsert(overnext))
                    ScopeDsymbol::multiplyDefined(0, f, overnext);
                overnext = NULL;
                s = fa;
                s->parent = sc->parent;
            }
        }
        if (overnext)
            ScopeDsymbol::multiplyDefined(0, s, overnext);
        if (s == this)
        {
            assert(global.errors);
            s = NULL;
        }
    }
    //printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
    aliassym = s;
    this->inSemantic = 0;
}
Beispiel #2
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;
    }
}