diff options
Diffstat (limited to 'gcc/d/dmd/access.c')
-rw-r--r-- | gcc/d/dmd/access.c | 560 |
1 files changed, 0 insertions, 560 deletions
diff --git a/gcc/d/dmd/access.c b/gcc/d/dmd/access.c deleted file mode 100644 index 11b26c5..0000000 --- a/gcc/d/dmd/access.c +++ /dev/null @@ -1,560 +0,0 @@ -/* Compiler implementation of the D programming language - * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/access.c - */ - -#include "root/dsystem.h" -#include "root/root.h" -#include "root/rmem.h" - -#include "errors.h" -#include "enum.h" -#include "aggregate.h" -#include "init.h" -#include "attrib.h" -#include "scope.h" -#include "id.h" -#include "mtype.h" -#include "declaration.h" -#include "aggregate.h" -#include "expression.h" -#include "module.h" -#include "template.h" - -/* Code to do access checks - */ - -bool hasPackageAccess(Scope *sc, Dsymbol *s); -bool hasPackageAccess(Module *mod, Dsymbol *s); -bool hasPrivateAccess(AggregateDeclaration *ad, Dsymbol *smember); -bool isFriendOf(AggregateDeclaration *ad, AggregateDeclaration *cd); -static Dsymbol *mostVisibleOverload(Dsymbol *s); - -/**************************************** - * Return Prot access for Dsymbol smember in this declaration. - */ -Prot getAccess(AggregateDeclaration *ad, Dsymbol *smember) -{ - Prot access_ret = Prot(Prot::none); - - assert(ad->isStructDeclaration() || ad->isClassDeclaration()); - if (smember->toParent() == ad) - { - access_ret = smember->prot(); - } - else if (smember->isDeclaration()->isStatic()) - { - access_ret = smember->prot(); - } - if (ClassDeclaration *cd = ad->isClassDeclaration()) - { - for (size_t i = 0; i < cd->baseclasses->length; i++) - { - BaseClass *b = (*cd->baseclasses)[i]; - - Prot access = getAccess(b->sym, smember); - switch (access.kind) - { - case Prot::none: - break; - - case Prot::private_: - access_ret = Prot(Prot::none); // private members of base class not accessible - break; - - case Prot::package_: - case Prot::protected_: - case Prot::public_: - case Prot::export_: - // If access is to be tightened - if (Prot::public_ < access.kind) - access = Prot(Prot::public_); - - // Pick path with loosest access - if (access_ret.isMoreRestrictiveThan(access)) - access_ret = access; - break; - - default: - assert(0); - } - } - } - - return access_ret; -} - -/******************************************************** - * Helper function for checkAccess() - * Returns: - * false is not accessible - * true is accessible - */ -static bool isAccessible( - Dsymbol *smember, - Dsymbol *sfunc, - AggregateDeclaration *dthis, - AggregateDeclaration *cdscope) -{ - assert(dthis); - - if (hasPrivateAccess(dthis, sfunc) || - isFriendOf(dthis, cdscope)) - { - if (smember->toParent() == dthis) - return true; - - if (ClassDeclaration *cdthis = dthis->isClassDeclaration()) - { - for (size_t i = 0; i < cdthis->baseclasses->length; i++) - { - BaseClass *b = (*cdthis->baseclasses)[i]; - Prot access = getAccess(b->sym, smember); - if (access.kind >= Prot::protected_ || - isAccessible(smember, sfunc, b->sym, cdscope)) - { - return true; - } - } - } - } - else - { - if (smember->toParent() != dthis) - { - if (ClassDeclaration *cdthis = dthis->isClassDeclaration()) - { - for (size_t i = 0; i < cdthis->baseclasses->length; i++) - { - BaseClass *b = (*cdthis->baseclasses)[i]; - if (isAccessible(smember, sfunc, b->sym, cdscope)) - return true; - } - } - } - } - return false; -} - -/******************************* - * Do access check for member of this class, this class being the - * type of the 'this' pointer used to access smember. - * Returns true if the member is not accessible. - */ -bool checkAccess(AggregateDeclaration *ad, Loc loc, Scope *sc, Dsymbol *smember) -{ - FuncDeclaration *f = sc->func; - AggregateDeclaration *cdscope = sc->getStructClassScope(); - - Dsymbol *smemberparent = smember->toParent(); - if (!smemberparent || !smemberparent->isAggregateDeclaration()) - { - return false; // then it is accessible - } - - // BUG: should enable this check - //assert(smember->parent->isBaseOf(this, NULL)); - - bool result; - Prot access; - if (smemberparent == ad) - { - access = smember->prot(); - result = access.kind >= Prot::public_ || - hasPrivateAccess(ad, f) || - isFriendOf(ad, cdscope) || - (access.kind == Prot::package_ && hasPackageAccess(sc, smember)) || - ad->getAccessModule() == sc->_module; - } - else if ((access = getAccess(ad, smember)).kind >= Prot::public_) - { - result = true; - } - else if (access.kind == Prot::package_ && hasPackageAccess(sc, ad)) - { - result = true; - } - else - { - result = isAccessible(smember, f, ad, cdscope); - } - if (!result) - { - ad->error(loc, "member %s is not accessible", smember->toChars()); - //printf("smember = %s %s, prot = %d, semanticRun = %d\n", - // smember->kind(), smember->toPrettyChars(), smember->prot(), smember->semanticRun); - return true; - } - return false; -} - -/**************************************** - * Determine if this is the same or friend of cd. - */ -bool isFriendOf(AggregateDeclaration *ad, AggregateDeclaration *cd) -{ - if (ad == cd) - return true; - - // Friends if both are in the same module - //if (toParent() == cd->toParent()) - if (cd && ad->getAccessModule() == cd->getAccessModule()) - { - return true; - } - - return false; -} - -/**************************************** - * Determine if scope sc has package level access to s. - */ -bool hasPackageAccess(Scope *sc, Dsymbol *s) -{ - return hasPackageAccess(sc->_module, s); -} - -bool hasPackageAccess(Module *mod, Dsymbol *s) -{ - Package *pkg = NULL; - - if (s->prot().pkg) - pkg = s->prot().pkg; - else - { - // no explicit package for protection, inferring most qualified one - for (; s; s = s->parent) - { - if (Module *m = s->isModule()) - { - DsymbolTable *dst = Package::resolve(m->md ? m->md->packages : NULL, NULL, NULL); - assert(dst); - Dsymbol *s2 = dst->lookup(m->ident); - assert(s2); - Package *p = s2->isPackage(); - if (p && p->isPackageMod()) - { - pkg = p; - break; - } - } - else if ((pkg = s->isPackage()) != NULL) - break; - } - } - - if (pkg) - { - if (pkg == mod->parent) - { - return true; - } - if (pkg->isPackageMod() == mod) - { - return true; - } - Dsymbol* ancestor = mod->parent; - for (; ancestor; ancestor = ancestor->parent) - { - if (ancestor == pkg) - { - return true; - } - } - } - - return false; -} - -/**************************************** - * Determine if scope sc has protected level access to cd. - */ -bool hasProtectedAccess(Scope *sc, Dsymbol *s) -{ - if (ClassDeclaration *cd = s->isClassMember()) // also includes interfaces - { - for (Scope *scx = sc; scx; scx = scx->enclosing) - { - if (!scx->scopesym) - continue; - ClassDeclaration *cd2 = scx->scopesym->isClassDeclaration(); - if (cd2 && cd->isBaseOf(cd2, NULL)) - return true; - } - } - return sc->_module == s->getAccessModule(); -} - -/********************************** - * Determine if smember has access to private members of this declaration. - */ -bool hasPrivateAccess(AggregateDeclaration *ad, Dsymbol *smember) -{ - if (smember) - { - AggregateDeclaration *cd = NULL; - Dsymbol *smemberparent = smember->toParent(); - if (smemberparent) - cd = smemberparent->isAggregateDeclaration(); - - if (ad == cd) // smember is a member of this class - { - return true; // so we get private access - } - - // If both are members of the same module, grant access - while (1) - { - Dsymbol *sp = smember->toParent(); - if (sp->isFuncDeclaration() && smember->isFuncDeclaration()) - smember = sp; - else - break; - } - if (!cd && ad->toParent() == smember->toParent()) - { - return true; - } - if (!cd && ad->getAccessModule() == smember->getAccessModule()) - { - return true; - } - } - return false; -} - -/**************************************** - * Check access to d for expression e.d - * Returns true if the declaration is not accessible. - */ -bool checkAccess(Loc loc, Scope *sc, Expression *e, Declaration *d) -{ - if (sc->flags & SCOPEnoaccesscheck) - return false; - - if (d->isUnitTestDeclaration()) - { - // Unittests are always accessible. - return false; - } - if (!e) - return false; - - if (e->type->ty == Tclass) - { - // Do access check - ClassDeclaration *cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym); - if (e->op == TOKsuper) - { - ClassDeclaration *cd2 = sc->func->toParent()->isClassDeclaration(); - if (cd2) - cd = cd2; - } - return checkAccess(cd, loc, sc, d); - } - else if (e->type->ty == Tstruct) - { - // Do access check - StructDeclaration *cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym); - return checkAccess(cd, loc, sc, d); - } - return false; -} - -/**************************************** - * Check access to package/module `p` from scope `sc`. - * - * Params: - * loc = source location for issued error message - * sc = scope from which to access to a fully qualified package name - * p = the package/module to check access for - * Returns: true if the package is not accessible. - * - * Because a global symbol table tree is used for imported packages/modules, - * access to them needs to be checked based on the imports in the scope chain - * (see Bugzilla 313). - * - */ -bool checkAccess(Scope *sc, Package *p) -{ - if (sc->_module == p) - return false; - for (; sc; sc = sc->enclosing) - { - if (sc->scopesym && sc->scopesym->isPackageAccessible(p, Prot(Prot::private_))) - return false; - } - - return true; -} - -/** - * Check whether symbols `s` is visible in `mod`. - * - * Params: - * mod = lookup origin - * s = symbol to check for visibility - * Returns: true if s is visible in mod - */ -bool symbolIsVisible(Module *mod, Dsymbol *s) -{ - // should sort overloads by ascending protection instead of iterating here - s = mostVisibleOverload(s); - - switch (s->prot().kind) - { - case Prot::undefined: - return true; - case Prot::none: - return false; // no access - case Prot::private_: - return s->getAccessModule() == mod; - case Prot::package_: - return s->getAccessModule() == mod || hasPackageAccess(mod, s); - case Prot::protected_: - return s->getAccessModule() == mod; - case Prot::public_: - case Prot::export_: - return true; - default: - assert(0); - } - return false; -} - -/** - * Same as above, but determines the lookup module from symbols `origin`. - */ -bool symbolIsVisible(Dsymbol *origin, Dsymbol *s) -{ - return symbolIsVisible(origin->getAccessModule(), s); -} - -/** - * Same as above but also checks for protected symbols visible from scope `sc`. - * Used for qualified name lookup. - * - * Params: - * sc = lookup scope - * s = symbol to check for visibility - * Returns: true if s is visible by origin - */ -bool symbolIsVisible(Scope *sc, Dsymbol *s) -{ - s = mostVisibleOverload(s); - - switch (s->prot().kind) - { - case Prot::undefined: - return true; - case Prot::none: - return false; // no access - case Prot::private_: - return sc->_module == s->getAccessModule(); - case Prot::package_: - return sc->_module == s->getAccessModule() || hasPackageAccess(sc->_module, s); - case Prot::protected_: - return hasProtectedAccess(sc, s); - case Prot::public_: - case Prot::export_: - return true; - default: - assert(0); - } - return false; -} - -/** - * Use the most visible overload to check visibility. Later perform an access - * check on the resolved overload. This function is similar to overloadApply, - * but doesn't recurse nor resolve aliases because protection/visibility is an - * attribute of the alias not the aliasee. - */ -static Dsymbol *mostVisibleOverload(Dsymbol *s) -{ - if (!s->isOverloadable()) - return s; - - Dsymbol *next = NULL; - Dsymbol *fstart = s; - Dsymbol *mostVisible = s; - for (; s; s = next) - { - // void func() {} - // private void func(int) {} - if (FuncDeclaration *fd = s->isFuncDeclaration()) - next = fd->overnext; - // template temp(T) {} - // private template temp(T:int) {} - else if (TemplateDeclaration *td = s->isTemplateDeclaration()) - next = td->overnext; - // alias common = mod1.func1; - // alias common = mod2.func2; - else if (FuncAliasDeclaration *fa = s->isFuncAliasDeclaration()) - next = fa->overnext; - // alias common = mod1.templ1; - // alias common = mod2.templ2; - else if (OverDeclaration *od = s->isOverDeclaration()) - next = od->overnext; - // alias name = sym; - // private void name(int) {} - else if (AliasDeclaration *ad = s->isAliasDeclaration()) - { - if (!ad->isOverloadable()) - { - //printf("Non overloadable Aliasee in overload list\n"); - assert(0); - } - // Yet unresolved aliases store overloads in overnext. - if (ad->semanticRun < PASSsemanticdone) - next = ad->overnext; - else - { - /* This is a bit messy due to the complicated implementation of - * alias. Aliases aren't overloadable themselves, but if their - * Aliasee is overloadable they can be converted to an overloadable - * alias. - * - * This is done by replacing the Aliasee w/ FuncAliasDeclaration - * (for functions) or OverDeclaration (for templates) which are - * simply overloadable aliases w/ weird names. - * - * Usually aliases should not be resolved for visibility checking - * b/c public aliases to private symbols are public. But for the - * overloadable alias situation, the Alias (_ad_) has been moved - * into it's own Aliasee, leaving a shell that we peel away here. - */ - Dsymbol *aliasee = ad->toAlias(); - if (aliasee->isFuncAliasDeclaration() || aliasee->isOverDeclaration()) - next = aliasee; - else - { - /* A simple alias can be at the end of a function or template overload chain. - * It can't have further overloads b/c it would have been - * converted to an overloadable alias. - */ - if (ad->overnext) - { - //printf("Unresolved overload of alias\n"); - assert(0); - } - break; - } - } - - // handled by overloadApply for unknown reason - assert(next != ad); // should not alias itself - assert(next != fstart); // should not alias the overload list itself - } - else - break; - - if (next && mostVisible->prot().isMoreRestrictiveThan(next->prot())) - mostVisible = next; - } - return mostVisible; -} |