Mercurial > projects > ddmd
diff dmd/AnonDeclaration.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | a8b50ff7f201 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/AnonDeclaration.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,169 @@ +module dmd.AnonDeclaration; + +import dmd.OutBuffer; +import dmd.Loc; +import dmd.Scope; +import dmd.Array; +import dmd.AttribDeclaration; +import dmd.HdrGenState; +import dmd.Dsymbol; +import dmd.AggregateDeclaration; +import dmd.AnonymousAggregateDeclaration; +import dmd.STC; +import dmd.Module; +import dmd.VarDeclaration; + +class AnonDeclaration : AttribDeclaration +{ + int isunion; + int sem = 0; // 1 if successful semantic() + + this(Loc loc, int isunion, Array decl) + { + super(decl); + this.loc = loc; + this.isunion = isunion; + } + + Dsymbol syntaxCopy(Dsymbol s) + { + assert(false); + } + + void semantic(Scope sc) + { + //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); + + Scope scx = null; + if (scope_) + { + sc = scope_; + scx = scope_; + scope_ = null; + } + + assert(sc.parent); + + Dsymbol parent = sc.parent.pastMixin(); + AggregateDeclaration ad = parent.isAggregateDeclaration(); + + if (!ad || (!ad.isStructDeclaration() && !ad.isClassDeclaration())) + { + error("can only be a part of an aggregate"); + return; + } + + if (decl) + { + AnonymousAggregateDeclaration aad = new AnonymousAggregateDeclaration(); + int adisunion; + + if (sc.anonAgg) + { + ad = sc.anonAgg; + adisunion = sc.inunion; + } + else + adisunion = ad.isUnionDeclaration() !is null; + + // printf("\tsc.anonAgg = %p\n", sc.anonAgg); + // printf("\tad = %p\n", ad); + // printf("\taad = %p\n", &aad); + + sc = sc.push(); + sc.anonAgg = aad; + sc.stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); + sc.inunion = isunion; + sc.offset = 0; + sc.flags = cast(SCOPE)0; + aad.structalign = sc.structalign; + aad.parent = ad; + + for (uint i = 0; i < decl.dim; i++) + { + Dsymbol s = cast(Dsymbol)decl.data[i]; + + s.semantic(sc); + if (isunion) + sc.offset = 0; + if (aad.sizeok == 2) + break; + } + sc = sc.pop(); + + // If failed due to forward references, unwind and try again later + if (aad.sizeok == 2) + { + ad.sizeok = 2; + //printf("\tsetting ad.sizeok %p to 2\n", ad); + if (!sc.anonAgg) + { + scope_ = scx ? scx : new Scope(sc); ///< + scope_.setNoFree(); + scope_.module_.addDeferredSemantic(this); + } + //printf("\tforward reference %p\n", this); + return; + } + if (sem == 0) + { + Module.dprogress++; + sem = 1; + //printf("\tcompleted %p\n", this); + } + else { + ;//printf("\talready completed %p\n", this); + } + + // 0 sized structs are set to 1 byte + if (aad.structsize == 0) + { + aad.structsize = 1; + aad.alignsize = 1; + } + + // Align size of anonymous aggregate + //printf("aad.structalign = %d, aad.alignsize = %d, sc.offset = %d\n", aad.structalign, aad.alignsize, sc.offset); + ad.alignmember(aad.structalign, aad.alignsize, &sc.offset); + //ad.structsize = sc.offset; + //printf("sc.offset = %d\n", sc.offset); + + // Add members of aad to ad + //printf("\tadding members of aad to '%s'\n", ad.toChars()); + for (uint i = 0; i < aad.fields.dim; i++) + { + VarDeclaration v = cast(VarDeclaration)aad.fields.data[i]; + + v.offset += sc.offset; + ad.fields.push(cast(void*)v); + } + + // Add size of aad to ad + if (adisunion) + { + if (aad.structsize > ad.structsize) + ad.structsize = aad.structsize; + sc.offset = 0; + } + else + { + ad.structsize = sc.offset + aad.structsize; + sc.offset = ad.structsize; + } + + if (ad.alignsize < aad.alignsize) + ad.alignsize = aad.alignsize; + } + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + string kind() + { + assert(false); + } +} +