Mercurial > projects > ddmd
annotate dmd/DeleteExp.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 | af724d3510d7 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.DeleteExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.UnaExp; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.IRState; | |
0 | 11 import dmd.HdrGenState; |
12 import dmd.Type; | |
13 import dmd.IndexExp; | |
174 | 14 import dmd.PREC; |
0 | 15 import dmd.Global; |
16 import dmd.VarExp; | |
17 import dmd.Identifier; | |
18 import dmd.StructDeclaration; | |
19 import dmd.Lexer; | |
20 import dmd.FuncDeclaration; | |
21 import dmd.TypeStruct; | |
22 import dmd.CallExp; | |
23 import dmd.DotVarExp; | |
24 import dmd.DeclarationExp; | |
25 import dmd.ExpInitializer; | |
26 import dmd.VarDeclaration; | |
27 import dmd.TypePointer; | |
28 import dmd.ClassDeclaration; | |
29 import dmd.TypeClass; | |
72 | 30 import dmd.TY; |
0 | 31 import dmd.TOK; |
32 import dmd.TypeAArray; | |
33 import dmd.TypeSArray; | |
34 | |
174 | 35 import dmd.expression.Util; |
0 | 36 import dmd.codegen.Util; |
37 import dmd.backend.Util; | |
38 import dmd.backend.OPER; | |
39 import dmd.backend.RTLSYM; | |
40 import dmd.backend.mTY; | |
41 import dmd.backend.Symbol; | |
72 | 42 import dmd.backend.TYM; |
43 | |
0 | 44 class DeleteExp : UnaExp |
45 { | |
46 this(Loc loc, Expression e) | |
47 { | |
178 | 48 register(); |
0 | 49 super(loc, TOK.TOKdelete, DeleteExp.sizeof, e); |
50 } | |
51 | |
72 | 52 override Expression semantic(Scope sc) |
0 | 53 { |
54 Type tb; | |
55 | |
56 UnaExp.semantic(sc); | |
57 e1 = resolveProperties(sc, e1); | |
58 e1 = e1.toLvalue(sc, null); | |
59 type = Type.tvoid; | |
60 | |
61 tb = e1.type.toBasetype(); | |
62 switch (tb.ty) | |
174 | 63 { |
0 | 64 case Tclass: |
174 | 65 { |
0 | 66 TypeClass tc = cast(TypeClass)tb; |
67 ClassDeclaration cd = tc.sym; | |
68 | |
69 if (cd.isCOMinterface()) | |
70 { /* Because COM classes are deleted by IUnknown.Release() | |
71 */ | |
72 error("cannot delete instance of COM interface %s", cd.toChars()); | |
73 } | |
74 break; | |
75 } | |
76 case Tpointer: | |
77 tb = (cast(TypePointer)tb).next.toBasetype(); | |
78 if (tb.ty == Tstruct) | |
79 { | |
80 TypeStruct ts = cast(TypeStruct)tb; | |
81 StructDeclaration sd = ts.sym; | |
82 FuncDeclaration f = sd.aggDelete; | |
83 FuncDeclaration fd = sd.dtor; | |
84 | |
85 if (!f && !fd) | |
86 break; | |
87 | |
88 /* Construct: | |
89 * ea = copy e1 to a tmp to do side effects only once | |
90 * eb = call destructor | |
91 * ec = call deallocator | |
92 */ | |
93 Expression ea = null; | |
94 Expression eb = null; | |
95 Expression ec = null; | |
96 VarDeclaration v; | |
97 | |
98 if (fd && f) | |
174 | 99 { |
0 | 100 Identifier id = Lexer.idPool("__tmp"); |
101 v = new VarDeclaration(loc, e1.type, id, new ExpInitializer(loc, e1)); | |
102 v.semantic(sc); | |
103 v.parent = sc.parent; | |
104 ea = new DeclarationExp(loc, v); | |
105 ea.type = v.type; | |
106 } | |
107 | |
108 if (fd) | |
174 | 109 { |
0 | 110 Expression e = ea ? new VarExp(loc, v) : e1; |
111 e = new DotVarExp(Loc(0), e, fd, 0); | |
112 eb = new CallExp(loc, e); | |
113 eb = eb.semantic(sc); | |
114 } | |
115 | |
116 if (f) | |
117 { | |
118 Type tpv = Type.tvoid.pointerTo(); | |
119 Expression e = ea ? new VarExp(loc, v) : e1.castTo(sc, tpv); | |
120 e = new CallExp(loc, new VarExp(loc, f), e); | |
121 ec = e.semantic(sc); | |
122 } | |
123 ea = combine(ea, eb); | |
124 ea = combine(ea, ec); | |
125 assert(ea); | |
126 return ea; | |
127 } | |
128 break; | |
129 | |
130 case Tarray: | |
131 /* BUG: look for deleting arrays of structs with dtors. | |
132 */ | |
133 break; | |
134 | |
135 default: | |
136 if (e1.op == TOKindex) | |
137 { | |
138 IndexExp ae = cast(IndexExp)e1; | |
139 Type tb1 = ae.e1.type.toBasetype(); | |
140 if (tb1.ty == Taarray) | |
141 break; | |
142 } | |
143 error("cannot delete type %s", e1.type.toChars()); | |
144 break; | |
145 } | |
174 | 146 |
0 | 147 if (e1.op == TOKindex) |
148 { | |
149 IndexExp ae = cast(IndexExp)e1; | |
150 Type tb1 = ae.e1.type.toBasetype(); | |
151 if (tb1.ty == Taarray) | |
174 | 152 { |
0 | 153 if (!global.params.useDeprecated) |
154 error("delete aa[key] deprecated, use aa.remove(key)"); | |
155 } | |
156 } | |
157 | |
158 return this; | |
159 } | |
160 | |
72 | 161 override Expression checkToBoolean() |
0 | 162 { |
163 assert(false); | |
164 } | |
165 | |
72 | 166 override bool checkSideEffect(int flag) |
0 | 167 { |
168 return true; | |
169 } | |
170 | |
72 | 171 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 172 { |
174 | 173 buf.writestring("delete "); |
174 expToCBuffer(buf, hgs, e1, precedence[op]); | |
0 | 175 } |
176 | |
72 | 177 override elem* toElem(IRState* irs) |
0 | 178 { |
179 elem* e; | |
180 int rtl; | |
181 Type tb; | |
182 | |
183 //printf("DeleteExp.toElem()\n"); | |
184 if (e1.op == TOKindex) | |
185 { | |
186 IndexExp ae = cast(IndexExp)e1; | |
187 tb = ae.e1.type.toBasetype(); | |
188 if (tb.ty == Taarray) | |
189 { | |
190 TypeAArray taa = cast(TypeAArray)tb; | |
191 elem* ea = ae.e1.toElem(irs); | |
192 elem* ekey = ae.e2.toElem(irs); | |
193 elem* ep; | |
194 elem* keyti; | |
195 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
72
diff
changeset
|
196 if (tybasic(ekey.Ety) == TYstruct || tybasic(ekey.Ety) == TYarray) |
0 | 197 { |
198 ekey = el_una(OPstrpar, TYstruct, ekey); | |
199 ekey.Enumbytes = ekey.E1.Enumbytes; | |
200 assert(ekey.Enumbytes); | |
201 } | |
202 | |
203 Symbol *s = taa.aaGetSymbol("Del", 0); | |
204 keyti = taa.index.getInternalTypeInfo(null).toElem(irs); | |
205 ep = el_params(ekey, keyti, ea, null); | |
206 e = el_bin(OPcall, TYnptr, el_var(s), ep); | |
207 goto Lret; | |
208 } | |
209 } | |
210 //e1.type.print(); | |
211 e = e1.toElem(irs); | |
212 tb = e1.type.toBasetype(); | |
213 switch (tb.ty) | |
214 { | |
215 case Tarray: | |
174 | 216 { |
0 | 217 e = addressElem(e, e1.type); |
218 rtl = RTLSYM_DELARRAYT; | |
219 | |
220 /* See if we need to run destructors on the array contents | |
221 */ | |
222 elem *et = null; | |
223 Type tv = tb.nextOf().toBasetype(); | |
224 while (tv.ty == Tsarray) | |
174 | 225 { |
0 | 226 TypeSArray ta = cast(TypeSArray)tv; |
227 tv = tv.nextOf().toBasetype(); | |
228 } | |
229 if (tv.ty == Tstruct) | |
174 | 230 { |
0 | 231 TypeStruct ts = cast(TypeStruct)tv; |
232 StructDeclaration sd = ts.sym; | |
233 if (sd.dtor) | |
234 et = tb.nextOf().getTypeInfo(null).toElem(irs); | |
235 } | |
236 if (!et) // if no destructors needed | |
237 et = el_long(TYnptr, 0); // pass null for TypeInfo | |
238 e = el_params(et, e, null); | |
239 // call _d_delarray_t(e, et); | |
240 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); | |
241 goto Lret; | |
242 } | |
243 case Tclass: | |
244 if (e1.op == TOKvar) | |
174 | 245 { |
0 | 246 VarExp ve = cast(VarExp)e1; |
247 if (ve.var.isVarDeclaration() && | |
248 ve.var.isVarDeclaration().onstack) | |
249 { | |
250 rtl = RTLSYM_CALLFINALIZER; | |
251 if (tb.isClassHandle().isInterfaceDeclaration()) | |
252 rtl = RTLSYM_CALLINTERFACEFINALIZER; | |
253 break; | |
254 } | |
255 } | |
256 e = addressElem(e, e1.type); | |
257 rtl = RTLSYM_DELCLASS; | |
258 if (tb.isClassHandle().isInterfaceDeclaration()) | |
259 rtl = RTLSYM_DELINTERFACE; | |
260 break; | |
261 | |
262 case Tpointer: | |
263 e = addressElem(e, e1.type); | |
264 rtl = RTLSYM_DELMEMORY; | |
265 break; | |
266 | |
267 default: | |
268 assert(0); | |
269 break; | |
270 } | |
271 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); | |
272 | |
273 Lret: | |
274 el_setLoc(e,loc); | |
275 return e; | |
276 } | |
277 } | |
278 |