Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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