Skip to content

Commit

Permalink
Merge pull request #2256 from 9rnsr/fix_imports
Browse files Browse the repository at this point in the history
Fix issue 313 & 314 implement more strict import mechanism
  • Loading branch information
andralex committed Mar 15, 2014
2 parents dea20e7 + 45d5530 commit 6cf3992
Show file tree
Hide file tree
Showing 67 changed files with 1,335 additions and 254 deletions.
5 changes: 2 additions & 3 deletions src/access.c
Expand Up @@ -281,9 +281,8 @@ bool hasPackageAccess(Scope *sc, Dsymbol *s)
Dsymbol *s2 = dst->lookup(m->ident);
assert(s2);
Package *p = s2->isPackage();
if (p && p->isPkgMod == PKGmodule)
if (p && p->isPackageMod())
{
assert(p->mod == m);
pkg = p;
break;
}
Expand All @@ -305,7 +304,7 @@ bool hasPackageAccess(Scope *sc, Dsymbol *s)
#endif
return true;
}
if (pkg->isPkgMod == PKGmodule && pkg->mod == sc->module)
if (pkg->isPackageMod() == sc->module)
{
#if LOG
printf("\ts is in same package.d module as sc\n");
Expand Down
41 changes: 40 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 All @@ -624,6 +649,12 @@ void ClassDeclaration::semantic(Scope *sc)
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];
Expand Down Expand Up @@ -949,7 +980,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 Expand Up @@ -1451,6 +1484,12 @@ void InterfaceDeclaration::semantic(Scope *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];
Expand Down
106 changes: 85 additions & 21 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 @@ -834,6 +834,7 @@ bool Dsymbol::inNonRoot()
OverloadSet::OverloadSet(Identifier *ident)
: Dsymbol(ident)
{
bug12359 = false;
}

void OverloadSet::push(Dsymbol *s)
Expand All @@ -856,6 +857,7 @@ ScopeDsymbol::ScopeDsymbol()
symtab = NULL;
imports = NULL;
prots = NULL;
pkgtab = NULL;
}

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

Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
Expand Down Expand Up @@ -895,12 +898,66 @@ 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
// FIXME: Issue 10604 - Not consistent access check for overloaded symbols
if ((flags & IgnorePrivateMembers) && /*!s1->isOverloadable() && */s1->prot() == PROTprivate)
s1 = NULL;
#if 1
if (!s1 || !imports)
return s1;

Dsymbol *s = s1;
if (!s->isFuncDeclaration())
return s1;

OverloadSet *a = NULL;
for (size_t n = 0; n < imports->dim; n++)
{
Import *ss = (*imports)[n]->isImport();
if (!ss || ss->names.dim == 0)
continue;

Dsymbol *s2 = ss->search(loc, ident, flags & IgnorePrivateImports);
if (!s2)
continue;

if (!s2->isFuncDeclaration())
continue;

if (!a)
{
a = new OverloadSet(s->ident);
a->parent = this;
a->bug12359 = true;
}
/* 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 == s3)
{
if (s3->isDeprecated() ||
s2->prot() > s3->prot() && s2->prot() != PROTnone)
a->a[j] = s2;
goto LcontinueX;
}
}
a->push(s2);
LcontinueX:
continue;
}
if (a)
{
a->push(s);
s1 = a;
}
#endif
return s1;
}
else if (!imports)
return NULL;
else

if (imports)
{
Dsymbol *s = NULL;
OverloadSet *a = NULL;
Expand All @@ -909,15 +966,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 @@ -994,24 +1049,33 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
}
}

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

if (s)
{
if (!(flags & IgnoreErrors) && s->prot() == PROTprivate && !s->parent->isTemplateMixin())
/* Build special symbol if we had multiple finds
*/
if (a)
{
a->push(s);
s = a;
}

// FIXME: Issue 10604 - Not consistent access check for overloaded symbols
if (!(flags & IgnoreErrors) /*&& !s->isOverloadable()*/ &&
s->prot() == PROTprivate && !s->parent->isTemplateMixin())
{
if (!s->isImport())
error(loc, "%s %s is private", s->kind(), s->toPrettyChars());
}
return s;
}
return s;
}

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

void ScopeDsymbol::importScope(Dsymbol *s, PROT protection)
Expand Down
7 changes: 7 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 Expand Up @@ -342,6 +348,7 @@ class OverloadSet : public Dsymbol
{
public:
Dsymbols a; // array of Dsymbols
bool bug12359;

OverloadSet(Identifier *ident);
void push(Dsymbol *s);
Expand Down

0 comments on commit 6cf3992

Please sign in to comment.