Mercurial > projects > ddmd
annotate dmd/VarExp.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | e28b18c23469 |
children | af1bebfd96a4 |
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) { | |
73 if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init) | |
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 */ | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
124 if (hasPureParent && v.isDataseg() && !v.isInvariant()) |
72 | 125 { |
126 error("pure function '%s' cannot access mutable static data '%s'", | |
127 sc.func.toChars(), v.toChars()); | |
128 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
129 else if (sc.func.isPure() && sc.parent != v.parent && !v.isInvariant() && !(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 { | |
145 if (v.isDataseg() && !v.isInvariant()) | |
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 } | |
72 | 210 |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
211 version (DMDV2) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
212 { |
72 | 213 override int isLvalue() |
0 | 214 { |
72 | 215 if (var.storage_class & STClazy) |
216 return 0; | |
0 | 217 return 1; |
218 } | |
219 } | |
72 | 220 override Expression toLvalue(Scope sc, Expression e) |
0 | 221 { |
72 | 222 static if (false) { |
223 tym = tybasic(e1.ET.Tty); | |
224 if (!(tyscalar(tym) || | |
225 tym == TYM.TYstruct || | |
226 tym == TYM.TYarray && e.Eoper == TOK.TOKaddr)) | |
227 { | |
228 synerr(EM_lvalue); // lvalue expected | |
229 } | |
230 } | |
231 if (var.storage_class & STC.STClazy) | |
232 error("lazy variables cannot be lvalues"); | |
233 | |
0 | 234 return this; |
235 } | |
236 | |
72 | 237 override Expression modifiableLvalue(Scope sc, Expression e) |
0 | 238 { |
72 | 239 //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); |
109 | 240 //if (type && type.toBasetype().ty == TY.Tsarray) |
241 // error("cannot change reference to static array '%s'", var.toChars()); | |
72 | 242 |
243 var.checkModify(loc, sc, type); | |
244 | |
245 // See if this expression is a modifiable lvalue (i.e. not const) | |
0 | 246 return toLvalue(sc, e); |
247 } | |
248 | |
72 | 249 override dt_t** toDt(dt_t** pdt) |
0 | 250 { |
251 assert(false); | |
252 } | |
253 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
254 version(DMDV1) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
255 override elem* toElem(IRState* irs) |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
256 { |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
257 assert(false); |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
258 } |
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
73
diff
changeset
|
259 |
72 | 260 override void scanForNestedRef(Scope sc) |
0 | 261 { |
72 | 262 //printf("VarExp.scanForNestedRef(%s)\n", toChars()); |
263 VarDeclaration v = var.isVarDeclaration(); | |
264 if (v) | |
64 | 265 v.checkNestedReference(sc, Loc(0)); |
0 | 266 } |
267 | |
72 | 268 override int inlineCost(InlineCostState* ics) |
0 | 269 { |
72 | 270 //printf("VarExp.inlineCost() %s\n", toChars()); |
0 | 271 return 1; |
272 } | |
273 | |
72 | 274 override Expression doInline(InlineDoState ids) |
0 | 275 { |
72 | 276 int i; |
277 | |
278 //printf("VarExp.doInline(%s)\n", toChars()); | |
279 for (i = 0; i < ids.from.dim; i++) | |
280 { | |
281 if (var == cast(Declaration)ids.from.data[i]) | |
282 { | |
283 VarExp ve = cast(VarExp)copy(); | |
284 | |
285 ve.var = cast(Declaration)ids.to.data[i]; | |
286 return ve; | |
287 } | |
288 } | |
0 | 289 return this; |
290 } | |
291 } | |
292 |