comparison dmd/AddrExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 2e2a5c3f943a
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
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;
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;
16 import dmd.ThisExp;
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;
28 import dmd.TypeSArray;
29
30 import dmd.backend.elem;
31 import dmd.backend.Util;
32 import dmd.codegen.Util;
33
34 class AddrExp : UnaExp
35 {
36 this(Loc loc, Expression e)
37 {
38 super(loc, TOK.TOKaddress, AddrExp.sizeof, e);
39 }
40
41 Expression semantic(Scope sc)
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 //printf("test3 deco = %p\n", e1.type.deco);
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
129 elem* toElem(IRState* irs)
130 {
131 elem* e;
132
133 //printf("AddrExp.toElem('%s')\n", toChars());
134
135 e = e1.toElem(irs);
136 e = addressElem(e, e1.type);
137 L2:
138 e.Ety = type.totym();
139 el_setLoc(e,loc);
140 return e;
141 }
142
143 MATCH implicitConvTo(Type t)
144 {
145 static if (false) {
146 printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
147 toChars(), type.toChars(), t.toChars());
148 }
149 MATCH result;
150
151 result = type.implicitConvTo(t);
152 //printf("\tresult = %d\n", result);
153
154 if (result == MATCHnomatch)
155 {
156 // Look for pointers to functions where the functions are overloaded.
157
158 t = t.toBasetype();
159
160 if (e1.op == TOKoverloadset &&
161 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
162 {
163 OverExp eo = cast(OverExp)e1;
164 FuncDeclaration f = null;
165 for (int i = 0; i < eo.vars.a.dim; i++)
166 {
167 Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
168 FuncDeclaration f2 = s.isFuncDeclaration();
169 assert(f2);
170 if (f2.overloadExactMatch(t.nextOf()))
171 {
172 if (f)
173 /* Error if match in more than one overload set,
174 * even if one is a 'better' match than the other.
175 */
176 ScopeDsymbol.multiplyDefined(loc, f, f2);
177 else
178 f = f2;
179 result = MATCHexact;
180 }
181 }
182 }
183
184 if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
185 t.ty == Tpointer && t.nextOf().ty == Tfunction &&
186 e1.op == TOKvar)
187 {
188 /* I don't think this can ever happen -
189 * it should have been
190 * converted to a SymOffExp.
191 */
192 assert(0);
193 VarExp ve = cast(VarExp)e1;
194 FuncDeclaration f = ve.var.isFuncDeclaration();
195 if (f && f.overloadExactMatch(t.nextOf()))
196 result = MATCHexact;
197 }
198 }
199
200 //printf("\tresult = %d\n", result);
201 return result;
202 }
203
204 Expression castTo(Scope sc, Type t)
205 {
206 Type tb;
207
208 static if (false) {
209 printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
210 }
211 Expression e = this;
212
213 tb = t.toBasetype();
214 type = type.toBasetype();
215 if (tb != type)
216 {
217 // Look for pointers to functions where the functions are overloaded.
218
219 if (e1.op == TOKoverloadset &&
220 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
221 {
222 OverExp eo = cast(OverExp)e1;
223 FuncDeclaration f = null;
224 for (int i = 0; i < eo.vars.a.dim; i++)
225 {
226 Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
227 FuncDeclaration f2 = s.isFuncDeclaration();
228 assert(f2);
229 if (f2.overloadExactMatch(t.nextOf()))
230 {
231 if (f)
232 /* Error if match in more than one overload set,
233 * even if one is a 'better' match than the other.
234 */
235 ScopeDsymbol.multiplyDefined(loc, f, f2);
236 else
237 f = f2;
238 }
239 }
240 if (f)
241 {
242 f.tookAddressOf++;
243 SymOffExp se = new SymOffExp(loc, f, 0, 0);
244 se.semantic(sc);
245 // Let SymOffExp.castTo() do the heavy lifting
246 return se.castTo(sc, t);
247 }
248 }
249
250
251 if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
252 tb.ty == Tpointer && tb.nextOf().ty == Tfunction &&
253 e1.op == TOKvar)
254 {
255 VarExp ve = cast(VarExp)e1;
256 FuncDeclaration f = ve.var.isFuncDeclaration();
257 if (f)
258 {
259 assert(0); // should be SymOffExp instead
260 f = f.overloadExactMatch(tb.nextOf());
261 if (f)
262 {
263 e = new VarExp(loc, f);
264 e.type = f.type;
265 e = new AddrExp(loc, e);
266 e.type = t;
267 return e;
268 }
269 }
270 }
271 e = Expression.castTo(sc, t);
272 }
273 e.type = t;
274 return e;
275 }
276
277 Expression optimize(int result)
278 {
279 Expression e;
280
281 //printf("AddrExp.optimize(result = %d) %s\n", result, toChars());
282
283 /* Rewrite &(a,b) as (a,&b)
284 */
285 if (e1.op == TOKcomma)
286 {
287 CommaExp ce = cast(CommaExp)e1;
288 AddrExp ae = new AddrExp(loc, ce.e2);
289 ae.type = type;
290 e = new CommaExp(ce.loc, ce.e1, ae);
291 e.type = type;
292 return e.optimize(result);
293 }
294
295 if (e1.op == TOKvar)
296 {
297 VarExp ve = cast(VarExp)e1;
298 if (ve.var.storage_class & STCmanifest)
299 e1 = e1.optimize(result);
300 }
301 else
302 e1 = e1.optimize(result);
303
304 // Convert &*ex to ex
305 if (e1.op == TOKstar)
306 {
307 Expression ex;
308
309 ex = (cast(PtrExp)e1).e1;
310 if (type.equals(ex.type))
311 e = ex;
312 else
313 {
314 e = ex.copy();
315 e.type = type;
316 }
317 return e;
318 }
319 if (e1.op == TOKvar)
320 {
321 VarExp ve = cast(VarExp)e1;
322 if (!ve.var.isOut() && !ve.var.isRef() &&
323 !ve.var.isImportedSymbol())
324 {
325 SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads);
326 se.type = type;
327 return se;
328 }
329 }
330 if (e1.op == TOKindex)
331 {
332 // Convert &array[n] to &array+n
333 IndexExp ae = cast(IndexExp)e1;
334
335 if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar)
336 {
337 long index = ae.e2.toInteger();
338 VarExp ve = cast(VarExp)ae.e1;
339 if (ve.type.ty == Tsarray
340 && !ve.var.isImportedSymbol())
341 {
342 TypeSArray ts = cast(TypeSArray)ve.type;
343 long dim = ts.dim.toInteger();
344 if (index < 0 || index >= dim)
345 error("array index %jd is out of bounds [0..%jd]", index, dim);
346 e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size()));
347 e.type = type;
348 return e;
349 }
350 }
351 }
352 return this;
353 }
354 }
355