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 //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
|
72
|
129 override elem* toElem(IRState* irs)
|
0
|
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
|
72
|
143 override MATCH implicitConvTo(Type t)
|
0
|
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
|
72
|
204 override Expression castTo(Scope sc, Type t)
|
0
|
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
|
72
|
277 override Expression optimize(int result)
|
0
|
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
|