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);
+	}
+}
+