1: 
  2: // Copyright (c) 1999-2006 by Digital Mars
  3: // All Rights Reserved
  4: // written by Walter Bright
  5: // http://www.digitalmars.com
  6: // License for redistribution is by either the Artistic License
  7: // in artistic.txt, or the GNU General Public License in gnu.txt.
  8: // See the included readme.txt for details.
  9: 
 10: 
 11: #include <stdio.h>
 12: #include <stdlib.h>
 13: static char __file__[] = __FILE__;      /* for tassert.h                */
 14: #include        "tassert.h"
 15: 
 16: #include "root.h"
 17: #include "rmem.h"
 18: 
 19: #include "enum.h"
 20: #include "aggregate.h"
 21: #include "init.h"
 22: #include "attrib.h"
 23: #include "scope.h"
 24: #include "id.h"
 25: #include "mtype.h"
 26: #include "declaration.h"
 27: #include "aggregate.h"
 28: #include "expression.h"
 29: #include "module.h"
 30: 
 31: #define LOG 0
 32: 
 33: /* Code to do access checks
 34:  */
 35: 
 36: int hasPackageAccess(Scope *sc, Dsymbol *s);
 37: 
 38: /****************************************
 39:  * Return PROT access for Dsymbol smember in this declaration.
 40:  */
 41: 
 42: enum PROT AggregateDeclaration::getAccess(Dsymbol *smember)
 43: {
 44:     return PROTpublic;
 45: }
 46: 
 47: enum PROT StructDeclaration::getAccess(Dsymbol *smember)
 48: {
 49:     enum PROT access_ret = PROTnone;
 50: 
 51: #if LOG
 52:     printf("+StructDeclaration::getAccess(this = '%s', smember = '%s')\n",
 53:         toChars(), smember->toChars());
 54: #endif
 55:     if (smember->toParent() == this)
 56:     {
 57:         access_ret = smember->prot();
 58:     }
 59:     else if (smember->isDeclaration()->isStatic())
 60:     {
 61:         access_ret = smember->prot();
 62:     }
 63:     return access_ret;
 64: }
 65: 
 66: enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
 67: {
 68:     enum PROT access_ret = PROTnone;
 69: 
 70: #if LOG
 71:     printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
 72:         toChars(), smember->toChars());
 73: #endif
 74:     if (smember->toParent() == this)
 75:     {
 76:         access_ret = smember->prot();
 77:     }
 78:     else
 79:     {
 80:         enum PROT access;
 81:         int i;
 82: 
 83:         if (smember->isDeclaration()->isStatic())
 84:         {
 85:             access_ret = smember->prot();
 86:         }
 87: 
 88:         for (i = 0; i < baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
89: { BaseClass *b = baseclasses->tdata()[i]; 90: 91: access = b->base->getAccess(smember); 92: switch (access) 93: { 94: case PROTnone: 95: break; 96: 97: case PROTprivate: 98: access = PROTnone; // private members of base class not accessible 99: break; 100: 101: case PROTpackage: 102: case PROTprotected: 103: case PROTpublic: 104: case PROTexport: 105: // If access is to be tightened 106: if (b->protection < access) 107: access = b->protection; 108: 109: // Pick path with loosest access 110: if (access > access_ret) 111: access_ret = access; 112: break; 113: 114: default: 115: assert(0); 116: } 117: } 118: } 119: #if LOG 120: printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n", 121: toChars(), smember->toChars(), access_ret); 122: #endif 123: return access_ret; 124: } 125: 126: /******************************************************** 127: * Helper function for ClassDeclaration::accessCheck() 128: * Returns: 129: * 0 no access 130: * 1 access 131: */ 132: 133: static int accessCheckX( 134: Dsymbol *smember, 135: Dsymbol *sfunc, 136: AggregateDeclaration *dthis, 137: AggregateDeclaration *cdscope) 138: { 139: assert(dthis); 140: 141: #if 0 142: printf("accessCheckX for %s.%s in function %s() in scope %s\n", 143: dthis->toChars(), smember->toChars(), 144: sfunc ? sfunc->toChars() : "NULL", 145: cdscope ? cdscope->toChars() : "NULL"); 146: #endif 147: if (dthis->hasPrivateAccess(sfunc) || 148: dthis->isFriendOf(cdscope)) 149: { 150: if (smember->toParent() == dthis) 151: return 1; 152: else 153: { 154: ClassDeclaration *cdthis = dthis->isClassDeclaration(); 155: if (cdthis) 156: { 157: for (int i = 0; i < cdthis->baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
158: { BaseClass *b = cdthis->baseclasses->tdata()[i]; 159: enum PROT access; 160: 161: access = b->base->getAccess(smember); 162: if (access >= PROTprotected || 163: accessCheckX(smember, sfunc, b->base, cdscope) 164: ) 165: return 1; 166: 167: } 168: } 169: } 170: } 171: else 172: { 173: if (smember->toParent() != dthis) 174: { 175: ClassDeclaration *cdthis = dthis->isClassDeclaration(); 176: if (cdthis) 177: { 178: for (int i = 0; i < cdthis->baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
179: { BaseClass *b = cdthis->baseclasses->tdata()[i]; 180: 181: if (accessCheckX(smember, sfunc, b->base, cdscope)) 182: return 1; 183: } 184: } 185: } 186: } 187: return 0; 188: } 189: 190: /******************************* 191: * Do access check for member of this class, this class being the 192: * type of the 'this' pointer used to access smember. 193: */ 194: 195: void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) 196: { 197: int result; 198: 199: FuncDeclaration *f = sc->func; 200: AggregateDeclaration *cdscope = sc->getStructClassScope(); 201: enum PROT access; 202: 203: #if LOG 204: printf("AggregateDeclaration::accessCheck() for %s.%s in function %s() in scope %s\n", 205: toChars(), smember->toChars(), 206: f ? f->toChars() : NULL, 207: cdscope ? cdscope->toChars() : NULL); 208: #endif 209: 210: Dsymbol *smemberparent = smember->toParent(); 211: if (!smemberparent || !smemberparent->isAggregateDeclaration()) 212: { 213: #if LOG 214: printf("not an aggregate member\n"); 215: #endif 216: return; // then it is accessible 217: } 218: 219: // BUG: should enable this check 220: //assert(smember->parent->isBaseOf(this, NULL)); 221: 222: if (smemberparent == this) 223: { enum PROT access = smember->prot();
warning C6246: Local declaration of 'access' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '201' of 'c:\projects\extern\d\dmd\src\access.c': Lines: 201
224: 225: result = access >= PROTpublic || 226: hasPrivateAccess(f) || 227: isFriendOf(cdscope) || 228: (access == PROTpackage && hasPackageAccess(sc, this)); 229: #if LOG 230: printf("result1 = %d\n", result); 231: #endif 232: } 233: else if ((access = this->getAccess(smember)) >= PROTpublic) 234: { 235: result = 1; 236: #if LOG 237: printf("result2 = %d\n", result); 238: #endif 239: } 240: else if (access == PROTpackage && hasPackageAccess(sc, this)) 241: { 242: result = 1; 243: #if LOG 244: printf("result3 = %d\n", result); 245: #endif 246: } 247: else 248: { 249: result = accessCheckX(smember, f, this, cdscope); 250: #if LOG 251: printf("result4 = %d\n", result); 252: #endif 253: } 254: if (!result) 255: { 256: error(loc, "member %s is not accessible", smember->toChars()); 257: } 258: } 259: 260: /**************************************** 261: * Determine if this is the same or friend of cd. 262: */ 263: 264: int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd) 265: { 266: #if LOG 267: printf("AggregateDeclaration::isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd->toChars() : "null"); 268: #endif 269: if (this == cd) 270: return 1; 271: 272: // Friends if both are in the same module 273: //if (toParent() == cd->toParent()) 274: if (cd && getModule() == cd->getModule()) 275: { 276: #if LOG 277: printf("\tin same module\n"); 278: #endif 279: return 1; 280: } 281: 282: #if LOG 283: printf("\tnot friend\n"); 284: #endif 285: return 0; 286: } 287: 288: /**************************************** 289: * Determine if scope sc has package level access to s. 290: */ 291: 292: int hasPackageAccess(Scope *sc, Dsymbol *s) 293: { 294: #if LOG 295: printf("hasPackageAccess(s = '%s', sc = '%p')\n", s->toChars(), sc); 296: #endif 297: 298: for (; s; s = s->parent) 299: { 300: if (s->isPackage() && !s->isModule()) 301: break; 302: } 303: #if LOG 304: if (s) 305: printf("\tthis is in package '%s'\n", s->toChars()); 306: #endif 307: 308: if (s && s == sc->module->parent) 309: { 310: #if LOG 311: printf("\ts is in same package as sc\n"); 312: #endif 313: return 1; 314: } 315: 316: 317: #if LOG 318: printf("\tno package access\n"); 319: #endif 320: return 0; 321: } 322: 323: /********************************** 324: * Determine if smember has access to private members of this declaration. 325: */ 326: 327: int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember) 328: { 329: if (smember) 330: { AggregateDeclaration *cd = NULL; 331: Dsymbol *smemberparent = smember->toParent(); 332: if (smemberparent) 333: cd = smemberparent->isAggregateDeclaration(); 334: 335: #if LOG 336: printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n", 337: toChars(), smember->toChars()); 338: #endif 339: 340: if (this == cd) // smember is a member of this class 341: { 342: #if LOG 343: printf("\tyes 1\n"); 344: #endif 345: return 1; // so we get private access 346: } 347: 348: // If both are members of the same module, grant access 349: while (1) 350: { Dsymbol *sp = smember->toParent(); 351: if (sp->isFuncDeclaration() && smember->isFuncDeclaration()) 352: smember = sp; 353: else 354: break; 355: } 356: if (!cd && toParent() == smember->toParent()) 357: { 358: #if LOG 359: printf("\tyes 2\n"); 360: #endif 361: return 1; 362: } 363: if (!cd && getModule() == smember->getModule()) 364: { 365: #if LOG 366: printf("\tyes 3\n"); 367: #endif 368: return 1; 369: } 370: } 371: #if LOG 372: printf("\tno\n"); 373: #endif 374: return 0; 375: } 376: 377: /**************************************** 378: * Check access to d for expression e.d 379: */ 380: 381: void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d) 382: { 383: #if LOG 384: if (e) 385: { printf("accessCheck(%s . %s)\n", e->toChars(), d->toChars()); 386: printf("\te->type = %s\n", e->type->toChars()); 387: } 388: else 389: { 390: //printf("accessCheck(%s)\n", d->toChars()); 391: } 392: #endif 393: if (!e) 394: { 395: if (d->prot() == PROTprivate && d->getModule() != sc->module || 396: d->prot() == PROTpackage && !hasPackageAccess(sc, d)) 397: 398: error(loc, "%s %s.%s is not accessible from %s", 399: d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars()); 400: } 401: else if (e->type->ty == Tclass) 402: { // Do access check 403: ClassDeclaration *cd; 404: 405: cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym); 406: #if 1 407: if (e->op == TOKsuper) 408: { ClassDeclaration *cd2; 409: 410: cd2 = sc->func->toParent()->isClassDeclaration(); 411: if (cd2) 412: cd = cd2; 413: } 414: #endif 415: cd->accessCheck(loc, sc, d); 416: } 417: else if (e->type->ty == Tstruct) 418: { // Do access check 419: StructDeclaration *cd; 420: 421: cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym); 422: cd->accessCheck(loc, sc, d); 423: } 424: } 425: