Commits

Anonymous committed 9d088cf

Updated D1 frontend

Comments (0)

Files changed (23)

     if (!result)
     {
 	error(loc, "member %s is not accessible", smember->toChars());
+	halt();
     }
 }
 
 
 int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
 {
-    unsigned i;
     int m = 0;
     Array *d = include(sc, sd);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    m |= s->addMember(sc, sd, m | memnum);
 	}
     }
 {
     Array *d = include(sc, NULL);
 
-    //printf("\tAttribDeclaration::semantic '%s'\n",toChars());
+    //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
     if (d)
     {
 	for (unsigned i = 0; i < d->dim; i++)
 
 void AttribDeclaration::semantic2(Scope *sc)
 {
-    unsigned i;
     Array *d = include(sc, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    s->semantic2(sc);
 	}
     }
 
 void AttribDeclaration::semantic3(Scope *sc)
 {
-    unsigned i;
     Array *d = include(sc, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    s->semantic3(sc);
 	}
     }
 
 void AttribDeclaration::inlineScan()
 {
-    unsigned i;
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
 	    s->inlineScan();
 	}
 {
     if (comment)
     {
-	unsigned i;
 	Array *d = include(NULL, NULL);
 
 	if (d)
 	{
-	    for (i = 0; i < d->dim; i++)
-	    {   Dsymbol *s;
-
-		s = (Dsymbol *)d->data[i];
+	    for (unsigned i = 0; i < d->dim; i++)
+ 	    {   Dsymbol *s = (Dsymbol *)d->data[i];
 		//printf("AttribDeclaration::addComment %s\n", s->toChars());
 		s->addComment(comment);
 	    }
 //    if (sc->docbuf)
 //	return;
 
-    unsigned i;
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    //printf("AttribDeclaration::emitComment %s\n", s->toChars());
 	    s->emitComment(sc);
 	}
 
 void AttribDeclaration::toObjFile(int multiobj)
 {
-    unsigned i;
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    s->toObjFile(multiobj);
 	}
     }
 
 int AttribDeclaration::cvMember(unsigned char *p)
 {
-    unsigned i;
     int nwritten = 0;
     int n;
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    n = s->cvMember(p);
 	    if (p)
 		p += n;
 
 void AttribDeclaration::checkCtorConstInit()
 {
-    unsigned i;
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    s->checkCtorConstInit();
 	}
     }
  */
 
 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
-{   unsigned i;
+{  
     Array *d = include(NULL, NULL);
 
     if (d)
     {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
+	for (unsigned i = 0; i < d->dim; i++)
+ 	{   Dsymbol *s = (Dsymbol *)d->data[i];
 	    s->addLocalClass(aclasses);
 	}
     }
 
 int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
 {
+	//printf("StaticIfDeclaration::addMember() '%s'\n",toChars());
     /* This is deferred until semantic(), so that
      * expressions in the condition can refer to declarations
      * in the same scope, such as:
 {
     Array *d = include(sc, sd);
 
-    //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars());
+    //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d);
     if (d)
     {
 	if (!addisdone)
 {
     this->exp = exp;
     this->sd = NULL;
+    this->compiled = 0;
 }
 
 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
 
 int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
 {
+    //printf("CompileDeclaration::addMember(sc = %p)\n", sc);
     this->sd = sd;
+    if (memnum == 0)
+    {	/* No members yet, so parse the mixin now
+ 	 */
+ 	compileIt(sc);
+ 	memnum |= AttribDeclaration::addMember(sc, sd, memnum);
+ 	compiled = 1;
+    }
     return memnum;
 }
 
-void CompileDeclaration::semantic(Scope *sc)
+void CompileDeclaration::compileIt(Scope *sc)
 {
-    //printf("CompileDeclaration::semantic()\n");
+     //printf("CompileDeclaration::compileIt()\n");
     exp = exp->semantic(sc);
     exp = resolveProperties(sc, exp);
     exp = exp->optimize(WANTvalue | WANTinterpret);
     if (exp->op != TOKstring)
     {	error("argument to mixin must be a string, not (%s)", exp->toChars());
-	return;
     }
+    else
+    {
     StringExp *se = (StringExp *)exp;
     se = se->toUTF8(sc);
     Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
     p.nextToken();
     decl = p.parseDeclDefs(0);
     if (p.token.value != TOKeof)
-    {
 	error("incomplete mixin declaration (%s)", se->toChars());
     }
+}
 
-    AttribDeclaration::addMember(sc, sd, 0);
-    AttribDeclaration::semantic(sc);
-}
+    void CompileDeclaration::semantic(Scope *sc)
+ {
+     //printf("CompileDeclaration::semantic()\n");
+ 
+     if (!compiled)
+     {
+ 	compileIt(sc);
+  	AttribDeclaration::addMember(sc, sd, 0);
+ 	compiled = 1;
+     }
+      AttribDeclaration::semantic(sc);
+  }
 
 void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     Expression *exp;
 
     ScopeDsymbol *sd;
+    int compiled;
 
     CompileDeclaration(Loc loc, Expression *exp);
     Dsymbol *syntaxCopy(Dsymbol *s);
     int addMember(Scope *sc, ScopeDsymbol *sd, int memnum);
+    void compileIt(Scope *sc);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };

d/dmd/constfold.c

 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
 
-   Modified by David Friedman, September 2004
+   Modified by Michael Parrott, September 2009
+   Using David Friedman's code
 */
 
 #include <stdio.h>
 	else
 	    e->type = type;
     }
-    else if (e1->op == TOKarrayliteral &&
+    else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
 	e1->type->toBasetype()->nextOf()->equals(e2->type))
     {
-	ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
+	ArrayLiteralExp *es1;
+ 	if (e1->op == TOKarrayliteral)
+ 	{   es1 = (ArrayLiteralExp *)e1;
 
 	es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
 	es1->elements->push(e2);
+	}
+ 	else
+ 	{
+ 	    es1 = new ArrayLiteralExp(e1->loc, e2);
+ 	}
 	e = es1;
 
 	if (type->toBasetype()->ty == Tsarray)

d/dmd/declaration.c

     return protection;
 }
 
+/*************************************
++  * Check to see if declaration can be modified in this context (sc).
++  * Issue error if not.
++  */
+ 
+ #if V2
+ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
+ {
+     if (sc->incontract && isParameter())
+ 	error(loc, "cannot modify parameter '%s' in contract", toChars());
+ 
+     if (isCtorinit())
+     {	// It's only modifiable if inside the right constructor
+ 	Dsymbol *s = sc->func;
+ 	while (1)
+ 	{
+ 	    FuncDeclaration *fd = NULL;
+ 	    if (s)
+ 		fd = s->isFuncDeclaration();
+ 	    if (fd &&
+ 		((fd->isCtorDeclaration() && storage_class & STCfield) ||
+ 		 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
+ 		fd->toParent() == toParent()
+ 	       )
+ 	    {
+ 		VarDeclaration *v = isVarDeclaration();
+ 		assert(v);
+ 		v->ctorinit = 1;
+ 		//printf("setting ctorinit\n");
 	    }
+ 	    else
 	    {
+ 		if (s)
+ 		{   s = s->toParent2();
+ 		    continue;
+ 		}
+ 		else
+		{
+ 		    const char *p = isStatic() ? "static " : "";
+ 		    error(loc, "can only initialize %sconst %s inside %sconstructor",
+ 			p, toChars(), p);
 		}
+ 	    }
+ 	    break;
+ 	}
+     }
+     else
+     {
+ 	VarDeclaration *v = isVarDeclaration();
+ 	if (v && v->canassign == 0)
+ 	{
+ 	    char *p = NULL;
+ 	    if (isConst())
+ 		p = "const";
+ 	    else if (isInvariant())
+ 		p = "invariant";
+ 	    else if (storage_class & STCmanifest)
+ 		p = "manifest constant";
+ 	    else if (!t->isAssignable())
+ 		p = "struct with immutable members";
+ 	    if (p)
+ 	    {	error(loc, "cannot modify %s", p);
+ 		halt();
+ 	    }
+ 	}
+     }
+ }
+ #endif
+ 
+
+
 /********************************* TupleDeclaration ****************************/
 
 TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
 
 Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
 {
+	//printf("AliasDeclaration::syntaxCopy()\n");
     assert(!s);
     AliasDeclaration *sa;
     if (type)
 void VarDeclaration::semantic(Scope *sc)
 {
     //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
-    //printf("type = %s\n", type->toChars());
+    //printf(" type = %s\n", type ? type->toChars() : "null");
+   //printf(" stc = x%x\n", sc->stc);
+   //printf(" storage_class = x%x\n", storage_class);
     //printf("linkage = %d\n", sc->linkage);
     //if (strcmp(toChars(), "mul") == 0) halt();
 
 	    originalType = type;
 	type = type->semantic(loc, sc);
     }
+    //printf(" semantic type = %s\n", type ? type->toChars() : "null");
 
     type->checkDeprecated(loc, sc);
     linkage = sc->linkage;
     else
 	attributes = sc->attributes;
     //printf("sc->stc = %x\n", sc->stc);
-    //printf("storage_class = %x\n", storage_class);
+    //printf("storage_class = x%x\n", storage_class);
 
     Dsymbol *parent = toParent();
     FuncDeclaration *fd = parent->isFuncDeclaration();
 	{
 	    error("field not allowed in interface");
 	}
-
+/* Templates cannot add fields to aggregates
+ 	 */
 	TemplateInstance *ti = parent->isTemplateInstance();
 	if (ti)
 	{
 	    // possibilities.
 	    if (fd && !isStatic() && !isConst() && !init->isVoidInitializer())
 	    {
-		Expression *e1;
-		Type *t;
-		sinteger_t dim;
 
 		//printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars());
 		if (!ei)
 		    init = ei;
 		}
 
-		e1 = new VarExp(loc, this);
-
-		t = type->toBasetype();
+		Expression *e1 = new VarExp(loc, this);
+  
+ 		Type *t = type->toBasetype();
 		if (t->ty == Tsarray)
 		{
 		    ei->exp = ei->exp->semantic(sc);
 		    if (!ei->exp->implicitConvTo(type))
 		    {
-			dim = ((TypeSArray *)t)->dim->toInteger();
+			sinteger_t dim = ((TypeSArray *)t)->dim->toInteger();
 			// If multidimensional static array, treat as one large array
 			while (1)
 			{
 	buf->writestring("const ");
     if (storage_class & STCstatic)
 	buf->writestring("static ");
+	if (storage_class & STCauto)
+ 	buf->writestring("auto ");
+ #if V2
+     if (storage_class & STCmanifest)
+ 	buf->writestring("manifest ");
+     if (storage_class & STCinvariant)
+ 	buf->writestring("invariant ");
+     if (storage_class & STCtls)
+ 	buf->writestring("__thread ");
+ #endif
     if (type)
 	type->toCBuffer(buf, ident, hgs);
     else
 	error("missing initializer in static constructor for const variable");
 }
 
-/************************************
- * Check to see if variable is a reference to an enclosing function
- * or not.
- */
+/************************************
+!  * Check to see if this variable is actually in an enclosing function
+!  * rather than the current one.
+   */
 
 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
 {
+	//printf("VarDeclaration::checkNestedReference() %s\n", toChars());
     if (parent && !isDataseg() && parent != sc->parent)
     {
+    	// The function that this variable is in
 	FuncDeclaration *fdv = toParent()->isFuncDeclaration();
+	// The current function
 	FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
 
 	if (fdv && fdthis)
 
 /*******************************
  * Does symbol go into data segment?
+ * Includes extern variables.
  */
 
 int VarDeclaration::isDataseg()

d/dmd/declaration.h

     STCnothrow	    = 0x2000000,	// never throws exceptions
     STCpure	    = 0x4000000,	// pure function
     STCtls	    = 0x8000000,	// thread local
+    STCalias	    = 0x10000000,	// alias parameter
 };
 
 struct Match
     CtorDeclaration *isCtorDeclaration() { return this; }
 };
 
+#if V2
 struct PostBlitDeclaration : FuncDeclaration
+ {
+     PostBlitDeclaration(Loc loc, Loc endloc);
+    PostBlitDeclaration(Loc loc, Loc endloc, Identifier *id);
+     Dsymbol *syntaxCopy(Dsymbol *);
+     void semantic(Scope *sc);
+     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+     int isVirtual();
+     int addPreInvariant();
+     int addPostInvariant();
+     int overloadInsert(Dsymbol *s);
+     void emitComment(Scope *sc);
+ 
+     PostBlitDeclaration *isPostBlitDeclaration() { return this; }
+ };
+ #endif
+
 struct DtorDeclaration : FuncDeclaration
 {
     DtorDeclaration(Loc loc, Loc endloc);
 };
 
 struct StaticDtorDeclaration : FuncDeclaration
-{
+{   VarDeclaration *vgate;	// 'gate' variable
     StaticDtorDeclaration(Loc loc, Loc endloc);
     Dsymbol *syntaxCopy(Dsymbol *);
     void semantic(Scope *sc);
      */
     if (f && f->type)
     {
-	TypeFunction *tf = (TypeFunction *)f->type;
+	TypeFunction *tf;
+ 	if (f->originalType)
+ 	{
+ 	    tf = (TypeFunction *)f->originalType;
+ 	}
+ 	else
+ 	    tf = (TypeFunction *)f->type;
 
 	if (tf->parameters)
 	{
     return s;
 }
 
+TemplateInstance *Dsymbol::inTemplateInstance()
+ {
+     for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
+     {
+ 	TemplateInstance *ti = parent->isTemplateInstance();
+ 	if (ti)
+ 	    return ti;
+     }
+     return NULL;
+ }
+
 /**********************************
  * Use this instead of toParent() when looking for the
  * 'this' pointer of the enclosing function/class.
     // Most Dsymbols have no further semantic analysis needed
 }
 
+/*********************************************
++  * Search for ident as member of s.
++  * Input:
++  *	flags:	1	don't find private members
++  *		2	don't give error messages
++  *		4	return NULL if ambiguous
++  * Returns:
++  *	NULL if not found
++  */
+
 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
 {
     //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
 
 AggregateDeclaration *Dsymbol::isMember()	// is this a member of an AggregateDeclaration?
 {
-    Dsymbol *parent = toParent();
+    //printf("Dsymbol::isMember() %s\n", toChars());
+      Dsymbol *parent = toParent();
+     //printf("parent is %s %s\n", parent->kind(), parent->toChars());
     return parent ? parent->isAggregateDeclaration() : NULL;
 }
 
 }
 
 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
-{   Dsymbol *s;
-    int i;
+{   
 
     //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
     // Look in symbols declared in this module
-    s = symtab ? symtab->lookup(ident) : NULL;
+    Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
     if (s)
     {
 	//printf("\ts = '%s.%s'\n",toChars(),s->toChars());
     else if (imports)
     {
 	// Look in imported modules
-	for (i = 0; i < imports->dim; i++)
+	for (int i = 0; i < imports->dim; i++)
 	{   ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
 	    Dsymbol *s2;
 
 		continue;
 
 	    //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
+	    /* Don't find private members if ss is a module
++ 	     */
 	    s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
 	    if (!s)
 		s = s2;
 	    {
 		if (s->toAlias() == s2->toAlias())
 		{
+			/* After following aliases, we found the same symbol,
++ 		     * so it's not an ambiguity.
++ 		     * But if one alias is deprecated, prefer the other.
++ 		     */
 		    if (s->isDeprecated())
 			s = s2;
 		}
     Dsymbol *pastMixin();
     Dsymbol *toParent();
     Dsymbol *toParent2();
+    TemplateInstance *inTemplateInstance();
 
     int dyncast() { return DYNCAST_DSYMBOL; }	// kludge for template.isSymbol()
 

d/dmd/expression.c

 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
 
-   Modified by David Friedman, December 2006
+   Modified by Michael Parrott, September 2009
+   Using David Friedman's code
 */
 
 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
     precedence[TOKassert] = PREC_primary;
     precedence[TOKfunction] = PREC_primary;
     precedence[TOKvar] = PREC_primary;
+    #if V2
+     precedence[TOKdefault] = PREC_primary;
+ 	#endif
 
     // post
     precedence[TOKdotti] = PREC_primary;
     precedence[TOKcomma] = PREC_expr;
 }
 
-/*************************************************************
- * Now that we have the right function f, we need to get the
- * right 'this' pointer if f is in an outer class, but our
- * existing 'this' pointer is in an inner class.
- * This code is analogous to that used for variables
- * in DotVarExp::semantic().
- */
-
-Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, Expression *e1, Declaration *var)
-{
+/*************************************************************
+!  * Given var, we need to get the
+!  * right 'this' pointer if var is in an outer class, but our
+   * existing 'this' pointer is in an inner class.
+!  * Input:
+!  *	e1	existing 'this'
+!  *	ad	struct or class we need the correct 'this' for
+!  *	var	the specific member of ad we're accessing
+   */
+
+Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
+ 	Expression *e1, Declaration *var)
+{
+	//printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
  L1:
     Type *t = e1->type->toBasetype();
+    //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
+    /* If e1 is not the 'this' pointer for ad
+      */
 
     if (ad &&
-	!(t->ty == Tpointer && t->next->ty == Tstruct &&
-	  ((TypeStruct *)t->next)->sym == ad)
+	!(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
+ 	  ((TypeStruct *)t->nextOf())->sym == ad)
 	&&
 	!(t->ty == Tstruct &&
 	  ((TypeStruct *)t)->sym == ad)
     {
 	ClassDeclaration *cd = ad->isClassDeclaration();
 	ClassDeclaration *tcd = t->isClassHandle();
+	
+	/* e1 is the right this if ad is a base class of e1
+ 	 */
 
 	if (!cd || !tcd ||
 	    !(tcd == cd || cd->isBaseOf(tcd, NULL))
 	   )
 	{
+		/* Only classes can be inner classes with an 'outer'
++ 	     * member pointing to the enclosing class instance
++ 	     */
 	    if (tcd && tcd->isNested())
-	    {   // Try again with outer scope
+	    {   /* e1 is the 'this' pointer for an inner class: tcd.
+! 		 * Rewrite it as the 'this' pointer for the outer class.
+! 		 */
 
 		e1 = new DotVarExp(loc, e1, tcd->vthis);
-		e1 = e1->semantic(sc);
-
-		// Skip over nested functions, and get the enclosing
+		e1->type = tcd->vthis->type;
+ 		// Do not call checkNestedRef()
+ 		//e1 = e1->semantic(sc);
+
+		// Skip up over nested functions, and get the enclosing
 		// class type.
-		Dsymbol *s = tcd->toParent();
-		while (s && s->isFuncDeclaration())
+		int n = 0;
+ 		Dsymbol *s;
+ 		for (s = tcd->toParent();
+ 		     s && s->isFuncDeclaration();
+ 		     s = s->toParent())
 		{   FuncDeclaration *f = s->isFuncDeclaration();
 		    if (f->vthis)
 		    {
+		    	//printf("rewriting e1 to %s's this\n", f->toChars());
+ 			n++;
 			e1 = new VarExp(loc, f->vthis);
 		    }
 		    s = s->toParent();
 		}
 		if (s && s->isClassDeclaration())
-		    e1->type = s->isClassDeclaration()->type;
+		    {   e1->type = s->isClassDeclaration()->type;
+ 		    if (n > 1)
+ 			e1 = e1->semantic(sc);
+ 		}
+ 		else
 		e1 = e1->semantic(sc);
 		goto L1;
 	    }
 #ifdef DEBUG
 	    printf("2: ");
 #endif
+/* Can't find a path from e1 to ad
+! 	     */
 	    error("this for %s needs to be type %s not type %s",
 		var->toChars(), ad->toChars(), t->toChars());
 	}
     }
 }
 
+/*********************************************
++  * Call copy constructor for struct value argument.
++  */
+ #if V2
+ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
+ {
+     Type *tb = e->type->toBasetype();
+     assert(tb->ty == Tstruct);
+     StructDeclaration *sd = ((TypeStruct *)tb)->sym;
+     if (sd->cpctor)
+     {
+ 	/* Create a variable tmp, and replace the argument e with:
+ 	 *	(tmp = e),tmp
+ 	 * and let AssignExp() handle the construction.
+ 	 * This is not the most efficent, ideally tmp would be constructed
+ 	 * directly onto the stack.
+ 	 */
+ 	Identifier *idtmp = Lexer::uniqueId("__tmp");
+ 	VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
+ 	Expression *ae = new DeclarationExp(loc, tmp);
+ 	e = new CommaExp(loc, ae, new VarExp(loc, tmp));
+ 	e = e->semantic(sc);
+     }
+     return e;
+ }
+ #endif
+
 
 /****************************************
  * Now that we know the exact type of the function we're calling,
 		    error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
 		    break;
 		}
-		arg = p->defaultArg->copy();
+		arg = p->defaultArg;
+ #if V2
+ 		if (arg->op == TOKdefault)
+ 		{   DefaultInitExp *de = (DefaultInitExp *)arg;
+ 		    arg = de->resolve(loc, sc);
+ 		}
+ 		else
+ #endif
+ 		    arg = arg->copy();
 		arguments->push(arg);
 		nargs++;
 	    }
 	    tb = arg->type->toBasetype();
 	    if (tb->ty == Tsarray)
 	    {	TypeSArray *ts = (TypeSArray *)tb;
-		Type *ta = tb->next->arrayOf();
+		Type *ta = ts->next->arrayOf();
 		if (ts->size(arg->loc) == 0)
 		{   arg = new NullExp(arg->loc);
 		    arg->type = ta;
 		else
 		    arg = arg->castTo(sc, ta);
 	    }
+	    
+	    #if V2
+ 	    if (tb->ty == Tstruct)
+ 	    {
+ 		arg = callCpCtor(loc, sc, arg);
+ 	    }
+  
+ 	    // Give error for overloaded function addresses
+ 	    if (arg->op == TOKsymoff)
+ 	    {	SymOffExp *se = (SymOffExp *)arg;
+ 		if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
+ 		    arg->error("function %s is overloaded", arg->toChars());
+ 	    }
+ 	#endif
 
 	    arg->rvalue();
 	}
 
 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
 {
+	//if (precedence[e->op] == 0) e->dump(0);
     if (precedence[e->op] < pr)
     {
 	buf->writeByte('(');
 Expression *Expression::semantic(Scope *sc)
 {
 #if LOGSEMANTIC
-    printf("Expression::semantic()\n");
+    printf("Expression::semantic() %s\n", toChars());
 #endif
     if (type)
 	type = type->semantic(loc, sc);
 	dump(0);
 	halt();
 #endif
+type = Type::tint32;
     }
 }
 
 	    e = new NullExp(loc);
 	else
 	    e = new AddrExp(loc, this);
-	e->type = tb->next->pointerTo();
+	e->type = ts->next->pointerTo();
     }
     return e;
 }
     {	Expression *e;
 
 	e = new PtrExp(loc, this);
-	e->type = type->next;
+	e->type = ((TypeReference *)type)->next;
 	return e;
     }
     return this;
     //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
     if (type && !type->isscalar())
     {
+    	//printf("%s, loc = %d\n", toChars(), loc.linnum);
 	error("integral constant must be scalar type, not %s", type->toChars());
 	type = Type::terror;
     }
 	fd->nestedFrameRef = 1;
     }
 #endif
+if (!sc->intypeof)
     sc->callSuper |= CSXthis;
     return this;
 
     }
 #endif
 
+if (!sc->intypeof)
     sc->callSuper |= CSXsuper;
     return this;
 
 	{
 	    AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
 	    e1 = getRightThis(loc, sc, ad, e1, var);
+	    if (!sc->noaccesscheck)
 	    accessCheck(loc, sc, e1, var);
 	}
     }
 	    ad = td->toParent()->isAggregateDeclaration();
 	}	
 	if (f->needThis())
+	{
 	    ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
+	}
 
 	checkDeprecated(sc, f);
 	accessCheck(loc, sc, ue->e1, f);
 	    }
 	    else
 	    {
+	    	if (!sc->intypeof)
+ 		{
 #if 0
 		if (sc->callSuper & (CSXthis | CSXsuper))
 		    error("reference to this before super()");
 		if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
 		    error("multiple constructor calls");
 		sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
+	}
 
 		f = f->overloadResolve(loc, arguments);
 		checkDeprecated(sc, f);
 	}
 	else
 	{
+		if (!sc->intypeof)
+ 	    {
 #if 0
 	    if (sc->callSuper & (CSXthis | CSXsuper))
 		error("reference to this before super()");
 	    if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
 		error("multiple constructor calls");
 	    sc->callSuper |= CSXany_ctor | CSXthis_ctor;
+	   }
 
 	    f = cd->ctor;
 	    f = f->overloadResolve(loc, arguments);
      * 1) is a virtual function
      * 2) has its address taken
      * 3) has a parent that escapes
-     * escapes.
+     *
+     * Note that since a non-virtual function can be called by
     * a virtual one, if that non-virtual function accesses a closure
+     * var, the closure still has to be taken. Hence, we check for isThis()
+     * instead of isVirtual(). (thanks to David Friedman)
      */
 
     //printf("FuncDeclaration::needsClosure() %s\n", toChars());
 	    assert(f != this);
 
 	    //printf("\t\tf = %s, %d, %d\n", f->toChars(), f->isVirtual(), f->tookAddressOf);
-	    if (f->isVirtual() || f->tookAddressOf)
+	    if (f->isThis() || f->tookAddressOf)
 		goto Lyes;	// assume f escapes this function's scope
 
 	    // Look to see if any parents of f that are below this escape
 	    for (Dsymbol *s = f->parent; s != this; s = s->parent)
 	    {
 		f = s->isFuncDeclaration();
-		if (f && (f->isVirtual() || f->tookAddressOf))
+		if (f && (f->isThis() || f->tookAddressOf))
 		    goto Lyes;
 	    }
 	}
     else
 	tret = cd->type; //->referenceTo();
     type = new TypeFunction(arguments, tret, varargs, LINKd);
+    
+    if (!originalType)
+ 	originalType = type;
 
     sc->flags |= SCOPEctor;
     type = type->semantic(loc, sc);
     //printf("StaticCtorDeclaration::semantic()\n");
 
     type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    
+    /* If the static ctor appears within a template instantiation,
++      * it could get called multiple times by the module constructors
++      * for different modules. Thus, protect it with a gate.
++      */
+     if (inTemplateInstance())
+     {
+ 	/* Add this prefix to the function:
++ 	 *	static int gate;
++ 	 *	if (++gate != 1) return;
++ 	 * Note that this is not thread safe; should not have threads
++ 	 * during static construction.
++ 	 */
+ 	Identifier *id = Lexer::idPool("__gate");
+ 	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+ 	v->storage_class = STCstatic;
+ 	Statements *sa = new Statements();
+ 	Statement *s = new DeclarationStatement(0, v);
+ 	sa->push(s);
+ 	Expression *e = new IdentifierExp(0, id);
+ 	e = new AddAssignExp(0, e, new IntegerExp(1));
+ 	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+ 	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+ 	sa->push(s);
+ 	if (fbody)
+ 	    sa->push(fbody);
+ 	fbody = new CompoundStatement(0, sa);
+     }
 
     FuncDeclaration::semantic(sc);
 
     : FuncDeclaration(loc, endloc,
       Identifier::generateId("_staticDtor"), STCstatic, NULL)
 {
+	vgate = NULL;
 }
 
 Dsymbol *StaticDtorDeclaration::syntaxCopy(Dsymbol *s)
     {
     }
     type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
+    
+    /* If the static ctor appears within a template instantiation,
++      * it could get called multiple times by the module constructors
++      * for different modules. Thus, protect it with a gate.
++      */
+     if (inTemplateInstance())
+     {
+ 	/* Add this prefix to the function:
++ 	 *	static int gate;
++ 	 *	if (--gate != 0) return;
++ 	 * Increment gate during constructor execution.
++ 	 * Note that this is not thread safe; should not have threads
++ 	 * during static destruction.
++ 	 */
+ 	Identifier *id = Lexer::idPool("__gate");
+ 	VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL);
+ 	v->storage_class = STCstatic;
+ 	Statements *sa = new Statements();
+ 	Statement *s = new DeclarationStatement(0, v);
+ 	sa->push(s);
+ 	Expression *e = new IdentifierExp(0, id);
+ 	e = new AddAssignExp(0, e, new IntegerExp(-1));
+ 	e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1));
+ 	s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL);
+ 	sa->push(s);
+ 	if (fbody)
+ 	    sa->push(fbody);
+ 	fbody = new CompoundStatement(0, sa);
+ 	vgate = v;
+     }
 
     FuncDeclaration::semantic(sc);
 
 
 static Identifier *unitTestId()
 {
-    static int n;
-    char buffer[10 + sizeof(n)*3 + 1];
-
-    sprintf(buffer,"__unittest%d", n);
-    n++;
-    return Lexer::idPool(buffer);
+    return Lexer::uniqueId("__unittest");
 }
 
 UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc)
 			sprintf(time, "%.8s", p + 11);
 			sprintf(timestamp, "%.24s", p);
 		    }
-
+			#if V1
 		    if (mod && id == Id::FILE)
 		    {
 			t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars());
 			t->value = TOKint64v;
 			t->uns64value = loc.linnum;
 		    }
-		    else if (id == Id::DATE)
+		    else
+ 			#endif //if V1
+ 		    if (id == Id::DATE)
 		    {
 			t->ustring = (unsigned char *)date;
 			goto Lstring;
 #if V2
     {	"pure",		TOKpure		},
     {	"nothrow",	TOKnothrow	},
+    {	"__thread",	TOKtls		},
     {	"__traits",	TOKtraits	},
     {	"__overloadset", TOKoverloadset	},
+    {	"__FILE__",	TOKfile		},
+    {	"__LINE__",	TOKline		},
 #endif
 };
 
 	TOKtraits,
 	TOKoverloadset,
 	TOKpure,
+	TOKnothrow,
+ 	TOKtls,
+ 	TOKline,
+ 	TOKfile,
 #endif
 
 	TOKMAX
 
     copyright = "Copyright (c) 1999-2008 by Digital Mars";
     written = "written by Walter Bright";
-    version = "v1.030";
+    version = "v1.031";
     global.structalign = 8;
 
     memset(&params, 0, sizeof(Param));
 		global.params.link = 0;
 	    else if (strcmp(p + 1, "cov") == 0)
 		global.params.cov = 1;
+		#if TARGET_LINUX
 	    else if (strcmp(p + 1, "fPIC") == 0)
 		global.params.pic = 1;
+		#endif
 	    else if (strcmp(p + 1, "multiobj") == 0)
 		global.params.multiobj = 1;
 	    else if (strcmp(p + 1, "g") == 0)
     }
     if (global.params.cov)
 	VersionCondition::addPredefinedGlobalIdent("D_Coverage");
+	if (global.params.pic)
+ 	VersionCondition::addPredefinedGlobalIdent("D_PIC");
 #if V2
     if (global.params.useUnitTests)
 	VersionCondition::addPredefinedGlobalIdent("unittest");
     {
 	/* Create a TupleExp
 	 */
+	e = e->semantic(sc);	// do this before turning on noaccesscheck
 	Expressions *exps = new Expressions;
 	exps->reserve(sym->fields.dim);
 	for (size_t i = 0; i < sym->fields.dim; i++)
 	    exps->push(fe);
 	}
 	e = new TupleExp(e->loc, exps);
+	sc = sc->push();
+ 	sc->noaccesscheck = 1;
 	e = e->semantic(sc);
+	sc->pop();
 	return e;
     }
 
     {
 	/* Create a TupleExp
 	 */
+	e = e->semantic(sc);	// do this before turning on noaccesscheck
 	Expressions *exps = new Expressions;
 	exps->reserve(sym->fields.dim);
 	for (size_t i = 0; i < sym->fields.dim; i++)
 	    exps->push(fe);
 	}
 	e = new TupleExp(e->loc, exps);
-	e = e->semantic(sc);
+	sc = sc->push();
+ 	sc->noaccesscheck = 1;
+  	e = e->semantic(sc);
+ 	sc->pop();
 	return e;
     }
 
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
 // in artistic.txt, or the GNU General Public License in gnu.txt.
 // See the included readme.txt for details.
 
+// This is the D parser
+
 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
 
-   Modified by David Friedman, September 2004
+   Modified by Michael Parrott, September 2009
+   Using David Friedman's code
 */
 
 #include <stdio.h>
 //	(type)(expression)
 #define CCASTSYNTAX	1
 
-// Support C array declarations, such as
+// Support postfix C array declarations, such as
 //	int a[3][4];
 #define CARRAYDECL	1
 
     return new StaticAssert(loc, exp, msg);
 }
 
+#if V2
+ TypeQualified *Parser::parseTypeof()
+ {   TypeQualified *t;
+     Loc loc = this->loc;
+ 
+     nextToken();
+     check(TOKlparen);
+     if (token.value == TOKreturn)	// typeof(return)
+     {
+ 	nextToken();
+ 	t = new TypeReturn(loc);
+     }
+     else
+     {	Expression *exp = parseExpression();	// typeof(expression)
+ 	t = new TypeTypeof(loc, exp);
+     }
+     check(TOKrparen);
+     return t;
+ }
+ #endif
+
 
 /***********************************
  * Parse extern (linkage)
     check(TOKlparen);
     while (1)
     {   Type *tb;
-	Identifier *ai;
+	Identifier *ai = NULL;
 	Type *at;
 	Argument *a;
 	unsigned storageClass;
 	Expression *ae;
 
-	ai = NULL;
 	storageClass = STCin;		// parameter is "in" by default
 	switch (token.value)
 	{
     }
     else
 	error("enum declaration is invalid");
+	
+	//printf("-parseEnum() %s\n", e->toChars());
 
     return e;
 }
     return baseclasses;
 }
 
-/**************************************
- * Parse a TemplateDeclaration.
- */
+/**************************************
++  * Parse constraint.
++  * Constraint is of the form:
++  *	if ( ConstraintExpression )
++  */
+ 
+ #if V2
+ Expression *Parser::parseConstraint()
+ {   Expression *e = NULL;
+ 
+     if (token.value == TOKif)
+     {
+ 	nextToken();	// skip over 'if'
+ 	check(TOKlparen);
+ 	e = parseExpression();
+ 	check(TOKrparen);
+     }
+     return e;
+ }
+ #endif
+ 
+ /**************************************
+   * Parse a TemplateDeclaration.
+   */
 
 TemplateDeclaration *Parser::parseTemplateDeclaration()
 {
 		nextToken();
 		tp = new TemplateTupleParameter(loc, tp_ident);
 	    }
+	    #if V2
+ 	    else if (token.value == TOKthis)
+ 	    {	// ThisParameter
+ 		nextToken();
+ 		if (token.value != TOKidentifier)
+ 		{   error("identifier expected for template this parameter");
+ 		    goto Lerr;
+ 		}
+ 		tp_ident = token.ident;
+ 		nextToken();
+ 		if (token.value == TOKcolon)	// : Type
+ 		{
+ 		    nextToken();
+ 		    tp_spectype = parseType();
+ 		}
+ 		if (token.value == TOKassign)	// = Type
+ 		{
+ 		    nextToken();
+ 		    tp_defaulttype = parseType();
+ 		}
+ 		tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+ 	    }
+ 		#endif
 	    else
 	    {	// ValueParameter
 		tp_valtype = parseBasicType();
 		tp_valtype = parseDeclarator(tp_valtype, &tp_ident);
 		if (!tp_ident)
 		{
-		    error("no identifier for template value parameter");
+		    error("identifier expected for template value parameter");
 		    tp_ident = new Identifier("error", TOKidentifier);
 		}
 		if (token.value == TOKcolon)	// : CondExpression
 	    break;
 
 	case TOKdot:
+	// Leading . as in .foo
 	    id = Id::empty;
 	    goto Lident;
 
     return t;
 }
 
+/******************************************
++  * Parse things that follow the initial type t.
++  *	t *
++  *	t []
++  *	t [type]
++  *	t [expression]
++  *	t [expression .. expression]
++  *	t function
++  *	t delegate
++  */
+
 Type *Parser::parseBasicType2(Type *t)
 {
     Type *ts;
 	    break;
 
 	case TOKlparen:
+	/* Parse things with parentheses around the identifier, like:
++ 	     *	int (*ident[3])[]
++ 	     * although the D style would be:
++ 	     *	int[]*[3] ident
++ 	     */
 	    nextToken();
 	    ts = parseDeclarator(t, pident);
 	    check(TOKrparen);
 	switch (token.value)
 	{
 #if CARRAYDECL
+/* Support C style array syntax:
++ 	     *   int ident[]
++ 	     * as opposed to D-style:
++ 	     *   int[] ident
++ 	     */
 	    case TOKlbracket:
 	    {	// This is the old C-style post [] syntax.
 		nextToken();
 		if (token.value == TOKrbracket)
-		{
+		{ // It's a dynamic array
 		    ta = new TypeDArray(t);			// []
 		    nextToken();
 		}
 		    ta = new TypeSArray(t, e);
 		    check(TOKrbracket);
 		}
+		/* Insert ta into
++ 		 *   ts -> ... -> t
++ 		 * so that
++ 		 *   ts -> ... -> ta -> t
++ 		 */
 		Type **pt;
 		for (pt = &ts; *pt != t; pt = &(*pt)->next)
 		    ;
     return ts;
 }
 
-/**********************************
- * Return array of Declaration *'s.
- */
+/**********************************
++  * Parse Declarations.
++  * These can be:
++  *	1. declarations at global/class level
++  *	2. declarations at statement level
+   * Return array of Declaration *'s.
+   */
 
 Array *Parser::parseDeclarations()
 {
     return a;
 }
 
-/*****************************************
- * Parse contracts following function declaration.
- */
+  /*****************************************
++  * Parse auto declarations of the form:
++  *   storageClass ident = init, ident = init, ... ;
++  * and return the array of them.
++  * Starts with token on the first ident.
++  * Ends with scanner past closing ';'
++  */
+ 
+ #if V2
+ Array *Parser::parseAutoDeclarations(unsigned storageClass, unsigned char *comment)
+ {
+     Array *a = new Array;
+ 
+     while (1)
+     {
+ 	Identifier *ident = token.ident;
+ 	nextToken();		// skip over ident
+ 	assert(token.value == TOKassign);
+ 	nextToken();		// skip over '='
+ 	Initializer *init = parseInitializer();
+ 	VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init);
+ 	v->storage_class = storageClass;
+ 	a->push(v);
+ 	if (token.value == TOKsemicolon)
+ 	{
+ 	    nextToken();
+ 	    addComment(v, comment);
+ 	}
+ 	else if (token.value == TOKcomma)
+ 	{
+ 	    nextToken();
+ 	    if (token.value == TOKidentifier &&
+ 		peek(&token)->value == TOKassign)
+ 	    {
+ 		addComment(v, comment);
+ 		continue;
+ 	    }
+ 	    else
+ 		error("Identifier expected following comma");
+ 	}
+ 	else
+ 	    error("semicolon expected following auto declaration, not '%s'", token.toChars());
+ 	break;
+     }
+     return a;
+ }
+ #endif
+ 
+ /*****************************************
+   * Parse contracts following function declaration.
+   */
 
 void Parser::parseContracts(FuncDeclaration *f)
 {
     }
 }
 
+/*****************************************
++  * Parses default argument initializer expression that is an assign expression,
++  * with special handling for __FILE__ and __LINE__.
++  */
+ 
+ #if V2
+ Expression *Parser::parseDefaultInitExp()
+ {
+     if (token.value == TOKfile ||
+ 	token.value == TOKline)
+     {
+	Token *t = peek(&token);
+ 	if (t->value == TOKcomma || t->value == TOKrparen)
+ 	{   Expression *e;
+ 
+ 	    if (token.value == TOKfile)
+ 		e = new FileInitExp(loc);
+ 	    else
+ 		e = new LineInitExp(loc);
+ 	    nextToken();
+ 	    return e;
+ 	}
+     }
+ 
+     Expression *e = parseAssignExp();
+     return e;
+ }
+ #endif
 
 /*****************************************
  * Input:
 	case TOKtypeid:
 	case TOKis:
 	case TOKlbracket:
+	#if V2
+ 	case TOKtraits:
+ 	case TOKfile:
+ 	case TOKline:
+	#endif
 	Lexp:
 	{   Expression *exp;
 
 	case TOKvolatile:
 	    nextToken();
 	    s = parseStatement(PSsemi | PScurlyscope);
+	    #if V2
+ 	    if (!global.params.useDeprecated)
+ 		error("volatile statements deprecated; used synchronized statements instead");
+ 		#endif
 	    s = new VolatileStatement(loc, s);
 	    break;
 
 int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt)
 {
     int haveId = 0;
+    
+    #if V2
+     if ((t->value == TOKconst || t->value == TOKinvariant) &&
+ 	peek(t)->value != TOKlparen)
+     {	/* const type
++ 	 * invariant type
++ 	 */
+ 	t = peek(t);
+     }
+ 	#endif
 
     if (!isBasicType(&t))
 	return FALSE;
     Identifier *id;
     enum TOK save;
     Loc loc = this->loc;
+    
+    //printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
 
     switch (token.value)
     {
 	    e = new NullExp(loc);
 	    nextToken();
 	    break;
+	    
+	#if V2
+ 	case TOKfile:
+ 	{   char *s = loc.filename ? loc.filename : mod->ident->toChars();
+ 	    e = new StringExp(loc, s, strlen(s), 0);
+ 	    nextToken();
+ 	    break;
+ 	}
+ 
+ 	case TOKline:
+ 	    e = new IntegerExp(loc, loc.linnum, Type::tint32);
+ 	    nextToken();
+ 	    break;
+ #endif
 
 	case TOKtrue:
 	    e = new IntegerExp(loc, 1, Type::tbool);
 	    e = new TypeidExp(loc, t);
 	    break;
 	}
+	
+	#if V2
+ 	case TOKtraits:
+ 	{   /* __traits(identifier, args...)
++ 	     */
+ 	    Identifier *ident;
+ 	    Objects *args = NULL;
+ 
+ 	    nextToken();
+ 	    check(TOKlparen);
+ 	    if (token.value != TOKidentifier)
+ 	    {   error("__traits(identifier, args...) expected");
+ 		goto Lerr;
+ 	    }
+ 	    ident = token.ident;
+ 	    nextToken();
+ 	    if (token.value == TOKcomma)
+ 		args = parseTemplateArgumentList2();	// __traits(identifier, args...)
+	    else
+ 		check(TOKrparen);		// __traits(identifier)
+ 
+ 	    e = new TraitsExp(loc, ident, args);
+ 	    break;
+ 	}
+ #endif
 
 	case TOKis:
 	{   Type *targ;
 		    case TOKfunction:
 		    case TOKdelegate:
 		    case TOKtypeof:
+		    
+		    #if V2
+ 		    case TOKfile:
+		    case TOKline:
+ 			#endif
 		    CASE_BASIC_TYPES:		// (type)int.size
 		    {	// (type) una_exp
 			Type *t;
     Expression *e2;
     Loc loc = this->loc;
 
-    //printf("Parser::parseExpression()\n");
+    //printf("Parser::parseExpression() loc = %d\n", loc.linnum);
     e = parseAssignExp();
     while (token.value == TOKcomma)
     {
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
 #include "enum.h"
 
 struct Type;
+struct TypeQualified;
 struct Expression;
 struct Declaration;
 struct Statement;
 struct Initializer;
 struct FuncDeclaration;
 struct CtorDeclaration;
+struct PostBlitDeclaration;
 struct DtorDeclaration;
 struct StaticCtorDeclaration;
 struct StaticDtorDeclaration;

d/dmd/statement.c

 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
 
-   Modified by David Friedman, September 2004
+   Modified by Michael Parrott, September 2009
+   Using David Friedman's code
 */
 
 #include <stdio.h>
         buf->writenl();
 }
 
-Statement *CompileStatement::semantic(Scope *sc)
-{
-    //printf("CompileStatement::semantic() %s\n", exp->toChars());
+Statements *CompileStatement::flatten(Scope *sc)
+{
+     //printf("CompileStatement::flatten() %s\n", exp->toChars());
     exp = exp->semantic(sc);
     exp = resolveProperties(sc, exp);
     exp = exp->optimize(WANTvalue | WANTinterpret);
     if (exp->op != TOKstring)
     {	error("argument to mixin must be a string, not (%s)", exp->toChars());
-	return this;
+	return NULL;
     }
     StringExp *se = (StringExp *)exp;
     se = se->toUTF8(sc);
     p.loc = loc;
     p.nextToken();
 
-    Statements *statements = new Statements();
+    Statements *a = new Statements();
     while (p.token.value != TOKeof)
     {
 	Statement *s = p.parseStatement(PSsemi | PScurlyscope);
-	statements->push(s);
+	a->push(s);
     }
 
-    Statement *s = new CompoundStatement(loc, statements);
-    return s->semantic(sc);
+    return a;
 }
 
+Statement *CompileStatement::semantic(Scope *sc)
+ {
+     printf("CompileStatement::semantic() %s\n", exp->toChars());
+     /* Shouldn't happen unless errors, as CompileStatement::flatten()
++      * should have replaced it.
++      * Return NULL so no further errors happen.
++      */
+     assert(global.errors);
+     return NULL;
+ }
+
 
 /******************************** DeclarationStatement ***************************/
 
 	i++;
     }
     if (statements->dim == 1)
-	return s;
+	{
+ 	return (Statement *)statements->data[0];
+     }
     return this;
 }
 
 {
     condition->toCBuffer(buf, hgs);
     buf->writenl();
+    buf->writeByte('{');
+    buf->writenl();
     if (ifbody)
 	ifbody->toCBuffer(buf, hgs);
+	buf->writeByte('}');
+    buf->writenl();
     if (elsebody)
     {
 	buf->writestring("else");
 	buf->writenl();
+	buf->writeByte('{');
+ 	buf->writenl();
 	elsebody->toCBuffer(buf, hgs);
+	buf->writeByte('}');
+ 	buf->writenl();
     }
     buf->writenl();
 }

d/dmd/statement.h

     CompileStatement(Loc loc, Expression *exp);
     Statement *syntaxCopy();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    Statements *flatten(Scope *sc);
     Statement *semantic(Scope *sc);
 };
 
 		}
 		//printf("\tm2 = %d\n", m);
 	    }
+	    
+	    /* If no match, see if we can implicitly convert farg to the
++ 	     * parameter type.
++ 	     */
+ 	    if (!m)
+ 	    {	m = farg->implicitConvTo(fparam->type);
+ 	    }
 
 	    if (m)
 	    {	if (m < match)
 		continue;
 	    }
 	}
+	
+	/* The following code for variadic arguments closely
++ 	 * matches TypeFunction::callMatch()
++ 	 */
 	if (!(fdtype->varargs == 2 && i + 1 == nfparams))
 	    goto Lnomatch;
 
 	/* Check for match with function parameter T...
 	 */
-	Type *t = fparam->type;
-	switch (t->ty)
+	Type *tb = fparam->type->toBasetype();
+ 	switch (tb->ty)
 	{
 	    // Perhaps we can do better with this, see TypeFunction::callMatch()
 	    case Tsarray:
-	    case Tarray:
+	    {	TypeSArray *tsa = (TypeSArray *)tb;
+ 		integer_t sz = tsa->dim->toInteger();
+ 		if (sz != nfargs - i)
+ 		    goto Lnomatch;
+	    }
+  	    case Tarray:
+ 	    {   TypeArray *ta = (TypeArray *)tb;
+ 		for (; i < nfargs; i++)
+ 		{
+ 		    Expression *arg = (Expression *)fargs->data[i];
+ 		    assert(arg);
+ 		    MATCH m;
+ 		    /* If lazy array of delegates,
++ 		     * convert arg(s) to delegate(s)
++ 		     */
+ 		    Type *tret = fparam->isLazyArray();
+ 		    if (tret)
+ 		    {
+ 			if (ta->next->equals(arg->type))
+ 			{   m = MATCHexact;
+ 			}
+ 			else
+ 			{
+ 			    m = arg->implicitConvTo(tret);
+ 			    if (m == MATCHnomatch)
+ 			    {
+ 				if (tret->toBasetype()->ty == Tvoid)
+ 				    m = MATCHconvert;
+ 			    }
+ 			}
+ 		    }
+ 		    else
+ 		    {
+ 			m = arg->type->deduceType(scope, ta->next, parameters, &dedtypes);
+ 			//m = arg->implicitConvTo(ta->next);
+ 		    }
+ 		    if (m == MATCHnomatch)
+ 			goto Lnomatch;
+ 		    if (m < match)
+ 			match = m;
+ 		}
+ 		goto Lmatch;
+ 	    }
 	    case Tclass:
 	    case Tident:
 		goto Lmatch;
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
+    this->semantictiargsdone = 0;
     this->withsym = NULL;
     this->nest = 0;
 #ifdef IN_GCC
     this->argsym = NULL;
     this->aliasdecl = NULL;
     this->semanticdone = 0;
+    this->semantictiargsdone = 1;
     this->withsym = NULL;
     this->nest = 0;
 #ifdef IN_GCC
 void TemplateInstance::semanticTiargs(Scope *sc)
 {
     //printf("+TemplateInstance::semanticTiargs() %s\n", toChars());
+    if (semantictiargsdone)
+ 	return;
+     semantictiargsdone = 1;
     semanticTiargs(loc, sc, tiargs);
 }
 
 void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
 {
     buf->writestring("mixin ");
-    int i;
-    for (i = 0; i < idents->dim; i++)
+    for (int i = 0; i < idents->dim; i++)
     {   Identifier *id = (Identifier *)idents->data[i];
 
     	if (i)
     buf->writestring("!(");
     if (tiargs)
     {
-        for (i = 0; i < tiargs->dim; i++)
+        for (int i = 0; i < tiargs->dim; i++)
         {   if (i)
                 buf->writebyte(',');
 	    Object *oarg = (Object *)tiargs->data[i];
         }
     }
     buf->writebyte(')');
+    if (ident)
+     {
+ 	buf->writebyte(' ');
+ 	buf->writestring(ident->toChars());
+     }
     buf->writebyte(';');
     buf->writenl();
 }
 					// sole member
     WithScopeSymbol *withsym;		// if a member of a with statement
     int semanticdone;	// has semantic() been done?
+    int semantictiargsdone;	// has semanticTiargs() been done?
     int nest;		// for recursion detection
     int havetempdecl;	// 1 if used second constructor
     Dsymbol *isnested;	// if referencing local symbols, this is the context
 	"4math4sqrtFfZf",
 	"4math5ldexpFeiZe",
 	"4math6rndtolFeZl",
+	#if V1
+  	"9intrinsic2btFPkkZi",
+ 	#else
+ 	"9intrinsic2btFxPkkZi",
+ 	#endif
 
 	"9intrinsic2btFPkkZi",
 	"9intrinsic3bsfFkZi",
     if (needsClosure())
     {   // Generate closure on the heap
 	// BUG: doesn't capture variadic arguments passed to this function
+	
+	#if V2
+ 	/* BUG: doesn't handle destructors for the local variables.
++ 	 * The way to do it is to make the closure variables the fields
++ 	 * of a class object:
++ 	 *    class Closure
++ 	 *    {   vtbl[]
++ 	 *	  monitor
++ 	 *	  ptr to destructor
++ 	 *	  sthis
++ 	 *	  ... closure variables ...
++ 	 *	  ~this() { call destructor }
++ 	 *    }
++ 	 */
+ #endif
+ 	//printf("FuncDeclaration::buildClosure()\n");
 
 	Symbol *sclosure;
 	sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype());
 	for (int i = 0; i < closureVars.dim; i++)
 	{   VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
 	    assert(v->isVarDeclaration());
+	    #if V2
+ 	    if (v->needsAutoDtor())
+ 		v->error("has scoped destruction, cannot build closure");
+ 		#endif
 
 	    /* Align and allocate space for v in the closure
 	     * just like AggregateDeclaration::addField() does.
 
 #endif
 
+/***************************
++  * Determine return style of function - whether in registers or
++  * through a hidden pointer to the caller's stack.
++  */
+ 
+ enum RET TypeFunction::retStyle()
+ {
+    //printf("TypeFunction::retStyle() %s\n", toChars());
+     Type *tn = next->toBasetype();
+ 
+     if (tn->ty == Tstruct)
+     {	StructDeclaration *sd = ((TypeStruct *)tn)->sym;
+ 	if (global.params.isLinux && linkage != LINKd)
+ 	    ;
+ #if V2
+ 	else if (sd->dtor || sd->cpctor)
+ 	    ;
+ #endif
+ 	else
+ 	{
+ 	    switch ((int)tn->size())
+ 	    {   case 1:
+ 		case 2:
+ 		case 4:
+ 		case 8:
+ 		    return RETregs;	// return small structs in regs
+ 					// (not 3 byte structs!)
+ 		default:
+ 		    break;
+ 	    }
+ 	}
+ 	return RETstack;
+     }
+     else if (global.params.isLinux &&
+ 	     linkage == LINKc &&
+ 	     tn->iscomplex())
+     {
+ 	if (tn->ty == Tcomplex32)
+ 	    return RETregs;	// in EDX:EAX, not ST1:ST0
+ 	else
+ 	    return RETstack;
+     }
+     else
+ 	return RETregs;
+ }
+
 /* NOTE: This file has been patched from the original DMD distribution to
    work with the GDC compiler.
 
-   Modified by David Friedman, September 2004
+   Modified by Michael Parrott, September 2009
+   Using David Friedman's code
 */
 
 #include <stdio.h>
 	dtdword(&dt, 0);		// BUG: should be an assert()
     }
     dtdword(&dt, 0);			// monitor
+    
+    #if V2
+     FuncDeclaration *sgetmembers = findGetMembers();
+     if (sgetmembers)
+ 	dtxoff(&dt, sgetmembers->toSymbol(), 0, TYnptr);
+     else
+ #endif
 
     // name[]
     char *name = toPrettyChars();
 
     assert(!scope);	// semantic() should have been run to completion
 
-    if (parent && parent->isTemplateInstance())
-	scclass = SCcomdat;
-    else
-	scclass = SCglobal;
+    scclass = SCglobal;
+     if (inTemplateInstance()) //possible changes needed here
+  	scclass = SCcomdat;
 
     // Put out the members
     for (i = 0; i < members->dim; i++)
 	    void *deallocator;
 	    OffsetTypeInfo[] offTi;
 	    void *defaultConstructor;
+	    const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
        }
      */
     dt_t *dt = NULL;
 
     // flags
     int flags = 4 | isCOMclass();
+    #if V2
+     flags |= 16;
+ #endif