Skip to content

Commit

Permalink
Fix import issues
Browse files Browse the repository at this point in the history
- Add package table in each scope, due to check which package/module name is accessible via imports.
- Renamed/Selective imports no longer create aliases for the introduced names.
- Merge imports in base class members to derived class
  • Loading branch information
9rnsr committed Mar 14, 2014
1 parent 614158f commit cad1dfd
Show file tree
Hide file tree
Showing 30 changed files with 810 additions and 170 deletions.
29 changes: 28 additions & 1 deletion src/class.c
Expand Up @@ -26,10 +26,13 @@
#include "mtype.h"
#include "scope.h"
#include "module.h"
#include "import.h"
#include "expression.h"
#include "statement.h"
#include "template.h"

bool isFriendOf(AggregateDeclaration *ad, AggregateDeclaration *cd);

/********************************* ClassDeclaration ****************************/

ClassDeclaration *ClassDeclaration::object;
Expand Down Expand Up @@ -614,6 +617,28 @@ void ClassDeclaration::semantic(Scope *sc)
size_t members_dim = members->dim;
sizeok = SIZEOKnone;

// Merge base class imports in this class
for (size_t i = 0; i < baseclasses->dim; i++)
{
ClassDeclaration *cd = (*baseclasses)[i]->base;
if (cd && cd->imports)
{
for (size_t j = 0; j < cd->imports->dim; j++)
{
Import *imp = (*cd->imports)[j]->isImport();
PROT prot = cd->prots[j];
if (imp && (prot == PROTpublic || prot == PROTprotected))
{
imp = imp->copy();
imp->protection = prot;
imp->isstatic = true; // Don't insert to sc->scopesym->imports
imp->overnext = NULL;
imp->importScope(sc);
}
}
}
}

/* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums.
*/
Expand Down Expand Up @@ -949,7 +974,9 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
error("base %s is forward referenced", b->base->ident->toChars());
else
{
s = b->base->search(loc, ident, flags);
int flags2 = flags | IgnoreImportedFQN;
if (!isFriendOf(this, b->base)) flags2 |= IgnorePrivateImports;
s = b->base->search(loc, ident, flags2);
if (s == this) // happens if s is nested in this and derives from this
s = NULL;
else if (s)
Expand Down
27 changes: 18 additions & 9 deletions src/dsymbol.c
Expand Up @@ -442,15 +442,15 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, RootObject *id)
switch (id->dyncast())
{
case DYNCAST_IDENTIFIER:
sm = s->search(loc, (Identifier *)id);
sm = s->search(loc, (Identifier *)id, IgnoreImportedFQN);
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);
sm = s->search(loc, ti->name, IgnoreImportedFQN);
if (!sm)
{
sm = s->search_correct(ti->name);
Expand Down Expand Up @@ -856,6 +856,7 @@ ScopeDsymbol::ScopeDsymbol()
symtab = NULL;
imports = NULL;
prots = NULL;
pkgtab = NULL;
}

ScopeDsymbol::ScopeDsymbol(Identifier *id)
Expand All @@ -865,6 +866,7 @@ ScopeDsymbol::ScopeDsymbol(Identifier *id)
symtab = NULL;
imports = NULL;
prots = NULL;
pkgtab = NULL;
}

Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
Expand Down Expand Up @@ -895,7 +897,10 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
//printf("\ts1 = %p, imports = %p, %d\n", s1, imports, imports ? imports->dim : 0);
if (s1)
{
//printf("\ts = '%s.%s'\n",toChars(),s1->toChars());
//printf("\ts = '%s.%s', prot = %d\n", toChars(), s1->toChars(), s1->prot());
// The found symbol which has private access should be invisible
if ((flags & IgnorePrivateMembers) && !s1->isOverloadable() && s1->prot() == PROTprivate)
s1 = NULL;
return s1;
}

Expand All @@ -908,15 +913,13 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
for (size_t i = 0; i < imports->dim; i++)
{
// If private import, don't search it
if ((flags & IgnorePrivateMembers) && prots[i] == PROTprivate)
if ((flags & IgnorePrivateSymbols) && 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() ? IgnorePrivateMembers : IgnoreNone);
//printf("\tscanning imports[%d] : %s '%s', prots = %d\n", i, ss->kind(), ss->toChars(), prots[i]);
Dsymbol *s2 = ss->search(loc, ident, flags & IgnorePrivateImports);
if (!s)
s = s2;
else if (s2 && s != s2)
Expand Down Expand Up @@ -1003,7 +1006,8 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
s = a;
}

