Mercurial > projects > ldc
annotate dmd/scope.c @ 1168:ab186e535e72
A different fix to #218 and DMD2682 that does not lead to constant folding regressions.
Fixes run/const_15, run/c/const_16_B.
The price is removing the lvalueness of struct literals. If it turns out too
much code depends on this behavior or we don't want to break with DMD, we
could keep struct literals as lvalues and instead convert struct literals used
as expression initializers into struct initializers.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sun, 29 Mar 2009 11:43:45 +0200 |
parents | f99a3b393c03 |
children | def7a1d494fd |
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; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
55 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
|
56 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
|
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; | |
1141
f99a3b393c03
Reorganize EnclosingHandlers to require less changes to the frontend and allow us to
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
94 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
|
95 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
|
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 } |