1: 
  2: // Copyright (c) 1999-2010 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: #include <stdio.h>
 11: static char __file__[] = __FILE__;      /* for tassert.h                */
 12: #include        "tassert.h"
 13: 
 14: #include "root.h"
 15: #include "speller.h"
 16: 
 17: #include "mars.h"
 18: #include "init.h"
 19: #include "identifier.h"
 20: #include "scope.h"
 21: #include "attrib.h"
 22: #include "dsymbol.h"
 23: #include "declaration.h"
 24: #include "aggregate.h"
 25: #include "module.h"
 26: #include "id.h"
 27: #include "lexer.h"
 28: 
 29: Scope *Scope::freelist = NULL;
 30: 
 31: void *Scope::operator new(size_t size)
 32: {
 33:     if (freelist)
 34:     {
 35:         Scope *s = freelist;
 36:         freelist = s->enclosing;
 37:         //printf("freelist %p\n", s);
 38:         assert(s->flags & SCOPEfree);
 39:         s->flags &= ~SCOPEfree;
 40:         return s;
 41:     }
 42: 
 43:     void *p = ::operator new(size);
 44:     //printf("new %p\n", p);
 45:     return p;
 46: }
 47: 
 48: Scope::Scope()
 49: {   // Create root scope
 50: 
 51:     //printf("Scope::Scope() %p\n", this);
 52:     this->module = NULL;
 53:     this->scopesym = NULL;
 54:     this->sd = NULL;
 55:     this->enclosing = NULL;
 56:     this->parent = NULL;
 57:     this->sw = NULL;
 58:     this->tf = NULL;
 59:     this->tinst = NULL;
 60:     this->sbreak = NULL;
 61:     this->scontinue = NULL;
 62:     this->fes = NULL;
 63:     this->structalign = global.structalign;
 64:     this->func = NULL;
 65:     this->slabel = NULL;
 66:     this->linkage = LINKd;
 67:     this->protection = PROTpublic;
 68:     this->explicitProtection = 0;
 69:     this->stc = 0;
 70:     this->offset = 0;
 71:     this->inunion = 0;
 72:     this->incontract = 0;
 73:     this->nofree = 0;
 74:     this->noctor = 0;
 75:     this->noaccesscheck = 0;
 76:     this->mustsemantic = 0;
 77:     this->intypeof = 0;
 78:     this->parameterSpecialization = 0;
 79:     this->callSuper = 0;
 80:     this->flags = 0;
 81:     this->anonAgg = NULL;
 82:     this->lastdc = NULL;
 83:     this->lastoffset = 0;
 84:     this->docbuf = NULL;
 85: }
 86: 
 87: Scope::Scope(Scope *enclosing)
 88: {
 89:     //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
 90:     assert(!(enclosing->flags & SCOPEfree));
 91:     this->module = enclosing->module;
 92:     this->func   = enclosing->func;
 93:     this->parent = enclosing->parent;
 94:     this->scopesym = NULL;
 95:     this->sd = NULL;
 96:     this->sw = enclosing->sw;
 97:     this->tf = enclosing->tf;
 98:     this->tinst = enclosing->tinst;
 99:     this->sbreak = enclosing->sbreak;
100:     this->scontinue = enclosing->scontinue;
101:     this->fes = enclosing->fes;
102:     this->structalign = enclosing->structalign;
103:     this->enclosing = enclosing;
104: #ifdef DEBUG
105:     if (enclosing->enclosing)
106:         assert(!(enclosing->enclosing->flags & SCOPEfree));
107:     if (this == enclosing->enclosing)
108:     {
109:         printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
110:     }
111:     assert(this != enclosing->enclosing);
112: #endif
113:     this->slabel = NULL;
114:     this->linkage = enclosing->linkage;
115:     this->protection = enclosing->protection;
116:     this->explicitProtection = enclosing->explicitProtection;
117:     this->stc = enclosing->stc;
118:     this->offset = 0;
119:     this->inunion = enclosing->inunion;
120:     this->incontract = enclosing->incontract;
121:     this->nofree = 0;
122:     this->noctor = enclosing->noctor;
123:     this->noaccesscheck = enclosing->noaccesscheck;
124:     this->mustsemantic = enclosing->mustsemantic;
125:     this->intypeof = enclosing->intypeof;
126:     this->parameterSpecialization = enclosing->parameterSpecialization;
127:     this->callSuper = enclosing->callSuper;
128:     this->flags = 0;
129:     this->anonAgg = NULL;
130:     this->lastdc = NULL;
131:     this->lastoffset = 0;
132:     this->docbuf = enclosing->docbuf;
133:     assert(this != enclosing);
134: }
135: 
136: Scope *Scope::createGlobal(Module *module)
137: {
138:     Scope *sc;
139: 
140:     sc = new Scope();
warning C6211: Leaking memory 'sc' due to an exception. Consider using a local catch block to clean up memory: Lines: 138, 140, 141, 142
141: sc->module = module; 142: sc->scopesym = new ScopeDsymbol(); 143: sc->scopesym->symtab = new DsymbolTable(); 144: 145: // Add top level package as member of this global scope 146: Dsymbol *m = module; 147: while (m->parent) 148: m = m->parent; 149: m->addMember(NULL, sc->scopesym, 1); 150: m->parent = NULL; // got changed by addMember() 151: 152: // Create the module scope underneath the global scope 153: sc = sc->push(module); 154: sc->parent = module; 155: return sc; 156: } 157: 158: Scope *Scope::push() 159: { 160: //printf("Scope::push()\n"); 161: Scope *s = new Scope(this); 162: assert(this != s); 163: return s; 164: } 165: 166: Scope *Scope::push(ScopeDsymbol *ss) 167: { 168: //printf("Scope::push(%s)\n", ss->toChars()); 169: Scope *s = push(); 170: s->scopesym = ss; 171: return s; 172: } 173: 174: Scope *Scope::pop() 175: { 176: //printf("Scope::pop() %p nofree = %d\n", this, nofree); 177: Scope *enc = enclosing; 178: 179: if (enclosing) 180: enclosing->callSuper |= callSuper; 181: 182: if (!nofree) 183: { enclosing = freelist; 184: freelist = this; 185: flags |= SCOPEfree; 186: } 187: 188: return enc; 189: } 190: 191: void Scope::mergeCallSuper(Loc loc, unsigned cs) 192: { 193: // This does a primitive flow analysis to support the restrictions 194: // regarding when and how constructors can appear. 195: // It merges the results of two paths. 196: // The two paths are callSuper and cs; the result is merged into callSuper. 197: 198: if (cs != callSuper) 199: { int a; 200: int b; 201: 202: callSuper |= cs & (CSXany_ctor | CSXlabel); 203: if (cs & CSXreturn) 204: { 205: } 206: else if (callSuper & CSXreturn) 207: { 208: callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); 209: } 210: else 211: { 212: a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; 213: b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; 214: if (a != b) 215: error(loc, "one path skips constructor"); 216: callSuper |= cs; 217: } 218: } 219: } 220: 221: Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym) 222: { Dsymbol *s; 223: Scope *sc; 224: 225: //printf("Scope::search(%p, '%s')\n", this, ident->toChars()); 226: if (ident == Id::empty) 227: { 228: // Look for module scope 229: for (sc = this; sc; sc = sc->enclosing) 230: { 231: assert(sc != sc->enclosing); 232: if (sc->scopesym) 233: { 234: s = sc->scopesym->isModule(); 235: if (s) 236: { 237: //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars()); 238: if (pscopesym) 239: *pscopesym = sc->scopesym; 240: return s; 241: } 242: } 243: } 244: return NULL; 245: } 246: 247: for (sc = this; sc; sc = sc->enclosing) 248: { 249: assert(sc != sc->enclosing); 250: if (sc->scopesym) 251: { 252: //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); 253: s = sc->scopesym->search(loc, ident, 0); 254: if (s) 255: { 256: if ((global.params.warnings || 257: global.params.Dversion > 1) && 258: ident == Id::length && 259: sc->scopesym->isArrayScopeSymbol() && 260: sc->enclosing && 261: sc->enclosing->search(loc, ident, NULL)) 262: { 263: warning(s->loc, "array 'length' hides other 'length' name in outer scope"); 264: } 265: 266: //printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind()); 267: if (pscopesym) 268: *pscopesym = sc->scopesym; 269: return s; 270: } 271: } 272: } 273: 274: return NULL; 275: } 276: 277: Dsymbol *Scope::insert(Dsymbol *s) 278: { Scope *sc; 279: 280: for (sc = this; sc; sc = sc->enclosing) 281: { 282: //printf("\tsc = %p\n", sc); 283: if (sc->scopesym) 284: { 285: //printf("\t\tsc->scopesym = %p\n", sc->scopesym); 286: if (!sc->scopesym->symtab) 287: sc->scopesym->symtab = new DsymbolTable(); 288: return sc->scopesym->symtabInsert(s); 289: } 290: } 291: assert(0); 292: return NULL; 293: } 294: 295: /******************************************** 296: * Search enclosing scopes for ClassDeclaration. 297: */ 298: 299: ClassDeclaration *Scope::getClassScope() 300: { Scope *sc; 301: 302: for (sc = this; sc; sc = sc->enclosing) 303: { 304: ClassDeclaration *cd; 305: 306: if (sc->scopesym) 307: { 308: cd = sc->scopesym->isClassDeclaration(); 309: if (cd) 310: return cd; 311: } 312: } 313: return NULL; 314: } 315: 316: /******************************************** 317: * Search enclosing scopes for ClassDeclaration. 318: */ 319: 320: AggregateDeclaration *Scope::getStructClassScope() 321: { Scope *sc; 322: 323: for (sc = this; sc; sc = sc->enclosing) 324: { 325: AggregateDeclaration *ad; 326: 327: if (sc->scopesym) 328: { 329: ad = sc->scopesym->isClassDeclaration(); 330: if (ad) 331: return ad; 332: else 333: { ad = sc->scopesym->isStructDeclaration(); 334: if (ad) 335: return ad; 336: } 337: } 338: } 339: return NULL; 340: } 341: 342: /******************************************* 343: * For TemplateDeclarations, we need to remember the Scope 344: * where it was declared. So mark the Scope as not 345: * to be free'd. 346: */ 347: 348: void Scope::setNoFree() 349: { Scope *sc; 350: //int i = 0; 351: 352: //printf("Scope::setNoFree(this = %p)\n", this); 353: for (sc = this; sc; sc = sc->enclosing) 354: { 355: //printf("\tsc = %p\n", sc); 356: sc->nofree = 1; 357: 358: assert(!(flags & SCOPEfree)); 359: //assert(sc != sc->enclosing); 360: //assert(!sc->enclosing || sc != sc->enclosing->enclosing); 361: //if (++i == 10) 362: //assert(0); 363: } 364: } 365: 366: 367: /************************************************ 368: * Given the failed search attempt, try to find 369: * one with a close spelling. 370: */ 371: 372: void *scope_search_fp(void *arg, const char *seed) 373: { 374: //printf("scope_search_fp('%s')\n", seed); 375: 376: /* If not in the lexer's string table, it certainly isn't in the symbol table. 377: * Doing this first is a lot faster. 378: */ 379: size_t len = strlen(seed); 380: if (!len) 381: return NULL; 382: StringValue *sv = Lexer::stringtable.lookup(seed, len); 383: if (!sv) 384: return NULL; 385: Identifier *id = (Identifier *)sv->ptrvalue; 386: assert(id); 387: 388: Scope *sc = (Scope *)arg; 389: Module::clearCache(); 390: Dsymbol *s = sc->search(0, id, NULL); 391: return s; 392: } 393: 394: Dsymbol *Scope::search_correct(Identifier *ident) 395: { 396: if (global.gag) 397: return NULL; // don't do it for speculative compiles; too time consuming 398: 399: return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars); 400: } 401: