diff dmd/init.c @ 336:aaade6ded589 trunk

[svn r357] Merged DMD 1.033
author lindquist
date Sat, 12 Jul 2008 19:38:31 +0200
parents 2b72433d5c8c
children eeb8b95ea92e
line wrap: on
line diff
--- a/dmd/init.c	Sat Jul 12 17:04:36 2008 +0200
+++ b/dmd/init.c	Sat Jul 12 19:38:31 2008 +0200
@@ -1,584 +1,586 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 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 "mars.h"
-#include "init.h"
-#include "expression.h"
-#include "statement.h"
-#include "identifier.h"
-#include "declaration.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "hdrgen.h"
-
-/********************************** Initializer *******************************/
-
-Initializer::Initializer(Loc loc)
-{
-    this->loc = loc;
-}
-
-Initializer *Initializer::syntaxCopy()
-{
-    return this;
-}
-
-Initializer *Initializer::semantic(Scope *sc, Type *t)
-{
-    return this;
-}
-
-Type *Initializer::inferType(Scope *sc)
-{
-    error(loc, "cannot infer type from initializer");
-    return Type::terror;
-}
-
-Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
-{   Initializers *a = NULL;
-
-    if (ai)
-    {
-	a = new Initializers();
-	a->setDim(ai->dim);
-	for (int i = 0; i < a->dim; i++)
-	{   Initializer *e = (Initializer *)ai->data[i];
-
-	    e = e->syntaxCopy();
-	    a->data[i] = e;
-	}
-    }
-    return a;
-}
-
-char *Initializer::toChars()
-{   OutBuffer *buf;
-    HdrGenState hgs;
-
-    memset(&hgs, 0, sizeof(hgs));
-    buf = new OutBuffer();
-    toCBuffer(buf, &hgs);
-    return buf->toChars();
-}
-
-/********************************** VoidInitializer ***************************/
-
-VoidInitializer::VoidInitializer(Loc loc)
-    : Initializer(loc)
-{
-    type = NULL;
-}
-
-
-Initializer *VoidInitializer::syntaxCopy()
-{
-    return new VoidInitializer(loc);
-}
-
-
-Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
-{
-    //printf("VoidInitializer::semantic(t = %p)\n", t);
-    type = t;
-    return this;
-}
-
-
-Expression *VoidInitializer::toExpression()
-{
-    error(loc, "void initializer has no value");
-    return new IntegerExp(0);
-}
-
-
-void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("void");
-}
-
-
-/********************************** StructInitializer *************************/
-
-StructInitializer::StructInitializer(Loc loc)
-    : Initializer(loc)
-{
-    ad = NULL;
-}
-
-Initializer *StructInitializer::syntaxCopy()
-{
-    StructInitializer *ai = new StructInitializer(loc);
-
-    assert(field.dim == value.dim);
-    ai->field.setDim(field.dim);
-    ai->value.setDim(value.dim);
-    for (int i = 0; i < field.dim; i++)
-    {    
-	ai->field.data[i] = field.data[i];
-
-	Initializer *init = (Initializer *)value.data[i];
-	init = init->syntaxCopy();
-	ai->value.data[i] = init;
-    }
-    return ai;
-}
-
-void StructInitializer::addInit(Identifier *field, Initializer *value)
-{
-    //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
-    this->field.push(field);
-    this->value.push(value);
-}
-
-Initializer *StructInitializer::semantic(Scope *sc, Type *t)
-{
-    TypeStruct *ts;
-    int errors = 0;
-
-    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
-    vars.setDim(field.dim);
-    t = t->toBasetype();
-    if (t->ty == Tstruct)
-    {	unsigned i;
-	unsigned fieldi = 0;
-
-	ts = (TypeStruct *)t;
-	ad = ts->sym;
-	for (i = 0; i < field.dim; i++)
-	{
-	    Identifier *id = (Identifier *)field.data[i];
-	    Initializer *val = (Initializer *)value.data[i];
-	    Dsymbol *s;
-	    VarDeclaration *v;
-
-	    if (id == NULL)
-	    {
-		if (fieldi >= ad->fields.dim)
-		{   error(loc, "too many initializers for %s", ad->toChars());
-		    continue;
-		}
-		else
-		{
-		    s = (Dsymbol *)ad->fields.data[fieldi];
-		}
-	    }
-	    else
-	    {
-		//s = ad->symtab->lookup(id);
-		s = ad->search(loc, id, 0);
-		if (!s)
-		{
-		    error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
-		    continue;
-		}
-
-		// Find out which field index it is
-		for (fieldi = 0; 1; fieldi++)
-		{
-		    if (fieldi >= ad->fields.dim)
-		    {
-			s->error("is not a per-instance initializable field");
-			break;
-		    }
-		    if (s == (Dsymbol *)ad->fields.data[fieldi])
-			break;
-		}
-	    }
-	    if (s && (v = s->isVarDeclaration()) != NULL)
-	    {
-		val = val->semantic(sc, v->type);
-		value.data[i] = (void *)val;
-		vars.data[i] = (void *)v;
-	    }
-	    else
-	    {	error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
-		errors = 1;
-	    }
-	    fieldi++;
-	}
-    }
-    else if (t->ty == Tdelegate && value.dim == 0)
-    {	/* Rewrite as empty delegate literal { }
-	 */
-	Arguments *arguments = new Arguments;
-	Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
-	FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
-	fd->fbody = new CompoundStatement(loc, new Statements());
-	fd->endloc = loc;
-	Expression *e = new FuncExp(loc, fd);
-	ExpInitializer *ie = new ExpInitializer(loc, e);
-	return ie->semantic(sc, t);
-    }
-    else
-    {
-	error(loc, "a struct is not a valid initializer for a %s", t->toChars());
-	errors = 1;
-    }
-    if (errors)
-    {
-	field.setDim(0);
-	value.setDim(0);
-	vars.setDim(0);
-    }
-    return this;
-}
-
-
-/***************************************
- * This works by transforming a struct initializer into
- * a struct literal. In the future, the two should be the
- * same thing.
- */
-Expression *StructInitializer::toExpression()
-{   Expression *e;
-
-    //printf("StructInitializer::toExpression() %s\n", toChars());
-    if (!ad)				// if fwd referenced
-    {
-	return NULL;
-    }
-    StructDeclaration *sd = ad->isStructDeclaration();
-    if (!sd)
-	return NULL;
-    Expressions *elements = new Expressions();
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (field.data[i])
-	    goto Lno;
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	Expression *ex = iz->toExpression();
-	if (!ex)
-	    goto Lno;
-	elements->push(ex);
-    }
-    e = new StructLiteralExp(loc, sd, elements);
-    e->type = sd->type;
-    return e;
-
-Lno:
-    delete elements;
-    //error(loc, "struct initializers as expressions are not allowed");
-    return NULL;
-}
-
-
-void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    //printf("StructInitializer::toCBuffer()\n");
-    buf->writebyte('{');
-    for (int i = 0; i < field.dim; i++)
-    {
-        if (i > 0)
-	    buf->writebyte(',');
-        Identifier *id = (Identifier *)field.data[i];
-        if (id)
-        {
-            buf->writestring(id->toChars());
-            buf->writebyte(':');
-        }
-        Initializer *iz = (Initializer *)value.data[i];
-        if (iz)
-            iz->toCBuffer(buf, hgs);
-    }
-    buf->writebyte('}');
-}
-
-/********************************** ArrayInitializer ************************************/
-
-ArrayInitializer::ArrayInitializer(Loc loc)
-    : Initializer(loc)
-{
-    dim = 0;
-    type = NULL;
-    sem = 0;
-}
-
-Initializer *ArrayInitializer::syntaxCopy()
-{
-    //printf("ArrayInitializer::syntaxCopy()\n");
-
-    ArrayInitializer *ai = new ArrayInitializer(loc);
-
-    assert(index.dim == value.dim);
-    ai->index.setDim(index.dim);
-    ai->value.setDim(value.dim);
-    for (int i = 0; i < ai->value.dim; i++)
-    {	Expression *e = (Expression *)index.data[i];
-	if (e)
-	    e = e->syntaxCopy();
-	ai->index.data[i] = e;
-
-	Initializer *init = (Initializer *)value.data[i];
-	init = init->syntaxCopy();
-	ai->value.data[i] = init;
-    }
-    return ai;
-}
-
-void ArrayInitializer::addInit(Expression *index, Initializer *value)
-{
-    this->index.push(index);
-    this->value.push(value);
-    dim = 0;
-    type = NULL;
-}
-
-Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
-{   unsigned i;
-    unsigned length;
-
-    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
-    if (sem)				// if semantic() already run
-	return this;
-    sem = 1;
-    type = t;
-    t = t->toBasetype();
-    switch (t->ty)
-    {
-	case Tpointer:
-	case Tsarray:
-	case Tarray:
-	    break;
-
-	default:
-	    error(loc, "cannot use array to initialize %s", type->toChars());
-	    return this;
-    }
-
-    length = 0;
-    for (i = 0; i < index.dim; i++)
-    {	Expression *idx;
-	Initializer *val;
-
-	idx = (Expression *)index.data[i];
-	if (idx)
-	{   idx = idx->semantic(sc);
-	    idx = idx->optimize(WANTvalue | WANTinterpret);
-	    index.data[i] = (void *)idx;
-	    length = idx->toInteger();
-	}
-
-	val = (Initializer *)value.data[i];
-	val = val->semantic(sc, t->next);
-	value.data[i] = (void *)val;
-	length++;
-	if (length == 0)
-	    error("array dimension overflow");
-	if (length > dim)
-	    dim = length;
-    }
-    unsigned long amax = 0x80000000;
-    if ((unsigned long) dim * t->next->size() >= amax)
-	error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size());
-    return this;
-}
-
-/********************************
- * If possible, convert array initializer to array literal.
- */
-
-Expression *ArrayInitializer::toExpression()
-{   Expressions *elements;
-    Expression *e;
-
-    //printf("ArrayInitializer::toExpression()\n");
-    //static int i; if (++i == 2) halt();
-    elements = new Expressions();
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (index.data[i])
-	    goto Lno;
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	Expression *ex = iz->toExpression();
-	if (!ex)
-	    goto Lno;
-	elements->push(ex);
-    }
-    e = new ArrayLiteralExp(loc, elements);
-    e->type = type;
-    return e;
-
-Lno:
-    delete elements;
-    error(loc, "array initializers as expressions are not allowed");
-    return NULL;
-}
-
-
-/********************************
- * If possible, convert array initializer to associative array initializer.
- */
-
-Initializer *ArrayInitializer::toAssocArrayInitializer()
-{   Expressions *keys;
-    Expressions *values;
-    Expression *e;
-
-    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
-    //static int i; if (++i == 2) halt();
-    keys = new Expressions();
-    keys->setDim(value.dim);
-    values = new Expressions();
-    values->setDim(value.dim);
-
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	e = (Expression *)index.data[i];
-	if (!e)
-	    goto Lno;
-	keys->data[i] = (void *)e;
-
-	Initializer *iz = (Initializer *)value.data[i];
-	if (!iz)
-	    goto Lno;
-	e = iz->toExpression();
-	if (!e)
-	    goto Lno;
-	values->data[i] = (void *)e;
-    }
-    e = new AssocArrayLiteralExp(loc, keys, values);
-    return new ExpInitializer(loc, e);
-
-Lno:
-    delete keys;
-    delete values;
-    error(loc, "not an associative array initializer");
-    return this;
-}
-
-
-Type *ArrayInitializer::inferType(Scope *sc)
-{
-    for (size_t i = 0; i < value.dim; i++)
-    {
-	if (index.data[i])
-	    goto Lno;
-    }
-    if (value.dim)
-    {
-	Initializer *iz = (Initializer *)value.data[0];
-	if (iz)
-	{   Type *t = iz->inferType(sc);
-	    t = new TypeSArray(t, new IntegerExp(value.dim));
-	    t = t->semantic(loc, sc);
-	    return t;
-	}
-    }
-
-Lno:
-    error(loc, "cannot infer type from this array initializer");
-    return Type::terror;
-}
-
-
-void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writebyte('[');
-    for (int i = 0; i < index.dim; i++)
-    {
-        if (i > 0)
-	    buf->writebyte(',');
-        Expression *ex = (Expression *)index.data[i];
-        if (ex)
-        {
-            ex->toCBuffer(buf, hgs);
-            buf->writebyte(':');
-        }
-        Initializer *iz = (Initializer *)value.data[i];
-        if (iz)
-            iz->toCBuffer(buf, hgs);
-    }
-    buf->writebyte(']');
-}
-
-
-/********************************** ExpInitializer ************************************/
-
-ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
-    : Initializer(loc)
-{
-    this->exp = exp;
-}
-
-Initializer *ExpInitializer::syntaxCopy()
-{
-    return new ExpInitializer(loc, exp->syntaxCopy());
-}
-
-Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
-{
-    //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
-    exp = exp->semantic(sc);
-    Type *tb = t->toBasetype();
-
-    /* Look for case of initializing a static array with a too-short
-     * string literal, such as:
-     *	char[5] foo = "abc";
-     * Allow this by doing an explicit cast, which will lengthen the string
-     * literal.
-     */
-    if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
-    {	StringExp *se = (StringExp *)exp;
-
-	if (!se->committed && se->type->ty == Tsarray &&
-	    ((TypeSArray *)se->type)->dim->toInteger() <
-	    ((TypeSArray *)t)->dim->toInteger())
-	{
-	    exp = se->castTo(sc, t);
-	    goto L1;
-	}
-    }
-
-    // Look for the case of statically initializing an array
-    // with a single member.
-    if (tb->ty == Tsarray &&
-	!tb->next->equals(exp->type->toBasetype()->next) &&
-	exp->implicitConvTo(tb->next)
-       )
-    {
-	t = tb->next;
-    }
-
-    exp = exp->implicitCastTo(sc, t);
-L1:
-    exp = exp->optimize(WANTvalue | WANTinterpret);
-    //printf("-ExpInitializer::semantic(): "); exp->print();
-    return this;
-}
-
-Type *ExpInitializer::inferType(Scope *sc)
-{
-    //printf("ExpInitializer::inferType() %s\n", toChars());
-    exp = exp->semantic(sc);
-    exp = resolveProperties(sc, exp);
-    return exp->type;
-}
-
-Expression *ExpInitializer::toExpression()
-{
-    return exp;
-}
-
-
-void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    exp->toCBuffer(buf, hgs);
-}
-
-
-
+
+// 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 "mars.h"
+#include "init.h"
+#include "expression.h"
+#include "statement.h"
+#include "identifier.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "hdrgen.h"
+
+/********************************** Initializer *******************************/
+
+Initializer::Initializer(Loc loc)
+{
+    this->loc = loc;
+}
+
+Initializer *Initializer::syntaxCopy()
+{
+    return this;
+}
+
+Initializer *Initializer::semantic(Scope *sc, Type *t)
+{
+    return this;
+}
+
+Type *Initializer::inferType(Scope *sc)
+{
+    error(loc, "cannot infer type from initializer");
+    return Type::terror;
+}
+
+Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
+{   Initializers *a = NULL;
+
+    if (ai)
+    {
+	a = new Initializers();
+	a->setDim(ai->dim);
+	for (int i = 0; i < a->dim; i++)
+	{   Initializer *e = (Initializer *)ai->data[i];
+
+	    e = e->syntaxCopy();
+	    a->data[i] = e;
+	}
+    }
+    return a;
+}
+
+char *Initializer::toChars()
+{   OutBuffer *buf;
+    HdrGenState hgs;
+
+    memset(&hgs, 0, sizeof(hgs));
+    buf = new OutBuffer();
+    toCBuffer(buf, &hgs);
+    return buf->toChars();
+}
+
+/********************************** VoidInitializer ***************************/
+
+VoidInitializer::VoidInitializer(Loc loc)
+    : Initializer(loc)
+{
+    type = NULL;
+}
+
+
+Initializer *VoidInitializer::syntaxCopy()
+{
+    return new VoidInitializer(loc);
+}
+
+
+Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
+{
+    //printf("VoidInitializer::semantic(t = %p)\n", t);
+    type = t;
+    return this;
+}
+
+
+Expression *VoidInitializer::toExpression()
+{
+    error(loc, "void initializer has no value");
+    return new IntegerExp(0);
+}
+
+
+void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("void");
+}
+
+
+/********************************** StructInitializer *************************/
+
+StructInitializer::StructInitializer(Loc loc)
+    : Initializer(loc)
+{
+    ad = NULL;
+}
+
+Initializer *StructInitializer::syntaxCopy()
+{
+    StructInitializer *ai = new StructInitializer(loc);
+
+    assert(field.dim == value.dim);
+    ai->field.setDim(field.dim);
+    ai->value.setDim(value.dim);
+    for (int i = 0; i < field.dim; i++)
+    {    
+	ai->field.data[i] = field.data[i];
+
+	Initializer *init = (Initializer *)value.data[i];
+	init = init->syntaxCopy();
+	ai->value.data[i] = init;
+    }
+    return ai;
+}
+
+void StructInitializer::addInit(Identifier *field, Initializer *value)
+{
+    //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
+    this->field.push(field);
+    this->value.push(value);
+}
+
+Initializer *StructInitializer::semantic(Scope *sc, Type *t)
+{
+    TypeStruct *ts;
+    int errors = 0;
+
+    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
+    vars.setDim(field.dim);
+    t = t->toBasetype();
+    if (t->ty == Tstruct)
+    {	unsigned i;
+	unsigned fieldi = 0;
+
+	ts = (TypeStruct *)t;
+	ad = ts->sym;
+	for (i = 0; i < field.dim; i++)
+	{
+	    Identifier *id = (Identifier *)field.data[i];
+	    Initializer *val = (Initializer *)value.data[i];
+	    Dsymbol *s;
+	    VarDeclaration *v;
+
+	    if (id == NULL)
+	    {
+		if (fieldi >= ad->fields.dim)
+		{   error(loc, "too many initializers for %s", ad->toChars());
+		    field.remove(i);
+		    i--;
+		    continue;
+		}
+		else
+		{
+		    s = (Dsymbol *)ad->fields.data[fieldi];
+		}
+	    }
+	    else
+	    {
+		//s = ad->symtab->lookup(id);
+		s = ad->search(loc, id, 0);
+		if (!s)
+		{
+		    error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
+		    continue;
+		}
+
+		// Find out which field index it is
+		for (fieldi = 0; 1; fieldi++)
+		{
+		    if (fieldi >= ad->fields.dim)
+		    {
+			s->error("is not a per-instance initializable field");
+			break;
+		    }
+		    if (s == (Dsymbol *)ad->fields.data[fieldi])
+			break;
+		}
+	    }
+	    if (s && (v = s->isVarDeclaration()) != NULL)
+	    {
+		val = val->semantic(sc, v->type);
+		value.data[i] = (void *)val;
+		vars.data[i] = (void *)v;
+	    }
+	    else
+	    {	error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
+		errors = 1;
+	    }
+	    fieldi++;
+	}
+    }
+    else if (t->ty == Tdelegate && value.dim == 0)
+    {	/* Rewrite as empty delegate literal { }
+	 */
+	Arguments *arguments = new Arguments;
+	Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
+	FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
+	fd->fbody = new CompoundStatement(loc, new Statements());
+	fd->endloc = loc;
+	Expression *e = new FuncExp(loc, fd);
+	ExpInitializer *ie = new ExpInitializer(loc, e);
+	return ie->semantic(sc, t);
+    }
+    else
+    {
+	error(loc, "a struct is not a valid initializer for a %s", t->toChars());
+	errors = 1;
+    }
+    if (errors)
+    {
+	field.setDim(0);
+	value.setDim(0);
+	vars.setDim(0);
+    }
+    return this;
+}
+
+
+/***************************************
+ * This works by transforming a struct initializer into
+ * a struct literal. In the future, the two should be the
+ * same thing.
+ */
+Expression *StructInitializer::toExpression()
+{   Expression *e;
+
+    //printf("StructInitializer::toExpression() %s\n", toChars());
+    if (!ad)				// if fwd referenced
+    {
+	return NULL;
+    }
+    StructDeclaration *sd = ad->isStructDeclaration();
+    if (!sd)
+	return NULL;
+    Expressions *elements = new Expressions();
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (field.data[i])
+	    goto Lno;
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	Expression *ex = iz->toExpression();
+	if (!ex)
+	    goto Lno;
+	elements->push(ex);
+    }
+    e = new StructLiteralExp(loc, sd, elements);
+    e->type = sd->type;
+    return e;
+
+Lno:
+    delete elements;
+    //error(loc, "struct initializers as expressions are not allowed");
+    return NULL;
+}
+
+
+void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    //printf("StructInitializer::toCBuffer()\n");
+    buf->writebyte('{');
+    for (int i = 0; i < field.dim; i++)
+    {
+        if (i > 0)
+	    buf->writebyte(',');
+        Identifier *id = (Identifier *)field.data[i];
+        if (id)
+        {
+            buf->writestring(id->toChars());
+            buf->writebyte(':');
+        }
+        Initializer *iz = (Initializer *)value.data[i];
+        if (iz)
+            iz->toCBuffer(buf, hgs);
+    }
+    buf->writebyte('}');
+}
+
+/********************************** ArrayInitializer ************************************/
+
+ArrayInitializer::ArrayInitializer(Loc loc)
+    : Initializer(loc)
+{
+    dim = 0;
+    type = NULL;
+    sem = 0;
+}
+
+Initializer *ArrayInitializer::syntaxCopy()
+{
+    //printf("ArrayInitializer::syntaxCopy()\n");
+
+    ArrayInitializer *ai = new ArrayInitializer(loc);
+
+    assert(index.dim == value.dim);
+    ai->index.setDim(index.dim);
+    ai->value.setDim(value.dim);
+    for (int i = 0; i < ai->value.dim; i++)
+    {	Expression *e = (Expression *)index.data[i];
+	if (e)
+	    e = e->syntaxCopy();
+	ai->index.data[i] = e;
+
+	Initializer *init = (Initializer *)value.data[i];
+	init = init->syntaxCopy();
+	ai->value.data[i] = init;
+    }
+    return ai;
+}
+
+void ArrayInitializer::addInit(Expression *index, Initializer *value)
+{
+    this->index.push(index);
+    this->value.push(value);
+    dim = 0;
+    type = NULL;
+}
+
+Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
+{   unsigned i;
+    unsigned length;
+
+    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
+    if (sem)				// if semantic() already run
+	return this;
+    sem = 1;
+    type = t;
+    t = t->toBasetype();
+    switch (t->ty)
+    {
+	case Tpointer:
+	case Tsarray:
+	case Tarray:
+	    break;
+
+	default:
+	    error(loc, "cannot use array to initialize %s", type->toChars());
+	    return this;
+    }
+
+    length = 0;
+    for (i = 0; i < index.dim; i++)
+    {	Expression *idx;
+	Initializer *val;
+
+	idx = (Expression *)index.data[i];
+	if (idx)
+	{   idx = idx->semantic(sc);
+	    idx = idx->optimize(WANTvalue | WANTinterpret);
+	    index.data[i] = (void *)idx;
+	    length = idx->toInteger();
+	}
+
+	val = (Initializer *)value.data[i];
+	val = val->semantic(sc, t->next);
+	value.data[i] = (void *)val;
+	length++;
+	if (length == 0)
+	    error(loc, "array dimension overflow");
+	if (length > dim)
+	    dim = length;
+    }
+    unsigned long amax = 0x80000000;
+    if ((unsigned long) dim * t->next->size() >= amax)
+	error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size());
+    return this;
+}
+
+/********************************
+ * If possible, convert array initializer to array literal.
+ */
+
+Expression *ArrayInitializer::toExpression()
+{   Expressions *elements;
+    Expression *e;
+
+    //printf("ArrayInitializer::toExpression()\n");
+    //static int i; if (++i == 2) halt();
+    elements = new Expressions();
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (index.data[i])
+	    goto Lno;
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	Expression *ex = iz->toExpression();
+	if (!ex)
+	    goto Lno;
+	elements->push(ex);
+    }
+    e = new ArrayLiteralExp(loc, elements);
+    e->type = type;
+    return e;
+
+Lno:
+    delete elements;
+    error(loc, "array initializers as expressions are not allowed");
+    return NULL;
+}
+
+
+/********************************
+ * If possible, convert array initializer to associative array initializer.
+ */
+
+Initializer *ArrayInitializer::toAssocArrayInitializer()
+{   Expressions *keys;
+    Expressions *values;
+    Expression *e;
+
+    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
+    //static int i; if (++i == 2) halt();
+    keys = new Expressions();
+    keys->setDim(value.dim);
+    values = new Expressions();
+    values->setDim(value.dim);
+
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	e = (Expression *)index.data[i];
+	if (!e)
+	    goto Lno;
+	keys->data[i] = (void *)e;
+
+	Initializer *iz = (Initializer *)value.data[i];
+	if (!iz)
+	    goto Lno;
+	e = iz->toExpression();
+	if (!e)
+	    goto Lno;
+	values->data[i] = (void *)e;
+    }
+    e = new AssocArrayLiteralExp(loc, keys, values);
+    return new ExpInitializer(loc, e);
+
+Lno:
+    delete keys;
+    delete values;
+    error(loc, "not an associative array initializer");
+    return this;
+}
+
+
+Type *ArrayInitializer::inferType(Scope *sc)
+{
+    for (size_t i = 0; i < value.dim; i++)
+    {
+	if (index.data[i])
+	    goto Lno;
+    }
+    if (value.dim)
+    {
+	Initializer *iz = (Initializer *)value.data[0];
+	if (iz)
+	{   Type *t = iz->inferType(sc);
+	    t = new TypeSArray(t, new IntegerExp(value.dim));
+	    t = t->semantic(loc, sc);
+	    return t;
+	}
+    }
+
+Lno:
+    error(loc, "cannot infer type from this array initializer");
+    return Type::terror;
+}
+
+
+void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writebyte('[');
+    for (int i = 0; i < index.dim; i++)
+    {
+        if (i > 0)
+	    buf->writebyte(',');
+        Expression *ex = (Expression *)index.data[i];
+        if (ex)
+        {
+            ex->toCBuffer(buf, hgs);
+            buf->writebyte(':');
+        }
+        Initializer *iz = (Initializer *)value.data[i];
+        if (iz)
+            iz->toCBuffer(buf, hgs);
+    }
+    buf->writebyte(']');
+}
+
+
+/********************************** ExpInitializer ************************************/
+
+ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
+    : Initializer(loc)
+{
+    this->exp = exp;
+}
+
+Initializer *ExpInitializer::syntaxCopy()
+{
+    return new ExpInitializer(loc, exp->syntaxCopy());
+}
+
+Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
+{
+    //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
+    exp = exp->semantic(sc);
+    Type *tb = t->toBasetype();
+
+    /* Look for case of initializing a static array with a too-short
+     * string literal, such as:
+     *	char[5] foo = "abc";
+     * Allow this by doing an explicit cast, which will lengthen the string
+     * literal.
+     */
+    if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
+    {	StringExp *se = (StringExp *)exp;
+
+	if (!se->committed && se->type->ty == Tsarray &&
+	    ((TypeSArray *)se->type)->dim->toInteger() <
+	    ((TypeSArray *)t)->dim->toInteger())
+	{
+	    exp = se->castTo(sc, t);
+	    goto L1;
+	}
+    }
+
+    // Look for the case of statically initializing an array
+    // with a single member.
+    if (tb->ty == Tsarray &&
+	!tb->next->equals(exp->type->toBasetype()->next) &&
+	exp->implicitConvTo(tb->next)
+       )
+    {
+	t = tb->next;
+    }
+
+    exp = exp->implicitCastTo(sc, t);
+L1:
+    exp = exp->optimize(WANTvalue | WANTinterpret);
+    //printf("-ExpInitializer::semantic(): "); exp->print();
+    return this;
+}
+
+Type *ExpInitializer::inferType(Scope *sc)
+{
+    //printf("ExpInitializer::inferType() %s\n", toChars());
+    exp = exp->semantic(sc);
+    exp = resolveProperties(sc, exp);
+    return exp->type;
+}
+
+Expression *ExpInitializer::toExpression()
+{
+    return exp;
+}
+
+
+void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    exp->toCBuffer(buf, hgs);
+}
+
+
+