Mercurial > projects > ddmd
annotate dmd/VarExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | 0c8cc2a10f99 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.VarExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Declaration; | |
6 import dmd.InterState; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.InlineCostState; | |
11 import dmd.FuncLiteralDeclaration; | |
12 import dmd.VarDeclaration; | |
13 import dmd.Dsymbol; | |
14 import dmd.FuncDeclaration; | |
15 import dmd.InlineDoState; | |
16 import dmd.HdrGenState; | |
17 import dmd.TOK; | |
18 import dmd.TY; | |
19 import dmd.STC; | |
148 | 20 import dmd.SymbolDeclaration; |
72 | 21 import dmd.SymbolExp; |
22 import dmd.Type; | |
23 import dmd.interpret.Util; | |
148 | 24 import dmd.backend.Util; |
72 | 25 import dmd.backend.dt_t; |
26 import dmd.expression.Util; | |
27 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
28 //! Variable |
0 | 29 class VarExp : SymbolExp |
30 { | |
73 | 31 this(Loc loc, Declaration var, bool hasOverloads = false) |
0 | 32 { |
178 | 33 register(); |
72 | 34 super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads); |
35 | |
36 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars()); | |
37 //if (strcmp(var.ident.toChars(), "func") == 0) halt(); | |
0 | 38 this.type = var.type; |
39 } | |
40 | |
72 | 41 override bool equals(Object o) |
0 | 42 { |
156 | 43 VarExp ne; |
44 | |
45 if ( this == o || | |
46 ((cast(Expression)o).op == TOKvar && | |
47 ((ne = cast(VarExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) && | |
48 var == ne.var)) | |
49 return true; | |
50 return false; | |
0 | 51 } |
52 | |
72 | 53 override Expression semantic(Scope sc) |
0 | 54 { |
72 | 55 FuncLiteralDeclaration fd; |
56 | |
57 version (LOGSEMANTIC) { | |
58 printf("VarExp.semantic(%s)\n", toChars()); | |
59 } | |
60 if (!type) | |
61 { | |
62 type = var.type; | |
63 static if (false) { | |
64 if (var.storage_class & STC.STClazy) | |
65 { | |
66 TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd); | |
67 type = new TypeDelegate(tf); | |
68 type = type.semantic(loc, sc); | |
69 } | |
70 } | |
71 } | |
72 | |
73 /* Fix for 1161 doesn't work because it causes protection | |
74 * problems when instantiating imported templates passing private | |
75 * variables as alias template parameters. | |
76 */ | |
77 //accessCheck(loc, sc, null, var); | |
78 | |
79 VarDeclaration v = var.isVarDeclaration(); | |
80 if (v) | |
81 { | |
82 static if (false) { | |
135 | 83 if ((v.isConst() || v.isImmutable()) && type.toBasetype().ty != TY.Tsarray && v.init) |
72 | 84 { |
85 ExpInitializer ei = v.init.isExpInitializer(); | |
86 if (ei) | |
87 { | |
88 //ei.exp.implicitCastTo(sc, type).print(); | |
89 return ei.exp.implicitCastTo(sc, type); | |
90 } | |
91 } | |
92 } | |
93 v.checkNestedReference(sc, loc); | |
94 version (DMDV2) { | |
95 static if (true) { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
96 if (sc.func && !sc.intypeof) |
72 | 97 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
98 /* Given: |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
99 * void f() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
100 * { int fx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
101 * pure void g() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
102 * { int gx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
103 * void h() |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
104 * { int hx; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
105 * void i() { } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
106 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
107 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
108 * } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
109 * i() can modify hx and gx but not fx |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
110 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
111 |
72 | 112 /* Determine if sc.func is pure or if any function that |
113 * encloses it is also pure. | |
114 */ | |
115 bool hasPureParent = false; | |
116 for (FuncDeclaration outerfunc = sc.func; outerfunc;) | |
117 { | |
118 if (outerfunc.isPure()) | |
119 { | |
120 hasPureParent = true; | |
121 break; | |
122 } | |
123 Dsymbol parent = outerfunc.toParent2(); | |
124 if (!parent) | |
125 break; | |
126 outerfunc = parent.isFuncDeclaration(); | |
127 } | |
128 | |
129 /* If ANY of its enclosing functions are pure, | |
130 * it cannot do anything impure. | |
131 * If it is pure, it cannot access any mutable variables other | |
132 * than those inside itself | |
133 */ | |
135 | 134 if (hasPureParent && v.isDataseg() && !v.isImmutable()) |
72 | 135 { |
136 error("pure function '%s' cannot access mutable static data '%s'", | |
137 sc.func.toChars(), v.toChars()); | |
138 } | |
135 | 139 else if (sc.func.isPure() && sc.parent != v.parent && !v.isImmutable() && !(v.storage_class & STC.STCmanifest)) |
72 | 140 { |
141 error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars()); | |
142 if (v.isEnumDeclaration()) | |
143 error("enum"); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
144 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
145 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
146 /* Do not allow safe functions to access __gshared data |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
147 */ |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
148 if (sc.func.isSafe() && v.storage_class & STCgshared) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
149 error("safe function '%s' cannot access __gshared data '%s'", |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
150 sc.func.toChars(), v.toChars()); |
72 | 151 } |
152 } else { | |
153 if (sc.func && sc.func.isPure() && !sc.intypeof) | |
154 { | |
135 | 155 if (v.isDataseg() && !v.isImmutable()) |
72 | 156 error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); |
157 } | |
158 } | |
159 } | |
160 } | |
161 else | |
162 { | |
163 static if (false) { | |
164 if ((fd = var.isFuncLiteralDeclaration()) !is null) | |
165 { | |
166 Expression e = new FuncExp(loc, fd); | |
167 e.type = type; | |
168 return e; | |
169 } | |
170 } | |
171 } | |
172 | |
0 | 173 return this; |
174 } | |
175 | |
72 | 176 override Expression optimize(int result) |
0 | 177 { |
178 return fromConstInitializer(result, this); | |
179 } | |
180 | |
72 | 181 override Expression interpret(InterState istate) |
0 | 182 { |
72 | 183 version (LOG) { |
184 printf("VarExp.interpret() %.*s\n", toChars()); | |
185 } | |
63 | 186 return getVarExp(loc, istate, var); |
0 | 187 } |
188 | |
72 | 189 override void dump(int indent) |
0 | 190 { |
191 assert(false); | |
192 } | |
193 | |
72 | 194 override string toChars() |
0 | 195 { |
196 return var.toChars(); | |
197 } | |
198 | |
72 | 199 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 200 { |
201 buf.writestring(var.toChars()); | |
202 } | |
203 | |
72 | 204 override void checkEscape() |
0 | 205 { |
72 | 206 VarDeclaration v = var.isVarDeclaration(); |
207 if (v) | |
208 { | |
209 Type tb = v.type.toBasetype(); | |
210 // if reference type | |
211 if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass) | |
212 { | |
213 if ((v.isAuto() || v.isScope()) && !v.noauto) | |
214 error("escaping reference to scope local %s", v.toChars()); | |
215 else if (v.storage_class & STC.STCvariadic) | |
216 error("escaping reference to variadic parameter %s", v.toChars()); | |
217 } | |
0 | 218 } |
219 } | |
135 | 220 |
221 override void checkEscapeRef() | |
222 { | |
223 VarDeclaration v = var.isVarDeclaration(); | |
224 if (v) | |
225 { | |
226 if (!v.isDataseg() && !(v.storage_class & (STCref | STCout))) | |
227 error("escaping reference to local variable %s", v.toChars()); | |
228 } | |
229 } | |
72 | 230 |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
231 version (DMDV2) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
232 { |
72 | 233 override int isLvalue() |
0 | 234 { |
72 | 235 if (var.storage_class & STClazy) |
236 return 0; | |
0 | 237 return 1; |
238 } | |
239 } | |
72 | 240 override Expression toLvalue(Scope sc, Expression e) |
0 | 241 { |
72 | 242 static if (false) { |
243 tym = tybasic(e1.ET.Tty); | |
244 if (!(tyscalar(tym) || | |
245 tym == TYM.TYstruct || | |
246 tym == TYM.TYarray && e.Eoper == TOK.TOKaddr)) | |
247 { | |
248 synerr(EM_lvalue); // lvalue expected | |
249 } | |
250 } | |
251 if (var.storage_class & STC.STClazy) | |
252 error("lazy variables cannot be lvalues"); | |
253 | |
0 | 254 return this; |
255 } | |
256 | |
72 | 257 override Expression modifiableLvalue(Scope sc, Expression e) |
0 | 258 { |
72 | 259 //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); |
109 | 260 //if (type && type.toBasetype().ty == TY.Tsarray) |
261 // error("cannot change reference to static array '%s'", var.toChars()); | |
72 | 262 |
263 var.checkModify(loc, sc, type); | |
264 | |
265 // See if this expression is a modifiable lvalue (i.e. not const) | |
0 | 266 return toLvalue(sc, e); |
267 } | |
268 | |
72 | 269 override dt_t** toDt(dt_t** pdt) |
0 | 270 { |
148 | 271 // writef("VarExp::toDt() %d\n", op); |
272 for (; *pdt; pdt = &((*pdt).DTnext)) | |
273 {} | |
274 | |
275 VarDeclaration v = var.isVarDeclaration(); | |
276 if (v && (v.isConst() || v.isImmutable()) && | |
277 type.toBasetype().ty != Tsarray && v.init) | |
278 { | |
279 if (v.inuse) | |
280 { | |
281 error("recursive reference %s", toChars()); | |
282 return pdt; | |
283 } | |
284 v.inuse++; | |
285 *pdt = v.init.toDt(); | |
286 v.inuse--; | |
287 return pdt; | |
288 } | |
289 SymbolDeclaration sd = var.isSymbolDeclaration(); | |
290 if (sd && sd.dsym) | |
291 { | |
292 sd.dsym.toDt(pdt); | |
293 return pdt; | |
294 } | |
295 debug writef("VarExp::toDt(), kind = %s\n", var.kind()); | |
296 | |
297 error("non-constant expression %s", toChars()); | |
298 pdt = dtnzeros(pdt, 1); | |
299 return pdt; | |
0 | 300 } |
301 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
302 version(DMDV1) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
303 override elem* toElem(IRState* irs) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
304 { |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
305 assert(false); |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
306 } |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
307 |
72 | 308 override void scanForNestedRef(Scope sc) |
0 | 309 { |
72 | 310 //printf("VarExp.scanForNestedRef(%s)\n", toChars()); |
311 VarDeclaration v = var.isVarDeclaration(); | |
312 if (v) | |
64 | 313 v.checkNestedReference(sc, Loc(0)); |
0 | 314 } |
315 | |
72 | 316 override int inlineCost(InlineCostState* ics) |
0 | 317 { |
72 | 318 //printf("VarExp.inlineCost() %s\n", toChars()); |
0 | 319 return 1; |
320 } | |
321 | |
72 | 322 override Expression doInline(InlineDoState ids) |
0 | 323 { |
72 | 324 int i; |
325 | |
326 //printf("VarExp.doInline(%s)\n", toChars()); | |
327 for (i = 0; i < ids.from.dim; i++) | |
328 { | |
329 if (var == cast(Declaration)ids.from.data[i]) | |
330 { | |
331 VarExp ve = cast(VarExp)copy(); | |
332 | |
333 ve.var = cast(Declaration)ids.to.data[i]; | |
334 return ve; | |
335 } | |
336 } | |
0 | 337 return this; |
338 } | |
339 } | |
340 |