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