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