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