diff dmd/struct.c @ 1587:def7a1d494fd

Merge DMD 1.051
author Christian Kamm <kamm incasoftware de>
date Fri, 06 Nov 2009 23:58:01 +0100
parents d9c5f5a43403
children 207a8a438dea
line wrap: on
line diff
--- a/dmd/struct.c	Fri Nov 06 21:51:41 2009 +0100
+++ b/dmd/struct.c	Fri Nov 06 23:58:01 2009 +0100
@@ -1,520 +1,520 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2009 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 "statement.h"
-
-/********************************* AggregateDeclaration ****************************/
-
-AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
-    : ScopeDsymbol(id)
-{
-    this->loc = loc;
-
-    storage_class = 0;
-    protection = PROTpublic;
-    type = NULL;
-    handle = NULL;
-    structsize = 0;		// size of struct
-    alignsize = 0;		// size of struct for alignment purposes
-    structalign = 0;		// struct member alignment in effect
-    hasUnions = 0;
-    sizeok = 0;			// size not determined yet
-    isdeprecated = 0;
-    inv = NULL;
-    aggNew = NULL;
-    aggDelete = NULL;
-
-#if IN_DMD
-    stag = NULL;
-    sinit = NULL;
-#endif
-    scope = NULL;
-#if DMDV2
-    dtor = NULL;
-
-    ctor = NULL;
-    defaultCtor = NULL;
-#endif
-
-#if IN_LLVM
-    availableExternally = true; // assume this unless proven otherwise
-#endif
-}
-
-enum PROT AggregateDeclaration::prot()
-{
-    return protection;
-}
-
-void AggregateDeclaration::semantic2(Scope *sc)
-{
-    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
-    if (scope)
-    {	error("has forward references");
-	return;
-    }
-    if (members)
-    {
-	sc = sc->push(this);
-	for (size_t i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic2(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::semantic3(Scope *sc)
-{   int i;
-
-    // LDC
-    if (!global.params.useAvailableExternally)
-        availableExternally = false;
-
-    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
-    if (members)
-    {
-	sc = sc->push(this);
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    s->semantic3(sc);
-	}
-	sc->pop();
-    }
-}
-
-void AggregateDeclaration::inlineScan()
-{   int i;
-
-    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
-    if (members)
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
-	    s->inlineScan();
-	}
-    }
-}
-
-unsigned AggregateDeclaration::size(Loc loc)
-{
-    //printf("AggregateDeclaration::size() = %d\n", structsize);
-    if (!members)
-	error(loc, "unknown size");
-    if (sizeok != 1)
-    {	error(loc, "no size yet for forward reference");
-	//*(char*)0=0;
-    }
-    return structsize;
-}
-
-Type *AggregateDeclaration::getType()
-{
-    return type;
-}
-
-int AggregateDeclaration::isDeprecated()
-{
-    return isdeprecated;
-}
-
-/****************************
- * Do byte or word alignment as necessary.
- * Align sizes of 0, as we may not know array sizes yet.
- */
-
-void AggregateDeclaration::alignmember(
-	unsigned salign,	// struct alignment that is in effect
-	unsigned size,		// alignment requirement of field
-	unsigned *poffset)
-{
-    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
-    if (salign > 1)
-    {
-	assert(size != 3);
-	int sa = size;
-	if (sa == 0 || salign < sa)
-	    sa = salign;
-	*poffset = (*poffset + sa - 1) & ~(sa - 1);
-    }
-    //printf("result = %d\n",offset);
-}
-
-
-void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
-{
-    unsigned memsize;		// size of member
-    unsigned memalignsize;	// size of member for alignment purposes
-    unsigned xalign;		// alignment boundaries
-
-    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
-
-    // Check for forward referenced types which will fail the size() call
-    Type *t = v->type->toBasetype();
-    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
-    {	TypeStruct *ts = (TypeStruct *)t;
-#if DMDV2
-	if (ts->sym == this)
-	{
-	    error("cannot have field %s with same struct type", v->toChars());
-	}
-#endif
-
-	if (ts->sym->sizeok != 1)
-	{
-	    sizeok = 2;		// cannot finish; flag as forward referenced
-	    return;
-	}
-    }
-    if (t->ty == Tident)
-    {
-	sizeok = 2;		// cannot finish; flag as forward referenced
-	return;
-    }
-
-    memsize = v->type->size(loc);
-    memalignsize = v->type->alignsize();
-    xalign = v->type->memalign(sc->structalign);
-    alignmember(xalign, memalignsize, &sc->offset);
-    v->offset = sc->offset;
-    sc->offset += memsize;
-    if (sc->offset > structsize)
-	structsize = sc->offset;
-    if (sc->structalign < memalignsize)
-	memalignsize = sc->structalign;
-    if (alignsize < memalignsize)
-	alignsize = memalignsize;
-    //printf("\talignsize = %d\n", alignsize);
-
-    v->storage_class |= STCfield;
-    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
-    fields.push(v);
-}
-
-
-/********************************* StructDeclaration ****************************/
-
-StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
-    : AggregateDeclaration(loc, id)
-{
-    zeroInit = 0;	// assume false until we do semantic processing
-#if DMDV2
-    hasIdentityAssign = 0;
-    cpctor = NULL;
-    postblit = NULL;
-#endif
-
-    // For forward references
-    type = new TypeStruct(this);
-}
-
-Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StructDeclaration *sd;
-
-    if (s)
-	sd = (StructDeclaration *)s;
-    else
-	sd = new StructDeclaration(loc, ident);
-    ScopeDsymbol::syntaxCopy(sd);
-    return sd;
-}
-
-void StructDeclaration::semantic(Scope *sc)
-{   int i;
-    Scope *sc2;
-
-    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    //static int count; if (++count == 20) *(char*)0=0;
-
-    assert(type);
-    if (!members)			// if forward reference
-	return;
-
-    if (symtab)
-    {   if (!scope)
-            return;             // semantic() already completed
-    }
-    else
-        symtab = new DsymbolTable();
-
-    Scope *scx = NULL;
-    if (scope)
-    {   sc = scope;
-        scx = scope;            // save so we don't make redundant copies
-        scope = NULL;
-    }
-
-    parent = sc->parent;
-#if STRUCTTHISREF
-    handle = type;
-#else
-    handle = type->pointerTo();
-#endif
-    structalign = sc->structalign;
-    protection = sc->protection;
-    if (sc->stc & STCdeprecated)
-	isdeprecated = 1;
-    assert(!isAnonymous());
-    if (sc->stc & STCabstract)
-	error("structs, unions cannot be abstract");
-#if DMDV2
-    if (storage_class & STCinvariant)
-        type = type->invariantOf();
-    else if (storage_class & STCconst)
-        type = type->constOf();
-#endif
-
-    if (sizeok == 0)		// if not already done the addMember step
-    {
-	for (i = 0; i < members->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)members->data[i];
-	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
-	    s->addMember(sc, this, 1);
-	}
-    }
-
-    sizeok = 0;
-    sc2 = sc->push(this);
-    sc2->stc = 0;
-    sc2->parent = this;
-    if (isUnionDeclaration())
-	sc2->inunion = 1;
-    sc2->protection = PROTpublic;
-    sc2->explicitProtection = 0;
-
-    int members_dim = members->dim;
-    for (i = 0; i < members_dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-	s->semantic(sc2);
-	if (isUnionDeclaration())
-	    sc2->offset = 0;
-#if 0
-	if (sizeok == 2)
-	{   //printf("forward reference\n");
-	    break;
-	}
-#endif
-    }
-
-    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
-     * a parameter that is a pointer to the struct. But if there
-     * isn't one, but is an opEquals or opCmp with a value, write
-     * another that is a shell around the value:
-     *	int opCmp(struct *p) { return opCmp(*p); }
-     */
-
-    TypeFunction *tfeqptr;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
-
-	arguments->push(arg);
-	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
-    }
-
-    TypeFunction *tfeq;
-    {
-	Arguments *arguments = new Arguments;
-	Argument *arg = new Argument(STCin, type, NULL, NULL);
-
-	arguments->push(arg);
-	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
-    }
-
-    Identifier *id = Id::eq;
-    for (int i = 0; i < 2; i++)
-    {
-	Dsymbol *s = search_function(this, id);
-	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
-	if (fdx)
-	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
-	    if (!fd)
-	    {	fd = fdx->overloadExactMatch(tfeq, getModule());
-		if (fd)
-		{   // Create the thunk, fdptr
-		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
-		    Expression *e = new IdentifierExp(loc, Id::p);
-		    e = new PtrExp(loc, e);
-		    Expressions *args = new Expressions();
-		    args->push(e);
-		    e = new IdentifierExp(loc, id);
-		    e = new CallExp(loc, e, args);
-		    fdptr->fbody = new ReturnStatement(loc, e);
-		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
-		    assert(s);
-		    s->members->push(fdptr);
-		    fdptr->addMember(sc, s, 1);
-		    fdptr->semantic(sc2);
-		}
-	    }
-	}
-
-	id = Id::cmp;
-    }
-#if DMDV2
-    dtor = buildDtor(sc2);
-    postblit = buildPostBlit(sc2);
-    cpctor = buildCpCtor(sc2);
-    buildOpAssign(sc2);
-#endif
-
-    sc2->pop();
-
-    if (sizeok == 2)
-    {	// semantic() failed because of forward references.
-	// Unwind what we did, and defer it for later
-	fields.setDim(0);
-	structsize = 0;
-	alignsize = 0;
-	structalign = 0;
-
-	scope = scx ? scx : new Scope(*sc);
-	scope->setNoFree();
-	scope->module->addDeferredSemantic(this);
-	//printf("\tdeferring %s\n", toChars());
-	return;
-    }
-
-    // 0 sized struct's are set to 1 byte
-    if (structsize == 0)
-    {
-	structsize = 1;
-	alignsize = 1;
-    }
-
-    // Round struct size up to next alignsize boundary.
-    // This will ensure that arrays of structs will get their internals
-    // aligned properly.
-    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
-
-    sizeok = 1;
-    Module::dprogress++;
-
-    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
-
-    // Determine if struct is all zeros or not
-    zeroInit = 1;
-    for (i = 0; i < fields.dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)fields.data[i];
-	VarDeclaration *vd = s->isVarDeclaration();
-	if (vd && !vd->isDataseg())
-	{
-	    if (vd->init)
-	    {
-		// Should examine init to see if it is really all 0's
-		zeroInit = 0;
-		break;
-	    }
-	    else
-	    {
-		if (!vd->type->isZeroInit(loc))
-		{
-		    zeroInit = 0;
-		    break;
-		}
-	    }
-	}
-    }
-
-    /* Look for special member functions.
-     */
-#if DMDV2
-    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
-#endif
-    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
-    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
-    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
-
-    if (sc->func)
-    {
-	semantic2(sc);
-	semantic3(sc);
-    }
-}
-
-void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   int i;
-
-    buf->printf("%s ", kind());
-    if (!isAnonymous())
-	buf->writestring(toChars());
-    if (!members)
-    {
-	buf->writeByte(';');
-	buf->writenl();
-	return;
-    }
-    buf->writenl();
-    buf->writeByte('{');
-    buf->writenl();
-    for (i = 0; i < members->dim; i++)
-    {
-	Dsymbol *s = (Dsymbol *)members->data[i];
-
-	buf->writestring("    ");
-	s->toCBuffer(buf, hgs);
-    }
-    buf->writeByte('}');
-    buf->writenl();
-}
-
-
-const char *StructDeclaration::kind()
-{
-    return "struct";
-}
-
-/********************************* UnionDeclaration ****************************/
-
-UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
-    : StructDeclaration(loc, id)
-{
-}
-
-Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
-{
-    UnionDeclaration *ud;
-
-    if (s)
-	ud = (UnionDeclaration *)s;
-    else
-	ud = new UnionDeclaration(loc, ident);
-    StructDeclaration::syntaxCopy(ud);
-    return ud;
-}
-
-
-const char *UnionDeclaration::kind()
-{
-    return "union";
-}
-
-
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2009 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 "statement.h"
+
+/********************************* AggregateDeclaration ****************************/
+
+AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
+    : ScopeDsymbol(id)
+{
+    this->loc = loc;
+
+    storage_class = 0;
+    protection = PROTpublic;
+    type = NULL;
+    handle = NULL;
+    structsize = 0;		// size of struct
+    alignsize = 0;		// size of struct for alignment purposes
+    structalign = 0;		// struct member alignment in effect
+    hasUnions = 0;
+    sizeok = 0;			// size not determined yet
+    isdeprecated = 0;
+    inv = NULL;
+    aggNew = NULL;
+    aggDelete = NULL;
+
+#if IN_DMD
+    stag = NULL;
+    sinit = NULL;
+#endif
+#if DMDV2
+    dtor = NULL;
+
+    ctor = NULL;
+    defaultCtor = NULL;
+#endif
+
+#if IN_LLVM
+    availableExternally = true; // assume this unless proven otherwise
+#endif
+}
+
+enum PROT AggregateDeclaration::prot()
+{
+    return protection;
+}
+
+void AggregateDeclaration::semantic2(Scope *sc)
+{
+    //printf("AggregateDeclaration::semantic2(%s)\n", toChars());
+    if (scope && members)
+    {	error("has forward references");
+	return;
+    }
+    if (members)
+    {
+	sc = sc->push(this);
+	for (size_t i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic2(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::semantic3(Scope *sc)
+{   int i;
+
+    // LDC
+    if (!global.params.useAvailableExternally)
+        availableExternally = false;
+
+    //printf("AggregateDeclaration::semantic3(%s)\n", toChars());
+    if (members)
+    {
+	sc = sc->push(this);
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    s->semantic3(sc);
+	}
+	sc->pop();
+    }
+}
+
+void AggregateDeclaration::inlineScan()
+{   int i;
+
+    //printf("AggregateDeclaration::inlineScan(%s)\n", toChars());
+    if (members)
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("inline scan aggregate symbol '%s'\n", s->toChars());
+	    s->inlineScan();
+	}
+    }
+}
+
+unsigned AggregateDeclaration::size(Loc loc)
+{
+    //printf("AggregateDeclaration::size() = %d\n", structsize);
+    if (!members)
+	error(loc, "unknown size");
+    if (sizeok != 1)
+    {	error(loc, "no size yet for forward reference");
+	//*(char*)0=0;
+    }
+    return structsize;
+}
+
+Type *AggregateDeclaration::getType()
+{
+    return type;
+}
+
+int AggregateDeclaration::isDeprecated()
+{
+    return isdeprecated;
+}
+
+/****************************
+ * Do byte or word alignment as necessary.
+ * Align sizes of 0, as we may not know array sizes yet.
+ */
+
+void AggregateDeclaration::alignmember(
+	unsigned salign,	// struct alignment that is in effect
+	unsigned size,		// alignment requirement of field
+	unsigned *poffset)
+{
+    //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
+    if (salign > 1)
+    {
+	assert(size != 3);
+	int sa = size;
+	if (sa == 0 || salign < sa)
+	    sa = salign;
+	*poffset = (*poffset + sa - 1) & ~(sa - 1);
+    }
+    //printf("result = %d\n",offset);
+}
+
+
+void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
+{
+    unsigned memsize;		// size of member
+    unsigned memalignsize;	// size of member for alignment purposes
+    unsigned xalign;		// alignment boundaries
+
+    //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
+
+    // Check for forward referenced types which will fail the size() call
+    Type *t = v->type->toBasetype();
+    if (t->ty == Tstruct /*&& isStructDeclaration()*/)
+    {	TypeStruct *ts = (TypeStruct *)t;
+#if DMDV2
+	if (ts->sym == this)
+	{
+	    error("cannot have field %s with same struct type", v->toChars());
+	}
+#endif
+
+	if (ts->sym->sizeok != 1)
+	{
+	    sizeok = 2;		// cannot finish; flag as forward referenced
+	    return;
+	}
+    }
+    if (t->ty == Tident)
+    {
+	sizeok = 2;		// cannot finish; flag as forward referenced
+	return;
+    }
+
+    memsize = v->type->size(loc);
+    memalignsize = v->type->alignsize();
+    xalign = v->type->memalign(sc->structalign);
+    alignmember(xalign, memalignsize, &sc->offset);
+    v->offset = sc->offset;
+    sc->offset += memsize;
+    if (sc->offset > structsize)
+	structsize = sc->offset;
+    if (sc->structalign < memalignsize)
+	memalignsize = sc->structalign;
+    if (alignsize < memalignsize)
+	alignsize = memalignsize;
+    //printf("\talignsize = %d\n", alignsize);
+
+    v->storage_class |= STCfield;
+    //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
+    fields.push(v);
+}
+
+
+/********************************* StructDeclaration ****************************/
+
+StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
+    : AggregateDeclaration(loc, id)
+{
+    zeroInit = 0;	// assume false until we do semantic processing
+#if DMDV2
+    hasIdentityAssign = 0;
+    cpctor = NULL;
+    postblit = NULL;
+#endif
+
+    // For forward references
+    type = new TypeStruct(this);
+}
+
+Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StructDeclaration *sd;
+
+    if (s)
+	sd = (StructDeclaration *)s;
+    else
+	sd = new StructDeclaration(loc, ident);
+    ScopeDsymbol::syntaxCopy(sd);
+    return sd;
+}
+
+void StructDeclaration::semantic(Scope *sc)
+{   int i;
+    Scope *sc2;
+
+    //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    //static int count; if (++count == 20) *(char*)0=0;
+
+    assert(type);
+    if (!members)			// if forward reference
+	return;
+
+    if (symtab)
+    {   if (!scope)
+            return;             // semantic() already completed
+    }
+    else
+        symtab = new DsymbolTable();
+
+    Scope *scx = NULL;
+    if (scope)
+    {   sc = scope;
+        scx = scope;            // save so we don't make redundant copies
+        scope = NULL;
+    }
+
+    parent = sc->parent;
+    type = type->semantic(loc, sc);
+#if STRUCTTHISREF
+    handle = type;
+#else
+    handle = type->pointerTo();
+#endif
+    structalign = sc->structalign;
+    protection = sc->protection;
+    if (sc->stc & STCdeprecated)
+	isdeprecated = 1;
+    assert(!isAnonymous());
+    if (sc->stc & STCabstract)
+	error("structs, unions cannot be abstract");
+#if DMDV2
+    if (storage_class & STCinvariant)
+        type = type->invariantOf();
+    else if (storage_class & STCconst)
+        type = type->constOf();
+#endif
+
+    if (sizeok == 0)		// if not already done the addMember step
+    {
+	for (i = 0; i < members->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)members->data[i];
+	    //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars());
+	    s->addMember(sc, this, 1);
+	}
+    }
+
+    sizeok = 0;
+    sc2 = sc->push(this);
+    sc2->stc = 0;
+    sc2->parent = this;
+    if (isUnionDeclaration())
+	sc2->inunion = 1;
+    sc2->protection = PROTpublic;
+    sc2->explicitProtection = 0;
+
+    int members_dim = members->dim;
+    for (i = 0; i < members_dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+	s->semantic(sc2);
+	if (isUnionDeclaration())
+	    sc2->offset = 0;
+#if 0
+	if (sizeok == 2)
+	{   //printf("forward reference\n");
+	    break;
+	}
+#endif
+    }
+
+    /* The TypeInfo_Struct is expecting an opEquals and opCmp with
+     * a parameter that is a pointer to the struct. But if there
+     * isn't one, but is an opEquals or opCmp with a value, write
+     * another that is a shell around the value:
+     *	int opCmp(struct *p) { return opCmp(*p); }
+     */
+
+    TypeFunction *tfeqptr;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, handle, Id::p, NULL);
+
+	arguments->push(arg);
+	tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc);
+    }
+
+    TypeFunction *tfeq;
+    {
+	Arguments *arguments = new Arguments;
+	Argument *arg = new Argument(STCin, type, NULL, NULL);
+
+	arguments->push(arg);
+	tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
+	tfeq = (TypeFunction *)tfeq->semantic(0, sc);
+    }
+
+    Identifier *id = Id::eq;
+    for (int i = 0; i < 2; i++)
+    {
+	Dsymbol *s = search_function(this, id);
+	FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
+	if (fdx)
+	{   FuncDeclaration *fd = fdx->overloadExactMatch(tfeqptr, getModule());
+	    if (!fd)
+	    {	fd = fdx->overloadExactMatch(tfeq, getModule());
+		if (fd)
+		{   // Create the thunk, fdptr
+		    FuncDeclaration *fdptr = new FuncDeclaration(loc, loc, fdx->ident, STCundefined, tfeqptr);
+		    Expression *e = new IdentifierExp(loc, Id::p);
+		    e = new PtrExp(loc, e);
+		    Expressions *args = new Expressions();
+		    args->push(e);
+		    e = new IdentifierExp(loc, id);
+		    e = new CallExp(loc, e, args);
+		    fdptr->fbody = new ReturnStatement(loc, e);
+		    ScopeDsymbol *s = fdx->parent->isScopeDsymbol();
+		    assert(s);
+		    s->members->push(fdptr);
+		    fdptr->addMember(sc, s, 1);
+		    fdptr->semantic(sc2);
+		}
+	    }
+	}
+
+	id = Id::cmp;
+    }
+#if DMDV2
+    dtor = buildDtor(sc2);
+    postblit = buildPostBlit(sc2);
+    cpctor = buildCpCtor(sc2);
+    buildOpAssign(sc2);
+#endif
+
+    sc2->pop();
+
+    if (sizeok == 2)
+    {	// semantic() failed because of forward references.
+	// Unwind what we did, and defer it for later
+	fields.setDim(0);
+	structsize = 0;
+	alignsize = 0;
+	structalign = 0;
+
+	scope = scx ? scx : new Scope(*sc);
+	scope->setNoFree();
+	scope->module->addDeferredSemantic(this);
+	//printf("\tdeferring %s\n", toChars());
+	return;
+    }
+
+    // 0 sized struct's are set to 1 byte
+    if (structsize == 0)
+    {
+	structsize = 1;
+	alignsize = 1;
+    }
+
+    // Round struct size up to next alignsize boundary.
+    // This will ensure that arrays of structs will get their internals
+    // aligned properly.
+    structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+
+    sizeok = 1;
+    Module::dprogress++;
+
+    //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
+
+    // Determine if struct is all zeros or not
+    zeroInit = 1;
+    for (i = 0; i < fields.dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)fields.data[i];
+	VarDeclaration *vd = s->isVarDeclaration();
+	if (vd && !vd->isDataseg())
+	{
+	    if (vd->init)
+	    {
+		// Should examine init to see if it is really all 0's
+		zeroInit = 0;
+		break;
+	    }
+	    else
+	    {
+		if (!vd->type->isZeroInit(loc))
+		{
+		    zeroInit = 0;
+		    break;
+		}
+	    }
+	}
+    }
+
+    /* Look for special member functions.
+     */
+#if DMDV2
+    ctor =   (CtorDeclaration *)search(0, Id::ctor, 0);
+#endif
+    inv =    (InvariantDeclaration *)search(0, Id::classInvariant, 0);
+    aggNew =       (NewDeclaration *)search(0, Id::classNew,       0);
+    aggDelete = (DeleteDeclaration *)search(0, Id::classDelete,    0);
+
+    if (sc->func)
+    {
+	semantic2(sc);
+	semantic3(sc);
+    }
+}
+
+void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   int i;
+
+    buf->printf("%s ", kind());
+    if (!isAnonymous())
+	buf->writestring(toChars());
+    if (!members)
+    {
+	buf->writeByte(';');
+	buf->writenl();
+	return;
+    }
+    buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
+    for (i = 0; i < members->dim; i++)
+    {
+	Dsymbol *s = (Dsymbol *)members->data[i];
+
+	buf->writestring("    ");
+	s->toCBuffer(buf, hgs);
+    }
+    buf->writeByte('}');
+    buf->writenl();
+}
+
+
+const char *StructDeclaration::kind()
+{
+    return "struct";
+}
+
+/********************************* UnionDeclaration ****************************/
+
+UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
+    : StructDeclaration(loc, id)
+{
+}
+
+Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
+{
+    UnionDeclaration *ud;
+
+    if (s)
+	ud = (UnionDeclaration *)s;
+    else
+	ud = new UnionDeclaration(loc, ident);
+    StructDeclaration::syntaxCopy(ud);
+    return ud;
+}
+
+
+const char *UnionDeclaration::kind()
+{
+    return "union";
+}
+
+