Mercurial > projects > ddmd
annotate dmd/AddrExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | af1bebfd96a4 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.AddrExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.UnaExp; | |
6 import dmd.MATCH; | |
7 import dmd.Type; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
0 | 10 import dmd.IRState; |
11 import dmd.ErrorExp; | |
12 import dmd.DotVarExp; | |
13 import dmd.FuncDeclaration; | |
14 import dmd.DelegateExp; | |
15 import dmd.VarExp; | |
16 import dmd.VarDeclaration; | |
72 | 17 import dmd.ThisExp; |
0 | 18 import dmd.TOK; |
19 import dmd.WANT; | |
20 import dmd.CommaExp; | |
21 import dmd.STC; | |
22 import dmd.PtrExp; | |
23 import dmd.SymOffExp; | |
24 import dmd.IndexExp; | |
25 import dmd.OverExp; | |
26 import dmd.Dsymbol; | |
27 import dmd.ScopeDsymbol; | |
28 import dmd.TY; | |
72 | 29 import dmd.TypeSArray; |
30 | |
0 | 31 import dmd.backend.elem; |
32 import dmd.backend.Util; | |
72 | 33 import dmd.codegen.Util; |
34 | |
0 | 35 class AddrExp : UnaExp |
36 { | |
37 this(Loc loc, Expression e) | |
38 { | |
178 | 39 register(); |
0 | 40 super(loc, TOK.TOKaddress, AddrExp.sizeof, e); |
41 } | |
42 | |
72 | 43 override Expression semantic(Scope sc) |
0 | 44 { |
45 version (LOGSEMANTIC) { | |
46 printf("AddrExp.semantic('%s')\n", toChars()); | |
47 } | |
48 if (!type) | |
49 { | |
50 UnaExp.semantic(sc); | |
51 e1 = e1.toLvalue(sc, null); | |
52 if (!e1.type) | |
53 { | |
54 error("cannot take address of %s", e1.toChars()); | |
55 return new ErrorExp(); | |
56 } | |
57 if (!e1.type.deco) | |
58 { | |
59 /* No deco means semantic() was not run on the type. | |
60 * We have to run semantic() on the symbol to get the right type: | |
61 * auto x = &bar; | |
62 * pure: int bar() { return 1;} | |
63 * otherwise the 'pure' is missing from the type assigned to x. | |
64 */ | |
65 | |
66 error("forward reference to %s", e1.toChars()); | |
67 return new ErrorExp(); | |
68 } | |
69 | |
70 type = e1.type.pointerTo(); | |
71 | |
72 // See if this should really be a delegate | |
73 if (e1.op == TOKdotvar) | |
74 { | |
75 DotVarExp dve = cast(DotVarExp)e1; | |
76 FuncDeclaration f = dve.var.isFuncDeclaration(); | |
77 | |
78 if (f) | |
79 { | |
80 if (!dve.hasOverloads) | |
81 f.tookAddressOf++; | |
82 Expression e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads); | |
83 e = e.semantic(sc); | |
84 return e; | |
85 } | |
86 } | |
87 else if (e1.op == TOKvar) | |
88 { | |
89 VarExp ve = cast(VarExp)e1; | |
90 | |
91 VarDeclaration v = ve.var.isVarDeclaration(); | |
92 if (v && !v.canTakeAddressOf()) | |
93 error("cannot take address of %s", e1.toChars()); | |
94 | |
95 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
96 | |
97 if (f) | |
98 { | |
99 if (!ve.hasOverloads || | |
100 /* Because nested functions cannot be overloaded, | |
101 * mark here that we took its address because castTo() | |
102 * may not be called with an exact match. | |
103 */ | |
104 f.toParent2().isFuncDeclaration()) | |
105 f.tookAddressOf++; | |
106 | |
107 if (f.isNested()) | |
108 { | |
109 Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads); | |
110 e = e.semantic(sc); | |
111 return e; | |
112 } | |
113 if (f.needThis() && hasThis(sc)) | |
114 { | |
115 /* Should probably supply 'this' after overload resolution, | |
116 * not before. | |
117 */ | |
118 Expression ethis = new ThisExp(loc); | |
119 Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads); | |
120 e = e.semantic(sc); | |
121 return e; | |
122 } | |
123 } | |
124 } | |
125 return optimize(WANTvalue); | |
126 } | |
127 return this; | |
128 } | |
129 | |
135 | 130 override void checkEscape() |
131 { | |
132 e1.checkEscapeRef(); | |
133 } | |
134 | |
72 | 135 override elem* toElem(IRState* irs) |
0 | 136 { |
137 elem* e; | |
138 | |
139 //printf("AddrExp.toElem('%s')\n", toChars()); | |
140 | |
141 e = e1.toElem(irs); | |
142 e = addressElem(e, e1.type); | |
143 L2: | |
144 e.Ety = type.totym(); | |
145 el_setLoc(e,loc); | |
146 return e; | |
147 } | |
148 | |
72 | 149 override MATCH implicitConvTo(Type t) |
0 | 150 { |
151 static if (false) { | |
152 printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
153 toChars(), type.toChars(), t.toChars()); | |
154 } | |
155 MATCH result; | |
156 | |
157 result = type.implicitConvTo(t); | |
158 //printf("\tresult = %d\n", result); | |
159 | |
160 if (result == MATCHnomatch) | |
161 { | |
162 // Look for pointers to functions where the functions are overloaded. | |
163 | |
164 t = t.toBasetype(); | |
165 | |
166 if (e1.op == TOKoverloadset && | |
167 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
168 { | |
169 OverExp eo = cast(OverExp)e1; | |
170 FuncDeclaration f = null; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
171 foreach (s; eo.vars.a) |
0 | 172 { |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
173 auto f2 = s.isFuncDeclaration(); |
0 | 174 assert(f2); |
175 if (f2.overloadExactMatch(t.nextOf())) | |
176 { | |
177 if (f) | |
178 /* Error if match in more than one overload set, | |
179 * even if one is a 'better' match than the other. | |
180 */ | |
181 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
182 else | |
183 f = f2; | |
184 result = MATCHexact; | |
185 } | |
186 } | |
187 } | |
188 | |
189 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
190 t.ty == Tpointer && t.nextOf().ty == Tfunction && | |
191 e1.op == TOKvar) | |
192 { | |
193 /* I don't think this can ever happen - | |
194 * it should have been | |
195 * converted to a SymOffExp. | |
196 */ | |
197 assert(0); | |
198 VarExp ve = cast(VarExp)e1; | |
199 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
200 if (f && f.overloadExactMatch(t.nextOf())) | |
201 result = MATCHexact; | |
202 } | |
203 } | |
204 | |
205 //printf("\tresult = %d\n", result); | |
206 return result; | |
207 } | |
208 | |
72 | 209 override Expression castTo(Scope sc, Type t) |
0 | 210 { |
211 Type tb; | |
212 | |
213 static if (false) { | |
214 printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); | |
215 } | |
216 Expression e = this; | |
217 | |
218 tb = t.toBasetype(); | |
219 type = type.toBasetype(); | |
220 if (tb != type) | |
221 { | |
222 // Look for pointers to functions where the functions are overloaded. | |
223 | |
224 if (e1.op == TOKoverloadset && | |
225 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
226 { | |
227 OverExp eo = cast(OverExp)e1; | |
228 FuncDeclaration f = null; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
229 foreach (s; eo.vars.a) |
0 | 230 { |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
77
diff
changeset
|
231 auto f2 = s.isFuncDeclaration(); |
0 | 232 assert(f2); |
233 if (f2.overloadExactMatch(t.nextOf())) | |
234 { | |
235 if (f) | |
236 /* Error if match in more than one overload set, | |
237 * even if one is a 'better' match than the other. | |
238 */ | |
239 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
240 else | |
241 f = f2; | |
242 } | |
243 } | |
244 if (f) | |
245 { | |
246 f.tookAddressOf++; | |
247 SymOffExp se = new SymOffExp(loc, f, 0, 0); | |
248 se.semantic(sc); | |
249 // Let SymOffExp.castTo() do the heavy lifting | |
250 return se.castTo(sc, t); | |
251 } | |
252 } | |
253 | |
254 | |
255 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
256 tb.ty == Tpointer && tb.nextOf().ty == Tfunction && | |
257 e1.op == TOKvar) | |
258 { | |
259 VarExp ve = cast(VarExp)e1; | |
260 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
261 if (f) | |
262 { | |
263 assert(0); // should be SymOffExp instead | |
264 f = f.overloadExactMatch(tb.nextOf()); | |
265 if (f) | |
266 { | |
267 e = new VarExp(loc, f); | |
268 e.type = f.type; | |
269 e = new AddrExp(loc, e); | |
270 e.type = t; | |
271 return e; | |
272 } | |
273 } | |
274 } | |
275 e = Expression.castTo(sc, t); | |
276 } | |
277 e.type = t; | |
278 return e; | |
279 } | |
280 | |
72 | 281 override Expression optimize(int result) |
0 | 282 { |
283 Expression e; | |
284 | |
285 //printf("AddrExp.optimize(result = %d) %s\n", result, toChars()); | |
286 | |
287 /* Rewrite &(a,b) as (a,&b) | |
288 */ | |
289 if (e1.op == TOKcomma) | |
290 { | |
291 CommaExp ce = cast(CommaExp)e1; | |
292 AddrExp ae = new AddrExp(loc, ce.e2); | |
293 ae.type = type; | |
294 e = new CommaExp(ce.loc, ce.e1, ae); | |
295 e.type = type; | |
296 return e.optimize(result); | |
297 } | |
298 | |
299 if (e1.op == TOKvar) | |
300 { | |
301 VarExp ve = cast(VarExp)e1; | |
302 if (ve.var.storage_class & STCmanifest) | |
303 e1 = e1.optimize(result); | |
304 } | |
305 else | |
306 e1 = e1.optimize(result); | |
307 | |
308 // Convert &*ex to ex | |
309 if (e1.op == TOKstar) | |
310 { | |
311 Expression ex; | |
312 | |
313 ex = (cast(PtrExp)e1).e1; | |
314 if (type.equals(ex.type)) | |
315 e = ex; | |
316 else | |
317 { | |
318 e = ex.copy(); | |
319 e.type = type; | |
320 } | |
321 return e; | |
322 } | |
323 if (e1.op == TOKvar) | |
324 { | |
325 VarExp ve = cast(VarExp)e1; | |
326 if (!ve.var.isOut() && !ve.var.isRef() && | |
327 !ve.var.isImportedSymbol()) | |
328 { | |
329 SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads); | |
330 se.type = type; | |
331 return se; | |
332 } | |
333 } | |
334 if (e1.op == TOKindex) | |
335 { | |
336 // Convert &array[n] to &array+n | |
337 IndexExp ae = cast(IndexExp)e1; | |
338 | |
339 if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar) | |
340 { | |
341 long index = ae.e2.toInteger(); | |
342 VarExp ve = cast(VarExp)ae.e1; | |
343 if (ve.type.ty == Tsarray | |
344 && !ve.var.isImportedSymbol()) | |
345 { | |
346 TypeSArray ts = cast(TypeSArray)ve.type; | |
347 long dim = ts.dim.toInteger(); | |
348 if (index < 0 || index >= dim) | |
349 error("array index %jd is out of bounds [0..%jd]", index, dim); | |
350 e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size())); | |
351 e.type = type; | |
352 return e; | |
353 } | |
354 } | |
355 } | |
356 return this; | |
357 } | |
358 } | |
359 |