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