0
|
1 module dmd.VarExp;
|
|
2
|
|
3 import dmd.Expression;
|
|
4 import dmd.Declaration;
|
|
5 import dmd.InterState;
|
|
6 import dmd.OutBuffer;
|
|
7 import dmd.Loc;
|
|
8 import dmd.Scope;
|
|
9 import dmd.InlineCostState;
|
|
10 import dmd.FuncLiteralDeclaration;
|
|
11 import dmd.VarDeclaration;
|
|
12 import dmd.Dsymbol;
|
|
13 import dmd.FuncDeclaration;
|
|
14 import dmd.InlineDoState;
|
|
15 import dmd.HdrGenState;
|
|
16 import dmd.TOK;
|
|
17 import dmd.TY;
|
|
18 import dmd.STC;
|
|
19 import dmd.SymbolExp;
|
|
20 import dmd.Type;
|
|
21 import dmd.backend.dt_t;
|
|
22 import dmd.expression.Util;
|
|
23
|
|
24 // Variable
|
|
25
|
|
26 class VarExp : SymbolExp
|
|
27 {
|
|
28 this(Loc loc, Declaration var, int hasOverloads = 0)
|
|
29 {
|
|
30 super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads);
|
|
31
|
|
32 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
|
|
33 //if (strcmp(var.ident.toChars(), "func") == 0) halt();
|
|
34 this.type = var.type;
|
|
35 }
|
|
36
|
45
|
37 bool equals(Object o)
|
0
|
38 {
|
|
39 assert(false);
|
|
40 }
|
|
41
|
|
42 Expression semantic(Scope sc)
|
|
43 {
|
|
44 FuncLiteralDeclaration fd;
|
|
45
|
|
46 version (LOGSEMANTIC) {
|
|
47 printf("VarExp.semantic(%s)\n", toChars());
|
|
48 }
|
|
49 if (!type)
|
|
50 {
|
|
51 type = var.type;
|
|
52 static if (false) {
|
|
53 if (var.storage_class & STC.STClazy)
|
|
54 {
|
|
55 TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd);
|
|
56 type = new TypeDelegate(tf);
|
|
57 type = type.semantic(loc, sc);
|
|
58 }
|
|
59 }
|
|
60 }
|
|
61
|
|
62 /* Fix for 1161 doesn't work because it causes protection
|
|
63 * problems when instantiating imported templates passing private
|
|
64 * variables as alias template parameters.
|
|
65 */
|
|
66 //accessCheck(loc, sc, null, var);
|
|
67
|
|
68 VarDeclaration v = var.isVarDeclaration();
|
|
69 if (v)
|
|
70 {
|
|
71 static if (false) {
|
|
72 if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init)
|
|
73 {
|
|
74 ExpInitializer ei = v.init.isExpInitializer();
|
|
75 if (ei)
|
|
76 {
|
|
77 //ei.exp.implicitCastTo(sc, type).print();
|
|
78 return ei.exp.implicitCastTo(sc, type);
|
|
79 }
|
|
80 }
|
|
81 }
|
|
82 v.checkNestedReference(sc, loc);
|
|
83 version (DMDV2) {
|
|
84 static if (true) {
|
|
85 if (sc.func)
|
|
86 {
|
|
87 /* Determine if sc.func is pure or if any function that
|
|
88 * encloses it is also pure.
|
|
89 */
|
|
90 bool hasPureParent = false;
|
|
91 for (FuncDeclaration outerfunc = sc.func; outerfunc;)
|
|
92 {
|
|
93 if (outerfunc.isPure())
|
|
94 {
|
|
95 hasPureParent = true;
|
|
96 break;
|
|
97 }
|
|
98 Dsymbol parent = outerfunc.toParent2();
|
|
99 if (!parent)
|
|
100 break;
|
|
101 outerfunc = parent.isFuncDeclaration();
|
|
102 }
|
|
103
|
|
104 /* If ANY of its enclosing functions are pure,
|
|
105 * it cannot do anything impure.
|
|
106 * If it is pure, it cannot access any mutable variables other
|
|
107 * than those inside itself
|
|
108 */
|
|
109 if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant())
|
|
110 {
|
|
111 error("pure function '%s' cannot access mutable static data '%s'",
|
|
112 sc.func.toChars(), v.toChars());
|
|
113 }
|
|
114 else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest))
|
|
115 {
|
|
116 error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars());
|
|
117 if (v.isEnumDeclaration())
|
|
118 error("enum");
|
|
119 }
|
|
120 }
|
|
121 } else {
|
|
122 if (sc.func && sc.func.isPure() && !sc.intypeof)
|
|
123 {
|
|
124 if (v.isDataseg() && !v.isInvariant())
|
|
125 error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars());
|
|
126 }
|
|
127 }
|
|
128 }
|
|
129 }
|
|
130 else
|
|
131 {
|
|
132 static if (false) {
|
|
133 if ((fd = var.isFuncLiteralDeclaration()) !is null)
|
|
134 {
|
|
135 Expression e = new FuncExp(loc, fd);
|
|
136 e.type = type;
|
|
137 return e;
|
|
138 }
|
|
139 }
|
|
140 }
|
|
141
|
|
142 return this;
|
|
143 }
|
|
144
|
|
145 Expression optimize(int result)
|
|
146 {
|
|
147 return fromConstInitializer(result, this);
|
|
148 }
|
|
149
|
|
150 Expression interpret(InterState* istate)
|
|
151 {
|
|
152 assert(false);
|
|
153 }
|
|
154
|
|
155 void dump(int indent)
|
|
156 {
|
|
157 assert(false);
|
|
158 }
|
|
159
|
|
160 string toChars()
|
|
161 {
|
|
162 return var.toChars();
|
|
163 }
|
|
164
|
|
165 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
|
166 {
|
|
167 buf.writestring(var.toChars());
|
|
168 }
|
|
169
|
|
170 void checkEscape()
|
|
171 {
|
|
172 VarDeclaration v = var.isVarDeclaration();
|
|
173 if (v)
|
|
174 {
|
|
175 Type tb = v.type.toBasetype();
|
|
176 // if reference type
|
|
177 if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass)
|
|
178 {
|
|
179 if ((v.isAuto() || v.isScope()) && !v.noauto)
|
|
180 error("escaping reference to scope local %s", v.toChars());
|
|
181 else if (v.storage_class & STC.STCvariadic)
|
|
182 error("escaping reference to variadic parameter %s", v.toChars());
|
|
183 }
|
|
184 }
|
|
185 }
|
|
186
|
|
187 version (DMDV2) {
|
|
188 int isLvalue()
|
|
189 {
|
|
190 if (var.storage_class & STClazy)
|
|
191 return 0;
|
|
192 return 1;
|
|
193 }
|
|
194 }
|
|
195 Expression toLvalue(Scope sc, Expression e)
|
|
196 {
|
|
197 static if (false) {
|
|
198 tym = tybasic(e1.ET.Tty);
|
|
199 if (!(tyscalar(tym) ||
|
|
200 tym == TYM.TYstruct ||
|
|
201 tym == TYM.TYarray && e.Eoper == TOK.TOKaddr))
|
|
202 {
|
|
203 synerr(EM_lvalue); // lvalue expected
|
|
204 }
|
|
205 }
|
|
206 if (var.storage_class & STC.STClazy)
|
|
207 error("lazy variables cannot be lvalues");
|
|
208
|
|
209 return this;
|
|
210 }
|
|
211
|
|
212 Expression modifiableLvalue(Scope sc, Expression e)
|
|
213 {
|
|
214 //printf("VarExp::modifiableLvalue('%s')\n", var.toChars());
|
|
215 if (type && type.toBasetype().ty == TY.Tsarray)
|
|
216 error("cannot change reference to static array '%s'", var.toChars());
|
|
217
|
|
218 var.checkModify(loc, sc, type);
|
|
219
|
|
220 // See if this expression is a modifiable lvalue (i.e. not const)
|
|
221 return toLvalue(sc, e);
|
|
222 }
|
|
223
|
|
224 dt_t** toDt(dt_t** pdt)
|
|
225 {
|
|
226 assert(false);
|
|
227 }
|
|
228
|
|
229 void scanForNestedRef(Scope sc)
|
|
230 {
|
|
231 assert(false);
|
|
232 }
|
|
233
|
|
234 int inlineCost(InlineCostState* ics)
|
|
235 {
|
|
236 //printf("VarExp.inlineCost() %s\n", toChars());
|
|
237 return 1;
|
|
238 }
|
|
239
|
|
240 Expression doInline(InlineDoState ids)
|
|
241 {
|
|
242 int i;
|
|
243
|
|
244 //printf("VarExp.doInline(%s)\n", toChars());
|
|
245 for (i = 0; i < ids.from.dim; i++)
|
|
246 {
|
|
247 if (var == cast(Declaration)ids.from.data[i])
|
|
248 {
|
|
249 VarExp ve = cast(VarExp)copy();
|
|
250
|
|
251 ve.var = cast(Declaration)ids.to.data[i];
|
|
252 return ve;
|
|
253 }
|
|
254 }
|
|
255 return this;
|
|
256 }
|
|
257 }
|
|
258
|