Mercurial > projects > ldc
annotate dmd/scope.c @ 1641:00cd99bedf06
Add missing files for the new frontend spell checker
author | Kelly Wilson <wilsonk cpsc.ucalgary.ca> |
---|---|
date | Mon, 08 Mar 2010 17:41:36 -0700 |
parents | 9bf06e02070b |
children |
rev | line source |
---|---|
159 | 1 |
1640 | 2 // Copyright (c) 1999-2010 by Digital Mars |
159 | 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" | |
1640 | 14 #include "speller.h" |
159 | 15 |
16 #include "mars.h" | |
17 #include "init.h" | |
18 #include "identifier.h" | |
19 #include "attrib.h" | |
20 #include "dsymbol.h" | |
21 #include "scope.h" | |
22 #include "declaration.h" | |
23 #include "aggregate.h" | |
24 #include "module.h" | |
25 #include "id.h" | |
26 | |
27 Scope *Scope::freelist = NULL; | |
28 | |
29 void *Scope::operator new(size_t size) | |
30 { | |
31 if (freelist) | |
32 { | |
33 Scope *s = freelist; | |
34 freelist = s->enclosing; | |
35 //printf("freelist %p\n", s); | |
36 assert(s->flags & SCOPEfree); | |
37 s->flags &= ~SCOPEfree; | |
38 return s; | |
39 } | |
40 | |
41 void *p = ::operator new(size); | |
42 //printf("new %p\n", p); | |
43 return p; | |
44 } | |
45 | |
46 Scope::Scope() | |
47 { // Create root scope | |
48 | |
49 //printf("Scope::Scope() %p\n", this); | |
50 this->module = NULL; | |
51 this->scopesym = NULL; | |
52 this->sd = NULL; | |
53 this->enclosing = NULL; | |
54 this->parent = NULL; | |
55 this->sw = NULL; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
56 this->enclosingFinally = NULL; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
57 this->enclosingScopeExit = NULL; |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
215
diff
changeset
|
58 this->tinst = NULL; |
159 | 59 this->sbreak = NULL; |
60 this->scontinue = NULL; | |
61 this->fes = NULL; | |
62 this->structalign = global.structalign; | |
63 this->func = NULL; | |
64 this->slabel = NULL; | |
65 this->linkage = LINKd; | |
66 this->protection = PROTpublic; | |
67 this->explicitProtection = 0; | |
68 this->stc = 0; | |
69 this->offset = 0; | |
70 this->inunion = 0; | |
71 this->incontract = 0; | |
72 this->nofree = 0; | |
73 this->noctor = 0; | |
74 this->noaccesscheck = 0; | |
1587 | 75 this->mustsemantic = 0; |
159 | 76 this->intypeof = 0; |
77 this->parameterSpecialization = 0; | |
78 this->callSuper = 0; | |
79 this->flags = 0; | |
80 this->anonAgg = NULL; | |
81 this->lastdc = NULL; | |
82 this->lastoffset = 0; | |
83 this->docbuf = NULL; | |
84 } | |
85 | |
86 Scope::Scope(Scope *enclosing) | |
87 { | |
88 //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); | |
89 assert(!(enclosing->flags & SCOPEfree)); | |
90 this->module = enclosing->module; | |
91 this->func = enclosing->func; | |
92 this->parent = enclosing->parent; | |
93 this->scopesym = NULL; | |
94 this->sd = NULL; | |
95 this->sw = enclosing->sw; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
96 this->enclosingFinally = enclosing->enclosingFinally; |
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
97 this->enclosingScopeExit = enclosing->enclosingScopeExit; |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
215
diff
changeset
|
98 this->tinst = enclosing->tinst; |
159 | 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; | |
1587 | 124 this->mustsemantic = enclosing->mustsemantic; |
159 | 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(); | |
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 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
561
diff
changeset
|
263 warning(s->loc, "array 'length' hides other 'length' name in outer scope"); |
159 | 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(); | |
1587 | 288 return sc->scopesym->symtabInsert(s); |
159 | 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 } | |
1640 | 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 Scope *sc = (Scope *)arg; | |
376 Identifier id(seed, 0); | |
377 Module::clearCache(); | |
378 Dsymbol *s = sc->search(0, &id, NULL); | |
379 return s; | |
380 } | |
381 | |
382 Dsymbol *Scope::search_correct(Identifier *ident) | |
383 { | |
384 if (global.gag) | |
385 return NULL; // don't do it for speculative compiles; too time consuming | |
386 | |
387 return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars); | |
388 } |