diff dmd/attrib.c @ 159:5acec6b2eef8 trunk

[svn r175] merged dmd 1.029
author ChristianK
date Thu, 01 May 2008 15:15:28 +0200
parents 61615fa85940
children aaade6ded589
line wrap: on
line diff
--- a/dmd/attrib.c	Thu May 01 13:33:02 2008 +0200
+++ b/dmd/attrib.c	Thu May 01 15:15:28 2008 +0200
@@ -1,1292 +1,1319 @@
-
-// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 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 <stdlib.h>
-#include <assert.h>
-
-#if _WIN32 || IN_GCC || IN_LLVM
-#include "mem.h"
-#elif linux
-#include "../root/mem.h"
-#endif
-
-#include "init.h"
-#include "declaration.h"
-#include "attrib.h"
-#include "cond.h"
-#include "scope.h"
-#include "id.h"
-#include "expression.h"
-#include "dsymbol.h"
-#include "aggregate.h"
-#include "module.h"
-#include "parse.h"
-#include "template.h"
-
-#include "../gen/enums.h"
-#include "../gen/logger.h"
-
-extern void obj_includelib(char *name);
-
-
-/********************************* AttribDeclaration ****************************/
-
-AttribDeclaration::AttribDeclaration(Array *decl)
-	: Dsymbol()
-{
-    this->decl = decl;
-}
-
-Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
-{
-    return decl;
-}
-
-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];
-	    m |= s->addMember(sc, sd, m | memnum);
-	}
-    }
-    return m;
-}
-
-void AttribDeclaration::semantic(Scope *sc)
-{
-    Array *d = include(sc, NULL);
-
-    //printf("\tAttribDeclaration::semantic '%s'\n",toChars());
-    if (d)
-    {
-	for (unsigned i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-
-	    s->semantic(sc);
-	}
-    }
-}
-
-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];
-	    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];
-	    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];
-	    //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
-	    s->inlineScan();
-	}
-    }
-}
-
-void AttribDeclaration::addComment(unsigned char *comment)
-{
-    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];
-		//printf("AttribDeclaration::addComment %s\n", s->toChars());
-		s->addComment(comment);
-	    }
-	}
-    }
-}
-
-void AttribDeclaration::emitComment(Scope *sc)
-{
-    //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
-
-    /* If generating doc comment, skip this because if we're inside
-     * a template, then include(NULL, NULL) will fail.
-     */
-//    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];
-	    //printf("AttribDeclaration::emitComment %s\n", s->toChars());
-	    s->emitComment(sc);
-	}
-    }
-}
-
-void AttribDeclaration::toObjFile()
-{
-    unsigned i;
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (i = 0; i < d->dim; i++)
-	{   Dsymbol *s;
-
-	    s = (Dsymbol *)d->data[i];
-	    s->toObjFile();
-	}
-    }
-}
-
-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];
-        n = s->cvMember(p);
-        if (p)
-        p += n;
-        nwritten += n;
-    }
-    }
-    return nwritten;
-}
-
-int AttribDeclaration::hasPointers()
-{
-    Array *d = include(NULL, NULL);
-
-    if (d)
-    {
-	for (size_t i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-	    if (s->hasPointers())
-		return 1;
-	}
-    }
-    return 0;
-}
-
-char *AttribDeclaration::kind()
-{
-    return "attribute";
-}
-
-int AttribDeclaration::oneMember(Dsymbol **ps)
-{
-    Array *d = include(NULL, NULL);
-
-    return Dsymbol::oneMembers(d, ps);
-}
-
-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];
-	    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];
-	    s->addLocalClass(aclasses);
-	}
-    }
-}
-
-
-void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    if (decl)
-    {
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    buf->writestring("    ");
-	    s->toCBuffer(buf, hgs);
-	}
-	buf->writeByte('}');
-    }
-    else
-	buf->writeByte(';');
-    buf->writenl();
-}
-
-/************************* StorageClassDeclaration ****************************/
-
-StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->stc = stc;
-}
-
-Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StorageClassDeclaration *scd;
-
-    assert(!s);
-    scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
-    return scd;
-}
-
-void StorageClassDeclaration::semantic(Scope *sc)
-{
-    if (decl)
-    {	unsigned stc_save = sc->stc;
-
-	if (stc & (STCauto | STCscope | STCstatic | STCextern))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
-	sc->stc |= stc;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->stc = stc_save;
-    }
-    else
-	sc->stc = stc;
-}
-
-void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    struct SCstring
-    {
-	int stc;
-	enum TOK tok;
-    };
-
-    static SCstring table[] =
-    {
-	{ STCauto,         TOKauto },
-	{ STCscope,        TOKscope },
-	{ STCstatic,       TOKstatic },
-	{ STCextern,       TOKextern },
-	{ STCconst,        TOKconst },
-	{ STCfinal,        TOKfinal },
-	{ STCabstract,     TOKabstract },
-	{ STCsynchronized, TOKsynchronized },
-	{ STCdeprecated,   TOKdeprecated },
-	{ STCoverride,     TOKoverride },
-    };
-
-    int written = 0;
-    for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
-    {
-	if (stc & table[i].stc)
-	{
-	    if (written)
-		buf->writeByte(' ');
-	    written = 1;
-	    buf->writestring(Token::toChars(table[i].tok));
-	}
-    }
-
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* LinkDeclaration ****************************/
-
-LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
-	: AttribDeclaration(decl)
-{
-    //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
-    linkage = p;
-}
-
-Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
-{
-    LinkDeclaration *ld;
-
-    assert(!s);
-    ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
-    return ld;
-}
-
-void LinkDeclaration::semantic(Scope *sc)
-{
-    //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
-    if (decl)
-    {	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->linkage = linkage_save;
-    }
-    else
-    {
-	sc->linkage = linkage;
-    }
-}
-
-void LinkDeclaration::semantic3(Scope *sc)
-{
-    //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
-    if (decl)
-    {	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic3(sc);
-	}
-	sc->linkage = linkage_save;
-    }
-    else
-    {
-	sc->linkage = linkage;
-    }
-}
-
-void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   char *p;
-
-    switch (linkage)
-    {
-	case LINKd:		p = "D";		break;
-	case LINKc:		p = "C";		break;
-	case LINKcpp:		p = "C++";		break;
-	case LINKwindows:	p = "Windows";		break;
-	case LINKpascal:	p = "Pascal";		break;
-	default:
-	    assert(0);
-	    break;
-    }
-    buf->writestring("extern (");
-    buf->writestring(p);
-    buf->writestring(") ");
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-char *LinkDeclaration::toChars()
-{
-    return "extern ()";
-}
-
-/********************************* ProtDeclaration ****************************/
-
-ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
-	: AttribDeclaration(decl)
-{
-    protection = p;
-    //printf("decl = %p\n", decl);
-}
-
-Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
-{
-    ProtDeclaration *pd;
-
-    assert(!s);
-    pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
-    return pd;
-}
-
-void ProtDeclaration::semantic(Scope *sc)
-{
-    if (decl)
-    {	enum PROT protection_save = sc->protection;
-	int explicitProtection_save = sc->explicitProtection;
-
-	sc->protection = protection;
-	sc->explicitProtection = 1;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->protection = protection_save;
-	sc->explicitProtection = explicitProtection_save;
-    }
-    else
-    {	sc->protection = protection;
-	sc->explicitProtection = 1;
-    }
-}
-
-void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{   char *p;
-
-    switch (protection)
-    {
-	case PROTprivate:	p = "private";		break;
-	case PROTpackage:	p = "package";		break;
-	case PROTprotected:	p = "protected";	break;
-	case PROTpublic:	p = "public";		break;
-	case PROTexport:	p = "export";		break;
-	default:
-	    assert(0);
-	    break;
-    }
-    buf->writestring(p);
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* AlignDeclaration ****************************/
-
-AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl)
-	: AttribDeclaration(decl)
-{
-    salign = sa;
-}
-
-Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
-{
-    AlignDeclaration *ad;
-
-    assert(!s);
-    ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl));
-    return ad;
-}
-
-void AlignDeclaration::semantic(Scope *sc)
-{
-    //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
-    if (decl)
-    {	unsigned salign_save = sc->structalign;
-
-	sc->structalign = salign;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->structalign = salign_save;
-    }
-    else
-	sc->structalign = salign;
-}
-
-
-void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("align (%d)", salign);
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-/********************************* AnonDeclaration ****************************/
-
-AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->loc = loc;
-    this->isunion = isunion;
-    this->scope = NULL;
-    this->sem = 0;
-}
-
-Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
-{
-    AnonDeclaration *ad;
-
-    assert(!s);
-    ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
-    return ad;
-}
-
-void AnonDeclaration::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;
-	int adisunion;
-
-	if (sc->anonAgg)
-	{   ad = sc->anonAgg;
-	    adisunion = sc->inunion;
-	}
-	else
-	    adisunion = ad->isUnionDeclaration() != 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);
-	sc->inunion = isunion;
-	sc->offset = 0;
-	sc->flags = 0;
-	aad.structalign = sc->structalign;
-	aad.parent = ad;
-
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (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 (unsigned i = 0; i < aad.fields.dim; i++)
-	{
-	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
-
-	    v->offset += sc->offset;
-	    ad->fields.push(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 AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf(isunion ? "union" : "struct");
-    buf->writestring("\n{\n");
-    if (decl)
-    {
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    //buf->writestring("    ");
-	    s->toCBuffer(buf, hgs);
-	}
-    }
-    buf->writestring("}\n");
-}
-
-char *AnonDeclaration::kind()
-{
-    return (char *)(isunion ? "anonymous union" : "anonymous struct");
-}
-
-/********************************* PragmaDeclaration ****************************/
-
-PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
-	: AttribDeclaration(decl)
-{
-    this->loc = loc;
-    this->ident = ident;
-    this->args = args;
-}
-
-Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
-{
-    PragmaDeclaration *pd;
-
-    assert(!s);
-    pd = new PragmaDeclaration(loc, ident,
-	Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
-    return pd;
-}
-
-void PragmaDeclaration::semantic(Scope *sc)
-{   // Should be merged with PragmaStatement
-
-#if IN_LLVM
-    int llvm_internal = 0;
-    char* llvm_str1 = NULL;
-
-#endif
-
-    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
-    if (ident == Id::msg)
-    {
-	if (args)
-	{
-	    for (size_t i = 0; i < args->dim; i++)
-	    {
-		Expression *e = (Expression *)args->data[i];
-
-		e = e->semantic(sc);
-		e = e->optimize(WANTvalue | WANTinterpret);
-		if (e->op == TOKstring)
-		{
-		    StringExp *se = (StringExp *)e;
-		    fprintf(stdmsg, "%.*s", (int)se->len, se->string);
-		}
-		else
-		    error("string expected for message, not '%s'", e->toChars());
-	    }
-	    fprintf(stdmsg, "\n");
-	}
-	goto Lnodecl;
-    }
-    else if (ident == Id::lib)
-    {
-	if (!args || args->dim != 1)
-	    error("string expected for library name");
-	else
-	{
-	    Expression *e = (Expression *)args->data[0];
-
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue | WANTinterpret);
-	    args->data[0] = (void *)e;
-	    if (e->op != TOKstring)
-		error("string expected for library name, not '%s'", e->toChars());
-	    else if (global.params.verbose)
-	    {
-		StringExp *se = (StringExp *)e;
-		char *name = (char *)mem.malloc(se->len + 1);
-		memcpy(name, se->string, se->len);
-		name[se->len] = 0;
-		printf("library   %s\n", name);
-		mem.free(name);
-	    }
-	}
-	goto Lnodecl;
-    }
-#if IN_GCC
-    else if (ident == Id::GNU_asm)
-    {
-	if (! args || args->dim != 2)
-	    error("identifier and string expected for asm name");
-	else
-	{
-	    Expression *e;
-	    Declaration *d = NULL;
-	    StringExp *s = NULL;
-
-	    e = (Expression *)args->data[0];
-	    e = e->semantic(sc);
-	    if (e->op == TOKvar)
-	    {
-		d = ((VarExp *)e)->var;
-		if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
-		    d = NULL;
-	    }
-	    if (!d)
-		error("first argument of GNU_asm must be a function or variable declaration");
-
-	    e = (Expression *)args->data[1];
-	    e = e->semantic(sc);
-	    e = e->optimize(WANTvalue);
-	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
-		s = ((StringExp *)e);
-	    else
-		error("second argument of GNU_asm must be a char string");
-
-	    if (d && s)
-		d->c_ident = Lexer::idPool((char*) s->string);
-	}
-	goto Lnodecl;
-    }
-#endif
-#if IN_LLVM
-    else if (ident == Id::LLVM_internal)
-    {
-        if (!args || args->dim < 1 || args->dim > 2)
-            error("needs 1-3 parameters");
-        else if (!decl || decl->dim < 1)
-            error("must apply to at least one declaration");
-        else
-        {
-            Expression *e;
-            StringExp *s = NULL;
-
-            e = (Expression *)args->data[0];
-            e = e->semantic(sc);
-            e = e->optimize(WANTvalue);
-            if (e->op == TOKstring && (s = (StringExp *)e))
-            {
-                char* str = (char*)s->string;
-                if (strcmp(str,"intrinsic")==0) {
-                    llvm_internal = LLVMintrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"va_start")==0) {
-                    llvm_internal = LLVMva_start;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_arg")==0) {
-                    llvm_internal = LLVMva_arg;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_intrinsic")==0) {
-                    llvm_internal = LLVMva_intrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"notypeinfo")==0) {
-                    llvm_internal = LLVMnotypeinfo;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"alloca")==0) {
-                    llvm_internal = LLVMalloca;
-                    assert(args->dim == 1);
-                }
-                else {
-                    error("unknown pragma command: %s", str);
-                }
-            }
-            else
-            error("1st argument must be a string");
-
-            if (llvm_internal)
-            switch (llvm_internal)
-            {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                e = (Expression *)args->data[1];
-                e = e->semantic(sc);
-                e = e->optimize(WANTvalue);
-                if (e->op == TOKstring && (s = (StringExp *)e)) {
-                    llvm_str1 = (char*)s->string;
-                }
-                else
-                error("2nd argument must be a string");
-                break;
-
-            case LLVMva_arg:
-            case LLVMva_start:
-            case LLVMnotypeinfo:
-            case LLVMalloca:
-                break;
-
-            default:
-                assert(0);
-            }
-        }
-    }
-#endif
-    else
-	error("unrecognized pragma(%s)", ident->toChars());
-
-    if (decl)
-    {
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-        
-#if IN_LLVM
-        if (llvm_internal)
-        {
-            switch(llvm_internal)
-            {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                    fd->llvmInternal1 = llvm_str1;
-                }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
-                }
-                break;
-
-            case LLVMva_start:
-            case LLVMva_arg:
-                if (TemplateDeclaration* td = s->isTemplateDeclaration()) {
-                    td->llvmInternal = llvm_internal;
-                    assert(td->parameters->dim == 1);
-                    assert(!td->overnext);
-                    assert(!td->overroot);
-                    assert(td->onemember);
-                    Logger::println("template->onemember = %s", td->onemember->toChars());
-                }
-                else {
-                    error("can only be used on templates");
-                    assert(0);
-                }
-                break;
-
-            case LLVMnotypeinfo:
-                s->llvmInternal = llvm_internal;
-                break;
-
-            case LLVMalloca:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
-                }
-                break;
-
-            default:
-                assert(0 && "invalid LLVM_internal pragma got through :/");
-            }
-        }
-        
-#endif
-    }
-    }
-    return;
-
-Lnodecl:
-    if (decl)
-	error("pragma is missing closing ';'");
-}
-
-int PragmaDeclaration::oneMember(Dsymbol **ps)
-{
-    *ps = NULL;
-    return TRUE;
-}
-
-char *PragmaDeclaration::kind()
-{
-    return "pragma";
-}
-
-void PragmaDeclaration::toObjFile()
-{
-    if (ident == Id::lib)
-    {
-	assert(args && args->dim == 1);
-
-	Expression *e = (Expression *)args->data[0];
-
-	assert(e->op == TOKstring);
-
-	StringExp *se = (StringExp *)e;
-	char *name = (char *)mem.malloc(se->len + 1);
-	memcpy(name, se->string, se->len);
-	name[se->len] = 0;
-	obj_includelib(name);
-    }
-    AttribDeclaration::toObjFile();
-}
-
-void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->printf("pragma(%s", ident->toChars());
-    if (args)
-    {
-	for (size_t i = 0; i < args->dim; i++)
-	{
-	    Expression *e = (Expression *)args->data[i];
-
-	    buf->writestring(", ");
-	    e->toCBuffer(buf, hgs);
-	}
-    }
-    buf->writestring(")");
-    AttribDeclaration::toCBuffer(buf, hgs);
-}
-
-
-/********************************* ConditionalDeclaration ****************************/
-
-ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl)
-	: AttribDeclaration(decl)
-{
-    //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
-    this->condition = condition;
-    this->elsedecl = elsedecl;
-}
-
-Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
-{
-    ConditionalDeclaration *dd;
-
-    assert(!s);
-    dd = new ConditionalDeclaration(condition->syntaxCopy(),
-	Dsymbol::arraySyntaxCopy(decl),
-	Dsymbol::arraySyntaxCopy(elsedecl));
-    return dd;
-}
-
-
-int ConditionalDeclaration::oneMember(Dsymbol **ps)
-{
-    //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
-    if (condition->inc)
-    {
-	Array *d = condition->include(NULL, NULL) ? decl : elsedecl;
-	return Dsymbol::oneMembers(d, ps);
-    }
-    *ps = NULL;
-    return TRUE;
-}
-
-void ConditionalDeclaration::emitComment(Scope *sc)
-{
-    //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
-    if (condition->inc)
-    {
-	AttribDeclaration::emitComment(sc);
-    }
-}
-
-// Decide if 'then' or 'else' code should be included
-
-Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
-{
-    //printf("ConditionalDeclaration::include()\n");
-    assert(condition);
-    return condition->include(sc, sd) ? decl : elsedecl;
-}
-
-
-void ConditionalDeclaration::addComment(unsigned char *comment)
-{
-    /* Because addComment is called by the parser, if we called
-     * include() it would define a version before it was used.
-     * But it's no problem to drill down to both decl and elsedecl,
-     * so that's the workaround.
-     */
-
-    if (comment)
-    {
-	Array *d = decl;
-
-	for (int j = 0; j < 2; j++)
-	{
-	    if (d)
-	    {
-		for (unsigned i = 0; i < d->dim; i++)
-		{   Dsymbol *s;
-
-		    s = (Dsymbol *)d->data[i];
-		    //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
-		    s->addComment(comment);
-		}
-	    }
-	    d = elsedecl;
-	}
-    }
-}
-
-void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    condition->toCBuffer(buf, hgs);
-    if (decl || elsedecl)
-    {
-	buf->writenl();
-	buf->writeByte('{');
-	buf->writenl();
-	if (decl)
-	{
-	    for (unsigned i = 0; i < decl->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)decl->data[i];
-
-		buf->writestring("    ");
-		s->toCBuffer(buf, hgs);
-	    }
-	}
-	buf->writeByte('}');
-	if (elsedecl)
-	{
-	    buf->writenl();
-	    buf->writestring("else");
-	    buf->writenl();
-	    buf->writeByte('{');
-	    buf->writenl();
-	    for (unsigned i = 0; i < elsedecl->dim; i++)
-	    {
-		Dsymbol *s = (Dsymbol *)elsedecl->data[i];
-
-		buf->writestring("    ");
-		s->toCBuffer(buf, hgs);
-	    }
-	    buf->writeByte('}');
-	}
-    }
-    else
-	buf->writeByte(':');
-    buf->writenl();
-}
-
-/***************************** StaticIfDeclaration ****************************/
-
-StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
-	Array *decl, Array *elsedecl)
-	: ConditionalDeclaration(condition, decl, elsedecl)
-{
-    //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
-    sd = NULL;
-    addisdone = 0;
-}
-
-
-Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
-{
-    StaticIfDeclaration *dd;
-
-    assert(!s);
-    dd = new StaticIfDeclaration(condition->syntaxCopy(),
-	Dsymbol::arraySyntaxCopy(decl),
-	Dsymbol::arraySyntaxCopy(elsedecl));
-    return dd;
-}
-
-
-int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    /* This is deferred until semantic(), so that
-     * expressions in the condition can refer to declarations
-     * in the same scope, such as:
-     *
-     * template Foo(int i)
-     * {
-     *     const int j = i + 1;
-     *     static if (j == 3)
-     *         const int k;
-     * }
-     */
-    this->sd = sd;
-    int m = 0;
-
-    if (memnum == 0)
-    {	m = AttribDeclaration::addMember(sc, sd, memnum);
-	addisdone = 1;
-    }
-    return m;
-}
-
-
-void StaticIfDeclaration::semantic(Scope *sc)
-{
-    Array *d = include(sc, sd);
-
-    //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars());
-    if (d)
-    {
-	if (!addisdone)
-	{   AttribDeclaration::addMember(sc, sd, 1);
-	    addisdone = 1;
-	}
-
-	for (unsigned i = 0; i < d->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)d->data[i];
-
-	    s->semantic(sc);
-	}
-    }
-}
-
-char *StaticIfDeclaration::kind()
-{
-    return "static if";
-}
-
-
-/***************************** CompileDeclaration *****************************/
-
-CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
-    : AttribDeclaration(NULL)
-{
-    this->exp = exp;
-    this->sd = NULL;
-}
-
-Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
-{
-    //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
-    CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
-    return sc;
-}
-
-int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
-{
-    this->sd = sd;
-    return memnum;
-}
-
-void CompileDeclaration::semantic(Scope *sc)
-{
-    //printf("CompileDeclaration::semantic()\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;
-    }
-    StringExp *se = (StringExp *)exp;
-    se = se->toUTF8(sc);
-    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
-    p.loc = loc;
-    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::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
-{
-    buf->writestring("mixin(");
-    exp->toCBuffer(buf, hgs);
-    buf->writestring(");");
-    buf->writenl();
-}
+
+// Compiler implementation of the D programming language
+// Copyright (c) 1999-2007 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 <stdlib.h>
+#include <assert.h>
+
+#if _WIN32 || IN_GCC || IN_LLVM
+#include "mem.h"
+#elif linux
+#include "../root/mem.h"
+#endif
+
+#include "init.h"
+#include "declaration.h"
+#include "attrib.h"
+#include "cond.h"
+#include "scope.h"
+#include "id.h"
+#include "expression.h"
+#include "dsymbol.h"
+#include "aggregate.h"
+#include "module.h"
+#include "parse.h"
+#include "template.h"
+
+#include "../gen/enums.h"
+#include "../gen/logger.h"
+
+extern void obj_includelib(char *name);
+
+
+/********************************* AttribDeclaration ****************************/
+
+AttribDeclaration::AttribDeclaration(Array *decl)
+	: Dsymbol()
+{
+    this->decl = decl;
+}
+
+Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
+{
+    return decl;
+}
+
+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];
+	    m |= s->addMember(sc, sd, m | memnum);
+	}
+    }
+    return m;
+}
+
+void AttribDeclaration::semantic(Scope *sc)
+{
+    Array *d = include(sc, NULL);
+
+    //printf("\tAttribDeclaration::semantic '%s'\n",toChars());
+    if (d)
+    {
+	for (unsigned i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+
+	    s->semantic(sc);
+	}
+    }
+}
+
+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];
+	    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];
+	    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];
+	    //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
+	    s->inlineScan();
+	}
+    }
+}
+
+void AttribDeclaration::addComment(unsigned char *comment)
+{
+    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];
+		//printf("AttribDeclaration::addComment %s\n", s->toChars());
+		s->addComment(comment);
+	    }
+	}
+    }
+}
+
+void AttribDeclaration::emitComment(Scope *sc)
+{
+    //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
+
+    /* If generating doc comment, skip this because if we're inside
+     * a template, then include(NULL, NULL) will fail.
+     */
+//    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];
+	    //printf("AttribDeclaration::emitComment %s\n", s->toChars());
+	    s->emitComment(sc);
+	}
+    }
+}
+
+void AttribDeclaration::toObjFile()
+{
+    unsigned i;
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (i = 0; i < d->dim; i++)
+	{   Dsymbol *s;
+
+	    s = (Dsymbol *)d->data[i];
+	    s->toObjFile();
+	}
+    }
+}
+
+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];
+	    n = s->cvMember(p);
+	    if (p)
+		p += n;
+	    nwritten += n;
+	}
+    }
+    return nwritten;
+}
+
+int AttribDeclaration::hasPointers()
+{
+    Array *d = include(NULL, NULL);
+
+    if (d)
+    {
+	for (size_t i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+	    if (s->hasPointers())
+		return 1;
+	}
+    }
+    return 0;
+}
+
+char *AttribDeclaration::kind()
+{
+    return "attribute";
+}
+
+int AttribDeclaration::oneMember(Dsymbol **ps)
+{
+    Array *d = include(NULL, NULL);
+
+    return Dsymbol::oneMembers(d, ps);
+}
+
+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];
+	    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];
+	    s->addLocalClass(aclasses);
+	}
+    }
+}
+
+
+void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    if (decl)
+    {
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    buf->writestring("    ");
+	    s->toCBuffer(buf, hgs);
+	}
+	buf->writeByte('}');
+    }
+    else
+	buf->writeByte(';');
+    buf->writenl();
+}
+
+/************************* StorageClassDeclaration ****************************/
+
+StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->stc = stc;
+}
+
+Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StorageClassDeclaration *scd;
+
+    assert(!s);
+    scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
+    return scd;
+}
+
+void StorageClassDeclaration::semantic(Scope *sc)
+{
+    if (decl)
+    {	unsigned stc_save = sc->stc;
+
+	if (stc & (STCauto | STCscope | STCstatic | STCextern))
+	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
+	sc->stc |= stc;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->stc = stc_save;
+    }
+    else
+	sc->stc = stc;
+}
+
+void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    struct SCstring
+    {
+	int stc;
+	enum TOK tok;
+    };
+
+    static SCstring table[] =
+    {
+	{ STCauto,         TOKauto },
+	{ STCscope,        TOKscope },
+	{ STCstatic,       TOKstatic },
+	{ STCextern,       TOKextern },
+	{ STCconst,        TOKconst },
+	{ STCfinal,        TOKfinal },
+	{ STCabstract,     TOKabstract },
+	{ STCsynchronized, TOKsynchronized },
+	{ STCdeprecated,   TOKdeprecated },
+	{ STCoverride,     TOKoverride },
+    };
+
+    int written = 0;
+    for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
+    {
+	if (stc & table[i].stc)
+	{
+	    if (written)
+		buf->writeByte(' ');
+	    written = 1;
+	    buf->writestring(Token::toChars(table[i].tok));
+	}
+    }
+
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* LinkDeclaration ****************************/
+
+LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
+	: AttribDeclaration(decl)
+{
+    //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
+    linkage = p;
+}
+
+Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
+{
+    LinkDeclaration *ld;
+
+    assert(!s);
+    ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
+    return ld;
+}
+
+void LinkDeclaration::semantic(Scope *sc)
+{
+    //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {	enum LINK linkage_save = sc->linkage;
+
+	sc->linkage = linkage;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->linkage = linkage_save;
+    }
+    else
+    {
+	sc->linkage = linkage;
+    }
+}
+
+void LinkDeclaration::semantic3(Scope *sc)
+{
+    //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {	enum LINK linkage_save = sc->linkage;
+
+	sc->linkage = linkage;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic3(sc);
+	}
+	sc->linkage = linkage_save;
+    }
+    else
+    {
+	sc->linkage = linkage;
+    }
+}
+
+void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   char *p;
+
+    switch (linkage)
+    {
+	case LINKd:		p = "D";		break;
+	case LINKc:		p = "C";		break;
+	case LINKcpp:		p = "C++";		break;
+	case LINKwindows:	p = "Windows";		break;
+	case LINKpascal:	p = "Pascal";		break;
+	default:
+	    assert(0);
+	    break;
+    }
+    buf->writestring("extern (");
+    buf->writestring(p);
+    buf->writestring(") ");
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+char *LinkDeclaration::toChars()
+{
+    return "extern ()";
+}
+
+/********************************* ProtDeclaration ****************************/
+
+ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
+	: AttribDeclaration(decl)
+{
+    protection = p;
+    //printf("decl = %p\n", decl);
+}
+
+Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
+{
+    ProtDeclaration *pd;
+
+    assert(!s);
+    pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
+    return pd;
+}
+
+void ProtDeclaration::semantic(Scope *sc)
+{
+    if (decl)
+    {	enum PROT protection_save = sc->protection;
+	int explicitProtection_save = sc->explicitProtection;
+
+	sc->protection = protection;
+	sc->explicitProtection = 1;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->protection = protection_save;
+	sc->explicitProtection = explicitProtection_save;
+    }
+    else
+    {	sc->protection = protection;
+	sc->explicitProtection = 1;
+    }
+}
+
+void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{   char *p;
+
+    switch (protection)
+    {
+	case PROTprivate:	p = "private";		break;
+	case PROTpackage:	p = "package";		break;
+	case PROTprotected:	p = "protected";	break;
+	case PROTpublic:	p = "public";		break;
+	case PROTexport:	p = "export";		break;
+	default:
+	    assert(0);
+	    break;
+    }
+    buf->writestring(p);
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* AlignDeclaration ****************************/
+
+AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl)
+	: AttribDeclaration(decl)
+{
+    salign = sa;
+}
+
+Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
+{
+    AlignDeclaration *ad;
+
+    assert(!s);
+    ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl));
+    return ad;
+}
+
+void AlignDeclaration::semantic(Scope *sc)
+{
+    //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
+    if (decl)
+    {	unsigned salign_save = sc->structalign;
+
+	sc->structalign = salign;
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+	}
+	sc->structalign = salign_save;
+    }
+    else
+	sc->structalign = salign;
+}
+
+
+void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("align (%d)", salign);
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+/********************************* AnonDeclaration ****************************/
+
+AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->loc = loc;
+    this->isunion = isunion;
+    this->scope = NULL;
+    this->sem = 0;
+}
+
+Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
+{
+    AnonDeclaration *ad;
+
+    assert(!s);
+    ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
+    return ad;
+}
+
+void AnonDeclaration::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;
+	int adisunion;
+
+	if (sc->anonAgg)
+	{   ad = sc->anonAgg;
+	    adisunion = sc->inunion;
+	}
+	else
+	    adisunion = ad->isUnionDeclaration() != 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);
+	sc->inunion = isunion;
+	sc->offset = 0;
+	sc->flags = 0;
+	aad.structalign = sc->structalign;
+	aad.parent = ad;
+
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (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 (unsigned i = 0; i < aad.fields.dim; i++)
+	{
+	    VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
+
+	    v->offset += sc->offset;
+	    ad->fields.push(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 AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf(isunion ? "union" : "struct");
+    buf->writestring("\n{\n");
+    if (decl)
+    {
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    //buf->writestring("    ");
+	    s->toCBuffer(buf, hgs);
+	}
+    }
+    buf->writestring("}\n");
+}
+
+char *AnonDeclaration::kind()
+{
+    return (char *)(isunion ? "anonymous union" : "anonymous struct");
+}
+
+/********************************* PragmaDeclaration ****************************/
+
+PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
+	: AttribDeclaration(decl)
+{
+    this->loc = loc;
+    this->ident = ident;
+    this->args = args;
+}
+
+Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
+{
+    PragmaDeclaration *pd;
+
+    assert(!s);
+    pd = new PragmaDeclaration(loc, ident,
+	Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
+    return pd;
+}
+
+void PragmaDeclaration::semantic(Scope *sc)
+{   // Should be merged with PragmaStatement
+
+#if IN_LLVM
+    int llvm_internal = 0;
+    char* llvm_str1 = NULL;
+
+#endif
+
+    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
+    if (ident == Id::msg)
+    {
+	if (args)
+	{
+	    for (size_t i = 0; i < args->dim; i++)
+	    {
+		Expression *e = (Expression *)args->data[i];
+
+		e = e->semantic(sc);
+		e = e->optimize(WANTvalue | WANTinterpret);
+		if (e->op == TOKstring)
+		{
+		    StringExp *se = (StringExp *)e;
+		    fprintf(stdmsg, "%.*s", (int)se->len, se->string);
+		}
+		else
+		    error("string expected for message, not '%s'", e->toChars());
+	    }
+	    fprintf(stdmsg, "\n");
+	}
+	goto Lnodecl;
+    }
+    else if (ident == Id::lib)
+    {
+	if (!args || args->dim != 1)
+	    error("string expected for library name");
+	else
+	{
+	    Expression *e = (Expression *)args->data[0];
+
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue | WANTinterpret);
+	    args->data[0] = (void *)e;
+	    if (e->op != TOKstring)
+		error("string expected for library name, not '%s'", e->toChars());
+	    else if (global.params.verbose)
+	    {
+		StringExp *se = (StringExp *)e;
+		char *name = (char *)mem.malloc(se->len + 1);
+		memcpy(name, se->string, se->len);
+		name[se->len] = 0;
+		printf("library   %s\n", name);
+		mem.free(name);
+	    }
+	}
+	goto Lnodecl;
+    }
+#if IN_GCC
+    else if (ident == Id::GNU_asm)
+    {
+	if (! args || args->dim != 2)
+	    error("identifier and string expected for asm name");
+	else
+	{
+	    Expression *e;
+	    Declaration *d = NULL;
+	    StringExp *s = NULL;
+
+	    e = (Expression *)args->data[0];
+	    e = e->semantic(sc);
+	    if (e->op == TOKvar)
+	    {
+		d = ((VarExp *)e)->var;
+		if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
+		    d = NULL;
+	    }
+	    if (!d)
+		error("first argument of GNU_asm must be a function or variable declaration");
+
+	    e = (Expression *)args->data[1];
+	    e = e->semantic(sc);
+	    e = e->optimize(WANTvalue);
+	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
+		s = ((StringExp *)e);
+	    else
+		error("second argument of GNU_asm must be a char string");
+
+	    if (d && s)
+		d->c_ident = Lexer::idPool((char*) s->string);
+	}
+	goto Lnodecl;
+    }
+#endif
+#if IN_LLVM
+    else if (ident == Id::LLVM_internal)
+    {
+        if (!args || args->dim < 1 || args->dim > 2)
+            error("needs 1-3 parameters");
+        else if (!decl || decl->dim < 1)
+            error("must apply to at least one declaration");
+        else
+        {
+            Expression *e;
+            StringExp *s = NULL;
+
+            e = (Expression *)args->data[0];
+            e = e->semantic(sc);
+            e = e->optimize(WANTvalue);
+            if (e->op == TOKstring && (s = (StringExp *)e))
+            {
+                char* str = (char*)s->string;
+                if (strcmp(str,"intrinsic")==0) {
+                    llvm_internal = LLVMintrinsic;
+                    assert(args->dim == 2);
+                }
+                else if (strcmp(str,"va_start")==0) {
+                    llvm_internal = LLVMva_start;
+                    assert(args->dim == 1);
+                }
+                else if (strcmp(str,"va_arg")==0) {
+                    llvm_internal = LLVMva_arg;
+                    assert(args->dim == 1);
+                }
+                else if (strcmp(str,"va_intrinsic")==0) {
+                    llvm_internal = LLVMva_intrinsic;
+                    assert(args->dim == 2);
+                }
+                else if (strcmp(str,"notypeinfo")==0) {
+                    llvm_internal = LLVMnotypeinfo;
+                    assert(args->dim == 1);
+                }
+                else if (strcmp(str,"alloca")==0) {
+                    llvm_internal = LLVMalloca;
+                    assert(args->dim == 1);
+                }
+                else {
+                    error("unknown pragma command: %s", str);
+                }
+            }
+            else
+            error("1st argument must be a string");
+
+            if (llvm_internal)
+            switch (llvm_internal)
+            {
+            case LLVMintrinsic:
+            case LLVMva_intrinsic:
+                e = (Expression *)args->data[1];
+                e = e->semantic(sc);
+                e = e->optimize(WANTvalue);
+                if (e->op == TOKstring && (s = (StringExp *)e)) {
+                    llvm_str1 = (char*)s->string;
+                }
+                else
+                error("2nd argument must be a string");
+                break;
+
+            case LLVMva_arg:
+            case LLVMva_start:
+            case LLVMnotypeinfo:
+            case LLVMalloca:
+                break;
+
+            default:
+                assert(0);
+            }
+        }
+    }
+#endif
+    else if (global.params.ignoreUnsupportedPragmas)
+    {
+	if (global.params.verbose)
+	{
+	    /* Print unrecognized pragmas
+	     */
+	    printf("pragma    %s", ident->toChars());
+	    if (args)
+	    {
+		for (size_t i = 0; i < args->dim; i++)
+		{
+		    Expression *e = (Expression *)args->data[i];
+		    e = e->semantic(sc);
+		    e = e->optimize(WANTvalue | WANTinterpret);
+		    if (i == 0)
+			printf(" (");
+		    else
+			printf(",");
+		    printf("%s", e->toChars());
+		}
+		if (args->dim)
+		    printf(")");
+	    }
+	    printf("\n");
+	}
+	goto Lnodecl;
+    }
+    else
+	error("unrecognized pragma(%s)", ident->toChars());
+
+    if (decl)
+    {
+	for (unsigned i = 0; i < decl->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->semantic(sc);
+        
+#if IN_LLVM
+        if (llvm_internal)
+        {
+            switch(llvm_internal)
+            {
+            case LLVMintrinsic:
+            case LLVMva_intrinsic:
+                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
+                    fd->llvmInternal = llvm_internal;
+                    fd->llvmInternal1 = llvm_str1;
+                }
+                else {
+                    error("may only be used on function declarations");
+                    assert(0);
+                }
+                break;
+
+            case LLVMva_start:
+            case LLVMva_arg:
+                if (TemplateDeclaration* td = s->isTemplateDeclaration()) {
+                    td->llvmInternal = llvm_internal;
+                    assert(td->parameters->dim == 1);
+                    assert(!td->overnext);
+                    assert(!td->overroot);
+                    assert(td->onemember);
+                    Logger::println("template->onemember = %s", td->onemember->toChars());
+                }
+                else {
+                    error("can only be used on templates");
+                    assert(0);
+                }
+                break;
+
+            case LLVMnotypeinfo:
+                s->llvmInternal = llvm_internal;
+                break;
+
+            case LLVMalloca:
+                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
+                    fd->llvmInternal = llvm_internal;
+                }
+                else {
+                    error("may only be used on function declarations");
+                    assert(0);
+                }
+                break;
+
+            default:
+                assert(0 && "invalid LLVM_internal pragma got through :/");
+            }
+        }
+        
+#endif
+    }
+    }
+    return;
+
+Lnodecl:
+    if (decl)
+	error("pragma is missing closing ';'");
+}
+
+int PragmaDeclaration::oneMember(Dsymbol **ps)
+{
+    *ps = NULL;
+    return TRUE;
+}
+
+char *PragmaDeclaration::kind()
+{
+    return "pragma";
+}
+
+void PragmaDeclaration::toObjFile()
+{
+    if (ident == Id::lib)
+    {
+	assert(args && args->dim == 1);
+
+	Expression *e = (Expression *)args->data[0];
+
+	assert(e->op == TOKstring);
+
+	StringExp *se = (StringExp *)e;
+	char *name = (char *)mem.malloc(se->len + 1);
+	memcpy(name, se->string, se->len);
+	name[se->len] = 0;
+	obj_includelib(name);
+    }
+    AttribDeclaration::toObjFile();
+}
+
+void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->printf("pragma(%s", ident->toChars());
+    if (args)
+    {
+	for (size_t i = 0; i < args->dim; i++)
+	{
+	    Expression *e = (Expression *)args->data[i];
+
+	    buf->writestring(", ");
+	    e->toCBuffer(buf, hgs);
+	}
+    }
+    buf->writestring(")");
+    AttribDeclaration::toCBuffer(buf, hgs);
+}
+
+
+/********************************* ConditionalDeclaration ****************************/
+
+ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl)
+	: AttribDeclaration(decl)
+{
+    //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
+    this->condition = condition;
+    this->elsedecl = elsedecl;
+}
+
+Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
+{
+    ConditionalDeclaration *dd;
+
+    assert(!s);
+    dd = new ConditionalDeclaration(condition->syntaxCopy(),
+	Dsymbol::arraySyntaxCopy(decl),
+	Dsymbol::arraySyntaxCopy(elsedecl));
+    return dd;
+}
+
+
+int ConditionalDeclaration::oneMember(Dsymbol **ps)
+{
+    //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
+    if (condition->inc)
+    {
+	Array *d = condition->include(NULL, NULL) ? decl : elsedecl;
+	return Dsymbol::oneMembers(d, ps);
+    }
+    *ps = NULL;
+    return TRUE;
+}
+
+void ConditionalDeclaration::emitComment(Scope *sc)
+{
+    //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
+    if (condition->inc)
+    {
+	AttribDeclaration::emitComment(sc);
+    }
+}
+
+// Decide if 'then' or 'else' code should be included
+
+Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
+{
+    //printf("ConditionalDeclaration::include()\n");
+    assert(condition);
+    return condition->include(sc, sd) ? decl : elsedecl;
+}
+
+
+void ConditionalDeclaration::addComment(unsigned char *comment)
+{
+    /* Because addComment is called by the parser, if we called
+     * include() it would define a version before it was used.
+     * But it's no problem to drill down to both decl and elsedecl,
+     * so that's the workaround.
+     */
+
+    if (comment)
+    {
+	Array *d = decl;
+
+	for (int j = 0; j < 2; j++)
+	{
+	    if (d)
+	    {
+		for (unsigned i = 0; i < d->dim; i++)
+		{   Dsymbol *s;
+
+		    s = (Dsymbol *)d->data[i];
+		    //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
+		    s->addComment(comment);
+		}
+	    }
+	    d = elsedecl;
+	}
+    }
+}
+
+void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    condition->toCBuffer(buf, hgs);
+    if (decl || elsedecl)
+    {
+	buf->writenl();
+	buf->writeByte('{');
+	buf->writenl();
+	if (decl)
+	{
+	    for (unsigned i = 0; i < decl->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)decl->data[i];
+
+		buf->writestring("    ");
+		s->toCBuffer(buf, hgs);
+	    }
+	}
+	buf->writeByte('}');
+	if (elsedecl)
+	{
+	    buf->writenl();
+	    buf->writestring("else");
+	    buf->writenl();
+	    buf->writeByte('{');
+	    buf->writenl();
+	    for (unsigned i = 0; i < elsedecl->dim; i++)
+	    {
+		Dsymbol *s = (Dsymbol *)elsedecl->data[i];
+
+		buf->writestring("    ");
+		s->toCBuffer(buf, hgs);
+	    }
+	    buf->writeByte('}');
+	}
+    }
+    else
+	buf->writeByte(':');
+    buf->writenl();
+}
+
+/***************************** StaticIfDeclaration ****************************/
+
+StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
+	Array *decl, Array *elsedecl)
+	: ConditionalDeclaration(condition, decl, elsedecl)
+{
+    //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
+    sd = NULL;
+    addisdone = 0;
+}
+
+
+Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
+{
+    StaticIfDeclaration *dd;
+
+    assert(!s);
+    dd = new StaticIfDeclaration(condition->syntaxCopy(),
+	Dsymbol::arraySyntaxCopy(decl),
+	Dsymbol::arraySyntaxCopy(elsedecl));
+    return dd;
+}
+
+
+int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    /* This is deferred until semantic(), so that
+     * expressions in the condition can refer to declarations
+     * in the same scope, such as:
+     *
+     * template Foo(int i)
+     * {
+     *     const int j = i + 1;
+     *     static if (j == 3)
+     *         const int k;
+     * }
+     */
+    this->sd = sd;
+    int m = 0;
+
+    if (memnum == 0)
+    {	m = AttribDeclaration::addMember(sc, sd, memnum);
+	addisdone = 1;
+    }
+    return m;
+}
+
+
+void StaticIfDeclaration::semantic(Scope *sc)
+{
+    Array *d = include(sc, sd);
+
+    //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars());
+    if (d)
+    {
+	if (!addisdone)
+	{   AttribDeclaration::addMember(sc, sd, 1);
+	    addisdone = 1;
+	}
+
+	for (unsigned i = 0; i < d->dim; i++)
+	{
+	    Dsymbol *s = (Dsymbol *)d->data[i];
+
+	    s->semantic(sc);
+	}
+    }
+}
+
+char *StaticIfDeclaration::kind()
+{
+    return "static if";
+}
+
+
+/***************************** CompileDeclaration *****************************/
+
+CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
+    : AttribDeclaration(NULL)
+{
+    this->exp = exp;
+    this->sd = NULL;
+}
+
+Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
+{
+    //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
+    CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
+    return sc;
+}
+
+int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
+{
+    this->sd = sd;
+    return memnum;
+}
+
+void CompileDeclaration::semantic(Scope *sc)
+{
+    //printf("CompileDeclaration::semantic()\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;
+    }
+    StringExp *se = (StringExp *)exp;
+    se = se->toUTF8(sc);
+    Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
+    p.loc = loc;
+    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::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+{
+    buf->writestring("mixin(");
+    exp->toCBuffer(buf, hgs);
+    buf->writestring(");");
+    buf->writenl();
+}