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: