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; }
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; } }