Mercurial > projects > ldc
diff dmd2/clone.c @ 1452:638d16625da2
LDC 2 compiles again.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 30 May 2009 17:23:32 +0100 |
parents | 356e65836fb5 |
children |
line wrap: on
line diff
--- a/dmd2/clone.c Thu May 28 00:07:21 2009 +0200 +++ b/dmd2/clone.c Sat May 30 17:23:32 2009 +0100 @@ -1,437 +1,443 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include <stdio.h> -#include <assert.h> - -#include "root.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" -#include "declaration.h" -#include "module.h" -#include "id.h" -#include "expression.h" -#include "statement.h" -#include "init.h" - - -/******************************************* - * We need an opAssign for the struct if - * it has a destructor or a postblit. - * We need to generate one if a user-specified one does not exist. - */ - -int StructDeclaration::needOpAssign() -{ -#define X 0 - if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars()); - if (hasIdentityAssign) - goto Ldontneed; - - if (dtor || postblit) - goto Lneed; - - /* If any of the fields need an opAssign, then we - * need it too. - */ - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - Type *tv = v->type->toBasetype(); - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->needOpAssign()) - goto Lneed; - } - } -Ldontneed: - if (X) printf("\tdontneed\n"); - return 0; - -Lneed: - if (X) printf("\tneed\n"); - return 1; -#undef X -} - -/****************************************** - * Build opAssign for struct. - * S* opAssign(S s) { ... } - */ - -FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) -{ - if (!needOpAssign()) - return NULL; - - //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); - - FuncDeclaration *fop = NULL; - - Argument *param = new Argument(STCnodtor, type, Id::p, NULL); - Arguments *fparams = new Arguments; - fparams->push(param); - Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd); -#if STRUCTTHISREF - ((TypeFunction *)ftype)->isref = 1; -#endif - - fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype); - - Expression *e = NULL; - if (postblit) - { /* Swap: - * tmp = *this; *this = s; tmp.dtor(); - */ - //printf("\tswap copy\n"); - Identifier *idtmp = Lexer::uniqueId("__tmp"); - VarDeclaration *tmp; - AssignExp *ec = NULL; - if (dtor) - { - tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0)); - tmp->noauto = 1; - e = new DeclarationExp(0, tmp); - ec = new AssignExp(0, - new VarExp(0, tmp), -#if STRUCTTHISREF - new ThisExp(0) -#else - new PtrExp(0, new ThisExp(0)) -#endif - ); - ec->op = TOKblit; - e = Expression::combine(e, ec); - } - ec = new AssignExp(0, -#if STRUCTTHISREF - new ThisExp(0), -#else - new PtrExp(0, new ThisExp(0)), -#endif - new IdentifierExp(0, Id::p)); - ec->op = TOKblit; - e = Expression::combine(e, ec); - if (dtor) - { - /* Instead of running the destructor on s, run it - * on tmp. This avoids needing to copy tmp back in to s. - */ - Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0); - ec = new CallExp(0, ec); - e = Expression::combine(e, ec); - } - } - else - { /* Do memberwise copy - */ - //printf("\tmemberwise copy\n"); - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - // this.v = s.v; - AssignExp *ec = new AssignExp(0, - new DotVarExp(0, new ThisExp(0), v, 0), - new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0)); - ec->op = TOKblit; - e = Expression::combine(e, ec); - } - } - Statement *s1 = new ExpStatement(0, e); - - /* Add: - * return this; - */ - e = new ThisExp(0); - Statement *s2 = new ReturnStatement(0, e); - - fop->fbody = new CompoundStatement(0, s1, s2); - - members->push(fop); - fop->addMember(sc, this, 1); - - sc = sc->push(); - sc->stc = 0; - sc->linkage = LINKd; - - fop->semantic(sc); - - sc->pop(); - - //printf("-StructDeclaration::buildOpAssign() %s\n", toChars()); - - return fop; -} - -/******************************************* - * Build copy constructor for struct. - * Copy constructors are compiler generated only, and are only - * callable from the compiler. They are not user accessible. - * A copy constructor is: - * void cpctpr(ref S s) - * { - * *this = s; - * this.postBlit(); - * } - * This is done so: - * - postBlit() never sees uninitialized data - * - memcpy can be much more efficient than memberwise copy - * - no fields are overlooked - */ - -FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc) -{ - //printf("StructDeclaration::buildCpCtor() %s\n", toChars()); - FuncDeclaration *fcp = NULL; - - /* Copy constructor is only necessary if there is a postblit function, - * otherwise the code generator will just do a bit copy. - */ - if (postblit) - { - //printf("generating cpctor\n"); - - Argument *param = new Argument(STCref, type, Id::p, NULL); - Arguments *fparams = new Arguments; - fparams->push(param); - Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd); - - fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype); - - // Build *this = p; - Expression *e = new ThisExp(0); -#if !STRUCTTHISREF - e = new PtrExp(0, e); -#endif - AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p)); - ea->op = TOKblit; - Statement *s = new ExpStatement(0, ea); - - // Build postBlit(); - e = new VarExp(0, postblit, 0); - e = new CallExp(0, e); - - s = new CompoundStatement(0, s, new ExpStatement(0, e)); - fcp->fbody = s; - - members->push(fcp); - - sc = sc->push(); - sc->stc = 0; - sc->linkage = LINKd; - - fcp->semantic(sc); - - sc->pop(); - } - - return fcp; -} - -/***************************************** - * Create inclusive postblit for struct by aggregating - * all the postblits in postblits[] with the postblits for - * all the members. - * Note the close similarity with AggregateDeclaration::buildDtor(), - * and the ordering changes (runs forward instead of backwards). - */ - -#if DMDV2 -FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) -{ - //printf("StructDeclaration::buildPostBlit() %s\n", toChars()); - Expression *e = NULL; - - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - Type *tv = v->type->toBasetype(); - size_t dim = 1; - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - dim *= ((TypeSArray *)tv)->dim->toInteger(); - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->postblit) - { Expression *ex; - - // this.v - ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); - - if (dim == 1) - { // this.v.dtor() - ex = new DotVarExp(0, ex, sd->postblit, 0); - ex = new CallExp(0, ex); - } - else - { - // Typeinfo.postblit(cast(void*)&this.v); - Expression *ea = new AddrExp(0, ex); - ea = new CastExp(0, ea, Type::tvoid->pointerTo()); - - Expression *et = v->type->getTypeInfo(sc); - et = new DotIdExp(0, et, Id::postblit); - - ex = new CallExp(0, et, ea); - } - e = Expression::combine(e, ex); // combine in forward order - } - } - } - - /* Build our own "postblit" which executes e - */ - if (e) - { //printf("Building __fieldPostBlit()\n"); - PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit")); - dd->fbody = new ExpStatement(0, e); - dtors.push(dd); - members->push(dd); - dd->semantic(sc); - } - - switch (postblits.dim) - { - case 0: - return NULL; - - case 1: - return (FuncDeclaration *)postblits.data[0]; - - default: - e = NULL; - for (size_t i = 0; i < postblits.dim; i++) - { FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i]; - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, fd, 0); - ex = new CallExp(0, ex); - e = Expression::combine(e, ex); - } - PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit")); - dd->fbody = new ExpStatement(0, e); - members->push(dd); - dd->semantic(sc); - return dd; - } -} - -#endif - -/***************************************** - * Create inclusive destructor for struct/class by aggregating - * all the destructors in dtors[] with the destructors for - * all the members. - * Note the close similarity with StructDeclaration::buildPostBlit(), - * and the ordering changes (runs backward instead of forwards). - */ - -FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) -{ - //printf("AggregateDeclaration::buildDtor() %s\n", toChars()); - Expression *e = NULL; - -#if DMDV2 - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - Type *tv = v->type->toBasetype(); - size_t dim = 1; - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - dim *= ((TypeSArray *)tv)->dim->toInteger(); - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->dtor) - { Expression *ex; - - // this.v - ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); - - if (dim == 1) - { // this.v.dtor() - ex = new DotVarExp(0, ex, sd->dtor, 0); - ex = new CallExp(0, ex); - } - else - { - // Typeinfo.destroy(cast(void*)&this.v); - Expression *ea = new AddrExp(0, ex); - ea = new CastExp(0, ea, Type::tvoid->pointerTo()); - - Expression *et = v->type->getTypeInfo(sc); - et = new DotIdExp(0, et, Id::destroy); - - ex = new CallExp(0, et, ea); - } - e = Expression::combine(ex, e); // combine in reverse order - } - } - } - - /* Build our own "destructor" which executes e - */ - if (e) - { //printf("Building __fieldDtor()\n"); - DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor")); - dd->fbody = new ExpStatement(0, e); - dtors.shift(dd); - members->push(dd); - dd->semantic(sc); - } -#endif - - switch (dtors.dim) - { - case 0: - return NULL; - - case 1: - return (FuncDeclaration *)dtors.data[0]; - - default: - e = NULL; - for (size_t i = 0; i < dtors.dim; i++) - { FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i]; - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, fd, 0); - ex = new CallExp(0, ex); - e = Expression::combine(ex, e); - } - DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor")); - dd->fbody = new ExpStatement(0, e); - members->push(dd); - dd->semantic(sc); - return dd; - } -} - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include <stdio.h> +#include <assert.h> + +#include "root.h" +#include "aggregate.h" +#include "scope.h" +#include "mtype.h" +#include "declaration.h" +#include "module.h" +#include "id.h" +#include "expression.h" +#include "statement.h" +#include "init.h" + + +/******************************************* + * We need an opAssign for the struct if + * it has a destructor or a postblit. + * We need to generate one if a user-specified one does not exist. + */ + +int StructDeclaration::needOpAssign() +{ +#define X 0 + if (X) printf("StructDeclaration::needOpAssign() %s\n", toChars()); + if (hasIdentityAssign) + goto Ldontneed; + + if (dtor || postblit) + goto Lneed; + + /* If any of the fields need an opAssign, then we + * need it too. + */ + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + if (v->storage_class & STCref) + continue; + Type *tv = v->type->toBasetype(); + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->needOpAssign()) + goto Lneed; + } + } +Ldontneed: + if (X) printf("\tdontneed\n"); + return 0; + +Lneed: + if (X) printf("\tneed\n"); + return 1; +#undef X +} + +/****************************************** + * Build opAssign for struct. + * S* opAssign(S s) { ... } + */ + +FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) +{ + if (!needOpAssign()) + return NULL; + + //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); + + FuncDeclaration *fop = NULL; + + Argument *param = new Argument(STCnodtor, type, Id::p, NULL); + Arguments *fparams = new Arguments; + fparams->push(param); + Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd); +#if STRUCTTHISREF + ((TypeFunction *)ftype)->isref = 1; +#endif + + fop = new FuncDeclaration(0, 0, Id::assign, STCundefined, ftype); + + Expression *e = NULL; + if (postblit) + { /* Swap: + * tmp = *this; *this = s; tmp.dtor(); + */ + //printf("\tswap copy\n"); + Identifier *idtmp = Lexer::uniqueId("__tmp"); + VarDeclaration *tmp; + AssignExp *ec = NULL; + if (dtor) + { + tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0)); + tmp->noauto = 1; + e = new DeclarationExp(0, tmp); + ec = new AssignExp(0, + new VarExp(0, tmp), +#if STRUCTTHISREF + new ThisExp(0) +#else + new PtrExp(0, new ThisExp(0)) +#endif + ); + ec->op = TOKblit; + e = Expression::combine(e, ec); + } + ec = new AssignExp(0, +#if STRUCTTHISREF + new ThisExp(0), +#else + new PtrExp(0, new ThisExp(0)), +#endif + new IdentifierExp(0, Id::p)); + ec->op = TOKblit; + e = Expression::combine(e, ec); + if (dtor) + { + /* Instead of running the destructor on s, run it + * on tmp. This avoids needing to copy tmp back in to s. + */ + Expression *ec = new DotVarExp(0, new VarExp(0, tmp), dtor, 0); + ec = new CallExp(0, ec); + e = Expression::combine(e, ec); + } + } + else + { /* Do memberwise copy + */ + //printf("\tmemberwise copy\n"); + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + // this.v = s.v; + AssignExp *ec = new AssignExp(0, + new DotVarExp(0, new ThisExp(0), v, 0), + new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0)); + ec->op = TOKblit; + e = Expression::combine(e, ec); + } + } + Statement *s1 = new ExpStatement(0, e); + + /* Add: + * return this; + */ + e = new ThisExp(0); + Statement *s2 = new ReturnStatement(0, e); + + fop->fbody = new CompoundStatement(0, s1, s2); + + members->push(fop); + fop->addMember(sc, this, 1); + + sc = sc->push(); + sc->stc = 0; + sc->linkage = LINKd; + + fop->semantic(sc); + + sc->pop(); + + //printf("-StructDeclaration::buildOpAssign() %s\n", toChars()); + + return fop; +} + +/******************************************* + * Build copy constructor for struct. + * Copy constructors are compiler generated only, and are only + * callable from the compiler. They are not user accessible. + * A copy constructor is: + * void cpctpr(ref S s) + * { + * *this = s; + * this.postBlit(); + * } + * This is done so: + * - postBlit() never sees uninitialized data + * - memcpy can be much more efficient than memberwise copy + * - no fields are overlooked + */ + +FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc) +{ + //printf("StructDeclaration::buildCpCtor() %s\n", toChars()); + FuncDeclaration *fcp = NULL; + + /* Copy constructor is only necessary if there is a postblit function, + * otherwise the code generator will just do a bit copy. + */ + if (postblit) + { + //printf("generating cpctor\n"); + + Argument *param = new Argument(STCref, type, Id::p, NULL); + Arguments *fparams = new Arguments; + fparams->push(param); + Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd); + + fcp = new FuncDeclaration(0, 0, Id::cpctor, STCundefined, ftype); + + // Build *this = p; + Expression *e = new ThisExp(0); +#if !STRUCTTHISREF + e = new PtrExp(0, e); +#endif + AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p)); + ea->op = TOKblit; + Statement *s = new ExpStatement(0, ea); + + // Build postBlit(); + e = new VarExp(0, postblit, 0); + e = new CallExp(0, e); + + s = new CompoundStatement(0, s, new ExpStatement(0, e)); + fcp->fbody = s; + + members->push(fcp); + + sc = sc->push(); + sc->stc = 0; + sc->linkage = LINKd; + + fcp->semantic(sc); + + sc->pop(); + } + + return fcp; +} + +/***************************************** + * Create inclusive postblit for struct by aggregating + * all the postblits in postblits[] with the postblits for + * all the members. + * Note the close similarity with AggregateDeclaration::buildDtor(), + * and the ordering changes (runs forward instead of backwards). + */ + +#if DMDV2 +FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) +{ + //printf("StructDeclaration::buildPostBlit() %s\n", toChars()); + Expression *e = NULL; + + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + if (v->storage_class & STCref) + continue; + Type *tv = v->type->toBasetype(); + size_t dim = 1; + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + dim *= ((TypeSArray *)tv)->dim->toInteger(); + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->postblit) + { Expression *ex; + + // this.v + ex = new ThisExp(0); + ex = new DotVarExp(0, ex, v, 0); + + if (dim == 1) + { // this.v.postblit() + ex = new DotVarExp(0, ex, sd->postblit, 0); + ex = new CallExp(0, ex); + } + else + { + // Typeinfo.postblit(cast(void*)&this.v); + Expression *ea = new AddrExp(0, ex); + ea = new CastExp(0, ea, Type::tvoid->pointerTo()); + + Expression *et = v->type->getTypeInfo(sc); + et = new DotIdExp(0, et, Id::postblit); + + ex = new CallExp(0, et, ea); + } + e = Expression::combine(e, ex); // combine in forward order + } + } + } + + /* Build our own "postblit" which executes e + */ + if (e) + { //printf("Building __fieldPostBlit()\n"); + PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__fieldPostBlit")); + dd->fbody = new ExpStatement(0, e); + postblits.shift(dd); + members->push(dd); + dd->semantic(sc); + } + + switch (postblits.dim) + { + case 0: + return NULL; + + case 1: + return (FuncDeclaration *)postblits.data[0]; + + default: + e = NULL; + for (size_t i = 0; i < postblits.dim; i++) + { FuncDeclaration *fd = (FuncDeclaration *)postblits.data[i]; + Expression *ex = new ThisExp(0); + ex = new DotVarExp(0, ex, fd, 0); + ex = new CallExp(0, ex); + e = Expression::combine(e, ex); + } + PostBlitDeclaration *dd = new PostBlitDeclaration(0, 0, Lexer::idPool("__aggrPostBlit")); + dd->fbody = new ExpStatement(0, e); + members->push(dd); + dd->semantic(sc); + return dd; + } +} + +#endif + +/***************************************** + * Create inclusive destructor for struct/class by aggregating + * all the destructors in dtors[] with the destructors for + * all the members. + * Note the close similarity with StructDeclaration::buildPostBlit(), + * and the ordering changes (runs backward instead of forwards). + */ + +FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) +{ + //printf("AggregateDeclaration::buildDtor() %s\n", toChars()); + Expression *e = NULL; + +#if DMDV2 + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + if (v->storage_class & STCref) + continue; + Type *tv = v->type->toBasetype(); + size_t dim = 1; + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + dim *= ((TypeSArray *)tv)->dim->toInteger(); + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->dtor) + { Expression *ex; + + // this.v + ex = new ThisExp(0); + ex = new DotVarExp(0, ex, v, 0); + + if (dim == 1) + { // this.v.dtor() + ex = new DotVarExp(0, ex, sd->dtor, 0); + ex = new CallExp(0, ex); + } + else + { + // Typeinfo.destroy(cast(void*)&this.v); + Expression *ea = new AddrExp(0, ex); + ea = new CastExp(0, ea, Type::tvoid->pointerTo()); + + Expression *et = v->type->getTypeInfo(sc); + et = new DotIdExp(0, et, Id::destroy); + + ex = new CallExp(0, et, ea); + } + e = Expression::combine(ex, e); // combine in reverse order + } + } + } + + /* Build our own "destructor" which executes e + */ + if (e) + { //printf("Building __fieldDtor()\n"); + DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor")); + dd->fbody = new ExpStatement(0, e); + dtors.shift(dd); + members->push(dd); + dd->semantic(sc); + } +#endif + + switch (dtors.dim) + { + case 0: + return NULL; + + case 1: + return (FuncDeclaration *)dtors.data[0]; + + default: + e = NULL; + for (size_t i = 0; i < dtors.dim; i++) + { FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i]; + Expression *ex = new ThisExp(0); + ex = new DotVarExp(0, ex, fd, 0); + ex = new CallExp(0, ex); + e = Expression::combine(ex, e); + } + DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor")); + dd->fbody = new ExpStatement(0, e); + members->push(dd); + dd->semantic(sc); + return dd; + } +} + +