if (!(flags & IgnoreErrors) && s->prot() == PROTprivate && !s->parent->isTemplateMixin())
if (!(flags & IgnoreErrors) && !s->isOverloadable() &&
s->prot() == PROTprivate && !s->parent->isTemplateMixin())
{
if (!s->isImport())
error(loc, "%s %s is private", s->kind(), s->toPrettyChars());
Expand All @@ -1012,6 +1016,11 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
}
}

if (!(flags & IgnoreImportedFQN) && pkgtab)
{
// find leftmost package/module name for FQN access
s1 = pkgtab->lookup(ident);
}
return s1;
}

Expand Down
6 changes: 6 additions & 0 deletions src/dsymbol.h
Expand Up @@ -123,6 +123,10 @@ enum
IgnorePrivateMembers = 0x01, // don't find private members
IgnoreErrors = 0x02, // don't give error messages
IgnoreAmbiguous = 0x04, // return NULL if ambiguous
IgnoreImportedFQN = 0x08, // don't find imported FQNs
IgnorePrivateImports = 0x10, // don't find privately imported symbols

IgnorePrivateSymbols = IgnorePrivateMembers | IgnorePrivateImports,
};

typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
Expand Down Expand Up @@ -279,6 +283,8 @@ class ScopeDsymbol : public Dsymbol
Dsymbols *imports; // imported Dsymbol's
PROT *prots; // array of PROT, one for each import

DsymbolTable *pkgtab; // accessible packages/modules from this scope

ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Expand Down
57 changes: 50 additions & 7 deletions src/expression.c
Expand Up @@ -3262,8 +3262,8 @@ Expression *DsymbolExp::semantic(Scope *sc)
error("forward reference of import %s", imp->toChars());
return new ErrorExp();
}
ScopeExp *ie = new ScopeExp(loc, imp->pkg);
return ie->semantic(sc);
type = Type::tvoid;
return this;
}
if (Package *pkg = s->isPackage())
{
Expand Down Expand Up @@ -6933,6 +6933,13 @@ Expression *DotIdExp::semanticX(Scope *sc)
e = e->semantic(sc);
return e;
}
case TOKdsymbol:
if (Import *imp = ((DsymbolExp *)e1)->s->isImport())
{
ds = imp->mod;
goto L1;
}
break;
default:
break;
}
Expand Down Expand Up @@ -7041,18 +7048,54 @@ Expression *DotIdExp::semanticY(Scope *sc, int flag)

Type *t1b = e1->type->toBasetype();

ScopeExp *ie = NULL;
Dsymbol *s;
if (eright->op == TOKdsymbol && ((DsymbolExp *)eright)->s->isImport())
{
Import *imp = (Import *)((DsymbolExp *)eright)->s;
if (imp->mod == sc->module)
s = imp->mod->search(loc, ident, IgnoreImportedFQN);
else
s = imp->search(loc, ident, IgnoreImportedFQN | IgnorePrivateMembers);
if (s)
goto L1;
else if (ident == Id::stringof)
{
OutBuffer buf;
buf.writestring(imp->mod->kind());
buf.writestring(" ");
buf.writestring(imp->mod->toChars());
buf.writeByte(0);
char *s = buf.extractData();
e = new StringExp(loc, s, strlen(s), 'c');
e = e->semantic(sc);
return e;
}
else
{
s = imp->search_correct(ident);
if (s)
error("undefined identifier '%s', did you mean '%s %s'?",
ident->toChars(), s->kind(), s->toChars());
else
error("undefined identifier '%s'", ident->toChars());
return new ErrorExp();
}
}
if (eright->op == TOKimport) // also used for template alias's
{
ScopeExp *ie = (ScopeExp *)eright;
ie = (ScopeExp *)eright;

/* Disable access to another module's private imports.
* The check for 'is sds our current module' is because
* the current module should have access to its own imports.
*/
Dsymbol *s = ie->sds->search(loc, ident,
(ie->sds->isModule() && ie->sds != sc->module) ? IgnorePrivateMembers : IgnoreNone);
s = ie->sds->search(loc, ident,
(ie->sds->isModule() && ie->sds != sc->module ? IgnoreImportedFQN | IgnorePrivateMembers : IgnoreNone)
);
if (s)
{
L1:
/* Check for access before resolving aliases because public
* aliases to private symbols are public.
*/
Expand Down Expand Up @@ -7158,8 +7201,8 @@ Expression *DotIdExp::semanticY(Scope *sc, int flag)
Import *imp = s->isImport();
if (imp)
{
ie = new ScopeExp(loc, imp->pkg);
return ie->semantic(sc);
DsymbolExp *se = new DsymbolExp(loc, imp);
return se->semantic(sc);
}

// BUG: handle other cases like in IdentifierExp::semantic()
Expand Down

0 comments on commit cad1dfd

Please sign in to comment.