Skip to content

Commit

Permalink
fix Issue 15900 - public imports not accessible using FQN
Browse files Browse the repository at this point in the history
- public imports in imported modules were not accessbile using their
  FQN, this was an oversight when adding the package tree masking to fix
  Bugzilla 313 (see #5426)
- fixed by recursively checking imported scopes for accessible packages
- reuse Module.insearch to not follow import cycles
- Uses the same reduced visibility distinction (only private vs. rest) as the
  unqualified symbol search, b/c extending importedScopes to track rich
  visibility (e.g. package(a.b)) was out of scope for a regression fix.
  This should be implemented when combining the search/import w/
  the symbol visibility mechanism.
  • Loading branch information
MartinNowak committed Jul 29, 2016
1 parent 2e620d1 commit 0a20f1d
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/access.d
Expand Up @@ -455,7 +455,7 @@ extern (C++) bool checkAccess(Loc loc, Scope* sc, Package p)
return false;
for (; sc; sc = sc.enclosing)
{
if (sc.scopesym && sc.scopesym.isPackageAccessible(p))
if (sc.scopesym && sc.scopesym.isPackageAccessible(p, Prot(PROTprivate)))
return false;
}
auto name = p.toPrettyChars();
Expand Down
6 changes: 3 additions & 3 deletions src/dimport.d
Expand Up @@ -273,14 +273,14 @@ public:
{
// import a.b.c.d;
auto p = pkg; // a
scopesym.addAccessiblePackage(p);
scopesym.addAccessiblePackage(p, protection);
foreach (id; (*packages)[1 .. packages.dim]) // [b, c]
{
p = cast(Package) p.symtab.lookup(id);
scopesym.addAccessiblePackage(p);
scopesym.addAccessiblePackage(p, protection);
}
}
scopesym.addAccessiblePackage(mod); // d
scopesym.addAccessiblePackage(mod, protection); // d
}

mod.semantic();
Expand Down
12 changes: 12 additions & 0 deletions src/dmodule.d
Expand Up @@ -1111,6 +1111,18 @@ public:
return s;
}

override bool isPackageAccessible(Package p, Prot protection, int flags = 0)
{
if (insearch) // don't follow import cycles
return false;
insearch = true;
scope (exit)
insearch = false;
if (flags & IgnorePrivateImports)
protection = Prot(PROTpublic); // only consider public imports
return super.isPackageAccessible(p, protection);
}

override Dsymbol symtabInsert(Dsymbol s)
{
searchCacheIdent = null; // symbol is inserted, so invalidate cache
Expand Down
26 changes: 18 additions & 8 deletions src/dsymbol.d
Expand Up @@ -1246,7 +1246,7 @@ private:
PROTKIND* prots; // array of PROTKIND, one for each import

import ddmd.root.array : BitArray;
BitArray accessiblePackages;// whitelist of accessible (imported) packages
BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages

public:
final extern (D) this()
Expand Down Expand Up @@ -1482,17 +1482,27 @@ public:
}
}

final void addAccessiblePackage(Package p)
final void addAccessiblePackage(Package p, Prot protection)
{
if (accessiblePackages.length <= p.tag)
accessiblePackages.length = p.tag + 1;
accessiblePackages[p.tag] = true;
auto pary = protection.kind == PROTprivate ? &privateAccessiblePackages : &accessiblePackages;
if (pary.length <= p.tag)
pary.length = p.tag + 1;
(*pary)[p.tag] = true;
}

final bool isPackageAccessible(Package p)
bool isPackageAccessible(Package p, Prot protection, int flags = 0)
{
return p.tag < accessiblePackages.length &&
accessiblePackages[p.tag];
if (p.tag < accessiblePackages.length && accessiblePackages[p.tag] ||
protection.kind == PROTprivate && p.tag < privateAccessiblePackages.length && privateAccessiblePackages[p.tag])
return true;
foreach (i, ss; importedScopes ? (*importedScopes)[] : null)
{
// only search visible scopes && imported modules should ignore private imports
if (protection.kind <= prots[i] &&
ss.isScopeDsymbol.isPackageAccessible(p, protection, IgnorePrivateImports))
return true;
}
return false;
}

override final bool isforwardRef()
Expand Down
3 changes: 2 additions & 1 deletion src/dsymbol.h
Expand Up @@ -296,7 +296,7 @@ class ScopeDsymbol : public Dsymbol
Dsymbols *importedScopes; // imported Dsymbol's
PROTKIND *prots; // array of PROTKIND, one for each import

BitArray accessiblePackages;
BitArray accessiblePackages, privateAccessiblePackages;

public:
ScopeDsymbol();
Expand All @@ -305,6 +305,7 @@ class ScopeDsymbol : public Dsymbol
Dsymbol *search(Loc loc, Identifier *ident, int flags = SearchLocalsOnly);
OverloadSet *mergeOverloadSet(Identifier *ident, OverloadSet *os, Dsymbol *s);
void importScope(Dsymbol *s, Prot protection);
virtual bool isPackageAccessible(Package p, Prot protection, int flags = 0);
bool isforwardRef();
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
const char *kind();
Expand Down
24 changes: 24 additions & 0 deletions test/compilable/imports/g313.d
@@ -0,0 +1,24 @@
module imports.g313;

// adds public package imports (see Bugzilla 15900)
public import imports.g313public;
// same w/ deferred semantics
static if (true)
public import imports.g313staticif;
mixin("public import imports.g313stringmixin;");

template impD()
{
public import imports.g313templatemixin;
}

mixin impD!();

void test15900()
{
// publically imported modules should obviously be available in here as well
imports.g313public.bug();
imports.g313staticif.bug();
imports.g313stringmixin.bug();
imports.g313templatemixin.bug();
}
3 changes: 3 additions & 0 deletions test/compilable/imports/g313public.d
@@ -0,0 +1,3 @@
void bug()
{
}
3 changes: 3 additions & 0 deletions test/compilable/imports/g313staticif.d
@@ -0,0 +1,3 @@
void bug()
{
}
3 changes: 3 additions & 0 deletions test/compilable/imports/g313stringmixin.d
@@ -0,0 +1,3 @@
void bug()
{
}
3 changes: 3 additions & 0 deletions test/compilable/imports/g313templatemixin.d
@@ -0,0 +1,3 @@
void bug()
{
}
12 changes: 12 additions & 0 deletions test/compilable/test313g.d
@@ -0,0 +1,12 @@
// REQUIRED_ARGS: -de
// EXTRA_SOURCES: imports/g313.d
import imports.g313;

void test15900()
{
// publically imported modules from g313 should be available here
imports.g313public.bug();
imports.g313staticif.bug();
imports.g313stringmixin.bug();
imports.g313templatemixin.bug();
}

0 comments on commit 0a20f1d

Please sign in to comment.