Mercurial > projects > ldc
annotate dmd/scope.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | b30fe7e1dbb9 |
children | f99a3b393c03 |
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 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
561
diff
changeset
|
260 warning(s->loc, "array 'length' hides other 'length' name in outer scope"); |
159 | 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 } |