Mercurial > projects > ldc
annotate dmd/scope.c @ 650:aa6a0b7968f7
Added test case for bug #100
Removed dubious check for not emitting static private global in other modules without access. This should be handled properly somewhere else, it's causing unresolved global errors for stuff that should work (in MiniD)
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 05 Oct 2008 17:28:15 +0200 |
parents | d4e95db0e62b |
children | b30fe7e1dbb9 |
rev | line source |
---|---|
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; | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
215
diff
changeset
|
57 this->tinst = NULL; |
159 | 58 this->sbreak = NULL; |
59 this->scontinue = NULL; | |
60 this->fes = NULL; | |
61 this->structalign = global.structalign; | |
62 this->func = NULL; | |
63 this->slabel = NULL; | |
64 this->linkage = LINKd; | |
65 this->protection = PROTpublic; | |
66 this->explicitProtection = 0; | |
67 this->stc = 0; | |
68 this->offset = 0; | |
69 this->inunion = 0; | |
70 this->incontract = 0; | |
71 this->nofree = 0; | |
72 this->noctor = 0; | |
73 this->noaccesscheck = 0; | |
74 this->intypeof = 0; | |
75 this->parameterSpecialization = 0; | |
76 this->callSuper = 0; | |
77 this->flags = 0; | |
78 this->anonAgg = NULL; | |
79 this->lastdc = NULL; | |
80 this->lastoffset = 0; | |
81 this->docbuf = NULL; | |
82 } | |
83 | |
84 Scope::Scope(Scope *enclosing) | |
85 { | |
86 //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); | |
87 assert(!(enclosing->flags & SCOPEfree)); | |
88 this->module = enclosing->module; | |
89 this->func = enclosing->func; | |
90 this->parent = enclosing->parent; | |
91 this->scopesym = NULL; | |
92 this->sd = NULL; | |
93 this->sw = enclosing->sw; | |
94 this->tf = enclosing->tf; | |
95 this->tfOfTry = enclosing->tfOfTry; | |
561
d4e95db0e62b
Introducing template instantiation traces for static asserts and errors within templates.
Christian Kamm <kamm incasoftware de>
parents:
215
diff
changeset
|
96 this->tinst = enclosing->tinst; |
159 | 97 this->sbreak = enclosing->sbreak; |
98 this->scontinue = enclosing->scontinue; | |
99 this->fes = enclosing->fes; | |
100 this->structalign = enclosing->structalign; | |
101 this->enclosing = enclosing; | |
102 #ifdef DEBUG | |
103 if (enclosing->enclosing) | |
104 assert(!(enclosing->enclosing->flags & SCOPEfree)); | |
105 if (this == enclosing->enclosing) | |
106 { | |
107 printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing); | |
108 } | |
109 assert(this != enclosing->enclosing); | |
110 #endif | |
111 this->slabel = NULL; | |
112 this->linkage = enclosing->linkage; | |
113 this->protection = enclosing->protection; | |
114 this->explicitProtection = enclosing->explicitProtection; | |
115 this->stc = enclosing->stc; | |
116 this->offset = 0; | |
117 this->inunion = enclosing->inunion; | |
118 this->incontract = enclosing->incontract; | |
119 this->nofree = 0; | |
120 this->noctor = enclosing->noctor; | |
121 this->noaccesscheck = enclosing->noaccesscheck; | |
122 this->intypeof = enclosing->intypeof; | |
123 this->parameterSpecialization = enclosing->parameterSpecialization; | |
124 this->callSuper = enclosing->callSuper; | |
125 this->flags = 0; | |
126 this->anonAgg = NULL; | |
127 this->lastdc = NULL; | |
128 this->lastoffset = 0; | |
129 this->docbuf = enclosing->docbuf; | |
130 assert(this != enclosing); | |
131 } | |
132 | |
133 Scope *Scope::createGlobal(Module *module) | |
134 { | |
135 Scope *sc; | |
136 | |
137 sc = new Scope(); | |
138 sc->module = module; | |
139 sc->scopesym = new ScopeDsymbol(); | |
140 sc->scopesym->symtab = new DsymbolTable(); | |
141 | |
142 // Add top level package as member of this global scope | |
143 Dsymbol *m = module; | |
144 while (m->parent) | |
145 m = m->parent; | |
146 m->addMember(NULL, sc->scopesym, 1); | |
147 m->parent = NULL; // got changed by addMember() | |
148 | |
149 // Create the module scope underneath the global scope | |
150 sc = sc->push(module); | |
151 sc->parent = module; | |
152 return sc; | |
153 } | |
154 | |
155 Scope *Scope::push() | |
156 { | |
157 //printf("Scope::push()\n"); | |
158 Scope *s = new Scope(this); | |
159 assert(this != s); | |
160 return s; | |
161 } | |
162 | |
163 Scope *Scope::push(ScopeDsymbol *ss) | |
164 { | |
165 //printf("Scope::push(%s)\n", ss->toChars()); | |
166 Scope *s = push(); | |
167 s->scopesym = ss; | |
168 return s; | |
169 } | |
170 | |
171 Scope *Scope::pop() | |
172 { | |
173 //printf("Scope::pop() %p nofree = %d\n", this, nofree); | |
174 Scope *enc = enclosing; | |
175 | |
176 if (enclosing) | |
177 enclosing->callSuper |= callSuper; | |
178 | |
179 if (!nofree) | |
180 { enclosing = freelist; | |
181 freelist = this; | |
182 flags |= SCOPEfree; | |
183 } | |
184 | |
185 return enc; | |
186 } | |
187 | |
188 void Scope::mergeCallSuper(Loc loc, unsigned cs) | |
189 { | |
190 // This does a primitive flow analysis to support the restrictions | |
191 // regarding when and how constructors can appear. | |
192 // It merges the results of two paths. | |
193 // The two paths are callSuper and cs; the result is merged into callSuper. | |
194 | |
195 if (cs != callSuper) | |
196 { int a; | |
197 int b; | |
198 | |
199 callSuper |= cs & (CSXany_ctor | CSXlabel); | |
200 if (cs & CSXreturn) | |
201 { | |
202 } | |
203 else if (callSuper & CSXreturn) | |
204 { | |
205 callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); | |
206 } | |
207 else | |
208 { | |
209 a = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; | |
210 b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; | |
211 if (a != b) | |
212 error(loc, "one path skips constructor"); | |
213 callSuper |= cs; | |
214 } | |
215 } | |
216 } | |
217 | |
218 Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym) | |
219 { Dsymbol *s; | |
220 Scope *sc; | |
221 | |
222 //printf("Scope::search(%p, '%s')\n", this, ident->toChars()); | |
223 if (ident == Id::empty) | |
224 { | |
225 // Look for module scope | |
226 for (sc = this; sc; sc = sc->enclosing) | |
227 { | |
228 assert(sc != sc->enclosing); | |
229 if (sc->scopesym) | |
230 { | |
231 s = sc->scopesym->isModule(); | |
232 if (s) | |
233 { | |
234 //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars()); | |
235 if (pscopesym) | |
236 *pscopesym = sc->scopesym; | |
237 return s; | |
238 } | |
239 } | |
240 } | |
241 return NULL; | |
242 } | |
243 | |
244 for (sc = this; sc; sc = sc->enclosing) | |
245 { | |
246 assert(sc != sc->enclosing); | |
247 if (sc->scopesym) | |
248 { | |
249 //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind()); | |
250 s = sc->scopesym->search(loc, ident, 0); | |
251 if (s) | |
252 { | |
253 if ((global.params.warnings || | |
254 global.params.Dversion > 1) && | |
255 ident == Id::length && | |
256 sc->scopesym->isArrayScopeSymbol() && | |
257 sc->enclosing && | |
258 sc->enclosing->search(loc, ident, NULL)) | |
259 { | |
215
a58d8f4b84df
[svn r231] Changed: warnings are no longer treated as an error.
lindquist
parents:
159
diff
changeset
|
260 // WTF ? |
159 | 261 if (global.params.warnings) |
262 fprintf(stdmsg, "warning - "); | |
263 error(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->symtab->insert(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 } |