0
|
1 module dmd.Scope;
|
|
2
|
|
3 import dmd.Module;
|
|
4 import dmd.ScopeDsymbol;
|
|
5 import dmd.FuncDeclaration;
|
|
6 import dmd.Id;
|
|
7 import dmd.Dsymbol;
|
|
8 import dmd.LabelStatement;
|
|
9 import dmd.SwitchStatement;
|
|
10 import dmd.TryFinallyStatement;
|
|
11 import dmd.TemplateInstance;
|
|
12 import dmd.Statement;
|
|
13 import dmd.ForeachStatement;
|
|
14 import dmd.LINK;
|
|
15 import dmd.PROT;
|
|
16 import dmd.STC;
|
|
17 import dmd.AnonymousAggregateDeclaration;
|
|
18 import dmd.AggregateDeclaration;
|
|
19 import dmd.ClassDeclaration;
|
|
20 import dmd.Identifier;
|
|
21 import dmd.Loc;
|
|
22 import dmd.OutBuffer;
|
|
23 import dmd.DocComment;
|
|
24 import dmd.DsymbolTable;
|
|
25 import dmd.Global;
|
|
26 import dmd.CSX;
|
|
27 import dmd.Util;
|
|
28
|
|
29 enum SCOPE
|
|
30 {
|
|
31 SCOPEctor = 1, // constructor type
|
|
32 SCOPEstaticif = 2, // inside static if
|
|
33 SCOPEfree = 4, // is on free list
|
|
34 }
|
|
35
|
|
36 class Scope
|
|
37 {
|
|
38 Scope enclosing; // enclosing Scope
|
|
39
|
|
40 Module module_; // Root module
|
|
41 ScopeDsymbol scopesym; // current symbol
|
|
42 ScopeDsymbol sd; // if in static if, and declaring new symbols,
|
|
43 // sd gets the addMember()
|
|
44 FuncDeclaration func; // function we are in
|
|
45 Dsymbol parent; // parent to use
|
|
46 LabelStatement slabel; // enclosing labelled statement
|
|
47 SwitchStatement sw; // enclosing switch statement
|
|
48 TryFinallyStatement tf; // enclosing try finally statement
|
|
49 TemplateInstance tinst; // enclosing template instance
|
|
50 Statement sbreak; // enclosing statement that supports "break"
|
|
51 Statement scontinue; // enclosing statement that supports "continue"
|
|
52 ForeachStatement fes; // if nested function for ForeachStatement, this is it
|
|
53 uint offset; // next offset to use in aggregate
|
|
54 int inunion; // we're processing members of a union
|
|
55 int incontract; // we're inside contract code
|
|
56 int nofree; // set if shouldn't free it
|
|
57 int noctor; // set if constructor calls aren't allowed
|
|
58 int intypeof; // in typeof(exp)
|
|
59 int parameterSpecialization; // if in template parameter specialization
|
|
60 int noaccesscheck; // don't do access checks
|
|
61 int mustsemantic; // cannot defer semantic()
|
|
62
|
|
63 uint callSuper; // primitive flow analysis for constructors
|
|
64 ///#define CSXthis_ctor 1 // called this()
|
|
65 ///#define CSXsuper_ctor 2 // called super()
|
|
66 ///#define CSXthis 4 // referenced this
|
|
67 ///#define CSXsuper 8 // referenced super
|
|
68 ///#define CSXlabel 0x10 // seen a label
|
|
69 ///#define CSXreturn 0x20 // seen a return statement
|
|
70 ///#define CSXany_ctor 0x40 // either this() or super() was called
|
|
71
|
|
72 uint structalign; // alignment for struct members
|
|
73 LINK linkage = LINK.LINKd; // linkage for external functions
|
|
74
|
|
75 PROT protection = PROT.PROTpublic; // protection for class members
|
|
76 int explicitProtection; // set if in an explicit protection attribute
|
|
77
|
|
78 STC stc; // storage class
|
|
79
|
|
80 SCOPE flags;
|
|
81
|
|
82 AnonymousAggregateDeclaration anonAgg; // for temporary analysis
|
|
83
|
|
84 DocComment lastdc; // documentation comment for last symbol at this scope
|
|
85 uint lastoffset; // offset in docbuf of where to insert next dec
|
|
86 OutBuffer docbuf; // buffer for documentation output
|
|
87
|
|
88 static Scope freelist;
|
|
89 /// static void *operator new(size_t sz);
|
|
90 static Scope createGlobal(Module module_)
|
|
91 {
|
|
92 Scope sc = new Scope();
|
|
93 sc.module_ = module_;
|
|
94 sc.scopesym = new ScopeDsymbol();
|
|
95 sc.scopesym.symtab = new DsymbolTable();
|
|
96
|
|
97 // Add top level package as member of this global scope
|
|
98 Dsymbol m = module_;
|
|
99 while (m.parent !is null)
|
|
100 m = m.parent;
|
|
101
|
13
|
102 m.addMember(null, sc.scopesym, true);
|
0
|
103 m.parent = null; // got changed by addMember()
|
|
104
|
|
105 // Create the module scope underneath the global scope
|
|
106 sc = sc.push(module_);
|
|
107 sc.parent = module_;
|
|
108 return sc;
|
|
109 }
|
|
110
|
|
111 this()
|
|
112 {
|
|
113 // Create root scope
|
|
114
|
|
115 //printf("Scope.Scope() %p\n", this);
|
|
116 this.structalign = global.structalign;
|
|
117 }
|
|
118
|
|
119 this(Module module_)
|
|
120 {
|
|
121 assert(false);
|
|
122 }
|
|
123
|
|
124 this(Scope enclosing)
|
|
125 {
|
|
126 //printf("Scope.Scope(enclosing = %p) %p\n", enclosing, this);
|
|
127 assert(!(enclosing.flags & SCOPE.SCOPEfree));
|
|
128 this.module_ = enclosing.module_;
|
|
129 this.func = enclosing.func;
|
|
130 this.parent = enclosing.parent;
|
|
131 this.sw = enclosing.sw;
|
|
132 this.tf = enclosing.tf;
|
|
133 this.tinst = enclosing.tinst;
|
|
134 this.sbreak = enclosing.sbreak;
|
|
135 this.scontinue = enclosing.scontinue;
|
|
136 this.fes = enclosing.fes;
|
|
137 this.structalign = enclosing.structalign;
|
|
138 this.enclosing = enclosing;
|
|
139 debug {
|
|
140 if (enclosing.enclosing)
|
|
141 assert(!(enclosing.enclosing.flags & SCOPE.SCOPEfree));
|
|
142
|
|
143 if (this is enclosing.enclosing) /// huh?
|
|
144 {
|
|
145 writef("this = %p, enclosing = %p, enclosing.enclosing = %p\n", this, enclosing, enclosing.enclosing);
|
|
146 }
|
|
147 assert(this !is enclosing.enclosing);
|
|
148 }
|
|
149 this.linkage = enclosing.linkage;
|
|
150 this.protection = enclosing.protection;
|
|
151 this.explicitProtection = enclosing.explicitProtection;
|
|
152 this.stc = enclosing.stc;
|
|
153 this.inunion = enclosing.inunion;
|
|
154 this.incontract = enclosing.incontract;
|
|
155 this.noctor = enclosing.noctor;
|
|
156 this.noaccesscheck = enclosing.noaccesscheck;
|
|
157 this.mustsemantic = enclosing.mustsemantic;
|
|
158 this.intypeof = enclosing.intypeof;
|
|
159 this.parameterSpecialization = enclosing.parameterSpecialization;
|
|
160 this.callSuper = enclosing.callSuper;
|
|
161 this.docbuf = enclosing.docbuf;
|
|
162 assert(this !is enclosing); /// huh?
|
|
163 }
|
|
164
|
|
165 Scope push()
|
|
166 {
|
|
167 //printf("Scope.push()\n");
|
|
168 Scope s = new Scope(this);
|
|
169 assert(this !is s); /// huh?
|
|
170 return s;
|
|
171 }
|
|
172
|
|
173 Scope push(ScopeDsymbol ss)
|
|
174 {
|
|
175 //printf("Scope.push(%s)\n", ss.toChars());
|
|
176 Scope s = push();
|
|
177 s.scopesym = ss;
|
|
178 return s;
|
|
179 }
|
|
180
|
|
181 Scope pop()
|
|
182 {
|
|
183 //printf("Scope.pop() %p nofree = %d\n", this, nofree);
|
|
184 Scope enc = enclosing;
|
|
185
|
|
186 if (enclosing)
|
|
187 enclosing.callSuper |= callSuper;
|
|
188
|
|
189 if (!nofree)
|
|
190 {
|
|
191 enclosing = freelist;
|
|
192 freelist = this;
|
|
193 flags |= SCOPE.SCOPEfree;
|
|
194 }
|
|
195
|
|
196 return enc;
|
|
197 }
|
|
198
|
|
199 void mergeCallSuper(Loc loc, uint cs)
|
|
200 {
|
|
201 // This does a primitive flow analysis to support the restrictions
|
|
202 // regarding when and how constructors can appear.
|
|
203 // It merges the results of two paths.
|
|
204 // The two paths are callSuper and cs; the result is merged into callSuper.
|
|
205
|
|
206 if (cs != callSuper)
|
|
207 {
|
|
208 int a;
|
|
209 int b;
|
|
210
|
|
211 callSuper |= cs & (CSX.CSXany_ctor | CSX.CSXlabel);
|
|
212 if (cs & CSX.CSXreturn)
|
|
213 {
|
|
214 ;
|
|
215 }
|
|
216 else if (callSuper & CSX.CSXreturn)
|
|
217 {
|
|
218 callSuper = cs | (callSuper & (CSX.CSXany_ctor | CSX.CSXlabel));
|
|
219 }
|
|
220 else
|
|
221 {
|
|
222 a = (cs & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
|
|
223 b = (callSuper & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
|
|
224
|
|
225 if (a != b)
|
|
226 error(loc, "one path skips constructor");
|
|
227 callSuper |= cs;
|
|
228 }
|
|
229 }
|
|
230 }
|
|
231
|
|
232 Dsymbol search(Loc loc, Identifier ident, Dsymbol* pscopesym)
|
|
233 {
|
|
234 Dsymbol s;
|
|
235 Scope sc;
|
|
236
|
|
237 //printf("Scope.search(%p, '%s')\n", this, ident.toChars());
|
|
238 if (ident is Id.empty)
|
|
239 {
|
|
240 // Look for module scope
|
|
241 for (sc = this; sc; sc = sc.enclosing)
|
|
242 {
|
|
243 assert(sc != sc.enclosing);
|
|
244 if (sc.scopesym)
|
|
245 {
|
|
246 s = sc.scopesym.isModule();
|
|
247 if (s)
|
|
248 {
|
|
249 //printf("\tfound %s.%s\n", s.parent ? s.parent.toChars() : "", s.toChars());
|
|
250 if (pscopesym)
|
|
251 *pscopesym = sc.scopesym;
|
|
252 return s;
|
|
253 }
|
|
254 }
|
|
255 }
|
|
256 return null;
|
|
257 }
|
|
258
|
|
259 for (sc = this; sc; sc = sc.enclosing)
|
|
260 {
|
|
261 assert(sc != sc.enclosing);
|
|
262 if (sc.scopesym)
|
|
263 {
|
|
264 //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc.scopesym.toChars(), sc.scopesym.kind());
|
|
265 s = sc.scopesym.search(loc, ident, 0);
|
|
266 if (s)
|
|
267 {
|
|
268 if ((global.params.warnings ||
|
|
269 global.params.Dversion > 1) &&
|
|
270 ident == Id.length &&
|
|
271 sc.scopesym.isArrayScopeSymbol() &&
|
|
272 sc.enclosing &&
|
|
273 sc.enclosing.search(loc, ident, null))
|
|
274 {
|
|
275 warning(s.loc, "array 'length' hides other 'length' name in outer scope");
|
|
276 }
|
|
277
|
|
278 //printf("\tfound %s.%s, kind = '%s'\n", s.parent ? s.parent.toChars() : "", s.toChars(), s.kind());
|
|
279 if (pscopesym)
|
|
280 *pscopesym = sc.scopesym;
|
|
281 return s;
|
|
282 }
|
|
283 }
|
|
284 }
|
|
285
|
|
286 return null;
|
|
287 }
|
|
288
|
|
289 Dsymbol insert(Dsymbol s)
|
|
290 {
|
|
291 for (Scope sc = this; sc; sc = sc.enclosing)
|
|
292 {
|
|
293 //printf("\tsc = %p\n", sc);
|
|
294 if (sc.scopesym)
|
|
295 {
|
|
296 //printf("\t\tsc.scopesym = %p\n", sc.scopesym);
|
|
297 if (!sc.scopesym.symtab)
|
|
298 sc.scopesym.symtab = new DsymbolTable();
|
|
299
|
|
300 return sc.scopesym.symtab.insert(s);
|
|
301 }
|
|
302 }
|
|
303
|
|
304 assert(false);
|
|
305 }
|
|
306
|
|
307 ClassDeclaration getClassScope()
|
|
308 {
|
|
309 assert(false);
|
|
310 }
|
|
311
|
|
312 /********************************************
|
|
313 * Search enclosing scopes for ClassDeclaration.
|
|
314 */
|
|
315 AggregateDeclaration getStructClassScope()
|
|
316 {
|
|
317 for (Scope sc = this; sc; sc = sc.enclosing)
|
|
318 {
|
|
319 AggregateDeclaration ad;
|
|
320
|
|
321 if (sc.scopesym)
|
|
322 {
|
|
323 ad = sc.scopesym.isClassDeclaration();
|
|
324 if (ad)
|
|
325 return ad;
|
|
326 else
|
|
327 {
|
|
328 ad = sc.scopesym.isStructDeclaration();
|
|
329 if (ad)
|
|
330 return ad;
|
|
331 }
|
|
332 }
|
|
333 }
|
|
334
|
|
335 return null;
|
|
336 }
|
|
337
|
|
338 void setNoFree()
|
|
339 {
|
|
340 //int i = 0;
|
|
341
|
|
342 //printf("Scope.setNoFree(this = %p)\n", this);
|
|
343 for (Scope sc = this; sc; sc = sc.enclosing)
|
|
344 {
|
|
345 //printf("\tsc = %p\n", sc);
|
|
346 sc.nofree = 1;
|
|
347
|
|
348 assert(!(flags & SCOPE.SCOPEfree));
|
|
349 //assert(sc != sc.enclosing);
|
|
350 //assert(!sc.enclosing || sc != sc.enclosing.enclosing);
|
|
351 //if (++i == 10)
|
|
352 //assert(0);
|
|
353 }
|
|
354 }
|
|
355 } |