root/trunk/src/scope.c

Revision 528, 10.2 kB (checked in by walter, 2 years ago)

bugzilla 4296 Reduce parasitic error messages

  • Property svn:eol-style set to native
Line 
1 // Copyright (c) 1999-2010 by Digital Mars
2 // All Rights Reserved
3 // written by Walter Bright
4 // http://www.digitalmars.com
5 // License for redistribution is by either the Artistic License
6 // in artistic.txt, or the GNU General Public License in gnu.txt.
7 // See the included readme.txt for details.
8
9 #include <stdio.h>
10 #include <assert.h>
11
12 #include "root.h"
13 #include "speller.h"
14
15 #include "mars.h"
16 #include "init.h"
17 #include "identifier.h"
18 #include "scope.h"
19 #include "attrib.h"
20 #include "dsymbol.h"
21 #include "declaration.h"
22 #include "aggregate.h"
23 #include "module.h"
24 #include "id.h"
25 #include "lexer.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;
56     this->tf = NULL;
57     this->tinst = NULL;
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->mustsemantic = 0;
75     this->intypeof = 0;
76     this->parameterSpecialization = 0;
77     this->callSuper = 0;
78     this->flags = 0;
79     this->anonAgg = NULL;
80     this->lastdc = NULL;
81     this->lastoffset = 0;
82     this->docbuf = NULL;
83 }
84
85 Scope::Scope(Scope *enclosing)
86 {
87     //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
88     assert(!(enclosing->flags & SCOPEfree));
89     this->module = enclosing->module;
90     this->func   = enclosing->func;
91     this->parent = enclosing->parent;
92     this->scopesym = NULL;
93     this->sd = NULL;
94     this->sw = enclosing->sw;
95     this->tf = enclosing->tf;
96     this->tinst = enclosing->tinst;
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->mustsemantic = enclosing->mustsemantic;
123     this->intypeof = enclosing->intypeof;
124     this->parameterSpecialization = enclosing->parameterSpecialization;
125     this->callSuper = enclosing->callSuper;
126     this->flags = 0;
127     this->anonAgg = NULL;
128     this->lastdc = NULL;
129     this->lastoffset = 0;
130     this->docbuf = enclosing->docbuf;
131     assert(this != enclosing);
132 }
133
134 Scope *Scope::createGlobal(Module *module)
135 {
136     Scope *sc;
137
138     sc = new Scope();
139     sc->module = module;
140     sc->scopesym = new ScopeDsymbol();
141     sc->scopesym->symtab = new DsymbolTable();
142
143     // Add top level package as member of this global scope
144     Dsymbol *m = module;
145     while (m->parent)
146         m = m->parent;
147     m->addMember(NULL, sc->scopesym, 1);
148     m->parent = NULL;                   // got changed by addMember()
149
150     // Create the module scope underneath the global scope
151     sc = sc->push(module);
152     sc->parent = module;
153     return sc;
154 }
155
156 Scope *Scope::push()
157 {
158     //printf("Scope::push()\n");
159     Scope *s = new Scope(this);
160     assert(this != s);
161     return s;
162 }
163
164 Scope *Scope::push(ScopeDsymbol *ss)
165 {
166     //printf("Scope::push(%s)\n", ss->toChars());
167     Scope *s = push();
168     s->scopesym = ss;
169     return s;
170 }
171
172 Scope *Scope::pop()
173 {
174     //printf("Scope::pop() %p nofree = %d\n", this, nofree);
175     Scope *enc = enclosing;
176
177     if (enclosing)
178         enclosing->callSuper |= callSuper;
179
180     if (!nofree)
181     {   enclosing = freelist;
182         freelist = this;
183         flags |= SCOPEfree;
184     }
185
186     return enc;
187 }
188
189 void Scope::mergeCallSuper(Loc loc, unsigned cs)
190 {
191     // This does a primitive flow analysis to support the restrictions
192     // regarding when and how constructors can appear.
193     // It merges the results of two paths.
194     // The two paths are callSuper and cs; the result is merged into callSuper.
195
196     if (cs != callSuper)
197     {   int a;
198         int b;
199
200         callSuper |= cs & (CSXany_ctor | CSXlabel);
201         if (cs & CSXreturn)
202         {
203         }
204         else if (callSuper & CSXreturn)
205         {
206             callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
207         }
208         else
209         {
210             a = (cs        & (CSXthis_ctor | CSXsuper_ctor)) != 0;
211             b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
212             if (a != b)
213                 error(loc, "one path skips constructor");
214             callSuper |= cs;
215         }
216     }
217 }
218
219 Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
220 {   Dsymbol *s;
221     Scope *sc;
222
223     //printf("Scope::search(%p, '%s')\n", this, ident->toChars());
224     if (ident == Id::empty)
225     {
226         // Look for module scope
227         for (sc = this; sc; sc = sc->enclosing)
228         {
229             assert(sc != sc->enclosing);
230             if (sc->scopesym)
231             {
232                 s = sc->scopesym->isModule();
233                 if (s)
234                 {
235                     //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
236                     if (pscopesym)
237                         *pscopesym = sc->scopesym;
238                     return s;
239                 }
240             }
241         }
242         return NULL;
243     }
244
245     for (sc = this; sc; sc = sc->enclosing)
246     {
247         assert(sc != sc->enclosing);
248         if (sc->scopesym)
249         {
250             //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
251             s = sc->scopesym->search(loc, ident, 0);
252             if (s)
253             {
254                 if ((global.params.warnings ||
255                     global.params.Dversion > 1) &&
256                     ident == Id::length &&
257                     sc->scopesym->isArrayScopeSymbol() &&
258                     sc->enclosing &&
259                     sc->enclosing->search(loc, ident, NULL))
260                 {
261                     warning(s->loc, "array 'length' hides other 'length' name in outer scope");
262                 }
263
264                 //printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
265                 if (pscopesym)
266                     *pscopesym = sc->scopesym;
267                 return s;
268             }
269         }
270     }
271
272     return NULL;
273 }
274
275 Dsymbol *Scope::insert(Dsymbol *s)
276 {   Scope *sc;
277
278     for (sc = this; sc; sc = sc->enclosing)
279     {
280         //printf("\tsc = %p\n", sc);
281         if (sc->scopesym)
282         {
283             //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
284             if (!sc->scopesym->symtab)
285                 sc->scopesym->symtab = new DsymbolTable();
286             return sc->scopesym->symtabInsert(s);
287         }
288     }
289     assert(0);
290     return NULL;
291 }
292
293 /********************************************
294  * Search enclosing scopes for ClassDeclaration.
295  */
296
297 ClassDeclaration *Scope::getClassScope()
298 {   Scope *sc;
299
300     for (sc = this; sc; sc = sc->enclosing)
301     {
302         ClassDeclaration *cd;
303
304         if (sc->scopesym)
305         {
306             cd = sc->scopesym->isClassDeclaration();
307             if (cd)
308                 return cd;
309         }
310     }
311     return NULL;
312 }
313
314 /********************************************
315  * Search enclosing scopes for ClassDeclaration.
316  */
317
318 AggregateDeclaration *Scope::getStructClassScope()
319 {   Scope *sc;
320
321     for (sc = this; sc; sc = sc->enclosing)
322     {
323         AggregateDeclaration *ad;
324
325         if (sc->scopesym)
326         {
327             ad = sc->scopesym->isClassDeclaration();
328             if (ad)
329                 return ad;
330             else
331             {   ad = sc->scopesym->isStructDeclaration();
332                 if (ad)
333                     return ad;
334             }
335         }
336     }
337     return NULL;
338 }
339
340 /*******************************************
341  * For TemplateDeclarations, we need to remember the Scope
342  * where it was declared. So mark the Scope as not
343  * to be free'd.
344  */
345
346 void Scope::setNoFree()
347 {   Scope *sc;
348     //int i = 0;
349
350     //printf("Scope::setNoFree(this = %p)\n", this);
351     for (sc = this; sc; sc = sc->enclosing)
352     {
353         //printf("\tsc = %p\n", sc);
354         sc->nofree = 1;
355
356         assert(!(flags & SCOPEfree));
357         //assert(sc != sc->enclosing);
358         //assert(!sc->enclosing || sc != sc->enclosing->enclosing);
359         //if (++i == 10)
360             //assert(0);
361     }
362 }
363
364
365 /************************************************
366  * Given the failed search attempt, try to find
367  * one with a close spelling.
368  */
369
370 void *scope_search_fp(void *arg, const char *seed)
371 {
372     //printf("scope_search_fp('%s')\n", seed);
373
374     /* If not in the lexer's string table, it certainly isn't in the symbol table.
375      * Doing this first is a lot faster.
376      */
377     size_t len = strlen(seed);
378     if (!len)
379         return NULL;
380     StringValue *sv = Lexer::stringtable.lookup(seed, len);
381     if (!sv)
382         return NULL;
383     Identifier *id = (Identifier *)sv->ptrvalue;
384     assert(id);
385
386     Scope *sc = (Scope *)arg;
387     Module::clearCache();
388     Dsymbol *s = sc->search(0, id, NULL);
389     return s;
390 }
391
392 Dsymbol *Scope::search_correct(Identifier *ident)
393 {
394     if (global.gag)
395         return NULL;            // don't do it for speculative compiles; too time consuming
396
397     return (Dsymbol *)speller(ident->toChars(), &scope_search_fp, this, idchars);
398 }
Note: See TracBrowser for help on using the browser.