Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 684 lines (585 sloc) 20.13 kb
3b5f969d »
2009-07-03 dmd 2.011
1
2 // Compiler implementation of the D programming language
952203d7 »
2011-08-07 modernize
3 // Copyright (c) 1999-2011 by Digital Mars
3b5f969d »
2009-07-03 dmd 2.011
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
10
11 #include <stdio.h>
12 #include <assert.h>
13
14 #include "root.h"
15 #include "aggregate.h"
16 #include "scope.h"
17 #include "mtype.h"
18 #include "declaration.h"
19 #include "module.h"
20 #include "id.h"
21 #include "expression.h"
22 #include "statement.h"
23 #include "init.h"
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
24 #include "template.h"
3b5f969d »
2009-07-03 dmd 2.011
25
26
27 /*******************************************
28 * We need an opAssign for the struct if
29 * it has a destructor or a postblit.
30 * We need to generate one if a user-specified one does not exist.
31 */
32
33 int StructDeclaration::needOpAssign()
34 {
35 #define X 0
36 if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars());
37 if (hasIdentityAssign)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
38 goto Ldontneed;
3b5f969d »
2009-07-03 dmd 2.011
39
40 if (dtor || postblit)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
41 goto Lneed;
3b5f969d »
2009-07-03 dmd 2.011
42
43 /* If any of the fields need an opAssign, then we
44 * need it too.
45 */
46 for (size_t i = 0; i < fields.dim; i++)
47 {
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
48 Dsymbol *s = fields.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
49 VarDeclaration *v = s->isVarDeclaration();
50 assert(v && v->storage_class & STCfield);
51 if (v->storage_class & STCref)
52 continue;
53 Type *tv = v->type->toBasetype();
54 while (tv->ty == Tsarray)
55 { TypeSArray *ta = (TypeSArray *)tv;
56 tv = tv->nextOf()->toBasetype();
57 }
58 if (tv->ty == Tstruct)
59 { TypeStruct *ts = (TypeStruct *)tv;
60 StructDeclaration *sd = ts->sym;
61 if (sd->needOpAssign())
62 goto Lneed;
63 }
3b5f969d »
2009-07-03 dmd 2.011
64 }
65 Ldontneed:
66 if (X) printf("\tdontneed\n");
67 return 0;
68
69 Lneed:
70 if (X) printf("\tneed\n");
71 return 1;
72 #undef X
73 }
74
75 /******************************************
76 * Build opAssign for struct.
3addcfba »
2010-03-31 remove tabs, any trailing spaces
77 * S* opAssign(S s) { ... }
e02e2097 »
2010-07-20 64 bit pic and tls
78 *
79 * Note that s will be constructed onto the stack, probably copy-constructed.
80 * Then, the body is:
81 * S tmp = *this; // bit copy
82 * *this = s; // bit copy
83 * tmp.dtor();
84 * Instead of running the destructor on s, run it on tmp instead.
3b5f969d »
2009-07-03 dmd 2.011
85 */
86
87 FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
88 {
89 if (!needOpAssign())
3addcfba »
2010-03-31 remove tabs, any trailing spaces
90 return NULL;
3b5f969d »
2009-07-03 dmd 2.011
91
2633f356 »
2009-07-03 dmd 2.012
92 //printf("StructDeclaration::buildOpAssign() %s\n", toChars());
3b5f969d »
2009-07-03 dmd 2.011
93
94 FuncDeclaration *fop = NULL;
95
a296c324 »
2009-11-19 refactor: Argument => Parameter
96 Parameter *param = new Parameter(STCnodtor, type, Id::p, NULL);
97 Parameters *fparams = new Parameters;
3b5f969d »
2009-07-03 dmd 2.011
98 fparams->push(param);
99 Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd);
2d92a591 »
2009-07-03 dmd 2.021
100 #if STRUCTTHISREF
101 ((TypeFunction *)ftype)->isref = 1;
102 #endif
3b5f969d »
2009-07-03 dmd 2.011
103
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
104 fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype);
3b5f969d »
2009-07-03 dmd 2.011
105
106 Expression *e = NULL;
107 if (postblit)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
108 { /* Swap:
109 * tmp = *this; *this = s; tmp.dtor();
110 */
111 //printf("\tswap copy\n");
112 Identifier *idtmp = Lexer::uniqueId("__tmp");
113 VarDeclaration *tmp;
114 AssignExp *ec = NULL;
115 if (dtor)
116 {
117 tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0));
3b625d5d »
2010-08-28 Issue 2716 - Confusion of auto and scope as the class attribute
118 tmp->noscope = 1;
3addcfba »
2010-03-31 remove tabs, any trailing spaces
119 tmp->storage_class |= STCctfe;
120 e = new DeclarationExp(0, tmp);
121 ec = new AssignExp(0,
122 new VarExp(0, tmp),
2d92a591 »
2009-07-03 dmd 2.021
123 #if STRUCTTHISREF
3addcfba »
2010-03-31 remove tabs, any trailing spaces
124 new ThisExp(0)
2d92a591 »
2009-07-03 dmd 2.021
125 #else
3addcfba »
2010-03-31 remove tabs, any trailing spaces
126 new PtrExp(0, new ThisExp(0))
2d92a591 »
2009-07-03 dmd 2.021
127 #endif
3addcfba »
2010-03-31 remove tabs, any trailing spaces
128 );
129 ec->op = TOKblit;
130 e = Expression::combine(e, ec);
131 }
132 ec = new AssignExp(0,
2d92a591 »
2009-07-03 dmd 2.021
133 #if STRUCTTHISREF
3addcfba »
2010-03-31 remove tabs, any trailing spaces
134 new ThisExp(0),
2d92a591 »
2009-07-03 dmd 2.021
135 #else
3addcfba »
2010-03-31 remove tabs, any trailing spaces
136 new PtrExp(0, new ThisExp(0)),
2d92a591 »
2009-07-03 dmd 2.021
137 #endif
3addcfba »
2010-03-31 remove tabs, any trailing spaces
138 new IdentifierExp(0, Id::p));
139 ec->op = TOKblit;
140 e = Expression::combine(e, ec);
141 if (dtor)
142 {
143 /* Instead of running the destructor on s, run it
144 * on tmp. This avoids needing to copy tmp back in to s.
145 */
952203d7 »
2011-08-07 modernize
146 Expression *ec2 = new DotVarExp(0, new VarExp(0, tmp), dtor, 0);
147 ec2 = new CallExp(0, ec2);
148 e = Expression::combine(e, ec2);
3addcfba »
2010-03-31 remove tabs, any trailing spaces
149 }
3b5f969d »
2009-07-03 dmd 2.011
150 }
151 else
3addcfba »
2010-03-31 remove tabs, any trailing spaces
152 { /* Do memberwise copy
153 */
154 //printf("\tmemberwise copy\n");
155 for (size_t i = 0; i < fields.dim; i++)
156 {
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
157 Dsymbol *s = fields.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
158 VarDeclaration *v = s->isVarDeclaration();
159 assert(v && v->storage_class & STCfield);
160 // this.v = s.v;
161 AssignExp *ec = new AssignExp(0,
162 new DotVarExp(0, new ThisExp(0), v, 0),
163 new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0));
164 ec->op = TOKblit;
165 e = Expression::combine(e, ec);
166 }
3b5f969d »
2009-07-03 dmd 2.011
167 }
168 Statement *s1 = new ExpStatement(0, e);
169
170 /* Add:
171 * return this;
172 */
173 e = new ThisExp(0);
174 Statement *s2 = new ReturnStatement(0, e);
175
176 fop->fbody = new CompoundStatement(0, s1, s2);
177
178 members->push(fop);
179 fop->addMember(sc, this, 1);
180
181 sc = sc->push();
182 sc->stc = 0;
183 sc->linkage = LINKd;
184
185 fop->semantic(sc);
186
187 sc->pop();
188
2633f356 »
2009-07-03 dmd 2.012
189 //printf("-StructDeclaration::buildOpAssign() %s\n", toChars());
3b5f969d »
2009-07-03 dmd 2.011
190
191 return fop;
192 }
193
8c13b5b2 »
2011-09-07 Stop too much strict opEquals signature checking
194 /*******************************************
195 * We need an opEquals for the struct if
196 * any fields has an opEquals.
197 * Generate one if a user-specified one does not exist.
198 */
199
200 int StructDeclaration::needOpEquals()
201 {
202 #define X 0
203 if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars());
204
96e755e7 »
2011-09-07 Separate between xopEquals and identity opEquals
205 if (hasIdentityEquals)
206 goto Lneed;
207
8c13b5b2 »
2011-09-07 Stop too much strict opEquals signature checking
208 /* If any of the fields has an opEquals, then we
209 * need it too.
210 */
211 for (size_t i = 0; i < fields.dim; i++)
212 {
213 Dsymbol *s = fields.tdata()[i];
214 VarDeclaration *v = s->isVarDeclaration();
215 assert(v && v->storage_class & STCfield);
216 if (v->storage_class & STCref)
217 continue;
218 Type *tv = v->type->toBasetype();
219 while (tv->ty == Tsarray)
220 { TypeSArray *ta = (TypeSArray *)tv;
221 tv = tv->nextOf()->toBasetype();
222 }
223 if (tv->ty == Tstruct)
224 { TypeStruct *ts = (TypeStruct *)tv;
225 StructDeclaration *sd = ts->sym;
96e755e7 »
2011-09-07 Separate between xopEquals and identity opEquals
226 if (sd->needOpEquals())
8c13b5b2 »
2011-09-07 Stop too much strict opEquals signature checking
227 goto Lneed;
228 }
229 }
230 if (X) printf("\tdontneed\n");
231 return 0;
232
233 Lneed:
234 if (X) printf("\tneed\n");
235 return 1;
236 #undef X
237 }
238
a958605b »
2009-11-22 bugzilla 3433
239 /******************************************
240 * Build opEquals for struct.
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
241 * const bool opEquals(const S s) { ... }
a958605b »
2009-11-22 bugzilla 3433
242 */
243
244 FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
245 {
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
246 Dsymbol *eq = search_function(this, Id::eq);
247 if (eq)
248 {
249 for (size_t i = 0; i <= 1; i++)
250 {
251 Expression *e =
252 i == 0 ? new NullExp(loc, type->constOf()) // dummy rvalue
253 : type->constOf()->defaultInit(); // dummy lvalue
254 Expressions *arguments = new Expressions();
255 arguments->push(e);
256
257 // check identity opEquals exists
258 FuncDeclaration *fd = eq->isFuncDeclaration();
259 if (fd)
260 { fd = fd->overloadResolve(loc, e, arguments, 1);
261 if (fd && !(fd->storage_class & STCdisable))
262 return fd;
263 }
264
265 TemplateDeclaration *td = eq->isTemplateDeclaration();
266 if (td)
267 { fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1);
268 if (fd && !(fd->storage_class & STCdisable))
269 return fd;
270 }
271 }
272 return NULL;
273 }
274
a958605b »
2009-11-22 bugzilla 3433
275 if (!needOpEquals())
3addcfba »
2010-03-31 remove tabs, any trailing spaces
276 return NULL;
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
277
a958605b »
2009-11-22 bugzilla 3433
278 //printf("StructDeclaration::buildOpEquals() %s\n", toChars());
279
280 Parameters *parameters = new Parameters;
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
281 parameters->push(new Parameter(STCin, type, Id::p, NULL));
282 TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
283 tf->mod = MODconst;
284 tf = (TypeFunction *)tf->semantic(loc, sc);
a958605b »
2009-11-22 bugzilla 3433
285
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
286 FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, tf);
a958605b »
2009-11-22 bugzilla 3433
287
288 Expression *e = NULL;
289 /* Do memberwise compare
290 */
291 //printf("\tmemberwise compare\n");
292 for (size_t i = 0; i < fields.dim; i++)
293 {
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
294 Dsymbol *s = fields.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
295 VarDeclaration *v = s->isVarDeclaration();
296 assert(v && v->storage_class & STCfield);
297 if (v->storage_class & STCref)
298 assert(0); // what should we do with this?
299 // this.v == s.v;
300 EqualExp *ec = new EqualExp(TOKequal, loc,
301 new DotVarExp(loc, new ThisExp(loc), v, 0),
302 new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0));
303 if (e)
304 e = new AndAndExp(loc, e, ec);
305 else
306 e = ec;
a958605b »
2009-11-22 bugzilla 3433
307 }
308 if (!e)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
309 e = new IntegerExp(loc, 1, Type::tbool);
a958605b »
2009-11-22 bugzilla 3433
310 fop->fbody = new ReturnStatement(loc, e);
311
312 members->push(fop);
313 fop->addMember(sc, this, 1);
314
315 sc = sc->push();
316 sc->stc = 0;
317 sc->linkage = LINKd;
318
319 fop->semantic(sc);
320
321 sc->pop();
322
323 //printf("-StructDeclaration::buildOpEquals() %s\n", toChars());
324
325 return fop;
326 }
327
58d73c56 »
2011-09-07 Fix buildOpEquals and add buildXopEquals
328 /******************************************
329 * Build __xopEquals for TypeInfo_Struct
330 * bool __xopEquals(in void* p, in void* q) { ... }
331 */
332
333 FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
334 {
335 if (!search_function(this, Id::eq))
336 return NULL;
337
338 /* static bool__xopEquals(in void* p, in void* q) {
339 * return ( *cast(const S*)(p) ).opEquals( *cast(const S*)(q) );
340 * }
341 */
342
343 Parameters *parameters = new Parameters;
344 parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL));
345 parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL));
346 TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
347 tf = (TypeFunction *)tf->semantic(loc, sc);
348
349 Identifier *id = Lexer::idPool("__xopEquals");
350 FuncDeclaration *fop = new FuncDeclaration(loc, 0, id, STCstatic, tf);
351
352 Expression *e = new CallExp(0,
353 new DotIdExp(0,
354 new PtrExp(0, new CastExp(0,
355 new IdentifierExp(0, Id::p), type->pointerTo()->constOf())),
356 Id::eq),
357 new PtrExp(0, new CastExp(0,
358 new IdentifierExp(0, Id::q), type->pointerTo()->constOf())));
359
360 fop->fbody = new ReturnStatement(loc, e);
361
362 size_t index = members->dim;
363 members->push(fop);
364
365 sc = sc->push();
366 sc->stc = 0;
367 sc->linkage = LINKd;
368
369 unsigned errors = global.startGagging();
370 fop->semantic(sc);
371 if (errors == global.gaggedErrors)
372 { fop->semantic2(sc);
373 if (errors == global.gaggedErrors)
374 { fop->semantic3(sc);
375 if (errors == global.gaggedErrors)
376 fop->addMember(sc, this, 1);
377 }
378 }
379 if (global.endGagging(errors)) // if errors happened
380 {
381 members->remove(index);
382
383 if (!xerreq)
384 {
385 Expression *e = new IdentifierExp(loc, Id::empty);
386 e = new DotIdExp(loc, e, Id::object);
387 e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
388 e = e->semantic(sc);
389 Dsymbol *s = getDsymbol(e);
390 FuncDeclaration *fd = s->isFuncDeclaration();
391
392 xerreq = fd;
393 }
394 fop = xerreq;
395 }
396
397 sc->pop();
398
399 return fop;
400 }
401
a958605b »
2009-11-22 bugzilla 3433
402
3b5f969d »
2009-07-03 dmd 2.011
403 /*******************************************
404 * Build copy constructor for struct.
405 * Copy constructors are compiler generated only, and are only
406 * callable from the compiler. They are not user accessible.
407 * A copy constructor is:
408 * void cpctpr(ref S s)
409 * {
3addcfba »
2010-03-31 remove tabs, any trailing spaces
410 * *this = s;
411 * this.postBlit();
3b5f969d »
2009-07-03 dmd 2.011
412 * }
413 * This is done so:
3addcfba »
2010-03-31 remove tabs, any trailing spaces
414 * - postBlit() never sees uninitialized data
415 * - memcpy can be much more efficient than memberwise copy
416 * - no fields are overlooked
3b5f969d »
2009-07-03 dmd 2.011
417 */
418
419 FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
420 {
421 //printf("StructDeclaration::buildCpCtor() %s\n", toChars());
422 FuncDeclaration *fcp = NULL;
423
424 /* Copy constructor is only necessary if there is a postblit function,
425 * otherwise the code generator will just do a bit copy.
426 */
427 if (postblit)
428 {
3addcfba »
2010-03-31 remove tabs, any trailing spaces
429 //printf("generating cpctor\n");
3b5f969d »
2009-07-03 dmd 2.011
430
3addcfba »
2010-03-31 remove tabs, any trailing spaces
431 Parameter *param = new Parameter(STCref, type, Id::p, NULL);
432 Parameters *fparams = new Parameters;
433 fparams->push(param);
434 Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
3b5f969d »
2009-07-03 dmd 2.011
435
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
436 fcp = new FuncDeclaration(loc, 0, Id::cpctor, STCundefined, ftype);
3addcfba »
2010-03-31 remove tabs, any trailing spaces
437 fcp->storage_class |= postblit->storage_class & STCdisable;
3b5f969d »
2009-07-03 dmd 2.011
438
1d865ec9 »
2011-06-04 rewrite of pull 66
439 if (!(fcp->storage_class & STCdisable))
440 {
441 // Build *this = p;
442 Expression *e = new ThisExp(0);
2d92a591 »
2009-07-03 dmd 2.021
443 #if !STRUCTTHISREF
1d865ec9 »
2011-06-04 rewrite of pull 66
444 e = new PtrExp(0, e);
2d92a591 »
2009-07-03 dmd 2.021
445 #endif
1d865ec9 »
2011-06-04 rewrite of pull 66
446 AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
447 ea->op = TOKblit;
448 Statement *s = new ExpStatement(0, ea);
3b5f969d »
2009-07-03 dmd 2.011
449
1d865ec9 »
2011-06-04 rewrite of pull 66
450 // Build postBlit();
451 e = new VarExp(0, postblit, 0);
452 e = new CallExp(0, e);
3b5f969d »
2009-07-03 dmd 2.011
453
1d865ec9 »
2011-06-04 rewrite of pull 66
454 s = new CompoundStatement(0, s, new ExpStatement(0, e));
455 fcp->fbody = s;
456 }
457 else
458 fcp->fbody = new ExpStatement(0, (Expression *)NULL);
3b5f969d »
2009-07-03 dmd 2.011
459
3addcfba »
2010-03-31 remove tabs, any trailing spaces
460 members->push(fcp);
3b5f969d »
2009-07-03 dmd 2.011
461
3addcfba »
2010-03-31 remove tabs, any trailing spaces
462 sc = sc->push();
463 sc->stc = 0;
464 sc->linkage = LINKd;
3b5f969d »
2009-07-03 dmd 2.011
465
3addcfba »
2010-03-31 remove tabs, any trailing spaces
466 fcp->semantic(sc);
3b5f969d »
2009-07-03 dmd 2.011
467
3addcfba »
2010-03-31 remove tabs, any trailing spaces
468 sc->pop();
3b5f969d »
2009-07-03 dmd 2.011
469 }
470
471 return fcp;
472 }
473
474 /*****************************************
475 * Create inclusive postblit for struct by aggregating
476 * all the postblits in postblits[] with the postblits for
477 * all the members.
478 * Note the close similarity with AggregateDeclaration::buildDtor(),
479 * and the ordering changes (runs forward instead of backwards).
480 */
481
f77efd17 »
2009-07-03 dmd 2.027
482 #if DMDV2
3b5f969d »
2009-07-03 dmd 2.011
483 FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc)
484 {
485 //printf("StructDeclaration::buildPostBlit() %s\n", toChars());
486 Expression *e = NULL;
b1efa686 »
2010-01-14 add @disable attribute
487 StorageClass stc = 0;
3b5f969d »
2009-07-03 dmd 2.011
488
489 for (size_t i = 0; i < fields.dim; i++)
490 {
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
491 Dsymbol *s = fields.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
492 VarDeclaration *v = s->isVarDeclaration();
493 assert(v && v->storage_class & STCfield);
494 if (v->storage_class & STCref)
495 continue;
496 Type *tv = v->type->toBasetype();
952203d7 »
2011-08-07 modernize
497 dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
3addcfba »
2010-03-31 remove tabs, any trailing spaces
498 while (tv->ty == Tsarray)
499 { TypeSArray *ta = (TypeSArray *)tv;
500 dim *= ((TypeSArray *)tv)->dim->toInteger();
501 tv = tv->nextOf()->toBasetype();
502 }
503 if (tv->ty == Tstruct)
504 { TypeStruct *ts = (TypeStruct *)tv;
505 StructDeclaration *sd = ts->sym;
506 if (sd->postblit)
1d865ec9 »
2011-06-04 rewrite of pull 66
507 {
3addcfba »
2010-03-31 remove tabs, any trailing spaces
508 stc |= sd->postblit->storage_class & STCdisable;
509
1d865ec9 »
2011-06-04 rewrite of pull 66
510 if (stc & STCdisable)
511 {
512 e = NULL;
513 break;
514 }
515
3addcfba »
2010-03-31 remove tabs, any trailing spaces
516 // this.v
1d865ec9 »
2011-06-04 rewrite of pull 66
517 Expression *ex = new ThisExp(0);
3addcfba »
2010-03-31 remove tabs, any trailing spaces
518 ex = new DotVarExp(0, ex, v, 0);
519
f9ee7522 »
2011-06-20 Issue 5574 - Struct destructor freaks out when an array of struct wit…
520 if (dim == 0)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
521 { // this.v.postblit()
522 ex = new DotVarExp(0, ex, sd->postblit, 0);
523 ex = new CallExp(0, ex);
524 }
525 else
526 {
527 // Typeinfo.postblit(cast(void*)&this.v);
528 Expression *ea = new AddrExp(0, ex);
529 ea = new CastExp(0, ea, Type::tvoid->pointerTo());
530
531 Expression *et = v->type->getTypeInfo(sc);
532 et = new DotIdExp(0, et, Id::postblit);
533
534 ex = new CallExp(0, et, ea);
535 }
536 e = Expression::combine(e, ex); // combine in forward order
537 }
538 }
3b5f969d »
2009-07-03 dmd 2.011
539 }
540
541 /* Build our own "postblit" which executes e
542 */
1d865ec9 »
2011-06-04 rewrite of pull 66
543 if (e || (stc & STCdisable))
3addcfba »
2010-03-31 remove tabs, any trailing spaces
544 { //printf("Building __fieldPostBlit()\n");
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
545 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__fieldPostBlit"));
3addcfba »
2010-03-31 remove tabs, any trailing spaces
546 dd->storage_class |= stc;
547 dd->fbody = new ExpStatement(0, e);
548 postblits.shift(dd);
549 members->push(dd);
550 dd->semantic(sc);
3b5f969d »
2009-07-03 dmd 2.011
551 }
552
553 switch (postblits.dim)
554 {
3addcfba »
2010-03-31 remove tabs, any trailing spaces
555 case 0:
556 return NULL;
557
558 case 1:
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
559 return postblits.tdata()[0];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
560
561 default:
562 e = NULL;
563 for (size_t i = 0; i < postblits.dim; i++)
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
564 { FuncDeclaration *fd = postblits.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
565 stc |= fd->storage_class & STCdisable;
1d865ec9 »
2011-06-04 rewrite of pull 66
566 if (stc & STCdisable)
567 {
568 e = NULL;
569 break;
570 }
3addcfba »
2010-03-31 remove tabs, any trailing spaces
571 Expression *ex = new ThisExp(0);
572 ex = new DotVarExp(0, ex, fd, 0);
573 ex = new CallExp(0, ex);
574 e = Expression::combine(e, ex);
575 }
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
576 PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, Lexer::idPool("__aggrPostBlit"));
3addcfba »
2010-03-31 remove tabs, any trailing spaces
577 dd->storage_class |= stc;
578 dd->fbody = new ExpStatement(0, e);
579 members->push(dd);
580 dd->semantic(sc);
581 return dd;
3b5f969d »
2009-07-03 dmd 2.011
582 }
583 }
584
585 #endif
586
587 /*****************************************
588 * Create inclusive destructor for struct/class by aggregating
589 * all the destructors in dtors[] with the destructors for
590 * all the members.
591 * Note the close similarity with StructDeclaration::buildPostBlit(),
592 * and the ordering changes (runs backward instead of forwards).
593 */
594
595 FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
596 {
597 //printf("AggregateDeclaration::buildDtor() %s\n", toChars());
598 Expression *e = NULL;
599
f77efd17 »
2009-07-03 dmd 2.027
600 #if DMDV2
3b5f969d »
2009-07-03 dmd 2.011
601 for (size_t i = 0; i < fields.dim; i++)
602 {
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
603 Dsymbol *s = fields.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
604 VarDeclaration *v = s->isVarDeclaration();
605 assert(v && v->storage_class & STCfield);
606 if (v->storage_class & STCref)
607 continue;
608 Type *tv = v->type->toBasetype();
952203d7 »
2011-08-07 modernize
609 dinteger_t dim = (tv->ty == Tsarray ? 1 : 0);
3addcfba »
2010-03-31 remove tabs, any trailing spaces
610 while (tv->ty == Tsarray)
611 { TypeSArray *ta = (TypeSArray *)tv;
612 dim *= ((TypeSArray *)tv)->dim->toInteger();
613 tv = tv->nextOf()->toBasetype();
614 }
615 if (tv->ty == Tstruct)
616 { TypeStruct *ts = (TypeStruct *)tv;
617 StructDeclaration *sd = ts->sym;
618 if (sd->dtor)
619 { Expression *ex;
620
621 // this.v
622 ex = new ThisExp(0);
623 ex = new DotVarExp(0, ex, v, 0);
624
f9ee7522 »
2011-06-20 Issue 5574 - Struct destructor freaks out when an array of struct wit…
625 if (dim == 0)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
626 { // this.v.dtor()
627 ex = new DotVarExp(0, ex, sd->dtor, 0);
628 ex = new CallExp(0, ex);
629 }
630 else
631 {
632 // Typeinfo.destroy(cast(void*)&this.v);
633 Expression *ea = new AddrExp(0, ex);
634 ea = new CastExp(0, ea, Type::tvoid->pointerTo());
635
636 Expression *et = v->type->getTypeInfo(sc);
637 et = new DotIdExp(0, et, Id::destroy);
638
639 ex = new CallExp(0, et, ea);
640 }
641 e = Expression::combine(ex, e); // combine in reverse order
642 }
643 }
3b5f969d »
2009-07-03 dmd 2.011
644 }
645
646 /* Build our own "destructor" which executes e
647 */
648 if (e)
3addcfba »
2010-03-31 remove tabs, any trailing spaces
649 { //printf("Building __fieldDtor()\n");
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
650 DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor"));
3addcfba »
2010-03-31 remove tabs, any trailing spaces
651 dd->fbody = new ExpStatement(0, e);
652 dtors.shift(dd);
653 members->push(dd);
654 dd->semantic(sc);
3b5f969d »
2009-07-03 dmd 2.011
655 }
656 #endif
657
658 switch (dtors.dim)
659 {
3addcfba »
2010-03-31 remove tabs, any trailing spaces
660 case 0:
661 return NULL;
662
663 case 1:
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
664 return dtors.tdata()[0];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
665
666 default:
667 e = NULL;
668 for (size_t i = 0; i < dtors.dim; i++)
9859b1b7 »
2011-07-05 Made use of type-checked array accessors mandatory, adapted code at c…
669 { FuncDeclaration *fd = dtors.tdata()[i];
3addcfba »
2010-03-31 remove tabs, any trailing spaces
670 Expression *ex = new ThisExp(0);
671 ex = new DotVarExp(0, ex, fd, 0);
672 ex = new CallExp(0, ex);
673 e = Expression::combine(ex, e);
674 }
965314fe »
2011-03-09 Fix several bugs with respect to dwarf file info:
675 DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor"));
3addcfba »
2010-03-31 remove tabs, any trailing spaces
676 dd->fbody = new ExpStatement(0, e);
677 members->push(dd);
678 dd->semantic(sc);
679 return dd;
3b5f969d »
2009-07-03 dmd 2.011
680 }
681 }
682
683
Something went wrong with that request. Please try again.