/******************************************************** * 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 0 printf("isAccessible for %s.%s in function %s() in scope %s\n", dthis->toChars(), smember->toChars(), sfunc ? sfunc->toChars() : "NULL", cdscope ? cdscope->toChars() : "NULL"); #endif 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->dim; i++) { BaseClass *b = (*cdthis->baseclasses)[i]; Prot access = getAccess(b->base, smember); if (access.kind >= PROTprotected || isAccessible(smember, sfunc, b->base, cdscope)) { return true; } } } } else { if (smember->toParent() != dthis) { if (ClassDeclaration *cdthis = dthis->isClassDeclaration()) { for (size_t i = 0; i < cdthis->baseclasses->dim; i++) { BaseClass *b = (*cdthis->baseclasses)[i]; if (isAccessible(smember, sfunc, b->base, cdscope)) return true; } } } } return false; }
void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) { int result; FuncDeclaration *f = sc->func; AggregateDeclaration *cdscope = sc->getStructClassScope(); enum PROT access; #if LOG printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", toChars(), smember->toChars(), f ? f->toChars() : NULL, cdscope ? cdscope->toChars() : NULL); #endif Dsymbol *smemberparent = smember->toParent(); if (!smemberparent || !smemberparent->isAggregateDeclaration()) { #if LOG printf("not an aggregate member\n"); #endif return; // then it is accessible } // BUG: should enable this check //assert(smember->parent->isBaseOf(this, NULL)); if (smemberparent == this) { enum PROT access2 = smember->prot(); result = access2 >= PROTpublic || hasPrivateAccess(f) || isFriendOf(cdscope) || (access2 == PROTpackage && hasPackageAccess(sc, this)); #if LOG printf("result1 = %d\n", result); #endif } else if ((access = this->getAccess(smember)) >= PROTpublic) { result = 1; #if LOG printf("result2 = %d\n", result); #endif } else if (access == PROTpackage && hasPackageAccess(sc, this)) { result = 1; #if LOG printf("result3 = %d\n", result); #endif } else { result = accessCheckX(smember, f, this, cdscope); #if LOG printf("result4 = %d\n", result); #endif } if (!result) { error(loc, "member %s is not accessible", smember->toChars()); } }
/******************************* * 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(); #if LOG printf("AggregateDeclaration::checkAccess() for %s.%s in function %s() in scope %s\n", ad->toChars(), smember->toChars(), f ? f->toChars() : NULL, cdscope ? cdscope->toChars() : NULL); #endif Dsymbol *smemberparent = smember->toParent(); if (!smemberparent || !smemberparent->isAggregateDeclaration()) { #if LOG printf("not an aggregate member\n"); #endif return false; // then it is accessible } // BUG: should enable this check //assert(smember->parent->isBaseOf(this, NULL)); bool result; Prot access; if (smemberparent == ad) { Prot access2 = smember->prot(); result = access2.kind >= PROTpublic || hasPrivateAccess(ad, f) || isFriendOf(ad, cdscope) || (access2.kind == PROTpackage && hasPackageAccess(sc, ad)) || ad->getAccessModule() == sc->module; #if LOG printf("result1 = %d\n", result); #endif } else if ((access = getAccess(ad, smember)).kind >= PROTpublic) { result = true; #if LOG printf("result2 = %d\n", result); #endif } else if (access.kind == PROTpackage && hasPackageAccess(sc, ad)) { result = true; #if LOG printf("result3 = %d\n", result); #endif } else { result = isAccessible(smember, f, ad, cdscope); #if LOG printf("result4 = %d\n", result); #endif } 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; }