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