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