From 8a20415cd1090df70d720a1ff5e3c88e292af3af Mon Sep 17 00:00:00 2001 From: kai Date: Tue, 6 Mar 2012 07:28:29 +0100 Subject: [PATCH] Fix white space. --- dmd/access.c | 26 +- dmd/aggregate.h | 30 +- dmd/arrayop.c | 432 +- dmd/arraytypes.h | 68 +- dmd/attrib.c | 8 +- dmd/attrib.h | 30 +- dmd/cast.c | 68 +- dmd/class.c | 244 +- dmd/clone.c | 350 +- dmd/complex_t.h | 148 +- dmd/cond.c | 48 +- dmd/cond.h | 206 +- dmd/constfold.c | 422 +- dmd/declaration.c | 196 +- dmd/declaration.h | 84 +- dmd/delegatize.c | 280 +- dmd/doc.c | 104 +- dmd/doc.h | 40 +- dmd/dsymbol.c | 306 +- dmd/dsymbol.h | 30 +- dmd/dump.c | 288 +- dmd/enum.c | 22 +- dmd/expression.c | 1394 +++---- dmd/expression.h | 256 +- dmd/func.c | 320 +- dmd/hdrgen.c | 200 +- dmd/hdrgen.h | 68 +- dmd/html.c | 1436 +++---- dmd/html.h | 86 +- dmd/identifier.c | 202 +- dmd/idgen.c | 54 +- dmd/impcnvgen.c | 914 ++--- dmd/imphint.c | 164 +- dmd/import.c | 152 +- dmd/import.h | 14 +- dmd/init.c | 294 +- dmd/init.h | 296 +- dmd/inline.c | 738 ++-- dmd/interpret.c | 9290 ++++++++++++++++++++++---------------------- dmd/json.c | 924 ++--- dmd/json.h | 48 +- dmd/lexer.c | 106 +- dmd/lexer.h | 2 +- dmd/macro.c | 898 ++--- dmd/macro.h | 90 +- dmd/mangle.c | 6 +- dmd/mars.c | 158 +- dmd/mars.h | 4 +- dmd/mem.h | 102 +- dmd/module.c | 26 +- dmd/module.h | 36 +- dmd/mtype.c | 114 +- dmd/mtype.h | 20 +- dmd/opover.c | 2 +- dmd/optimize.c | 154 +- dmd/parse.c | 260 +- dmd/parse.h | 8 +- dmd/speller.c | 8 +- dmd/statement.c | 664 ++-- dmd/statement.h | 138 +- dmd/staticassert.c | 18 +- dmd/staticassert.h | 82 +- dmd/struct.c | 180 +- dmd/template.c | 688 ++-- dmd/template.h | 28 +- dmd/unialpha.c | 646 +-- dmd/utf.c | 640 +-- dmd/utf.h | 70 +- dmd/version.c | 362 +- dmd/version.h | 102 +- 70 files changed, 12946 insertions(+), 12946 deletions(-) diff --git a/dmd/access.c b/dmd/access.c index 91f09e5c..fae07af9 100644 --- a/dmd/access.c +++ b/dmd/access.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -81,17 +81,17 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember) access_ret = smember->prot(); } - for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *b = (*baseclasses)[i]; + for (size_t i = 0; i < baseclasses->dim; i++) + { BaseClass *b = (*baseclasses)[i]; - enum PROT access = b->base->getAccess(smember); + enum PROT access = b->base->getAccess(smember); switch (access) { case PROTnone: break; case PROTprivate: - access_ret = PROTnone; // private members of base class not accessible + access_ret = PROTnone; // private members of base class not accessible break; case PROTpackage: @@ -150,9 +150,9 @@ static int accessCheckX( ClassDeclaration *cdthis = dthis->isClassDeclaration(); if (cdthis) { - for (size_t i = 0; i < cdthis->baseclasses->dim; i++) - { BaseClass *b = (*cdthis->baseclasses)[i]; - enum PROT access = b->base->getAccess(smember); + for (size_t i = 0; i < cdthis->baseclasses->dim; i++) + { BaseClass *b = (*cdthis->baseclasses)[i]; + enum PROT access = b->base->getAccess(smember); if (access >= PROTprotected || accessCheckX(smember, sfunc, b->base, cdscope) ) @@ -169,8 +169,8 @@ static int accessCheckX( ClassDeclaration *cdthis = dthis->isClassDeclaration(); if (cdthis) { - for (size_t i = 0; i < cdthis->baseclasses->dim; i++) - { BaseClass *b = (*cdthis->baseclasses)[i]; + for (size_t i = 0; i < cdthis->baseclasses->dim; i++) + { BaseClass *b = (*cdthis->baseclasses)[i]; if (accessCheckX(smember, sfunc, b->base, cdscope)) return 1; @@ -214,12 +214,12 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember) //assert(smember->parent->isBaseOf(this, NULL)); if (smemberparent == this) - { enum PROT access2 = smember->prot(); + { enum PROT access2 = smember->prot(); - result = access2 >= PROTpublic || + result = access2 >= PROTpublic || hasPrivateAccess(f) || isFriendOf(cdscope) || - (access2 == PROTpackage && hasPackageAccess(sc, this)); + (access2 == PROTpackage && hasPackageAccess(sc, this)); #if LOG printf("result1 = %d\n", result); #endif diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 32d6a3ec..5b19d28b 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -61,7 +61,7 @@ struct AggregateDeclaration : ScopeDsymbol unsigned alignsize; // size of struct for alignment purposes unsigned structalign; // struct member alignment in effect int hasUnions; // set if aggregate has overlapping fields - VarDeclarations fields; // VarDeclaration fields + VarDeclarations fields; // VarDeclaration fields unsigned sizeok; // set when structsize contains valid data // 0: no size // 1: size is correct @@ -82,7 +82,7 @@ struct AggregateDeclaration : ScopeDsymbol Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration CtorDeclaration *defaultCtor; // default constructor Dsymbol *aliasthis; // forward unresolved lookups to aliasthis - bool noDefaultCtor; // no default construction + bool noDefaultCtor; // no default construction #endif FuncDeclarations dtors; // Array of destructors @@ -100,12 +100,12 @@ struct AggregateDeclaration : ScopeDsymbol static void alignmember(unsigned salign, unsigned size, unsigned *poffset); Type *getType(); void addField(Scope *sc, VarDeclaration *v); - int firstFieldInUnion(int indx); // first field in union that includes indx - int numFieldsInUnion(int firstIndex); // #fields in union starting at index + int firstFieldInUnion(int indx); // first field in union that includes indx + int numFieldsInUnion(int firstIndex); // #fields in union starting at index int isDeprecated(); // is aggregate deprecated? FuncDeclaration *buildDtor(Scope *sc); int isNested(); - int isExport(); + int isExport(); void emitComment(Scope *sc); void toJsonBuffer(OutBuffer *buf); @@ -150,7 +150,7 @@ struct StructDeclaration : AggregateDeclaration #if DMDV2 int hasIdentityAssign; // !=0 if has identity opAssign FuncDeclaration *cpctor; // generated copy-constructor, if any - FuncDeclaration *eq; // bool opEquals(ref const T), if any + FuncDeclaration *eq; // bool opEquals(ref const T), if any FuncDeclarations postblits; // Array of postblit functions FuncDeclaration *postblit; // aggregate postblit @@ -207,17 +207,17 @@ struct BaseClass ClassDeclaration *base; int offset; // 'this' pointer offset - FuncDeclarations vtbl; // for interfaces: Array of FuncDeclaration's + FuncDeclarations vtbl; // for interfaces: Array of FuncDeclaration's // making up the vtbl[] - size_t baseInterfaces_dim; + size_t baseInterfaces_dim; BaseClass *baseInterfaces; // if BaseClass is an interface, these // are a copy of the InterfaceDeclaration::interfaces BaseClass(); BaseClass(Type *type, enum PROT protection); - int fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance); + int fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance); void copyBaseInterfaces(BaseClasses *); }; @@ -232,7 +232,7 @@ struct ClassDeclaration : AggregateDeclaration { static ClassDeclaration *object; static ClassDeclaration *classinfo; - static ClassDeclaration *errorException; + static ClassDeclaration *errorException; ClassDeclaration *baseClass; // NULL only if this is Object #if DMDV1 @@ -241,13 +241,13 @@ struct ClassDeclaration : AggregateDeclaration #endif FuncDeclaration *staticCtor; FuncDeclaration *staticDtor; - Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] - Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] + Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] + Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] BaseClasses *baseclasses; // Array of BaseClass's; first is super, // rest are Interface's - size_t interfaces_dim; + size_t interfaces_dim; BaseClass **interfaces; // interfaces[interfaces_dim] for this class // (does not include baseClass) @@ -276,7 +276,7 @@ struct ClassDeclaration : AggregateDeclaration virtual int isBaseInfoComplete(); Dsymbol *search(Loc, Identifier *ident, int flags); - Dsymbol *searchBase(Loc, Identifier *ident); + Dsymbol *searchBase(Loc, Identifier *ident); #if DMDV2 int isFuncHidden(FuncDeclaration *fd); #endif diff --git a/dmd/arrayop.c b/dmd/arrayop.c index e043d779..8b847f0a 100644 --- a/dmd/arrayop.c +++ b/dmd/arrayop.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -13,7 +13,7 @@ #include "rmem.h" -#include "aav.h" +#include "aav.h" #include "expression.h" #include "statement.h" @@ -31,7 +31,7 @@ extern int binary(const char *p , const char **tab, int high); * Hash table of array op functions already generated or known about. */ -AA *arrayfuncs; +AA *arrayfuncs; #endif /********************************************** @@ -125,195 +125,195 @@ Expression *BinExp::arrayOp(Scope *sc) size_t namelen = buf.offset; buf.writeByte(0); - char *name = buf.toChars(); - Identifier *ident = Lexer::idPool(name); + char *name = buf.toChars(); + Identifier *ident = Lexer::idPool(name); /* Look up name in hash table */ -#if IN_DMD - FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident); - FuncDeclaration *fd = (FuncDeclaration *)*pfd; -#elif IN_LLVM +#if IN_DMD + FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident); + FuncDeclaration *fd = (FuncDeclaration *)*pfd; +#elif IN_LLVM StringValue *sv = sc->module->arrayfuncs.update(name, namelen); FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue; -#endif +#endif if (!fd) { -#if IN_DMD - static const char *libArrayopFuncs[] = - { - "_arrayExpSliceAddass_a", - "_arrayExpSliceAddass_d", // T[]+=T - "_arrayExpSliceAddass_f", // T[]+=T - "_arrayExpSliceAddass_g", - "_arrayExpSliceAddass_h", - "_arrayExpSliceAddass_i", - "_arrayExpSliceAddass_k", - "_arrayExpSliceAddass_s", - "_arrayExpSliceAddass_t", - "_arrayExpSliceAddass_u", - "_arrayExpSliceAddass_w", - - "_arrayExpSliceDivass_d", // T[]/=T - "_arrayExpSliceDivass_f", // T[]/=T - - "_arrayExpSliceMinSliceAssign_a", - "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[] - "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[] - "_arrayExpSliceMinSliceAssign_g", - "_arrayExpSliceMinSliceAssign_h", - "_arrayExpSliceMinSliceAssign_i", - "_arrayExpSliceMinSliceAssign_k", - "_arrayExpSliceMinSliceAssign_s", - "_arrayExpSliceMinSliceAssign_t", - "_arrayExpSliceMinSliceAssign_u", - "_arrayExpSliceMinSliceAssign_w", - - "_arrayExpSliceMinass_a", - "_arrayExpSliceMinass_d", // T[]-=T - "_arrayExpSliceMinass_f", // T[]-=T - "_arrayExpSliceMinass_g", - "_arrayExpSliceMinass_h", - "_arrayExpSliceMinass_i", - "_arrayExpSliceMinass_k", - "_arrayExpSliceMinass_s", - "_arrayExpSliceMinass_t", - "_arrayExpSliceMinass_u", - "_arrayExpSliceMinass_w", - - "_arrayExpSliceMulass_d", // T[]*=T - "_arrayExpSliceMulass_f", // T[]*=T - "_arrayExpSliceMulass_i", - "_arrayExpSliceMulass_k", - "_arrayExpSliceMulass_s", - "_arrayExpSliceMulass_t", - "_arrayExpSliceMulass_u", - "_arrayExpSliceMulass_w", - - "_arraySliceExpAddSliceAssign_a", - "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T - "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T - "_arraySliceExpAddSliceAssign_g", - "_arraySliceExpAddSliceAssign_h", - "_arraySliceExpAddSliceAssign_i", - "_arraySliceExpAddSliceAssign_k", - "_arraySliceExpAddSliceAssign_s", - "_arraySliceExpAddSliceAssign_t", - "_arraySliceExpAddSliceAssign_u", - "_arraySliceExpAddSliceAssign_w", - - "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T - "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T - - "_arraySliceExpMinSliceAssign_a", - "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T - "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T - "_arraySliceExpMinSliceAssign_g", - "_arraySliceExpMinSliceAssign_h", - "_arraySliceExpMinSliceAssign_i", - "_arraySliceExpMinSliceAssign_k", - "_arraySliceExpMinSliceAssign_s", - "_arraySliceExpMinSliceAssign_t", - "_arraySliceExpMinSliceAssign_u", - "_arraySliceExpMinSliceAssign_w", - - "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T - "_arraySliceExpMulSliceAddass_f", - "_arraySliceExpMulSliceAddass_r", - - "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T - "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T - "_arraySliceExpMulSliceAssign_i", - "_arraySliceExpMulSliceAssign_k", - "_arraySliceExpMulSliceAssign_s", - "_arraySliceExpMulSliceAssign_t", - "_arraySliceExpMulSliceAssign_u", - "_arraySliceExpMulSliceAssign_w", - - "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T - "_arraySliceExpMulSliceMinass_f", - "_arraySliceExpMulSliceMinass_r", - - "_arraySliceSliceAddSliceAssign_a", - "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[] - "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[] - "_arraySliceSliceAddSliceAssign_g", - "_arraySliceSliceAddSliceAssign_h", - "_arraySliceSliceAddSliceAssign_i", - "_arraySliceSliceAddSliceAssign_k", - "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[] - "_arraySliceSliceAddSliceAssign_s", - "_arraySliceSliceAddSliceAssign_t", - "_arraySliceSliceAddSliceAssign_u", - "_arraySliceSliceAddSliceAssign_w", - - "_arraySliceSliceAddass_a", - "_arraySliceSliceAddass_d", // T[]+=T[] - "_arraySliceSliceAddass_f", // T[]+=T[] - "_arraySliceSliceAddass_g", - "_arraySliceSliceAddass_h", - "_arraySliceSliceAddass_i", - "_arraySliceSliceAddass_k", - "_arraySliceSliceAddass_s", - "_arraySliceSliceAddass_t", - "_arraySliceSliceAddass_u", - "_arraySliceSliceAddass_w", - - "_arraySliceSliceMinSliceAssign_a", - "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[] - "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[] - "_arraySliceSliceMinSliceAssign_g", - "_arraySliceSliceMinSliceAssign_h", - "_arraySliceSliceMinSliceAssign_i", - "_arraySliceSliceMinSliceAssign_k", - "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[] - "_arraySliceSliceMinSliceAssign_s", - "_arraySliceSliceMinSliceAssign_t", - "_arraySliceSliceMinSliceAssign_u", - "_arraySliceSliceMinSliceAssign_w", - - "_arraySliceSliceMinass_a", - "_arraySliceSliceMinass_d", // T[]-=T[] - "_arraySliceSliceMinass_f", // T[]-=T[] - "_arraySliceSliceMinass_g", - "_arraySliceSliceMinass_h", - "_arraySliceSliceMinass_i", - "_arraySliceSliceMinass_k", - "_arraySliceSliceMinass_s", - "_arraySliceSliceMinass_t", - "_arraySliceSliceMinass_u", - "_arraySliceSliceMinass_w", - - "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[] - "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[] - "_arraySliceSliceMulSliceAssign_i", - "_arraySliceSliceMulSliceAssign_k", - "_arraySliceSliceMulSliceAssign_s", - "_arraySliceSliceMulSliceAssign_t", - "_arraySliceSliceMulSliceAssign_u", - "_arraySliceSliceMulSliceAssign_w", - - "_arraySliceSliceMulass_d", // T[]*=T[] - "_arraySliceSliceMulass_f", // T[]*=T[] - "_arraySliceSliceMulass_i", - "_arraySliceSliceMulass_k", - "_arraySliceSliceMulass_s", - "_arraySliceSliceMulass_t", - "_arraySliceSliceMulass_u", - "_arraySliceSliceMulass_w", - }; - - int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); - if (i == -1) - { -#ifdef DEBUG // Make sure our array is alphabetized - for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++) - { - if (strcmp(name, libArrayopFuncs[i]) == 0) - assert(0); - } -#endif -#endif +#if IN_DMD + static const char *libArrayopFuncs[] = + { + "_arrayExpSliceAddass_a", + "_arrayExpSliceAddass_d", // T[]+=T + "_arrayExpSliceAddass_f", // T[]+=T + "_arrayExpSliceAddass_g", + "_arrayExpSliceAddass_h", + "_arrayExpSliceAddass_i", + "_arrayExpSliceAddass_k", + "_arrayExpSliceAddass_s", + "_arrayExpSliceAddass_t", + "_arrayExpSliceAddass_u", + "_arrayExpSliceAddass_w", + + "_arrayExpSliceDivass_d", // T[]/=T + "_arrayExpSliceDivass_f", // T[]/=T + + "_arrayExpSliceMinSliceAssign_a", + "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[] + "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[] + "_arrayExpSliceMinSliceAssign_g", + "_arrayExpSliceMinSliceAssign_h", + "_arrayExpSliceMinSliceAssign_i", + "_arrayExpSliceMinSliceAssign_k", + "_arrayExpSliceMinSliceAssign_s", + "_arrayExpSliceMinSliceAssign_t", + "_arrayExpSliceMinSliceAssign_u", + "_arrayExpSliceMinSliceAssign_w", + + "_arrayExpSliceMinass_a", + "_arrayExpSliceMinass_d", // T[]-=T + "_arrayExpSliceMinass_f", // T[]-=T + "_arrayExpSliceMinass_g", + "_arrayExpSliceMinass_h", + "_arrayExpSliceMinass_i", + "_arrayExpSliceMinass_k", + "_arrayExpSliceMinass_s", + "_arrayExpSliceMinass_t", + "_arrayExpSliceMinass_u", + "_arrayExpSliceMinass_w", + + "_arrayExpSliceMulass_d", // T[]*=T + "_arrayExpSliceMulass_f", // T[]*=T + "_arrayExpSliceMulass_i", + "_arrayExpSliceMulass_k", + "_arrayExpSliceMulass_s", + "_arrayExpSliceMulass_t", + "_arrayExpSliceMulass_u", + "_arrayExpSliceMulass_w", + + "_arraySliceExpAddSliceAssign_a", + "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T + "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T + "_arraySliceExpAddSliceAssign_g", + "_arraySliceExpAddSliceAssign_h", + "_arraySliceExpAddSliceAssign_i", + "_arraySliceExpAddSliceAssign_k", + "_arraySliceExpAddSliceAssign_s", + "_arraySliceExpAddSliceAssign_t", + "_arraySliceExpAddSliceAssign_u", + "_arraySliceExpAddSliceAssign_w", + + "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T + "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T + + "_arraySliceExpMinSliceAssign_a", + "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T + "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T + "_arraySliceExpMinSliceAssign_g", + "_arraySliceExpMinSliceAssign_h", + "_arraySliceExpMinSliceAssign_i", + "_arraySliceExpMinSliceAssign_k", + "_arraySliceExpMinSliceAssign_s", + "_arraySliceExpMinSliceAssign_t", + "_arraySliceExpMinSliceAssign_u", + "_arraySliceExpMinSliceAssign_w", + + "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T + "_arraySliceExpMulSliceAddass_f", + "_arraySliceExpMulSliceAddass_r", + + "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T + "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T + "_arraySliceExpMulSliceAssign_i", + "_arraySliceExpMulSliceAssign_k", + "_arraySliceExpMulSliceAssign_s", + "_arraySliceExpMulSliceAssign_t", + "_arraySliceExpMulSliceAssign_u", + "_arraySliceExpMulSliceAssign_w", + + "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T + "_arraySliceExpMulSliceMinass_f", + "_arraySliceExpMulSliceMinass_r", + + "_arraySliceSliceAddSliceAssign_a", + "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_g", + "_arraySliceSliceAddSliceAssign_h", + "_arraySliceSliceAddSliceAssign_i", + "_arraySliceSliceAddSliceAssign_k", + "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_s", + "_arraySliceSliceAddSliceAssign_t", + "_arraySliceSliceAddSliceAssign_u", + "_arraySliceSliceAddSliceAssign_w", + + "_arraySliceSliceAddass_a", + "_arraySliceSliceAddass_d", // T[]+=T[] + "_arraySliceSliceAddass_f", // T[]+=T[] + "_arraySliceSliceAddass_g", + "_arraySliceSliceAddass_h", + "_arraySliceSliceAddass_i", + "_arraySliceSliceAddass_k", + "_arraySliceSliceAddass_s", + "_arraySliceSliceAddass_t", + "_arraySliceSliceAddass_u", + "_arraySliceSliceAddass_w", + + "_arraySliceSliceMinSliceAssign_a", + "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_g", + "_arraySliceSliceMinSliceAssign_h", + "_arraySliceSliceMinSliceAssign_i", + "_arraySliceSliceMinSliceAssign_k", + "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_s", + "_arraySliceSliceMinSliceAssign_t", + "_arraySliceSliceMinSliceAssign_u", + "_arraySliceSliceMinSliceAssign_w", + + "_arraySliceSliceMinass_a", + "_arraySliceSliceMinass_d", // T[]-=T[] + "_arraySliceSliceMinass_f", // T[]-=T[] + "_arraySliceSliceMinass_g", + "_arraySliceSliceMinass_h", + "_arraySliceSliceMinass_i", + "_arraySliceSliceMinass_k", + "_arraySliceSliceMinass_s", + "_arraySliceSliceMinass_t", + "_arraySliceSliceMinass_u", + "_arraySliceSliceMinass_w", + + "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[] + "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[] + "_arraySliceSliceMulSliceAssign_i", + "_arraySliceSliceMulSliceAssign_k", + "_arraySliceSliceMulSliceAssign_s", + "_arraySliceSliceMulSliceAssign_t", + "_arraySliceSliceMulSliceAssign_u", + "_arraySliceSliceMulSliceAssign_w", + + "_arraySliceSliceMulass_d", // T[]*=T[] + "_arraySliceSliceMulass_f", // T[]*=T[] + "_arraySliceSliceMulass_i", + "_arraySliceSliceMulass_k", + "_arraySliceSliceMulass_s", + "_arraySliceSliceMulass_t", + "_arraySliceSliceMulass_u", + "_arraySliceSliceMulass_w", + }; + + int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); + if (i == -1) + { +#ifdef DEBUG // Make sure our array is alphabetized + for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++) + { + if (strcmp(name, libArrayopFuncs[i]) == 0) + assert(0); + } +#endif +#endif /* Not in library, so generate it. * Construct the function body: * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) @@ -323,13 +323,13 @@ Expression *BinExp::arrayOp(Scope *sc) Parameters *fparams = new Parameters(); Expression *loopbody = buildArrayLoop(fparams); - Parameter *p = (*fparams)[0 /*fparams->dim - 1*/]; + Parameter *p = (*fparams)[0 /*fparams->dim - 1*/]; #if DMDV1 // for (size_t i = 0; i < p.length; i++) Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); Statement *s1 = new ForStatement(0, - new ExpStatement(0, d), + new ExpStatement(0, d), new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), new ExpStatement(0, loopbody)); @@ -349,33 +349,33 @@ Expression *BinExp::arrayOp(Scope *sc) */ TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); //printf("ftype: %s\n", ftype->toChars()); - fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype); + fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype); fd->fbody = fbody; fd->protection = PROTpublic; - fd->linkage = LINKc; - fd->isArrayOp = 1; + fd->linkage = LINKc; + fd->isArrayOp = 1; sc->module->importedFrom->members->push(fd); sc = sc->push(); sc->parent = sc->module->importedFrom; sc->stc = 0; - sc->linkage = LINKc; + sc->linkage = LINKc; fd->semantic(sc); fd->semantic2(sc); fd->semantic3(sc); sc->pop(); -#if IN_DMD - } - else - { /* In library, refer to it. - */ - fd = FuncDeclaration::genCfunc(type, ident); - } - *pfd = fd; // cache symbol in hash table -#elif IN_LLVM +#if IN_DMD + } + else + { /* In library, refer to it. + */ + fd = FuncDeclaration::genCfunc(type, ident); + } + *pfd = fd; // cache symbol in hash table +#elif IN_LLVM sv->ptrvalue = fd; // cache symbol in hash table -#endif +#endif } /* Call the function fd(arguments) @@ -442,9 +442,9 @@ X(Mod) X(Xor) X(And) X(Or) -#if DMDV2 -X(Pow) -#endif +#if DMDV2 +X(Pow) +#endif #undef X @@ -478,9 +478,9 @@ X(Mod) X(Xor) X(And) X(Or) -#if DMDV2 -X(Pow) -#endif +#if DMDV2 +X(Pow) +#endif #undef X @@ -536,7 +536,7 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams) ex2 = new CastExp(0, ex2, e1->type->nextOf()); #endif Expression *ex1 = e1->buildArrayLoop(fparams); - Parameter *param = (*fparams)[0]; + Parameter *param = (*fparams)[0]; param->storageClass = 0; Expression *e = new AssignExp(0, ex1, ex2); return e; @@ -549,9 +549,9 @@ Expression *Str##AssignExp::buildArrayLoop(Parameters *fparams) \ */ \ Expression *ex2 = e2->buildArrayLoop(fparams); \ Expression *ex1 = e1->buildArrayLoop(fparams); \ - Parameter *param = (*fparams)[0]; \ + Parameter *param = (*fparams)[0]; \ param->storageClass = 0; \ - Expression *e = new Str##AssignExp(loc, ex1, ex2); \ + Expression *e = new Str##AssignExp(loc, ex1, ex2); \ return e; \ } @@ -563,9 +563,9 @@ X(Mod) X(Xor) X(And) X(Or) -#if DMDV2 -X(Pow) -#endif +#if DMDV2 +X(Pow) +#endif #undef X @@ -602,9 +602,9 @@ X(Mod) X(Xor) X(And) X(Or) -#if DMDV2 -X(Pow) -#endif +#if DMDV2 +X(Pow) +#endif #undef X diff --git a/dmd/arraytypes.h b/dmd/arraytypes.h index 45458ce1..61eb7b50 100644 --- a/dmd/arraytypes.h +++ b/dmd/arraytypes.h @@ -26,49 +26,49 @@ struct FuncDeclaration; struct Identifier; struct Initializer; -typedef ArrayBase TemplateParameters; +typedef ArrayBase TemplateParameters; -typedef ArrayBase Expressions; +typedef ArrayBase Expressions; -typedef ArrayBase Statements; +typedef ArrayBase Statements; -typedef ArrayBase BaseClasses; +typedef ArrayBase BaseClasses; -typedef ArrayBase ClassDeclarations; +typedef ArrayBase ClassDeclarations; -typedef ArrayBase Dsymbols; +typedef ArrayBase Dsymbols; -typedef ArrayBase Objects; +typedef ArrayBase Objects; -typedef ArrayBase FuncDeclarations; +typedef ArrayBase FuncDeclarations; -typedef ArrayBase Parameters; +typedef ArrayBase Parameters; -typedef ArrayBase Identifiers; +typedef ArrayBase Identifiers; -typedef ArrayBase Initializers; - -typedef ArrayBase VarDeclarations; - -typedef ArrayBase Types; - -typedef ArrayBase ScopeDsymbols; - -typedef ArrayBase Catches; - -typedef ArrayBase StaticDtorDeclarations; - -typedef ArrayBase SharedStaticDtorDeclarations; -typedef ArrayBase Modules; -typedef ArrayBase CaseStatements; - -typedef ArrayBase CompoundStatements; - -typedef ArrayBase GotoCaseStatements; - -typedef ArrayBase TemplateInstances; -typedef ArrayBase Blocks; - -typedef ArrayBase Symbols; +typedef ArrayBase Initializers; + +typedef ArrayBase VarDeclarations; + +typedef ArrayBase Types; + +typedef ArrayBase ScopeDsymbols; + +typedef ArrayBase Catches; + +typedef ArrayBase StaticDtorDeclarations; + +typedef ArrayBase SharedStaticDtorDeclarations; +typedef ArrayBase Modules; +typedef ArrayBase CaseStatements; + +typedef ArrayBase CompoundStatements; + +typedef ArrayBase GotoCaseStatements; + +typedef ArrayBase TemplateInstances; +typedef ArrayBase Blocks; + +typedef ArrayBase Symbols; #endif diff --git a/dmd/attrib.c b/dmd/attrib.c index aff21495..eebf0837 100644 --- a/dmd/attrib.c +++ b/dmd/attrib.c @@ -1142,7 +1142,7 @@ void PragmaDeclaration::semantic(Scope *sc) else error("unrecognized pragma(%s)", ident->toChars()); -Ldecl: +Ldecl: if (decl) { for (unsigned i = 0; i < decl->dim; i++) @@ -1160,10 +1160,10 @@ Ldecl: Lnodecl: if (decl) - { + { error("pragma is missing closing ';'"); - goto Ldecl; // do them anyway, to avoid segfaults. - } + goto Ldecl; // do them anyway, to avoid segfaults. + } } int PragmaDeclaration::oneMember(Dsymbol **ps) diff --git a/dmd/attrib.h b/dmd/attrib.h index a92717dc..b8269525 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -29,10 +29,10 @@ struct HdrGenState; struct AttribDeclaration : Dsymbol { - Dsymbols *decl; // array of Dsymbol's + Dsymbols *decl; // array of Dsymbol's - AttribDeclaration(Dsymbols *decl); - virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s); + AttribDeclaration(Dsymbols *decl); + virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void setScopeNewSc(Scope *sc, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, @@ -49,7 +49,7 @@ struct AttribDeclaration : Dsymbol const char *kind(); int oneMember(Dsymbol **ps); int hasPointers(); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor(); void checkCtorConstInit(); void addLocalClass(ClassDeclarations *); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -70,7 +70,7 @@ struct StorageClassDeclaration: AttribDeclaration { StorageClass stc; - StorageClassDeclaration(StorageClass stc, Dsymbols *decl); + StorageClassDeclaration(StorageClass stc, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void setScope(Scope *sc); void semantic(Scope *sc); @@ -83,7 +83,7 @@ struct LinkDeclaration : AttribDeclaration { enum LINK linkage; - LinkDeclaration(enum LINK p, Dsymbols *decl); + LinkDeclaration(enum LINK p, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void setScope(Scope *sc); void semantic(Scope *sc); @@ -96,7 +96,7 @@ struct ProtDeclaration : AttribDeclaration { enum PROT protection; - ProtDeclaration(enum PROT p, Dsymbols *decl); + ProtDeclaration(enum PROT p, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void importAll(Scope *sc); void setScope(Scope *sc); @@ -110,7 +110,7 @@ struct AlignDeclaration : AttribDeclaration { unsigned salign; - AlignDeclaration(Loc loc, unsigned sa, Dsymbols *decl); + AlignDeclaration(Loc loc, unsigned sa, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void setScope(Scope *sc); void semantic(Scope *sc); @@ -122,7 +122,7 @@ struct AnonDeclaration : AttribDeclaration int isunion; int sem; // 1 if successful semantic() - AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); + AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -133,7 +133,7 @@ struct PragmaDeclaration : AttribDeclaration { Expressions *args; // array of Expression's - PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl); + PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void setScope(Scope *sc); @@ -153,13 +153,13 @@ struct PragmaDeclaration : AttribDeclaration struct ConditionalDeclaration : AttribDeclaration { Condition *condition; - Dsymbols *elsedecl; // array of Dsymbol's for else block + Dsymbols *elsedecl; // array of Dsymbol's for else block - ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl); + ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl); Dsymbol *syntaxCopy(Dsymbol *s); int oneMember(Dsymbol **ps); void emitComment(Scope *sc); - Dsymbols *include(Scope *sc, ScopeDsymbol *s); + Dsymbols *include(Scope *sc, ScopeDsymbol *s); void addComment(unsigned char *comment); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toJsonBuffer(OutBuffer *buf); @@ -172,7 +172,7 @@ struct StaticIfDeclaration : ConditionalDeclaration ScopeDsymbol *sd; int addisdone; - StaticIfDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl); + StaticIfDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl); Dsymbol *syntaxCopy(Dsymbol *s); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void semantic(Scope *sc); diff --git a/dmd/cast.c b/dmd/cast.c index 3176f846..04fdb80d 100644 --- a/dmd/cast.c +++ b/dmd/cast.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -123,8 +123,8 @@ MATCH Expression::implicitConvTo(Type *t) toChars(), type->toChars(), t->toChars()); #endif //static int nest; if (++nest == 10) halt(); - if (t == Type::terror) - return MATCHnomatch; + if (t == Type::terror) + return MATCHnomatch; if (!type) { error("%s is not an expression", toChars()); type = Type::terror; @@ -379,8 +379,8 @@ MATCH StructLiteralExp::implicitConvTo(Type *t) ((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym) { m = MATCHconst; - for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (*elements)[i]; + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; Type *te = e->type; if (t->mod == 0) te = te->mutableOf(); @@ -399,7 +399,7 @@ MATCH StructLiteralExp::implicitConvTo(Type *t) #endif MATCH StringExp::implicitConvTo(Type *t) -{ +{ #if 0 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", toChars(), committed, type->toChars(), t->toChars()); @@ -467,18 +467,18 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t) result = MATCHnomatch; } - for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (*elements)[i]; + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; MATCH m = (MATCH)e->implicitConvTo(tb->nextOf()); if (m < result) result = m; // remember worst match if (result == MATCHnomatch) break; // no need to check for worse } - - if (!result) - result = type->implicitConvTo(t); - + + if (!result) + result = type->implicitConvTo(t); + return result; } else @@ -667,12 +667,12 @@ Expression *Expression::castTo(Scope *sc, Type *t) } -Expression *ErrorExp::castTo(Scope *sc, Type *t) -{ - return this; -} - - +Expression *ErrorExp::castTo(Scope *sc, Type *t) +{ + return this; +} + + Expression *RealExp::castTo(Scope *sc, Type *t) { Expression *e = this; if (type != t) @@ -765,7 +765,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) return new ErrorExp(); } - StringExp *se = this; + StringExp *se = this; if (!committed) { se = (StringExp *)copy(); se->committed = 1; @@ -777,7 +777,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t) return se; } - Type *tb = t->toBasetype(); + Type *tb = t->toBasetype(); //printf("\ttype = %s\n", type->toChars()); if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate) return Expression::castTo(sc, t); @@ -921,11 +921,11 @@ Expression *StringExp::castTo(Scope *sc, Type *t) } se->string = buffer.extractData(); se->len = newlen; - { - d_uns64 szx = tb->nextOf()->size(); - assert(szx <= 255); - se->sz = (unsigned char)szx; - } + { + d_uns64 szx = tb->nextOf()->size(); + assert(szx <= 255); + se->sz = (unsigned char)szx; + } break; default: @@ -940,9 +940,9 @@ L2: // See if need to truncate or extend the literal if (tb->ty == Tsarray) { - dinteger_t dim2 = ((TypeSArray *)tb)->dim->toInteger(); + dinteger_t dim2 = ((TypeSArray *)tb)->dim->toInteger(); - //printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2); + //printf("dim from = %d, to = %d\n", (int)se->len, (int)dim2); // Changing dimensions if (dim2 != se->len) @@ -1050,10 +1050,10 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) e = (ArrayLiteralExp *)copy(); e->elements = (Expressions *)elements->copy(); - for (size_t i = 0; i < elements->dim; i++) - { Expression *ex = (*elements)[i]; + for (size_t i = 0; i < elements->dim; i++) + { Expression *ex = (*elements)[i]; ex = ex->castTo(sc, tb->nextOf()); - (*e->elements)[i] = ex; + (*e->elements)[i] = ex; } e->type = t; return e; @@ -1451,14 +1451,14 @@ Expression *BinExp::typeCombine(Scope *sc) } else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) { - if (t1->ty == Tsarray && e2->op == TOKarrayliteral) - goto Lt1; + if (t1->ty == Tsarray && e2->op == TOKarrayliteral) + goto Lt1; goto Lt2; } else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1)) { - if (t2->ty == Tsarray && e1->op == TOKarrayliteral) - goto Lt2; + if (t2->ty == Tsarray && e1->op == TOKarrayliteral) + goto Lt2; goto Lt1; } else if (t1->ty == Tclass || t2->ty == Tclass) diff --git a/dmd/class.c b/dmd/class.c index 24554f91..c590f8b2 100644 --- a/dmd/class.c +++ b/dmd/class.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -31,7 +31,7 @@ ClassDeclaration *ClassDeclaration::classinfo; ClassDeclaration *ClassDeclaration::object; -ClassDeclaration *ClassDeclaration::errorException; +ClassDeclaration *ClassDeclaration::errorException; ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) : AggregateDeclaration(loc, id) @@ -171,12 +171,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla Type::typeinfoshared->error("%s", msg); Type::typeinfoshared = this; } - - if (id == Id::TypeInfo_Wild) - { if (Type::typeinfowild) - Type::typeinfowild->error("%s", msg); - Type::typeinfowild = this; - } + + if (id == Id::TypeInfo_Wild) + { if (Type::typeinfowild) + Type::typeinfowild->error("%s", msg); + Type::typeinfowild = this; + } #endif } @@ -186,12 +186,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla object = this; } - if (id == Id::Error) - { if (errorException) - errorException->error("%s", msg); - errorException = this; - } - + if (id == Id::Error) + { if (errorException) + errorException->error("%s", msg); + errorException = this; + } + if (id == Id::ClassInfo) { if (classinfo) classinfo->error("%s", msg); @@ -226,7 +226,7 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) cd->storage_class |= storage_class; cd->baseclasses->setDim(this->baseclasses->dim); - for (size_t i = 0; i < cd->baseclasses->dim; i++) + for (size_t i = 0; i < cd->baseclasses->dim; i++) { BaseClass *b = (BaseClass *)this->baseclasses->data[i]; BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); @@ -238,7 +238,7 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) } void ClassDeclaration::semantic(Scope *sc) -{ +{ //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); //printf("sc->stc = %x\n", sc->stc); @@ -289,7 +289,7 @@ void ClassDeclaration::semantic(Scope *sc) } // Expand any tuples in baseclasses[] - for (size_t i = 0; i < baseclasses->dim; ) + for (size_t i = 0; i < baseclasses->dim; ) { BaseClass *b = (BaseClass *)baseclasses->data[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -379,7 +379,7 @@ void ClassDeclaration::semantic(Scope *sc) // Treat the remaining entries in baseclasses as interfaces // Check for errors, handle forward references - for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; ) + for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; @@ -501,7 +501,7 @@ void ClassDeclaration::semantic(Scope *sc) { interfaceSemantic(sc); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->addMember(sc, this, 1); @@ -547,9 +547,9 @@ void ClassDeclaration::semantic(Scope *sc) if (ad) t = ad->handle; else if (fd) - { AggregateDeclaration *ad2 = fd->isMember2(); - if (ad2) - t = ad2->handle; + { AggregateDeclaration *ad2 = fd->isMember2(); + if (ad2) + t = ad2->handle; else { t = new TypePointer(Type::tvoid); @@ -605,13 +605,13 @@ void ClassDeclaration::semantic(Scope *sc) } structsize = sc->offset; Scope scsave = *sc; - size_t members_dim = members->dim; + size_t members_dim = members->dim; sizeok = 0; /* Set scope so if there are forward references, we still might be able to * resolve individual members like enums. */ - for (size_t i = 0; i < members_dim; i++) + for (size_t i = 0; i < members_dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' @@ -623,7 +623,7 @@ void ClassDeclaration::semantic(Scope *sc) } } - for (size_t i = 0; i < members_dim; i++) + for (size_t i = 0; i < members_dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->semantic(sc); } @@ -699,7 +699,7 @@ void ClassDeclaration::semantic(Scope *sc) #endif // Allocate instance of each new interface - for (size_t i = 0; i < vtblInterfaces->dim; i++) + for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; unsigned thissize = PTRSIZE; @@ -748,7 +748,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (baseclasses->dim) buf->writestring(" : "); } - for (size_t i = 0; i < baseclasses->dim; i++) + for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (BaseClass *)baseclasses->data[i]; @@ -762,7 +762,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; @@ -798,7 +798,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) if (!cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); - for (size_t i = 0; i < cd->baseclasses->dim; i++) + for (size_t i = 0; i < cd->baseclasses->dim; i++) { BaseClass *b = (BaseClass *)cd->baseclasses->data[i]; if (b->base == this || isBaseOf2(b->base)) @@ -822,14 +822,14 @@ int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) */ if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration()) { - cd->semantic(NULL); - if (!cd->baseClass) + cd->semantic(NULL); + if (!cd->baseClass) cd->error("base class is forward referenced by %s", toChars()); } - if (this == cd->baseClass) - return 1; - + if (this == cd->baseClass) + return 1; + cd = cd->baseClass; } return 0; @@ -844,7 +844,7 @@ int ClassDeclaration::isBaseInfoComplete() { if (!baseClass) return ident == Id::Object; - for (size_t i = 0; i < baseclasses->dim; i++) + for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (BaseClass *)baseclasses->data[i]; if (!b->base || !b->base->isBaseInfoComplete()) return 0; @@ -857,14 +857,14 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) Dsymbol *s; //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); - if (scope && !symtab) + if (scope && !symtab) { Scope *sc = scope; sc->mustsemantic++; semantic(sc); sc->mustsemantic--; } - if (!members || !symtab) + if (!members || !symtab) { error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; @@ -876,7 +876,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) { // Search bases classes in depth-first, left to right order - for (size_t i = 0; i < baseclasses->dim; i++) + for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (BaseClass *)baseclasses->data[i]; @@ -898,23 +898,23 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) return s; } -Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident) -{ - // Search bases classes in depth-first, left to right order - - for (size_t i = 0; i < baseclasses->dim; i++) - { - BaseClass *b = (*baseclasses)[i]; - Dsymbol *cdb = b->type->isClassHandle(); - if (cdb->ident->equals(ident)) - return cdb; - cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident); - if (cdb) - return cdb; - } - return NULL; -} - +Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident) +{ + // Search bases classes in depth-first, left to right order + + for (size_t i = 0; i < baseclasses->dim; i++) + { + BaseClass *b = (*baseclasses)[i]; + Dsymbol *cdb = b->type->isClassHandle(); + if (cdb->ident->equals(ident)) + return cdb; + cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident); + if (cdb) + return cdb; + } + return NULL; +} + /********************************************************** * fd is in the vtbl[] for this class. * Return 1 if function is hidden (not findable through search). @@ -940,10 +940,10 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) } FuncDeclaration *fdstart = s->toAlias()->isFuncDeclaration(); //printf("%s fdstart = %p\n", s->kind(), fdstart); - if (overloadApply(fdstart, &isf, fd)) - return 0; - - return !fd->parent->isTemplateMixin(); + if (overloadApply(fdstart, &isf, fd)) + return 0; + + return !fd->parent->isTemplateMixin(); } #endif @@ -955,58 +955,58 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) { //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); - FuncDeclaration *fdmatch = NULL; - FuncDeclaration *fdambig = NULL; + FuncDeclaration *fdmatch = NULL; + FuncDeclaration *fdambig = NULL; ClassDeclaration *cd = this; - Dsymbols *vtbl = &cd->vtbl; + Dsymbols *vtbl = &cd->vtbl; while (1) { for (size_t i = 0; i < vtbl->dim; i++) { - FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration(); + FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration(); if (!fd) continue; // the first entry might be a ClassInfo //printf("\t[%d] = %s\n", i, fd->toChars()); if (ident == fd->ident && - fd->type->covariant(tf) == 1) - { //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration()); - if (!fdmatch) - goto Lfd; - - { - // Function type matcing: exact > covariant - int m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch; - int m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch; - if (m1 > m2) - goto Lfd; - else if (m1 < m2) - goto Lfdmatch; - } - - { - // The way of definition: non-mixin > mixin - int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; - int m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; - if (m1 > m2) - goto Lfd; - else if (m1 < m2) - goto Lfdmatch; - } - - Lambig: - fdambig = fd; - //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars()); - continue; - - Lfd: - fdmatch = fd, fdambig = NULL; - //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars()); - continue; - - Lfdmatch: - continue; + fd->type->covariant(tf) == 1) + { //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration()); + if (!fdmatch) + goto Lfd; + + { + // Function type matcing: exact > covariant + int m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch; + int m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch; + if (m1 > m2) + goto Lfd; + else if (m1 < m2) + goto Lfdmatch; + } + + { + // The way of definition: non-mixin > mixin + int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; + int m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; + if (m1 > m2) + goto Lfd; + else if (m1 < m2) + goto Lfdmatch; + } + + Lambig: + fdambig = fd; + //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars()); + continue; + + Lfd: + fdmatch = fd, fdambig = NULL; + //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars()); + continue; + + Lfdmatch: + continue; } //else printf("\t\t%d\n", fd->type->covariant(tf)); } @@ -1016,9 +1016,9 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) cd = cd->baseClass; } - if (fdambig) - error("ambiguous virtual function %s", fdambig->toChars()); - return fdmatch; + if (fdambig) + error("ambiguous virtual function %s", fdambig->toChars()); + return fdmatch; } void ClassDeclaration::interfaceSemantic(Scope *sc) @@ -1068,7 +1068,7 @@ int ClassDeclaration::isAbstract() { if (isabstract) return TRUE; - for (size_t i = 1; i < vtbl.dim; i++) + for (size_t i = 1; i < vtbl.dim; i++) { FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); @@ -1145,7 +1145,7 @@ Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) } void InterfaceDeclaration::semantic(Scope *sc) -{ +{ //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); if (inuse) return; @@ -1182,7 +1182,7 @@ void InterfaceDeclaration::semantic(Scope *sc) } // Expand any tuples in baseclasses[] - for (size_t i = 0; i < baseclasses->dim; ) + for (size_t i = 0; i < baseclasses->dim; ) { BaseClass *b = (BaseClass *)baseclasses->data[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -1203,7 +1203,7 @@ void InterfaceDeclaration::semantic(Scope *sc) } // Check for errors, handle forward references - for (size_t i = 0; i < baseclasses->dim; ) + for (size_t i = 0; i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; @@ -1266,11 +1266,11 @@ void InterfaceDeclaration::semantic(Scope *sc) vtbl.push(this); // leave room at vtbl[0] for classinfo // Cat together the vtbl[]'s from base interfaces - for (size_t i = 0; i < interfaces_dim; i++) + for (size_t i = 0; i < interfaces_dim; i++) { BaseClass *b = interfaces[i]; // Skip if b has already appeared - for (size_t k = 0; k < i; k++) + for (size_t k = 0; k < i; k++) { if (b == interfaces[k]) goto Lcontinue; @@ -1278,12 +1278,12 @@ void InterfaceDeclaration::semantic(Scope *sc) // Copy vtbl[] from base class if (b->base->vtblOffset()) - { size_t d = b->base->vtbl.dim; + { size_t d = b->base->vtbl.dim; if (d > 1) { vtbl.reserve(d - 1); - for (size_t j = 1; j < d; j++) - vtbl.push((Dsymbol *)b->base->vtbl.data[j]); + for (size_t j = 1; j < d; j++) + vtbl.push((Dsymbol *)b->base->vtbl.data[j]); } } else @@ -1295,26 +1295,26 @@ void InterfaceDeclaration::semantic(Scope *sc) ; } - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } sc = sc->push(this); - sc->stc &= STCsafe | STCtrusted | STCsystem; + sc->stc &= STCsafe | STCtrusted | STCsystem; sc->parent = this; if (isCOMinterface()) sc->linkage = LINKwindows; sc->structalign = 8; - sc->protection = PROTpublic; - sc->explicitProtection = 0; + sc->protection = PROTpublic; + sc->explicitProtection = 0; structalign = sc->structalign; sc->offset = PTRSIZE * 2; inuse++; - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->semantic(sc); } inuse--; @@ -1407,7 +1407,7 @@ int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) int InterfaceDeclaration::isBaseInfoComplete() { assert(!baseClass); - for (size_t i = 0; i < baseclasses->dim; i++) + for (size_t i = 0; i < baseclasses->dim; i++) { BaseClass *b = (BaseClass *)baseclasses->data[i]; if (!b->base || !b->base->isBaseInfoComplete ()) return 0; @@ -1480,7 +1480,7 @@ BaseClass::BaseClass(Type *type, enum PROT protection) * by base classes) */ -int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance) +int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance) { ClassDeclaration *id = base; int result = 0; @@ -1490,7 +1490,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins vtbl->setDim(base->vtbl.dim); // first entry is ClassInfo reference - for (size_t j = base->vtblOffset(); j < base->vtbl.dim; j++) + for (size_t j = base->vtblOffset(); j < base->vtbl.dim; j++) { FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); FuncDeclaration *fd; diff --git a/dmd/clone.c b/dmd/clone.c index 320390c7..b2bf8f6b 100644 --- a/dmd/clone.c +++ b/dmd/clone.c @@ -1,175 +1,175 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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 -#include - -#include "root.h" -#include "aggregate.h" -#include "scope.h" -#include "mtype.h" -#include "declaration.h" -#include "module.h" -#include "id.h" -#include "expression.h" -#include "statement.h" - - -/********************************* - * Generate expression that calls opClone() - * for each member of the struct - * (can be NULL for members that don't need one) - */ - -#if DMDV2 -Expression *StructDeclaration::cloneMembers() -{ - Expression *e = NULL; - - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - Type *tv = v->type->toBasetype(); - dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - dim *= ((TypeSArray *)tv)->dim->toInteger(); - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->opclone) - { - - // this.v - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); - - if (dim == 1) - { // this.v.opClone() - ex = new DotVarExp(0, ex, sd->opclone, 0); - ex = new CallExp(0, ex); - } - else - { - // _callOpClones(&this.v, opclone, dim) - Expressions *args = new Expressions(); - args->push(new AddrExp(0, ex)); - args->push(new SymOffExp(0, sd->opclone, 0)); - args->push(new IntegerExp(dim)); - FuncDeclaration *ec = FuncDeclaration::genCfunc(Type::tvoid, "_callOpClones"); - ex = new CallExp(0, new VarExp(0, ec), args); - } - e = Expression::combine(e, ex); - } - } - } - return e; -} -#endif - -/***************************************** - * Create inclusive destructor for struct by aggregating - * all the destructors in dtors[] with the destructors for - * all the members. - */ - -FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) -{ - //printf("StructDeclaration::buildDtor() %s\n", toChars()); - Expression *e = NULL; - -#if DMDV2 - for (size_t i = 0; i < fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - Type *tv = v->type->toBasetype(); - dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - dim *= ((TypeSArray *)tv)->dim->toInteger(); - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->dtor) - { Expression *ex; - - // this.v - ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); - - if (dim == 1) - { // this.v.dtor() - ex = new DotVarExp(0, ex, sd->dtor, 0); - ex = new CallExp(0, ex); - } - else - { - // Typeinfo.destroy(cast(void*)&this.v); - Expression *ea = new AddrExp(0, ex); - ea = new CastExp(0, ea, Type::tvoid->pointerTo()); - Expressions *args = new Expressions(); - args->push(ea); - - Expression *et = v->type->getTypeInfo(sc); - et = new DotIdExp(0, et, Id::destroy); - - ex = new CallExp(0, et, args); - } - e = Expression::combine(ex, e); // combine in reverse order - } - } - } - - /* Build our own "destructor" which executes e - */ - if (e) - { //printf("Building __fieldDtor()\n"); - DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor")); - dd->fbody = new ExpStatement(0, e); - dtors.shift(dd); - members->push(dd); - dd->semantic(sc); - } -#endif - - switch (dtors.dim) - { - case 0: - return NULL; - - case 1: - return (FuncDeclaration *)dtors.data[0]; - - default: - e = NULL; - for (size_t i = 0; i < dtors.dim; i++) - { FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i]; - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, fd); - ex = new CallExp(0, ex); - e = Expression::combine(ex, e); - } - DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor")); - dd->fbody = new ExpStatement(0, e); - members->push(dd); - dd->semantic(sc); - return dd; - } -} - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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 +#include + +#include "root.h" +#include "aggregate.h" +#include "scope.h" +#include "mtype.h" +#include "declaration.h" +#include "module.h" +#include "id.h" +#include "expression.h" +#include "statement.h" + + +/********************************* + * Generate expression that calls opClone() + * for each member of the struct + * (can be NULL for members that don't need one) + */ + +#if DMDV2 +Expression *StructDeclaration::cloneMembers() +{ + Expression *e = NULL; + + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + Type *tv = v->type->toBasetype(); + dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + dim *= ((TypeSArray *)tv)->dim->toInteger(); + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->opclone) + { + + // this.v + Expression *ex = new ThisExp(0); + ex = new DotVarExp(0, ex, v, 0); + + if (dim == 1) + { // this.v.opClone() + ex = new DotVarExp(0, ex, sd->opclone, 0); + ex = new CallExp(0, ex); + } + else + { + // _callOpClones(&this.v, opclone, dim) + Expressions *args = new Expressions(); + args->push(new AddrExp(0, ex)); + args->push(new SymOffExp(0, sd->opclone, 0)); + args->push(new IntegerExp(dim)); + FuncDeclaration *ec = FuncDeclaration::genCfunc(Type::tvoid, "_callOpClones"); + ex = new CallExp(0, new VarExp(0, ec), args); + } + e = Expression::combine(e, ex); + } + } + } + return e; +} +#endif + +/***************************************** + * Create inclusive destructor for struct by aggregating + * all the destructors in dtors[] with the destructors for + * all the members. + */ + +FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) +{ + //printf("StructDeclaration::buildDtor() %s\n", toChars()); + Expression *e = NULL; + +#if DMDV2 + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + Type *tv = v->type->toBasetype(); + dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + dim *= ((TypeSArray *)tv)->dim->toInteger(); + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (sd->dtor) + { Expression *ex; + + // this.v + ex = new ThisExp(0); + ex = new DotVarExp(0, ex, v, 0); + + if (dim == 1) + { // this.v.dtor() + ex = new DotVarExp(0, ex, sd->dtor, 0); + ex = new CallExp(0, ex); + } + else + { + // Typeinfo.destroy(cast(void*)&this.v); + Expression *ea = new AddrExp(0, ex); + ea = new CastExp(0, ea, Type::tvoid->pointerTo()); + Expressions *args = new Expressions(); + args->push(ea); + + Expression *et = v->type->getTypeInfo(sc); + et = new DotIdExp(0, et, Id::destroy); + + ex = new CallExp(0, et, args); + } + e = Expression::combine(ex, e); // combine in reverse order + } + } + } + + /* Build our own "destructor" which executes e + */ + if (e) + { //printf("Building __fieldDtor()\n"); + DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor")); + dd->fbody = new ExpStatement(0, e); + dtors.shift(dd); + members->push(dd); + dd->semantic(sc); + } +#endif + + switch (dtors.dim) + { + case 0: + return NULL; + + case 1: + return (FuncDeclaration *)dtors.data[0]; + + default: + e = NULL; + for (size_t i = 0; i < dtors.dim; i++) + { FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i]; + Expression *ex = new ThisExp(0); + ex = new DotVarExp(0, ex, fd); + ex = new CallExp(0, ex); + e = Expression::combine(ex, e); + } + DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor")); + dd->fbody = new ExpStatement(0, e); + members->push(dd); + dd->semantic(sc); + return dd; + } +} + + diff --git a/dmd/complex_t.h b/dmd/complex_t.h index 132b952b..a1b4f4ed 100644 --- a/dmd/complex_t.h +++ b/dmd/complex_t.h @@ -1,74 +1,74 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright and Burton Radons -// 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. - -#ifndef DMD_COMPLEX_T_H -#define DMD_COMPLEX_T_H - -/* Roll our own complex type for compilers that don't support complex - */ - -struct complex_t -{ - long double re; - long double im; - - complex_t() { this->re = 0; this->im = 0; } - complex_t(long double re) { this->re = re; this->im = 0; } - complex_t(long double re, long double im) { this->re = re; this->im = im; } - - complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; } - complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; } - complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; } - complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); } - - complex_t operator / (complex_t y) - { - long double abs_y_re = y.re < 0 ? -y.re : y.re; - long double abs_y_im = y.im < 0 ? -y.im : y.im; - long double r, den; - - if (abs_y_re < abs_y_im) - { - r = y.re / y.im; - den = y.im + r * y.re; - return complex_t((re * r + im) / den, - (im * r - re) / den); - } - else - { - r = y.im / y.re; - den = y.re + r * y.im; - return complex_t((re + r * im) / den, - (im - r * re) / den); - } - } - - operator bool () { return re || im; } - - int operator == (complex_t y) { return re == y.re && im == y.im; } - int operator != (complex_t y) { return re != y.re || im != y.im; } -}; - -inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; } -inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); } -inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); } - - -inline long double creall(complex_t x) -{ - return x.re; -} - -inline long double cimagl(complex_t x) -{ - return x.im; -} - -#endif + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// written by Walter Bright and Burton Radons +// 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. + +#ifndef DMD_COMPLEX_T_H +#define DMD_COMPLEX_T_H + +/* Roll our own complex type for compilers that don't support complex + */ + +struct complex_t +{ + long double re; + long double im; + + complex_t() { this->re = 0; this->im = 0; } + complex_t(long double re) { this->re = re; this->im = 0; } + complex_t(long double re, long double im) { this->re = re; this->im = im; } + + complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; } + complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; } + complex_t operator - () { complex_t r; r.re = -re; r.im = -im; return r; } + complex_t operator * (complex_t y) { return complex_t(re * y.re - im * y.im, im * y.re + re * y.im); } + + complex_t operator / (complex_t y) + { + long double abs_y_re = y.re < 0 ? -y.re : y.re; + long double abs_y_im = y.im < 0 ? -y.im : y.im; + long double r, den; + + if (abs_y_re < abs_y_im) + { + r = y.re / y.im; + den = y.im + r * y.re; + return complex_t((re * r + im) / den, + (im * r - re) / den); + } + else + { + r = y.im / y.re; + den = y.re + r * y.im; + return complex_t((re + r * im) / den, + (im - r * re) / den); + } + } + + operator bool () { return re || im; } + + int operator == (complex_t y) { return re == y.re && im == y.im; } + int operator != (complex_t y) { return re != y.re || im != y.im; } +}; + +inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; } +inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); } +inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); } + + +inline long double creall(complex_t x) +{ + return x.re; +} + +inline long double cimagl(complex_t x) +{ + return x.im; +} + +#endif diff --git a/dmd/cond.c b/dmd/cond.c index ba6657d4..80d92742 100644 --- a/dmd/cond.c +++ b/dmd/cond.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -22,15 +22,15 @@ #include "lexer.h" #include "mtype.h" #include "scope.h" -#include "arraytypes.h" +#include "arraytypes.h" -int findCondition(Strings *ids, Identifier *ident) +int findCondition(Strings *ids, Identifier *ident) { if (ids) { - for (size_t i = 0; i < ids->dim; i++) + for (size_t i = 0; i < ids->dim; i++) { - const char *id = (*ids)[i]; + const char *id = (*ids)[i]; if (strcmp(id, ident->toChars()) == 0) return TRUE; @@ -73,8 +73,8 @@ void DebugCondition::setGlobalLevel(unsigned level) void DebugCondition::addGlobalIdent(const char *ident) { if (!global.params.debugids) - global.params.debugids = new Strings(); - global.params.debugids->push((char *)ident); + global.params.debugids = new Strings(); + global.params.debugids->push((char *)ident); } @@ -97,7 +97,7 @@ int DebugCondition::include(Scope *sc, ScopeDsymbol *s) inc = 1; else { if (!mod->debugidsNot) - mod->debugidsNot = new Strings(); + mod->debugidsNot = new Strings(); mod->debugidsNot->push(ident->toChars()); } } @@ -134,10 +134,10 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident) * redefinition breaks makefiles and older builds. */ "Posix", - "D_NET", + "D_NET", #endif "OSX", "FreeBSD", - "OpenBSD", + "OpenBSD", "Solaris", "LittleEndian", "BigEndian", "all", @@ -174,8 +174,8 @@ void VersionCondition::addGlobalIdent(const char *ident) void VersionCondition::addPredefinedGlobalIdent(const char *ident) { if (!global.params.versionids) - global.params.versionids = new Strings(); - global.params.versionids->push((char *)ident); + global.params.versionids = new Strings(); + global.params.versionids->push((char *)ident); } @@ -200,7 +200,7 @@ int VersionCondition::include(Scope *sc, ScopeDsymbol *s) else { if (!mod->versionidsNot) - mod->versionidsNot = new Strings(); + mod->versionidsNot = new Strings(); mod->versionidsNot->push(ident->toChars()); } } @@ -308,14 +308,14 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) inc = 2; return 0; } - Type *t = targ->trySemantic(loc, sc); - if (t) - targ = t; - else - inc = 2; // condition is false - - if (!t) - { + Type *t = targ->trySemantic(loc, sc); + if (t) + targ = t; + else + inc = 2; // condition is false + + if (!t) + { } else if (id && tspec) { @@ -328,19 +328,19 @@ int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) TemplateParameters parameters; parameters.setDim(1); - parameters[0] = &tp; + parameters[0] = &tp; Objects dedtypes; dedtypes.setDim(1); - m = targ->deduceType(sc, tspec, ¶meters, &dedtypes); + m = targ->deduceType(sc, tspec, ¶meters, &dedtypes); if (m == MATCHnomatch || (m != MATCHexact && tok == TOKequal)) inc = 2; else { inc = 1; - Type *tded = (Type *)dedtypes[0]; + Type *tded = (Type *)dedtypes[0]; if (!tded) tded = targ; Dsymbol *s = new AliasDeclaration(loc, id, tded); diff --git a/dmd/cond.h b/dmd/cond.h index 4da14195..745dab23 100644 --- a/dmd/cond.h +++ b/dmd/cond.h @@ -1,103 +1,103 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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. - -#ifndef DMD_DEBCOND_H -#define DMD_DEBCOND_H - -struct Expression; -struct Identifier; -struct OutBuffer; -struct Module; -struct Scope; -struct ScopeDsymbol; -struct DebugCondition; -#include "lexer.h" // dmdhg -enum TOK; -struct HdrGenState; - -int findCondition(Strings *ids, Identifier *ident); - -struct Condition -{ - Loc loc; - int inc; // 0: not computed yet - // 1: include - // 2: do not include - - Condition(Loc loc); - - virtual Condition *syntaxCopy() = 0; - virtual int include(Scope *sc, ScopeDsymbol *s) = 0; - virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; -}; - -struct DVCondition : Condition -{ - unsigned level; - Identifier *ident; - Module *mod; - - DVCondition(Module *mod, unsigned level, Identifier *ident); - - Condition *syntaxCopy(); -}; - -struct DebugCondition : DVCondition -{ - static void setGlobalLevel(unsigned level); - static void addGlobalIdent(const char *ident); - static void addPredefinedGlobalIdent(const char *ident); - - DebugCondition(Module *mod, unsigned level, Identifier *ident); - - int include(Scope *sc, ScopeDsymbol *s); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct VersionCondition : DVCondition -{ - static void setGlobalLevel(unsigned level); - static void checkPredefined(Loc loc, const char *ident); - static void addGlobalIdent(const char *ident); - static void addPredefinedGlobalIdent(const char *ident); - - VersionCondition(Module *mod, unsigned level, Identifier *ident); - - int include(Scope *sc, ScopeDsymbol *s); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct StaticIfCondition : Condition -{ - Expression *exp; - - StaticIfCondition(Loc loc, Expression *exp); - Condition *syntaxCopy(); - int include(Scope *sc, ScopeDsymbol *s); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -struct IftypeCondition : Condition -{ - /* iftype (targ id tok tspec) - */ - Type *targ; - Identifier *id; // can be NULL - enum TOK tok; // ':' or '==' - Type *tspec; // can be NULL - - IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec); - Condition *syntaxCopy(); - int include(Scope *sc, ScopeDsymbol *s); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - - -#endif + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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. + +#ifndef DMD_DEBCOND_H +#define DMD_DEBCOND_H + +struct Expression; +struct Identifier; +struct OutBuffer; +struct Module; +struct Scope; +struct ScopeDsymbol; +struct DebugCondition; +#include "lexer.h" // dmdhg +enum TOK; +struct HdrGenState; + +int findCondition(Strings *ids, Identifier *ident); + +struct Condition +{ + Loc loc; + int inc; // 0: not computed yet + // 1: include + // 2: do not include + + Condition(Loc loc); + + virtual Condition *syntaxCopy() = 0; + virtual int include(Scope *sc, ScopeDsymbol *s) = 0; + virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; +}; + +struct DVCondition : Condition +{ + unsigned level; + Identifier *ident; + Module *mod; + + DVCondition(Module *mod, unsigned level, Identifier *ident); + + Condition *syntaxCopy(); +}; + +struct DebugCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void addGlobalIdent(const char *ident); + static void addPredefinedGlobalIdent(const char *ident); + + DebugCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct VersionCondition : DVCondition +{ + static void setGlobalLevel(unsigned level); + static void checkPredefined(Loc loc, const char *ident); + static void addGlobalIdent(const char *ident); + static void addPredefinedGlobalIdent(const char *ident); + + VersionCondition(Module *mod, unsigned level, Identifier *ident); + + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct StaticIfCondition : Condition +{ + Expression *exp; + + StaticIfCondition(Loc loc, Expression *exp); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct IftypeCondition : Condition +{ + /* iftype (targ id tok tspec) + */ + Type *targ; + Identifier *id; // can be NULL + enum TOK tok; // ':' or '==' + Type *tspec; // can be NULL + + IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec); + Condition *syntaxCopy(); + int include(Scope *sc, ScopeDsymbol *s); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + + +#endif diff --git a/dmd/constfold.c b/dmd/constfold.c index 6baf73be..bb70380e 100644 --- a/dmd/constfold.c +++ b/dmd/constfold.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -38,8 +38,8 @@ static real_t zero; // work around DMC bug for now #define LOG 0 -int RealEquals(real_t x1, real_t x2); - +int RealEquals(real_t x1, real_t x2); + Expression *expType(Type *type, Expression *e) { if (type != e->type) @@ -493,7 +493,7 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2) { real_t r2 = e2->toReal(); #ifdef __DMC__ - c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I; + c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I; #elif defined(IN_GCC) c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2); #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) @@ -501,14 +501,14 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2) // arm also doesn't like fmodl c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2)); #else - c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2)); + c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2)); #endif } else if (e2->type->isimaginary()) { real_t i2 = e2->toImaginary(); #ifdef __DMC__ - c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I; + c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I; #elif defined(IN_GCC) c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2); #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) @@ -516,7 +516,7 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2) // arm also doesn't like fmodl c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2)); #else - c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2)); + c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2)); #endif } else @@ -543,21 +543,21 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2) e2 = new IntegerExp(loc, 1, e2->type); n2 = 1; } - if (n2 == -1 && !type->isunsigned()) - { // Check for int.min % -1 - if (n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64) - { - e2->error("integer overflow: int.min % -1"); - e2 = new IntegerExp(loc, 1, e2->type); - n2 = 1; - } - else if (n1 == 0x8000000000000000LL) // long.min % -1 - { - e2->error("integer overflow: long.min % -1"); - e2 = new IntegerExp(loc, 1, e2->type); - n2 = 1; - } - } + if (n2 == -1 && !type->isunsigned()) + { // Check for int.min % -1 + if (n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64) + { + e2->error("integer overflow: int.min % -1"); + e2 = new IntegerExp(loc, 1, e2->type); + n2 = 1; + } + else if (n1 == 0x8000000000000000LL) // long.min % -1 + { + e2->error("integer overflow: long.min % -1"); + e2 = new IntegerExp(loc, 1, e2->type); + n2 = 1; + } + } if (e1->type->isunsigned() || e2->type->isunsigned()) n = ((d_uns64) n1) % ((d_uns64) n2); else @@ -580,9 +580,9 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2) Loc loc = e1->loc; dinteger_t value = e1->toInteger(); - dinteger_t dcount = e2->toInteger(); - assert(dcount <= 0xFFFFFFFF); - unsigned count = (unsigned)dcount; + dinteger_t dcount = e2->toInteger(); + assert(dcount <= 0xFFFFFFFF); + unsigned count = (unsigned)dcount; switch (e1->type->toBasetype()->ty) { case Tint8: @@ -590,7 +590,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2) break; case Tuns8: - case Tchar: + case Tchar: value = (d_uns8)(value) >> count; break; @@ -599,7 +599,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2) break; case Tuns16: - case Twchar: + case Twchar: value = (d_uns16)(value) >> count; break; @@ -608,7 +608,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2) break; case Tuns32: - case Tdchar: + case Tdchar: value = (d_uns32)(value) >> count; break; @@ -635,28 +635,28 @@ Expression *Ushr(Type *type, Expression *e1, Expression *e2) Loc loc = e1->loc; dinteger_t value = e1->toInteger(); - dinteger_t dcount = e2->toInteger(); - assert(dcount <= 0xFFFFFFFF); - unsigned count = (unsigned)dcount; + dinteger_t dcount = e2->toInteger(); + assert(dcount <= 0xFFFFFFFF); + unsigned count = (unsigned)dcount; switch (e1->type->toBasetype()->ty) { case Tint8: case Tuns8: - case Tchar: - // Possible only with >>>=. >>> always gets promoted to int. + case Tchar: + // Possible only with >>>=. >>> always gets promoted to int. value = (value & 0xFF) >> count; break; case Tint16: case Tuns16: - case Twchar: - // Possible only with >>>=. >>> always gets promoted to int. + case Twchar: + // Possible only with >>>=. >>> always gets promoted to int. value = (value & 0xFFFF) >> count; break; case Tint32: case Tuns32: - case Tdchar: + case Tdchar: value = (value & 0xFFFFFFFF) >> count; break; @@ -764,8 +764,8 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) else { for (size_t i = 0; i < es1->elements->dim; i++) - { Expression *ee1 = (*es1->elements)[i]; - Expression *ee2 = (*es2->elements)[i]; + { Expression *ee1 = (*es1->elements)[i]; + Expression *ee2 = (*es2->elements)[i]; Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); if (v == EXP_CANT_INTERPRET) @@ -778,9 +778,9 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) } else if (e1->op == TOKarrayliteral && e2->op == TOKstring) { // Swap operands and use common code - Expression *etmp = e1; + Expression *etmp = e1; e1 = e2; - e2 = etmp; + e2 = etmp; goto Lsa; } else if (e1->op == TOKstring && e2->op == TOKarrayliteral) @@ -794,11 +794,11 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) cmp = 0; else { - cmp = 1; // if dim1 winds up being 0 + cmp = 1; // if dim1 winds up being 0 for (size_t i = 0; i < dim1; i++) { uinteger_t c = es1->charAt(i); - Expression *ee2 = (*es2->elements)[i]; + Expression *ee2 = (*es2->elements)[i]; if (ee2->isConst() != 1) return EXP_CANT_INTERPRET; cmp = (c == ee2->toInteger()); @@ -824,8 +824,8 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) { cmp = 1; for (size_t i = 0; i < es1->elements->dim; i++) - { Expression *ee1 = (*es1->elements)[i]; - Expression *ee2 = (*es2->elements)[i]; + { Expression *ee1 = (*es1->elements)[i]; + Expression *ee2 = (*es2->elements)[i]; if (ee1 == ee2) continue; @@ -909,11 +909,11 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) cmp = (es1->var == es2->var && es1->offset == es2->offset); } - else - { + else + { return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, type, e1, e2); - } + } if (op == TOKnotidentity) cmp ^= 1; return new IntegerExp(loc, cmp, type); @@ -1158,7 +1158,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1) assert(sd); Expressions *elements = new Expressions; for (size_t i = 0; i < sd->fields.dim; i++) - { Dsymbol *s = sd->fields.tdata()[i]; + { Dsymbol *s = sd->fields.tdata()[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); @@ -1221,13 +1221,13 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) uinteger_t i = e2->toInteger(); if (i >= es1->len) - { + { e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len); - e = new ErrorExp(); - } + e = new ErrorExp(); + } else - { - e = new IntegerExp(loc, es1->charAt(i), type); + { + e = new IntegerExp(loc, es1->charAt(i), type); } } else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) @@ -1236,38 +1236,38 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) uinteger_t i = e2->toInteger(); if (i >= length) - { - e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length); - e = new ErrorExp(); + { + e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length); + e = new ErrorExp(); } - else if (e1->op == TOKarrayliteral) + else if (e1->op == TOKarrayliteral) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - e = ale->elements->tdata()[i]; + e = ale->elements->tdata()[i]; e->type = type; - if (e->hasSideEffect()) - e = EXP_CANT_INTERPRET; + if (e->hasSideEffect()) + e = EXP_CANT_INTERPRET; } } else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64) { uinteger_t i = e2->toInteger(); - if (e1->op == TOKarrayliteral) + if (e1->op == TOKarrayliteral) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; if (i >= ale->elements->dim) - { - e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); - e = new ErrorExp(); + { + e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); + e = new ErrorExp(); } else - { e = ale->elements->tdata()[i]; + { e = ale->elements->tdata()[i]; e->type = type; - if (e->hasSideEffect()) - e = EXP_CANT_INTERPRET; + if (e->hasSideEffect()) + e = EXP_CANT_INTERPRET; } } } - else if (e1->op == TOKassocarrayliteral) + else if (e1->op == TOKassocarrayliteral) { AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1; /* Search the keys backwards, in case there are duplicate keys @@ -1275,15 +1275,15 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) for (size_t i = ae->keys->dim; i;) { i--; - Expression *ekey = ae->keys->tdata()[i]; + Expression *ekey = ae->keys->tdata()[i]; Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); if (ex == EXP_CANT_INTERPRET) return ex; if (ex->isBool(TRUE)) - { e = ae->values->tdata()[i]; + { e = ae->values->tdata()[i]; e->type = type; - if (e->hasSideEffect()) - e = EXP_CANT_INTERPRET; + if (e->hasSideEffect()) + e = EXP_CANT_INTERPRET; break; } } @@ -1311,12 +1311,12 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) uinteger_t iupr = upr->toInteger(); if (iupr > es1->len || ilwr > iupr) - { + { e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); - e = new ErrorExp(); - } + e = new ErrorExp(); + } else - { + { void *s; size_t len = iupr - ilwr; int sz = es1->sz; @@ -1335,23 +1335,23 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) } else if (e1->op == TOKarrayliteral && lwr->op == TOKint64 && upr->op == TOKint64 && - !e1->hasSideEffect()) + !e1->hasSideEffect()) { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; uinteger_t ilwr = lwr->toInteger(); uinteger_t iupr = upr->toInteger(); if (iupr > es1->elements->dim || ilwr > iupr) - { + { e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); - e = new ErrorExp(); - } + e = new ErrorExp(); + } else { Expressions *elements = new Expressions(); elements->setDim(iupr - ilwr); - memcpy(elements->tdata(), - es1->elements->tdata() + ilwr, - (iupr - ilwr) * sizeof(es1->elements->tdata()[0])); + memcpy(elements->tdata(), + es1->elements->tdata() + ilwr, + (iupr - ilwr) * sizeof(es1->elements->tdata()[0])); e = new ArrayLiteralExp(e1->loc, elements); e->type = type; } @@ -1359,64 +1359,64 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) return e; } -/* Set a slice of char array literal 'existingAE' from a string 'newval'. - * existingAE[firstIndex..firstIndex+newval.length] = newval. - */ -void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex) -{ - size_t newlen = newval->len; - size_t sz = newval->sz; - unsigned char *s = (unsigned char *)newval->string; - Type *elemType = existingAE->type->nextOf(); - for (size_t j = 0; j < newlen; j++) - { - dinteger_t val; - switch (sz) - { - case 1: val = s[j]; break; - case 2: val = ((unsigned short *)s)[j]; break; - case 4: val = ((unsigned *)s)[j]; break; - default: - assert(0); - break; - } - existingAE->elements->tdata()[j+firstIndex] - = new IntegerExp(newval->loc, val, elemType); - } -} - -/* Set a slice of string 'existingSE' from a char array literal 'newae'. - * existingSE[firstIndex..firstIndex+newae.length] = newae. - */ -void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex) -{ - unsigned char *s = (unsigned char *)existingSE->string; - for (size_t j = 0; j < newae->elements->dim; j++) - { - unsigned value = (unsigned)(newae->elements->tdata()[j]->toInteger()); - switch (existingSE->sz) - { - case 1: s[j+firstIndex] = value; break; - case 2: ((unsigned short *)s)[j+firstIndex] = value; break; - case 4: ((unsigned *)s)[j+firstIndex] = value; break; - default: - assert(0); - break; - } - } -} - -/* Set a slice of string 'existingSE' from a string 'newstr'. - * existingSE[firstIndex..firstIndex+newstr.length] = newstr. - */ -void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex) -{ - unsigned char *s = (unsigned char *)existingSE->string; - size_t sz = existingSE->sz; - assert(sz == newstr->sz); - memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len); -} - +/* Set a slice of char array literal 'existingAE' from a string 'newval'. + * existingAE[firstIndex..firstIndex+newval.length] = newval. + */ +void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex) +{ + size_t newlen = newval->len; + size_t sz = newval->sz; + unsigned char *s = (unsigned char *)newval->string; + Type *elemType = existingAE->type->nextOf(); + for (size_t j = 0; j < newlen; j++) + { + dinteger_t val; + switch (sz) + { + case 1: val = s[j]; break; + case 2: val = ((unsigned short *)s)[j]; break; + case 4: val = ((unsigned *)s)[j]; break; + default: + assert(0); + break; + } + existingAE->elements->tdata()[j+firstIndex] + = new IntegerExp(newval->loc, val, elemType); + } +} + +/* Set a slice of string 'existingSE' from a char array literal 'newae'. + * existingSE[firstIndex..firstIndex+newae.length] = newae. + */ +void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex) +{ + unsigned char *s = (unsigned char *)existingSE->string; + for (size_t j = 0; j < newae->elements->dim; j++) + { + unsigned value = (unsigned)(newae->elements->tdata()[j]->toInteger()); + switch (existingSE->sz) + { + case 1: s[j+firstIndex] = value; break; + case 2: ((unsigned short *)s)[j+firstIndex] = value; break; + case 4: ((unsigned *)s)[j+firstIndex] = value; break; + default: + assert(0); + break; + } + } +} + +/* Set a slice of string 'existingSE' from a string 'newstr'. + * existingSE[firstIndex..firstIndex+newstr.length] = newstr. + */ +void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex) +{ + unsigned char *s = (unsigned char *)existingSE->string; + size_t sz = existingSE->sz; + assert(sz == newstr->sz); + memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len); +} + /* Also return EXP_CANT_INTERPRET if this fails */ Expression *Cat(Type *type, Expression *e1, Expression *e2) @@ -1450,11 +1450,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) dinteger_t v = e->toInteger(); - size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v); + size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v); s = mem.malloc((len + 1) * sz); - if (t->ty == tn->ty) - memcpy((unsigned char *)s, &v, sz); - else + if (t->ty == tn->ty) + memcpy((unsigned char *)s, &v, sz); + else utf_encode(sz, s, v); // Add terminating 0 @@ -1474,24 +1474,24 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) e->type = type; return e; } - else if (e1->op == TOKnull && e2->op == TOKnull) - { - if (type == e1->type) - { - // Handle null ~= null - if (t1->ty == Tarray && t2 == t1->nextOf()) - { - e = new ArrayLiteralExp(e1->loc, e2); - e->type = type; - return e; - } - else - return e1; - } - if (type == e2->type) - return e2; - return new NullExp(e1->loc, type); - } + else if (e1->op == TOKnull && e2->op == TOKnull) + { + if (type == e1->type) + { + // Handle null ~= null + if (t1->ty == Tarray && t2 == t1->nextOf()) + { + e = new ArrayLiteralExp(e1->loc, e2); + e->type = type; + return e; + } + else + return e1; + } + if (type == e2->type) + return e2; + return new NullExp(e1->loc, type); + } else if (e1->op == TOKstring && e2->op == TOKstring) { // Concatenate the strings @@ -1520,65 +1520,65 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) es = new StringExp(loc, s, len); es->sz = sz; es->committed = es1->committed | es2->committed; - es->type = type; - e = es; - } - else if (e2->op == TOKstring && e1->op == TOKarrayliteral && - t1->nextOf()->isintegral()) - { - // [chars] ~ string --> [chars] - StringExp *es = (StringExp *)e2; - ArrayLiteralExp *ea = (ArrayLiteralExp *)e1; - size_t len = es->len + ea->elements->dim; - Expressions * elems = new Expressions; - elems->setDim(len); - for (size_t i= 0; i < ea->elements->dim; ++i) - { - elems->tdata()[i] = ea->elements->tdata()[i]; - } - ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); - dest->type = type; - sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim); - return dest; - } - else if (e1->op == TOKstring && e2->op == TOKarrayliteral && - t2->nextOf()->isintegral()) - { - // string ~ [chars] --> [chars] - StringExp *es = (StringExp *)e1; - ArrayLiteralExp *ea = (ArrayLiteralExp *)e2; - size_t len = es->len + ea->elements->dim; - Expressions * elems = new Expressions; - elems->setDim(len); - for (size_t i= 0; i < ea->elements->dim; ++i) - { - elems->tdata()[es->len + i] = ea->elements->tdata()[i]; - } - ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); - dest->type = type; - sliceAssignArrayLiteralFromString(dest, es, 0); - return dest; + es->type = type; + e = es; + } + else if (e2->op == TOKstring && e1->op == TOKarrayliteral && + t1->nextOf()->isintegral()) + { + // [chars] ~ string --> [chars] + StringExp *es = (StringExp *)e2; + ArrayLiteralExp *ea = (ArrayLiteralExp *)e1; + size_t len = es->len + ea->elements->dim; + Expressions * elems = new Expressions; + elems->setDim(len); + for (size_t i= 0; i < ea->elements->dim; ++i) + { + elems->tdata()[i] = ea->elements->tdata()[i]; + } + ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); + dest->type = type; + sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim); + return dest; + } + else if (e1->op == TOKstring && e2->op == TOKarrayliteral && + t2->nextOf()->isintegral()) + { + // string ~ [chars] --> [chars] + StringExp *es = (StringExp *)e1; + ArrayLiteralExp *ea = (ArrayLiteralExp *)e2; + size_t len = es->len + ea->elements->dim; + Expressions * elems = new Expressions; + elems->setDim(len); + for (size_t i= 0; i < ea->elements->dim; ++i) + { + elems->tdata()[es->len + i] = ea->elements->tdata()[i]; + } + ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); + dest->type = type; + sliceAssignArrayLiteralFromString(dest, es, 0); + return dest; } else if (e1->op == TOKstring && e2->op == TOKint64) { - // string ~ char --> string + // string ~ char --> string void *s; StringExp *es1 = (StringExp *)e1; StringExp *es; int sz = es1->sz; dinteger_t v = e2->toInteger(); - // Is it a concatentation of homogenous types? - // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar) - bool homoConcat = (sz == t2->size()); - size_t len = es1->len; - len += homoConcat ? 1 : utf_codeLength(sz, v); - + // Is it a concatentation of homogenous types? + // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar) + bool homoConcat = (sz == t2->size()); + size_t len = es1->len; + len += homoConcat ? 1 : utf_codeLength(sz, v); + s = mem.malloc((len + 1) * sz); memcpy(s, es1->string, es1->len * sz); - if (homoConcat) - memcpy((unsigned char *)s + (sz * es1->len), &v, sz); - else + if (homoConcat) + memcpy((unsigned char *)s + (sz * es1->len), &v, sz); + else utf_encode(sz, (unsigned char *)s + (sz * es1->len), v); // Add terminating 0 diff --git a/dmd/declaration.c b/dmd/declaration.c index a9335756..4909b14c 100644 --- a/dmd/declaration.c +++ b/dmd/declaration.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -111,7 +111,7 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t) if (fd && ((fd->isCtorDeclaration() && storage_class & STCfield) || (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) && - fd->toParent2() == toParent() + fd->toParent2() == toParent() ) { VarDeclaration *v = isVarDeclaration(); @@ -194,7 +194,7 @@ Type *TupleDeclaration::getType() /* It's only a type tuple if all the Object's are types */ for (size_t i = 0; i < objects->dim; i++) - { Object *o = (*objects)[i]; + { Object *o = (*objects)[i]; if (o->dyncast() != DYNCAST_TYPE) { @@ -221,7 +221,7 @@ Type *TupleDeclaration::getType() #else Parameter *arg = new Parameter(STCin, t, NULL, NULL); #endif - (*args)[i] = arg; + (*args)[i] = arg; if (!t->deco) hasdeco = 0; } @@ -238,7 +238,7 @@ int TupleDeclaration::needThis() { //printf("TupleDeclaration::needThis(%s)\n", toChars()); for (size_t i = 0; i < objects->dim; i++) - { Object *o = (*objects)[i]; + { Object *o = (*objects)[i]; if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; if (e->op == TOKdsymbol) @@ -282,7 +282,7 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) assert(!s); TypedefDeclaration *st; st = new TypedefDeclaration(loc, ident, basetype, init); - + // Syntax copy for header file if (!htype) // Don't overwrite original { if (type) // Make copy for both old and new instances @@ -300,43 +300,43 @@ Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) } else st->hbasetype = hbasetype->syntaxCopy(); - + return st; } void TypedefDeclaration::semantic(Scope *sc) { //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); - if (sem == SemanticStart) - { sem = SemanticIn; - parent = sc->parent; - int errors = global.errors; - Type *savedbasetype = basetype; + if (sem == SemanticStart) + { sem = SemanticIn; + parent = sc->parent; + int errors = global.errors; + Type *savedbasetype = basetype; basetype = basetype->semantic(loc, sc); - if (errors != global.errors) - { - basetype = savedbasetype; - sem = SemanticStart; - return; - } - sem = SemanticDone; + if (errors != global.errors) + { + basetype = savedbasetype; + sem = SemanticStart; + return; + } + sem = SemanticDone; #if DMDV2 type = type->addStorageClass(storage_class); #endif - Type *savedtype = type; + Type *savedtype = type; type = type->semantic(loc, sc); if (sc->parent->isFuncDeclaration() && init) semantic2(sc); - if (errors != global.errors) - { - basetype = savedbasetype; - type = savedtype; - sem = SemanticStart; - return; - } + if (errors != global.errors) + { + basetype = savedbasetype; + type = savedtype; + sem = SemanticStart; + return; + } storage_class |= sc->stc & STCdeprecated; } - else if (sem == SemanticIn) + else if (sem == SemanticIn) { error("circular definition"); } @@ -345,18 +345,18 @@ void TypedefDeclaration::semantic(Scope *sc) void TypedefDeclaration::semantic2(Scope *sc) { //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); - if (sem == SemanticDone) - { sem = Semantic2Done; + if (sem == SemanticDone) + { sem = Semantic2Done; if (init) { - Initializer *savedinit = init; - int errors = global.errors; - init = init->semantic(sc, basetype, WANTinterpret); - if (errors != global.errors) - { - init = savedinit; - return; - } + Initializer *savedinit = init; + int errors = global.errors; + init = init->semantic(sc, basetype, WANTinterpret); + if (errors != global.errors) + { + init = savedinit; + return; + } ExpInitializer *ie = init->isExpInitializer(); if (ie) @@ -470,7 +470,7 @@ void AliasDeclaration::semantic(Scope *sc) #endif storage_class |= sc->stc & STCdeprecated; - protection = sc->protection; + protection = sc->protection; // Given: // alias foo.bar.abc def; @@ -481,9 +481,9 @@ void AliasDeclaration::semantic(Scope *sc) // type. If it is a symbol, then aliassym is set and type is NULL - // toAlias() will return aliasssym. - int errors = global.errors; - Type *savedtype = type; - + int errors = global.errors; + Type *savedtype = type; + Dsymbol *s; Type *t; Expression *e; @@ -496,7 +496,7 @@ void AliasDeclaration::semantic(Scope *sc) s = type->toDsymbol(sc); if (s #if DMDV2 - && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) + && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) #endif ) goto L2; // it's a symbolic alias @@ -536,15 +536,15 @@ void AliasDeclaration::semantic(Scope *sc) } else if (t) { - type = t->semantic(loc, sc); - //printf("\talias resolved to type %s\n", type->toChars()); + type = t->semantic(loc, sc); + //printf("\talias resolved to type %s\n", type->toChars()); } if (overnext) ScopeDsymbol::multiplyDefined(0, this, overnext); this->inSemantic = 0; - - if (errors != global.errors) - type = savedtype; + + if (errors != global.errors) + type = savedtype; return; L2: @@ -558,7 +558,7 @@ void AliasDeclaration::semantic(Scope *sc) } else { - Dsymbol *savedovernext = overnext; + Dsymbol *savedovernext = overnext; FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); if (f) { @@ -574,25 +574,25 @@ void AliasDeclaration::semantic(Scope *sc) } } if (overnext) - ScopeDsymbol::multiplyDefined(0, this, overnext); + ScopeDsymbol::multiplyDefined(0, this, overnext); if (s == this) { assert(global.errors); s = NULL; } - if (errors != global.errors) - { - type = savedtype; - overnext = savedovernext; - aliassym = NULL; - inSemantic = 0; - return; - } + if (errors != global.errors) + { + type = savedtype; + overnext = savedovernext; + aliassym = NULL; + inSemantic = 0; + return; + } } - if (!type || type->ty != Terror) - { //printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars()); + if (!type || type->ty != Terror) + { //printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars()); aliassym = s; - } + } this->inSemantic = 0; } @@ -654,7 +654,7 @@ Dsymbol *AliasDeclaration::toAlias() //static int count; if (++count == 75) exit(0); //*(char*)0=0; if (inSemantic) { error("recursive alias declaration"); - aliassym = new AliasDeclaration(loc, ident, Type::terror); + aliassym = new AliasDeclaration(loc, ident, Type::terror); type = Type::terror; } else if (!aliassym && scope) @@ -666,7 +666,7 @@ Dsymbol *AliasDeclaration::toAlias() void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("alias "); -#if 0 +#if 0 if (hgs->hdrgen) { if (haliassym) @@ -724,11 +724,11 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer aliassym = NULL; onstack = 0; canassign = 0; - ctfeAdrOnStack = (size_t)(-1); -#if DMDV2 - rundtor = NULL; - edtor = NULL; -#endif + ctfeAdrOnStack = (size_t)(-1); +#if DMDV2 + rundtor = NULL; + edtor = NULL; +#endif #if IN_LLVM aggrIndex = 0; @@ -794,11 +794,11 @@ void VarDeclaration::semantic(Scope *sc) //if (strcmp(toChars(), "mul") == 0) halt(); #endif - if (scope) - { sc = scope; - scope = NULL; - } - + if (scope) + { sc = scope; + scope = NULL; + } + storage_class |= sc->stc; if (storage_class & STCextern && init) error("extern symbols cannot have initializers"); @@ -813,7 +813,7 @@ void VarDeclaration::semantic(Scope *sc) if (!type) { inuse++; type = init->inferType(sc); - type = type->semantic(loc, sc); + type = type->semantic(loc, sc); inuse--; inferred = 1; @@ -990,10 +990,10 @@ void VarDeclaration::semantic(Scope *sc) } // If it's a member template - AggregateDeclaration *ad2 = ti->tempdecl->isMember(); - if (ad2 && storage_class != STCundefined) + AggregateDeclaration *ad2 = ti->tempdecl->isMember(); + if (ad2 && storage_class != STCundefined) { - error("cannot use template to add field to aggregate '%s'", ad2->toChars()); + error("cannot use template to add field to aggregate '%s'", ad2->toChars()); } } } @@ -1102,7 +1102,7 @@ void VarDeclaration::semantic(Scope *sc) Expression *e = init->toExpression(); if (!e) { - init = init->semantic(sc, type, 0); // Don't need to interpret + init = init->semantic(sc, type, 0); // Don't need to interpret e = init->toExpression(); if (!e) { error("is not a static and cannot have static initializer"); @@ -1121,7 +1121,7 @@ void VarDeclaration::semantic(Scope *sc) ei->exp = ei->exp->semantic(sc); if (!ei->exp->implicitConvTo(type)) { - dinteger_t dim = ((TypeSArray *)t)->dim->toInteger(); + dinteger_t dim = ((TypeSArray *)t)->dim->toInteger(); // If multidimensional static array, treat as one large array while (1) { @@ -1203,7 +1203,7 @@ void VarDeclaration::semantic(Scope *sc) } else { - init = init->semantic(sc, type, WANTinterpret); + init = init->semantic(sc, type, WANTinterpret); if (fd && isConst() && !isStatic()) { // Make it static storage_class |= STCstatic; @@ -1221,7 +1221,7 @@ void VarDeclaration::semantic(Scope *sc) if (!global.errors && !inferred) { - unsigned errors = global.startGagging(); + unsigned errors = global.startGagging(); Expression *e; Initializer *i2 = init; inuse++; @@ -1233,10 +1233,10 @@ void VarDeclaration::semantic(Scope *sc) } else if (si || ai) { i2 = init->syntaxCopy(); - i2 = i2->semantic(sc, type, WANTinterpret); + i2 = i2->semantic(sc, type, WANTinterpret); } inuse--; - if (global.endGagging(errors)) // if errors happened + if (global.endGagging(errors)) // if errors happened { #if DMDV2 /* Save scope for later use, to try again @@ -1311,7 +1311,7 @@ void VarDeclaration::semantic2(Scope *sc) printf("type = %p\n", ei->exp->type); } #endif - init = init->semantic(sc, type, WANTinterpret); + init = init->semantic(sc, type, WANTinterpret); inuse--; } } @@ -1419,12 +1419,12 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) // The current function FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); - if (fdv && fdthis && fdv != fdthis && fdthis->ident != Id::ensure) + if (fdv && fdthis && fdv != fdthis && fdthis->ident != Id::ensure) { - /* __ensure is always called directly, - * so it never becomes closure. - */ - + /* __ensure is always called directly, + * so it never becomes closure. + */ + if (loc.filename) fdthis->getLevel(loc, fdv); nestedref = 1; @@ -1535,15 +1535,15 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc) return e; } -/****************************************** - */ - -void ObjectNotFound(Identifier *id) -{ - Type::error(0, "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars()); - fatal(); -} - +/****************************************** + */ + +void ObjectNotFound(Identifier *id) +{ + Type::error(0, "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars()); + fatal(); +} + /********************************* ClassInfoDeclaration ****************************/ diff --git a/dmd/declaration.h b/dmd/declaration.h index c6edf0ef..c7d0bba7 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -282,22 +282,22 @@ struct VarDeclaration : Declaration // 2: on stack, run destructor anyway int canassign; // it can be assigned to Dsymbol *aliassym; // if redone as alias to another symbol - - // When interpreting, these point to the value (NULL if value not determinable) - // The index of this variable on the CTFE stack, -1 if not allocated - size_t ctfeAdrOnStack; - // The various functions are used only to detect compiler CTFE bugs - Expression *getValue(); - bool hasValue(); - void setValueNull(); - void setValueWithoutChecking(Expression *newval); - void setValue(Expression *newval); - + + // When interpreting, these point to the value (NULL if value not determinable) + // The index of this variable on the CTFE stack, -1 if not allocated + size_t ctfeAdrOnStack; + // The various functions are used only to detect compiler CTFE bugs + Expression *getValue(); + bool hasValue(); + void setValueNull(); + void setValueWithoutChecking(Expression *newval); + void setValue(Expression *newval); + #if DMDV2 VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see // if the destructor should be run. Used to prevent // dtor calls on postblitted vars - Expression *edtor; // if !=NULL, does the destruction of the variable + Expression *edtor; // if !=NULL, does the destruction of the variable #endif VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); @@ -667,18 +667,18 @@ enum BUILTIN BUILTINtan, // std.math.tan BUILTINsqrt, // std.math.sqrt BUILTINfabs, // std.math.fabs - BUILTINatan2, // std.math.atan2 - BUILTINrndtol, // std.math.rndtol - BUILTINexpm1, // std.math.expm1 - BUILTINexp2, // std.math.exp2 - BUILTINyl2x, // std.math.yl2x - BUILTINyl2xp1, // std.math.yl2xp1 - BUILTINbsr, // core.bitop.bsr - BUILTINbsf, // core.bitop.bsf - BUILTINbswap, // core.bitop.bswap + BUILTINatan2, // std.math.atan2 + BUILTINrndtol, // std.math.rndtol + BUILTINexpm1, // std.math.expm1 + BUILTINexp2, // std.math.exp2 + BUILTINyl2x, // std.math.yl2x + BUILTINyl2xp1, // std.math.yl2xp1 + BUILTINbsr, // core.bitop.bsr + BUILTINbsf, // core.bitop.bsf + BUILTINbswap, // core.bitop.bswap }; -Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments); +Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments); #else enum BUILTIN { }; @@ -686,7 +686,7 @@ enum BUILTIN { }; struct FuncDeclaration : Declaration { - Types *fthrows; // Array of Type's of exceptions (not used) + Types *fthrows; // Array of Type's of exceptions (not used) Statement *frequire; Statement *fensure; Statement *fbody; @@ -706,25 +706,25 @@ struct FuncDeclaration : Declaration #if IN_GCC VarDeclaration *v_argptr; // '_argptr' variable #endif - VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions - VarDeclarations *parameters; // Array of VarDeclaration's for parameters + VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions + VarDeclarations *parameters; // Array of VarDeclaration's for parameters DsymbolTable *labtab; // statement label symbol table Declaration *overnext; // next in overload list Loc endloc; // location of closing curly bracket int vtblIndex; // for member functions, index into vtbl[] int naked; // !=0 if naked int inlineAsm; // !=0 if has inline assembler - ILS inlineStatusStmt; - ILS inlineStatusExp; + ILS inlineStatusStmt; + ILS inlineStatusExp; int inlineNest; // !=0 if nested inline - int isArrayOp; // !=0 if array operation + int isArrayOp; // !=0 if array operation int semanticRun; // 1 semantic() run // 2 semantic2() run // 3 semantic3() started // 4 semantic3() done // 5 toObjFile() run // this function's frame ptr - int semantic3Errors; // !=0 if errors in semantic3 + int semantic3Errors; // !=0 if errors in semantic3 ForeachStatement *fes; // if foreach body, this is the foreach int introducing; // !=0 if 'introducing' function Type *tintro; // if !=NULL, then this is the type @@ -752,14 +752,14 @@ struct FuncDeclaration : Declaration int tookAddressOf; // set if someone took the address of // this function - VarDeclarations closureVars; // local variables in this function + VarDeclarations closureVars; // local variables in this function // which are referenced by nested // functions - - unsigned flags; - #define FUNCFLAGpurityInprocess 1 // working on determining purity - #define FUNCFLAGsafetyInprocess 2 // working on determining safety - #define FUNCFLAGnothrowInprocess 4 // working on determining nothrow + + unsigned flags; + #define FUNCFLAGpurityInprocess 1 // working on determining purity + #define FUNCFLAGsafetyInprocess 2 // working on determining safety + #define FUNCFLAGnothrowInprocess 4 // working on determining nothrow #else int nestedFrameRef; // !=0 if nested variables referenced #endif @@ -802,20 +802,20 @@ struct FuncDeclaration : Declaration int isTrusted(); virtual int isNested(); int needThis(); - int isVirtualMethod(); + int isVirtualMethod(); virtual int isVirtual(); virtual int isFinal(); virtual int addPreInvariant(); virtual int addPostInvariant(); Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL); void inlineScan(); - int canInline(int hasthis, int hdrscan = false, int statementsToo = true); - Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps); + int canInline(int hasthis, int hdrscan = false, int statementsToo = true); + Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps); const char *kind(); void toDocBuffer(OutBuffer *buf); FuncDeclaration *isUnique(); int needsClosure(); - int hasNestedFrameRefs(); + int hasNestedFrameRefs(); Statement *mergeFrequire(Statement *); Statement *mergeFensure(Statement *); Parameters *getParameters(int *pvarargs); @@ -966,7 +966,7 @@ struct StaticCtorDeclaration : FuncDeclaration int isVirtual(); int addPreInvariant(); int addPostInvariant(); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor(); void emitComment(Scope *sc); void toJsonBuffer(OutBuffer *buf); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -994,7 +994,7 @@ struct StaticDtorDeclaration : FuncDeclaration AggregateDeclaration *isThis(); int isStaticDestructor(); int isVirtual(); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor(); int addPreInvariant(); int addPostInvariant(); void emitComment(Scope *sc); diff --git a/dmd/delegatize.c b/dmd/delegatize.c index 617ece35..a4d37152 100644 --- a/dmd/delegatize.c +++ b/dmd/delegatize.c @@ -1,140 +1,140 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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 -#include - -#include "mars.h" -#include "expression.h" -#include "statement.h" -#include "mtype.h" -#include "utf.h" -#include "declaration.h" -#include "aggregate.h" -#include "scope.h" - -/******************************************** - * Convert from expression to delegate that returns the expression, - * i.e. convert: - * expr - * to: - * t delegate() { return expr; } - */ - -int lambdaSetParent(Expression *e, void *param); -int lambdaCheckForNestedRef(Expression *e, void *param); - -Expression *Expression::toDelegate(Scope *sc, Type *t) -{ - //printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars()); - TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd); - FuncLiteralDeclaration *fld = - new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL); - Expression *e; - sc = sc->push(); - sc->parent = fld; // set current function to be the delegate - e = this; - e->apply(&lambdaSetParent, sc); - e->apply(&lambdaCheckForNestedRef, sc); - sc = sc->pop(); - Statement *s; - if (t->ty == Tvoid) - s = new ExpStatement(loc, e); - else - s = new ReturnStatement(loc, e); - fld->fbody = s; - e = new FuncExp(loc, fld); - e = e->semantic(sc); - return e; -} - -/****************************************** - * Patch the parent of declarations to be the new function literal. - */ -int lambdaSetParent(Expression *e, void *param) -{ - Scope *sc = (Scope *)param; - /* We could use virtual functions instead of a switch, - * but it doesn't seem worth the bother. - */ - switch (e->op) - { - case TOKdeclaration: - { DeclarationExp *de = (DeclarationExp *)e; - de->declaration->parent = sc->parent; - break; - } - - case TOKindex: - { IndexExp *de = (IndexExp *)e; - if (de->lengthVar) - { //printf("lengthVar\n"); - de->lengthVar->parent = sc->parent; - } - break; - } - - case TOKslice: - { SliceExp *se = (SliceExp *)e; - if (se->lengthVar) - { //printf("lengthVar\n"); - se->lengthVar->parent = sc->parent; - } - break; - } - - default: - break; - } - return 0; -} - -/******************************************* - * Look for references to variables in a scope enclosing the new function literal. - */ -int lambdaCheckForNestedRef(Expression *e, void *param) -{ - Scope *sc = (Scope *)param; - /* We could use virtual functions instead of a switch, - * but it doesn't seem worth the bother. - */ - switch (e->op) - { - case TOKsymoff: - { SymOffExp *se = (SymOffExp *)e; - VarDeclaration *v = se->var->isVarDeclaration(); - if (v) - v->checkNestedReference(sc, 0); - break; - } - - case TOKvar: - { VarExp *ve = (VarExp *)e; - VarDeclaration *v = ve->var->isVarDeclaration(); - if (v) - v->checkNestedReference(sc, 0); - break; - } - - case TOKthis: - case TOKsuper: - { ThisExp *te = (ThisExp *)e; - VarDeclaration *v = te->var->isVarDeclaration(); - if (v) - v->checkNestedReference(sc, 0); - break; - } - - default: - break; - } - return 0; -} - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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 +#include + +#include "mars.h" +#include "expression.h" +#include "statement.h" +#include "mtype.h" +#include "utf.h" +#include "declaration.h" +#include "aggregate.h" +#include "scope.h" + +/******************************************** + * Convert from expression to delegate that returns the expression, + * i.e. convert: + * expr + * to: + * t delegate() { return expr; } + */ + +int lambdaSetParent(Expression *e, void *param); +int lambdaCheckForNestedRef(Expression *e, void *param); + +Expression *Expression::toDelegate(Scope *sc, Type *t) +{ + //printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars()); + TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd); + FuncLiteralDeclaration *fld = + new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL); + Expression *e; + sc = sc->push(); + sc->parent = fld; // set current function to be the delegate + e = this; + e->apply(&lambdaSetParent, sc); + e->apply(&lambdaCheckForNestedRef, sc); + sc = sc->pop(); + Statement *s; + if (t->ty == Tvoid) + s = new ExpStatement(loc, e); + else + s = new ReturnStatement(loc, e); + fld->fbody = s; + e = new FuncExp(loc, fld); + e = e->semantic(sc); + return e; +} + +/****************************************** + * Patch the parent of declarations to be the new function literal. + */ +int lambdaSetParent(Expression *e, void *param) +{ + Scope *sc = (Scope *)param; + /* We could use virtual functions instead of a switch, + * but it doesn't seem worth the bother. + */ + switch (e->op) + { + case TOKdeclaration: + { DeclarationExp *de = (DeclarationExp *)e; + de->declaration->parent = sc->parent; + break; + } + + case TOKindex: + { IndexExp *de = (IndexExp *)e; + if (de->lengthVar) + { //printf("lengthVar\n"); + de->lengthVar->parent = sc->parent; + } + break; + } + + case TOKslice: + { SliceExp *se = (SliceExp *)e; + if (se->lengthVar) + { //printf("lengthVar\n"); + se->lengthVar->parent = sc->parent; + } + break; + } + + default: + break; + } + return 0; +} + +/******************************************* + * Look for references to variables in a scope enclosing the new function literal. + */ +int lambdaCheckForNestedRef(Expression *e, void *param) +{ + Scope *sc = (Scope *)param; + /* We could use virtual functions instead of a switch, + * but it doesn't seem worth the bother. + */ + switch (e->op) + { + case TOKsymoff: + { SymOffExp *se = (SymOffExp *)e; + VarDeclaration *v = se->var->isVarDeclaration(); + if (v) + v->checkNestedReference(sc, 0); + break; + } + + case TOKvar: + { VarExp *ve = (VarExp *)e; + VarDeclaration *v = ve->var->isVarDeclaration(); + if (v) + v->checkNestedReference(sc, 0); + break; + } + + case TOKthis: + case TOKsuper: + { ThisExp *te = (ThisExp *)e; + VarDeclaration *v = te->var->isVarDeclaration(); + if (v) + v->checkNestedReference(sc, 0); + break; + } + + default: + break; + } + return 0; +} + diff --git a/dmd/doc.c b/dmd/doc.c index 5595c9c4..1bcb93a9 100644 --- a/dmd/doc.c +++ b/dmd/doc.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -65,11 +65,11 @@ struct MacroSection : Section void write(DocComment *dc, Scope *sc, Dsymbol *s, OutBuffer *buf); }; -typedef ArrayBase
Sections; - +typedef ArrayBase
Sections; + struct DocComment { - Sections sections; // Section*[] + Sections sections; // Section*[] Section *summary; Section *copyright; @@ -135,7 +135,7 @@ LINK = $0\n\ LINK2 = $+\n\ LPAREN= (\n\ RPAREN= )\n\ -DOLLAR= $\n\ +DOLLAR= $\n\ \n\ RED = $0\n\ BLUE = $0\n\ @@ -225,9 +225,9 @@ void Module::gendocfile() global.params.ddocfiles->shift(p); // Override with the ddoc macro files from the command line - for (size_t i = 0; i < global.params.ddocfiles->dim; i++) + for (size_t i = 0; i < global.params.ddocfiles->dim; i++) { - FileName f(global.params.ddocfiles->tdata()[i], 0); + FileName f(global.params.ddocfiles->tdata()[i], 0); File file(&f); file.readv(); // BUG: convert file contents to UTF-8 before use @@ -252,14 +252,14 @@ void Module::gendocfile() Macro::define(¯otable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p)); } - // Set time macros - { time_t t; + // Set time macros + { time_t t; time(&t); char *p = ctime(&t); p = mem.strdup(p); Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p)); Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); - } + } char *docfilename = docfile->toChars(); Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); @@ -379,12 +379,12 @@ void escapeDdocString(OutBuffer *buf, unsigned start) unsigned char c = buf->data[u]; switch(c) { - case '$': - buf->remove(u, 1); - buf->insert(u, "$(DOLLAR)", 9); - u += 8; - break; - + case '$': + buf->remove(u, 1); + buf->insert(u, "$(DOLLAR)", 9); + u += 8; + break; + case '(': buf->remove(u, 1); //remove the ( buf->insert(u, "$(LPAREN)", 9); //insert this instead @@ -530,9 +530,9 @@ void ScopeDsymbol::emitMemberComments(Scope *sc) buf->writestring(m); unsigned offset2 = buf->offset; // to see if we write anything sc = sc->push(this); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; //printf("\ts = '%s'\n", s->toChars()); s->emitComment(sc); } @@ -702,9 +702,9 @@ void EnumDeclaration::emitComment(Scope *sc) // if (!comment) { if (isAnonymous() && members) { - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->emitComment(sc); } return; @@ -803,35 +803,35 @@ void prefix(OutBuffer *buf, Dsymbol *s) } } -void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclaration *td) +void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclaration *td) { - //printf("declarationToDocBuffer() %s, originalType = %s, td = %s\n", decl->toChars(), decl->originalType ? decl->originalType->toChars() : "--", td ? td->toChars() : "--"); - if (decl->ident) + //printf("declarationToDocBuffer() %s, originalType = %s, td = %s\n", decl->toChars(), decl->originalType ? decl->originalType->toChars() : "--", td ? td->toChars() : "--"); + if (decl->ident) { - prefix(buf, decl); + prefix(buf, decl); - if (decl->type) + if (decl->type) { HdrGenState hgs; hgs.ddoc = 1; - Type *origType = decl->originalType ? decl->originalType : decl->type; - if (origType->ty == Tfunction) - { - TypeFunction *attrType = (TypeFunction*)(decl->ident == Id::ctor ? origType : decl->type); - ((TypeFunction*)origType)->toCBufferWithAttributes(buf, decl->ident, &hgs, attrType, td); + Type *origType = decl->originalType ? decl->originalType : decl->type; + if (origType->ty == Tfunction) + { + TypeFunction *attrType = (TypeFunction*)(decl->ident == Id::ctor ? origType : decl->type); + ((TypeFunction*)origType)->toCBufferWithAttributes(buf, decl->ident, &hgs, attrType, td); } else - origType->toCBuffer(buf, decl->ident, &hgs); + origType->toCBuffer(buf, decl->ident, &hgs); } else - buf->writestring(decl->ident->toChars()); + buf->writestring(decl->ident->toChars()); buf->writestring(";\n"); } } -void Declaration::toDocBuffer(OutBuffer *buf) -{ - declarationToDocBuffer(this, buf, NULL); -} +void Declaration::toDocBuffer(OutBuffer *buf) +{ + declarationToDocBuffer(this, buf, NULL); +} void AliasDeclaration::toDocBuffer(OutBuffer *buf) { @@ -878,7 +878,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf) */ unsigned o = buf->offset; - declarationToDocBuffer(this, buf, td); + declarationToDocBuffer(this, buf, td); highlightCode(NULL, this, buf, o); } @@ -889,7 +889,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf) } } -#if DMDV1 +#if DMDV1 void CtorDeclaration::toDocBuffer(OutBuffer *buf) { HdrGenState hgs; @@ -898,7 +898,7 @@ void CtorDeclaration::toDocBuffer(OutBuffer *buf) Parameter::argsToCBuffer(buf, &hgs, arguments, varargs); buf->writestring(";\n"); } -#endif +#endif void AggregateDeclaration::toDocBuffer(OutBuffer *buf) { @@ -961,8 +961,8 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf) buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); } int any = 0; - for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *bc = (*baseclasses)[i]; + for (size_t i = 0; i < baseclasses->dim; i++) + { BaseClass *bc = (*baseclasses)[i]; if (bc->protection == PROTprivate) continue; @@ -1017,7 +1017,7 @@ DocComment::DocComment() } DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment) -{ +{ //printf("parse(%s): '%s'\n", s->toChars(), comment); if (sc->lastdc && isDitto(comment)) return NULL; @@ -1028,16 +1028,16 @@ DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment) dc->parseSections(comment); - for (size_t i = 0; i < dc->sections.dim; i++) - { Section *sec = dc->sections[i]; + for (size_t i = 0; i < dc->sections.dim; i++) + { Section *sec = dc->sections[i]; - if (icmp("copyright", sec->name, sec->namelen) == 0) + if (icmp("copyright", sec->name, sec->namelen) == 0) { - dc->copyright = sec; + dc->copyright = sec; } - if (icmp("macros", sec->name, sec->namelen) == 0) + if (icmp("macros", sec->name, sec->namelen) == 0) { - dc->macros = sec; + dc->macros = sec; } } @@ -1116,7 +1116,7 @@ void DocComment::parseSections(unsigned char *comment) goto L1; if (*p == '\n') { p++; - if (*p == '\n' && !summary && !namelen && !inCode) + if (*p == '\n' && !summary && !namelen && !inCode) { pend = p; p++; @@ -1173,8 +1173,8 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf) if (sections.dim) { buf->writestring("$(DDOC_SECTIONS \n"); - for (size_t i = 0; i < sections.dim; i++) - { Section *sec = sections[i]; + for (size_t i = 0; i < sections.dim; i++) + { Section *sec = sections[i]; if (sec->nooutput) continue; @@ -1751,7 +1751,7 @@ Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, unsigned len) if (tf->parameters) { for (size_t k = 0; k < tf->parameters->dim; k++) - { Parameter *arg = (*tf->parameters)[k]; + { Parameter *arg = (*tf->parameters)[k]; if (arg->ident && cmp(arg->ident->toChars(), p, len) == 0) { diff --git a/dmd/doc.h b/dmd/doc.h index 6fe5e99a..ffa97fb9 100644 --- a/dmd/doc.h +++ b/dmd/doc.h @@ -1,20 +1,20 @@ - -// 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. - -#ifndef DMD_DOC_H -#define DMD_DOC_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -void escapeDdocString(OutBuffer *buf, unsigned start); - -#endif + +// 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. + +#ifndef DMD_DOC_H +#define DMD_DOC_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +void escapeDdocString(OutBuffer *buf, unsigned start); + +#endif diff --git a/dmd/dsymbol.c b/dmd/dsymbol.c index 1fbf08a2..08f26ce3 100644 --- a/dmd/dsymbol.c +++ b/dmd/dsymbol.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -119,15 +119,15 @@ int Dsymbol::oneMember(Dsymbol **ps) * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. */ -int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps) +int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps) { //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0); Dsymbol *s = NULL; if (members) { - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *sx = (*members)[i]; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *sx = (*members)[i]; int x = sx->oneMember(ps); //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps); @@ -163,12 +163,12 @@ int Dsymbol::hasPointers() return 0; } -bool Dsymbol::hasStaticCtorOrDtor() -{ - //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars()); - return FALSE; -} - +bool Dsymbol::hasStaticCtorOrDtor() +{ + //printf("Dsymbol::hasStaticCtorOrDtor() %s\n", toChars()); + return FALSE; +} + char *Dsymbol::toChars() { return ident ? ident->toChars() : (char *)"__anonymous"; @@ -219,13 +219,13 @@ char *Dsymbol::locToChars() { OutBuffer buf; - if (!loc.filename) // avoid bug 5861. - { + if (!loc.filename) // avoid bug 5861. + { Module *m = getModule(); if (m && m->srcfile) loc.filename = m->srcfile->toChars(); - } + } return loc.toChars(); } @@ -549,29 +549,29 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) void Dsymbol::error(const char *format, ...) { //printf("Dsymbol::error()\n"); - if (!loc.filename) // avoid bug 5861. + if (!loc.filename) // avoid bug 5861. { - Module *m = getModule(); + Module *m = getModule(); - if (m && m->srcfile) - loc.filename = m->srcfile->toChars(); - } + if (m && m->srcfile) + loc.filename = m->srcfile->toChars(); + } va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(loc, format, ap); va_end(ap); } void Dsymbol::error(Loc loc, const char *format, ...) { - va_list ap; - va_start(ap, format); - verror(loc, format, ap); - va_end(ap); -} - -void Dsymbol::verror(Loc loc, const char *format, va_list ap) -{ + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); +} + +void Dsymbol::verror(Loc loc, const char *format, va_list ap) +{ if (!global.gag) { char *p = loc.toChars(); @@ -589,11 +589,11 @@ void Dsymbol::verror(Loc loc, const char *format, va_list ap) fprintf(stdmsg, "\n"); fflush(stdmsg); -//halt(); - } - else - { - global.gaggedErrors++; +//halt(); + } + else + { + global.gaggedErrors++; } global.errors++; @@ -608,24 +608,24 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc) // Don't complain if we're inside a deprecated symbol's scope for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) { if (sp->isDeprecated()) - goto L1; + goto L1; } - for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing) + for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing) { - if (sc2->scopesym && sc2->scopesym->isDeprecated()) - goto L1; + if (sc2->scopesym && sc2->scopesym->isDeprecated()) + goto L1; // If inside a StorageClassDeclaration that is deprecated - if (sc2->stc & STCdeprecated) - goto L1; + if (sc2->stc & STCdeprecated) + goto L1; } error(loc, "is deprecated"); } - - L1: - ; + + L1: + ; } /********************************** @@ -638,10 +638,10 @@ Module *Dsymbol::getModule() Dsymbol *s; //printf("Dsymbol::getModule()\n"); - TemplateDeclaration *td = getFuncTemplateDecl(this); - if (td) - return td->getModule(); - + TemplateDeclaration *td = getFuncTemplateDecl(this); + if (td) + return td->getModule(); + s = this; while (s) { @@ -695,19 +695,19 @@ enum PROT Dsymbol::prot() */ -Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a) +Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a) { - Dsymbols *b = NULL; + Dsymbols *b = NULL; if (a) { b = a->copy(); - for (size_t i = 0; i < b->dim; i++) + for (size_t i = 0; i < b->dim; i++) { - Dsymbol *s = (*b)[i]; + Dsymbol *s = (*b)[i]; s = s->syntaxCopy(NULL); - (*b)[i] = s; + (*b)[i] = s; } } return b; @@ -794,7 +794,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) // Look in symbols declared in this module Dsymbol *s = symtab ? symtab->lookup(ident) : NULL; - //printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0); + //printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0); // hide the aliases generated by selective or renamed private imports if (s && flags & 1) @@ -811,8 +811,8 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) else if (imports) { // Look in imported modules - for (size_t i = 0; i < imports->dim; i++) - { Dsymbol *ss = (*imports)[i]; + for (size_t i = 0; i < imports->dim; i++) + { Dsymbol *ss = (*imports)[i]; Dsymbol *s2; // If private import, don't search it @@ -822,7 +822,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) //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->isImport() ? 1 : 0); + s2 = ss->search(loc, ident, ss->isImport() ? 1 : 0); if (!s) s = s2; else if (s2 && s != s2) @@ -851,7 +851,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) ) ) { - ScopeDsymbol::multiplyDefined(loc, s, s2); + ScopeDsymbol::multiplyDefined(loc, s, s2); break; } } @@ -860,15 +860,15 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) if (s) { Declaration *d = s->isDeclaration(); - if (d && d->protection == PROTprivate && - !d->parent->isTemplateMixin()) + if (d && d->protection == PROTprivate && + !d->parent->isTemplateMixin()) error(loc, "%s is private", d->toPrettyChars()); } } return s; } -void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection) +void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection) { //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection); @@ -876,11 +876,11 @@ void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection) if (s != this) { if (!imports) - imports = new Dsymbols(); + imports = new Dsymbols(); else { - for (size_t i = 0; i < imports->dim; i++) - { Dsymbol *ss = (*imports)[i]; + for (size_t i = 0; i < imports->dim; i++) + { Dsymbol *ss = (*imports)[i]; if (ss == s) // if already imported { if (protection > prots[i]) @@ -964,40 +964,40 @@ Dsymbol *ScopeDsymbol::symtabInsert(Dsymbol *s) return symtab->insert(s); } -/**************************************** - * Return true if any of the members are static ctors or static dtors, or if - * any members have members that are. +/**************************************** + * Return true if any of the members are static ctors or static dtors, or if + * any members have members that are. */ -bool ScopeDsymbol::hasStaticCtorOrDtor() +bool ScopeDsymbol::hasStaticCtorOrDtor() { if (members) { for (size_t i = 0; i < members->dim; i++) - { Dsymbol *member = (*members)[i]; + { Dsymbol *member = (*members)[i]; - if (member->hasStaticCtorOrDtor()) - return TRUE; + if (member->hasStaticCtorOrDtor()) + return TRUE; } } - return FALSE; -} - -/*************************************** - * Determine number of Dsymbols, folding in AttribDeclaration members. - */ - -#if DMDV2 -static int dimDg(void *ctx, size_t n, Dsymbol *) -{ - ++*(size_t *)ctx; - return 0; -} - -size_t ScopeDsymbol::dim(Dsymbols *members) -{ - size_t n = 0; - foreach(members, &dimDg, &n); + return FALSE; +} + +/*************************************** + * Determine number of Dsymbols, folding in AttribDeclaration members. + */ + +#if DMDV2 +static int dimDg(void *ctx, size_t n, Dsymbol *) +{ + ++*(size_t *)ctx; + return 0; +} + +size_t ScopeDsymbol::dim(Dsymbols *members) +{ + size_t n = 0; + foreach(members, &dimDg, &n); return n; } #endif @@ -1011,67 +1011,67 @@ size_t ScopeDsymbol::dim(Dsymbols *members) */ #if DMDV2 -struct GetNthSymbolCtx +struct GetNthSymbolCtx { - size_t nth; - Dsymbol *sym; -}; + size_t nth; + Dsymbol *sym; +}; -static int getNthSymbolDg(void *ctx, size_t n, Dsymbol *sym) -{ - GetNthSymbolCtx *p = (GetNthSymbolCtx *)ctx; - if (n == p->nth) - { p->sym = sym; - return 1; +static int getNthSymbolDg(void *ctx, size_t n, Dsymbol *sym) +{ + GetNthSymbolCtx *p = (GetNthSymbolCtx *)ctx; + if (n == p->nth) + { p->sym = sym; + return 1; } - return 0; -} - -Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn) -{ - GetNthSymbolCtx ctx = { nth, NULL }; - int res = foreach(members, &getNthSymbolDg, &ctx); - return res ? ctx.sym : NULL; -} -#endif - -/*************************************** - * Expands attribute declarations in members in depth first - * order. Calls dg(void *ctx, size_t symidx, Dsymbol *sym) for each - * member. - * If dg returns !=0, stops and returns that value else returns 0. - * Use this function to avoid the O(N + N^2/2) complexity of - * calculating dim and calling N times getNth. - */ - -#if DMDV2 -int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn) -{ - assert(dg); - if (!members) - return 0; - - size_t n = pn ? *pn : 0; // take over index - int result = 0; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = (*members)[i]; - - if (AttribDeclaration *a = s->isAttribDeclaration()) - result = foreach(a->decl, dg, ctx, &n); - else if (TemplateMixin *tm = s->isTemplateMixin()) - result = foreach(tm->members, dg, ctx, &n); - else if (s->isTemplateInstance()) - ; + return 0; +} + +Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn) +{ + GetNthSymbolCtx ctx = { nth, NULL }; + int res = foreach(members, &getNthSymbolDg, &ctx); + return res ? ctx.sym : NULL; +} +#endif + +/*************************************** + * Expands attribute declarations in members in depth first + * order. Calls dg(void *ctx, size_t symidx, Dsymbol *sym) for each + * member. + * If dg returns !=0, stops and returns that value else returns 0. + * Use this function to avoid the O(N + N^2/2) complexity of + * calculating dim and calling N times getNth. + */ + +#if DMDV2 +int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn) +{ + assert(dg); + if (!members) + return 0; + + size_t n = pn ? *pn : 0; // take over index + int result = 0; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + + if (AttribDeclaration *a = s->isAttribDeclaration()) + result = foreach(a->decl, dg, ctx, &n); + else if (TemplateMixin *tm = s->isTemplateMixin()) + result = foreach(tm->members, dg, ctx, &n); + else if (s->isTemplateInstance()) + ; else - result = dg(ctx, n++, s); - - if (result) - break; + result = dg(ctx, n++, s); + + if (result) + break; } if (pn) - *pn = n; // update index - return result; + *pn = n; // update index + return result; } #endif @@ -1220,27 +1220,27 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) * multiple times, it gets set only once. */ if (!*pvar) // if not already initialized - { /* Create variable v and set it to the value of $ + { /* Create variable v and set it to the value of $ */ VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - if (ce->op == TOKtuple) + if (ce->op == TOKtuple) { /* It is for an expression tuple, so the - * length will be a compile-time constant. + * length will be a compile-time constant. */ Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCconst; } - else - { /* For arrays, $ will either be a compile-time constant - * (in which case its value in set during constant-folding), - * or a variable (in which case an expression is created in - * toir.c). - */ - VoidInitializer *e = new VoidInitializer(0); - e->type = Type::tsize_t; - v->init = e; - } + else + { /* For arrays, $ will either be a compile-time constant + * (in which case its value in set during constant-folding), + * or a variable (in which case an expression is created in + * toir.c). + */ + VoidInitializer *e = new VoidInitializer(0); + e->type = Type::tsize_t; + v->init = e; + } *pvar = v; } return (*pvar); diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index c3e8905e..e4cffee4 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -145,7 +145,7 @@ struct Dsymbol : Object int isAnonymous(); void error(Loc loc, const char *format, ...) IS_PRINTF(3); void error(const char *format, ...) IS_PRINTF(2); - void verror(Loc loc, const char *format, va_list ap); + void verror(Loc loc, const char *format, va_list ap); void checkDeprecated(Loc loc, Scope *sc); Module *getModule(); // module where declared Module *getCompilationModule(); // possibly different for templates @@ -156,7 +156,7 @@ struct Dsymbol : Object int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() - static Dsymbols *arraySyntaxCopy(Dsymbols *a); + static Dsymbols *arraySyntaxCopy(Dsymbols *a); virtual const char *toPrettyChars(); virtual const char *kind(); @@ -197,9 +197,9 @@ struct Dsymbol : Object virtual enum PROT prot(); virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual int oneMember(Dsymbol **ps); - static int oneMembers(Dsymbols *members, Dsymbol **ps); + static int oneMembers(Dsymbols *members, Dsymbol **ps); virtual int hasPointers(); - virtual bool hasStaticCtorOrDtor(); + virtual bool hasStaticCtorOrDtor(); virtual void addLocalClass(ClassDeclarations *) { } virtual void checkCtorConstInit() { } @@ -255,7 +255,7 @@ struct Dsymbol : Object virtual Import *isImport() { return NULL; } virtual EnumDeclaration *isEnumDeclaration() { return NULL; } virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; } - //virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; } + //virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; } virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; } virtual AttribDeclaration *isAttribDeclaration() { return NULL; } virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; } @@ -282,17 +282,17 @@ struct Dsymbol : Object struct ScopeDsymbol : Dsymbol { - Dsymbols *members; // all Dsymbol's in this scope + Dsymbols *members; // all Dsymbol's in this scope DsymbolTable *symtab; // members[] sorted into table - Dsymbols *imports; // imported Dsymbol's + Dsymbols *imports; // imported Dsymbol's unsigned char *prots; // array of PROT, one for each import ScopeDsymbol(); ScopeDsymbol(Identifier *id); Dsymbol *syntaxCopy(Dsymbol *s); Dsymbol *search(Loc loc, Identifier *ident, int flags); - void importScope(Dsymbol *s, enum PROT protection); + void importScope(Dsymbol *s, enum PROT protection); int isforwardRef(); void defineRef(Dsymbol *s); static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2); @@ -300,15 +300,15 @@ struct ScopeDsymbol : Dsymbol const char *kind(); FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor(); void emitMemberComments(Scope *sc); - static size_t dim(Dsymbols *members); - static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL); - - typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s); - static int foreach(Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn=NULL); + static size_t dim(Dsymbols *members); + static Dsymbol *getNth(Dsymbols *members, size_t nth, size_t *pn = NULL); + + typedef int (*ForeachDg)(void *ctx, size_t idx, Dsymbol *s); + static int foreach(Dsymbols *members, ForeachDg dg, void *ctx, size_t *pn=NULL); ScopeDsymbol *isScopeDsymbol() { return this; } }; diff --git a/dmd/dump.c b/dmd/dump.c index c5647dd8..d1468264 100644 --- a/dmd/dump.c +++ b/dmd/dump.c @@ -1,144 +1,144 @@ - -// 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 -#include -#include - -#include "mars.h" -#include "mtype.h" -#include "declaration.h" -#include "expression.h" -#include "template.h" - -static void indent(int indent) -{ - int i; - - for (i = 0; i < indent; i++) - printf(" "); -} - -static char *type_print(Type *type) -{ - return type ? type->toChars() : (char *) "null"; -} - -void dumpExpressions(int i, Expressions *exps) -{ - for (size_t j = 0; j < exps->dim; j++) - { Expression *e = (Expression *)exps->data[j]; - indent(i); - printf("(\n"); - e->dump(i + 2); - indent(i); - printf(")\n"); - } -} - -void Expression::dump(int i) -{ - indent(i); - printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type)); -} - -void IntegerExp::dump(int i) -{ - indent(i); - printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type)); -} - -void IdentifierExp::dump(int i) -{ - indent(i); - printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type)); -} - -void DsymbolExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s\n", this, s->toChars(), type_print(type)); -} - -void VarExp::dump(int i) -{ - indent(i); - printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type)); -} - -void UnaExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); - if (e1) - e1->dump(i + 2); -} - -void CallExp::dump(int i) -{ - UnaExp::dump(i); - dumpExpressions(i, arguments); -} - -void SliceExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); - if (e1) - e1->dump(i + 2); - if (lwr) - lwr->dump(i + 2); - if (upr) - upr->dump(i + 2); -} - -void DotIdExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DotVarExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DotTemplateInstanceExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1); - if (e1) - e1->dump(i + 2); -} - -void DelegateExp::dump(int i) -{ - indent(i); - printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1); - if (e1) - e1->dump(i + 2); -} - -void BinExp::dump(int i) -{ - indent(i); - printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2); - if (e1) - e1->dump(i + 2); - if (e2) - e2->dump(i + 2); -} - - + +// 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 +#include +#include + +#include "mars.h" +#include "mtype.h" +#include "declaration.h" +#include "expression.h" +#include "template.h" + +static void indent(int indent) +{ + int i; + + for (i = 0; i < indent; i++) + printf(" "); +} + +static char *type_print(Type *type) +{ + return type ? type->toChars() : (char *) "null"; +} + +void dumpExpressions(int i, Expressions *exps) +{ + for (size_t j = 0; j < exps->dim; j++) + { Expression *e = (Expression *)exps->data[j]; + indent(i); + printf("(\n"); + e->dump(i + 2); + indent(i); + printf(")\n"); + } +} + +void Expression::dump(int i) +{ + indent(i); + printf("%p %s type=%s\n", this, Token::toChars(op), type_print(type)); +} + +void IntegerExp::dump(int i) +{ + indent(i); + printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type)); +} + +void IdentifierExp::dump(int i) +{ + indent(i); + printf("%p ident '%s' type=%s\n", this, ident->toChars(), type_print(type)); +} + +void DsymbolExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s\n", this, s->toChars(), type_print(type)); +} + +void VarExp::dump(int i) +{ + indent(i); + printf("%p %s var=%s type=%s\n", this, Token::toChars(op), var->toChars(), type_print(type)); +} + +void UnaExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); + if (e1) + e1->dump(i + 2); +} + +void CallExp::dump(int i) +{ + UnaExp::dump(i); + dumpExpressions(i, arguments); +} + +void SliceExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s e1=%p\n", this, Token::toChars(op), type_print(type), e1); + if (e1) + e1->dump(i + 2); + if (lwr) + lwr->dump(i + 2); + if (upr) + upr->dump(i + 2); +} + +void DotIdExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s ident=%s e1=%p\n", this, Token::toChars(op), type_print(type), ident->toChars(), e1); + if (e1) + e1->dump(i + 2); +} + +void DotVarExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s var='%s' e1=%p\n", this, Token::toChars(op), type_print(type), var->toChars(), e1); + if (e1) + e1->dump(i + 2); +} + +void DotTemplateInstanceExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s ti='%s' e1=%p\n", this, Token::toChars(op), type_print(type), ti->toChars(), e1); + if (e1) + e1->dump(i + 2); +} + +void DelegateExp::dump(int i) +{ + indent(i); + printf("%p %s func=%s type=%s e1=%p\n", this, Token::toChars(op), func->toChars(), type_print(type), e1); + if (e1) + e1->dump(i + 2); +} + +void BinExp::dump(int i) +{ + indent(i); + printf("%p %s type=%s e1=%p e2=%p\n", this, Token::toChars(op), type_print(type), e1, e2); + if (e1) + e1->dump(i + 2); + if (e2) + e2->dump(i + 2); +} + + diff --git a/dmd/enum.c b/dmd/enum.c index c8161252..7d4cdddc 100644 --- a/dmd/enum.c +++ b/dmd/enum.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -68,7 +68,7 @@ void EnumDeclaration::semantic0(Scope *sc) return; if (!isAnonymous() || memtype) return; - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); if (em && em->value) @@ -80,7 +80,7 @@ void EnumDeclaration::semantic0(Scope *sc) } void EnumDeclaration::semantic(Scope *sc) -{ +{ uinteger_t number; Type *t; Scope *sce; @@ -140,7 +140,7 @@ void EnumDeclaration::semantic(Scope *sc) if (members->dim == 0) error("enum %s must have at least one member", toChars()); int first = 1; - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); Expression *e; @@ -228,13 +228,13 @@ void EnumDeclaration::semantic(Scope *sc) if (isAnonymous()) { //sce->enclosing->insert(em); - for (Scope *sct = sce->enclosing; sct; sct = sct->enclosing) + for (Scope *sct = sce->enclosing; sct; sct = sct->enclosing) { - if (sct->scopesym) + if (sct->scopesym) { - if (!sct->scopesym->symtab) - sct->scopesym->symtab = new DsymbolTable(); - em->addMember(sce, sct->scopesym, 1); + if (!sct->scopesym->symtab) + sct->scopesym->symtab = new DsymbolTable(); + em->addMember(sce, sct->scopesym, 1); break; } } @@ -279,7 +279,7 @@ int EnumDeclaration::oneMember(Dsymbol **ps) } void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ +{ buf->writestring("enum "); if (ident) { buf->writestring(ident->toChars()); @@ -299,7 +299,7 @@ void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { EnumMember *em = ((Dsymbol *)members->data[i])->isEnumMember(); if (!em) diff --git a/dmd/expression.c b/dmd/expression.c index 980b2258..283fe485 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -54,10 +54,10 @@ int isnan(double); #include "attrib.h" #include "hdrgen.h" #include "parse.h" -#include "doc.h" +#include "doc.h" -Expression *createTypeInfoArray(Scope *sc, Expression *args[], unsigned dim); +Expression *createTypeInfoArray(Scope *sc, Expression *args[], unsigned dim); Expression *expandVar(int result, VarDeclaration *v); #define LOGSEMANTIC 0 @@ -183,17 +183,17 @@ FuncDeclaration *hasThis(Scope *sc) break; Dsymbol *parent = fd->parent; - while (1) + while (1) { - if (!parent) - goto Lno; + if (!parent) + goto Lno; TemplateInstance *ti = parent->isTemplateInstance(); if (ti) parent = ti->parent; else break; } - fd = parent->isFuncDeclaration(); + fd = parent->isFuncDeclaration(); } if (!fd->isThis()) @@ -435,29 +435,29 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt } /**************************************** - * Get TemplateDeclaration enclosing FuncDeclaration. - */ - -TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s) -{ - FuncDeclaration *f = s->isFuncDeclaration(); - if (f && f->parent) - { TemplateInstance *ti = f->parent->isTemplateInstance(); - - if (ti && - !ti->isTemplateMixin() && - (ti->name == f->ident || - ti->toAlias()->ident == f->ident) - && - ti->tempdecl && ti->tempdecl->onemember) - { - return ti->tempdecl; - } - } - return NULL; -} - -/**************************************** + * Get TemplateDeclaration enclosing FuncDeclaration. + */ + +TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s) +{ + FuncDeclaration *f = s->isFuncDeclaration(); + if (f && f->parent) + { TemplateInstance *ti = f->parent->isTemplateInstance(); + + if (ti && + !ti->isTemplateMixin() && + (ti->name == f->ident || + ti->toAlias()->ident == f->ident) + && + ti->tempdecl && ti->tempdecl->onemember) + { + return ti->tempdecl; + } + } + return NULL; +} + +/**************************************** * Preprocess arguments to function. */ @@ -468,7 +468,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) expandTuples(exps); for (size_t i = 0; i < exps->dim; i++) - { Expression *arg = (*exps)[i]; + { Expression *arg = (*exps)[i]; if (!arg->type) { @@ -481,7 +481,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) } arg = resolveProperties(sc, arg); - (*exps)[i] = arg; + (*exps)[i] = arg; //arg->rvalue(); #if 0 @@ -489,7 +489,7 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) { arg = new AddrExp(arg->loc, arg); arg = arg->semantic(sc); - (*exps)[i] = arg; + (*exps)[i] = arg; } #endif } @@ -524,23 +524,23 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) } #endif -// Check if this function is a member of a template which has only been -// instantiated speculatively, eg from inside is(typeof()). -// Return the speculative template instance it is part of, -// or NULL if not speculative. -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd) -{ - Dsymbol * par = fd->parent; - while (par) - { - TemplateInstance *ti = par->isTemplateInstance(); - if (ti && ti->speculative) - return ti; - par = par->toParent(); - } - return NULL; -} - +// Check if this function is a member of a template which has only been +// instantiated speculatively, eg from inside is(typeof()). +// Return the speculative template instance it is part of, +// or NULL if not speculative. +TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd) +{ + Dsymbol * par = fd->parent; + while (par) + { + TemplateInstance *ti = par->isTemplateInstance(); + if (ti && ti->speculative) + return ti; + par = par->toParent(); + } + return NULL; +} + /**************************************** * Now that we know the exact type of the function we're calling, * the arguments[] need to be adjusted: @@ -560,20 +560,20 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum if (nargs > nparams && tf->varargs == 0) error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars()); -#if DMDV2 - // If inferring return type, and semantic3() needs to be run if not already run - if (!tf->next && fd->inferRetType) - { - TemplateInstance *spec = isSpeculativeFunction(fd); - int olderrs = global.errors; - fd->semantic3(fd->scope); - // Update the template instantiation with the number - // of errors which occured. - if (spec && global.errors != olderrs) - spec->errors = global.errors - olderrs; - } -#endif - +#if DMDV2 + // If inferring return type, and semantic3() needs to be run if not already run + if (!tf->next && fd->inferRetType) + { + TemplateInstance *spec = isSpeculativeFunction(fd); + int olderrs = global.errors; + fd->semantic3(fd->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } +#endif + unsigned n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) int done = 0; @@ -614,9 +614,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); if (arg->implicitConvTo(p->type)) { - if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf())) - goto L2; - else if (nargs != nparams) + if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf())) + goto L2; + else if (nargs != nparams) { error(loc, "expected %zu function arguments, not %zu", nparams, nargs); return; } @@ -653,7 +653,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum c->type = v->type; for (size_t u = i; u < nargs; u++) - { Expression *a = (*arguments)[u]; + { Expression *a = (*arguments)[u]; if (tret && !((TypeArray *)tb)->next->equals(a->type)) a = a->toDelegate(sc, tret); @@ -746,15 +746,15 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum */ if (!tf->parameterEscapes(p)) { - Expression *a = arg; - if (a->op == TOKcast) - a = ((CastExp *)a)->e1; - + Expression *a = arg; + if (a->op == TOKcast) + a = ((CastExp *)a)->e1; + /* Function literals can only appear once, so if this * appearance was scoped, there cannot be any others. */ - if (a->op == TOKfunction) - { FuncExp *fe = (FuncExp *)a; + if (a->op == TOKfunction) + { FuncExp *fe = (FuncExp *)a; fe->fd->tookAddressOf = 0; } @@ -762,8 +762,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum * this doesn't count as taking the address of it. * We only worry about 'escaping' references to the function. */ - else if (a->op == TOKdelegate) - { DelegateExp *de = (DelegateExp *)a; + else if (a->op == TOKdelegate) + { DelegateExp *de = (DelegateExp *)a; if (de->e1->op == TOKvar) { VarExp *ve = (VarExp *)de->e1; FuncDeclaration *f = ve->var->isFuncDeclaration(); @@ -977,24 +977,24 @@ Expression *Expression::semantic(Scope *sc) return this; } -/********************************** - * Try to run semantic routines. - * If they fail, return NULL. - */ - -Expression *Expression::trySemantic(Scope *sc) -{ - //printf("+trySemantic(%s)\n", toChars()); - unsigned errors = global.startGagging(); - Expression *e = semantic(sc); - if (global.endGagging(errors)) - { - e = NULL; - } - //printf("-trySemantic(%s)\n", toChars()); - return e; -} - +/********************************** + * Try to run semantic routines. + * If they fail, return NULL. + */ + +Expression *Expression::trySemantic(Scope *sc) +{ + //printf("+trySemantic(%s)\n", toChars()); + unsigned errors = global.startGagging(); + Expression *e = semantic(sc); + if (global.endGagging(errors)) + { + e = NULL; + } + //printf("-trySemantic(%s)\n", toChars()); + return e; +} + void Expression::print() { fprintf(stdmsg, "%s\n", toChars()); @@ -1033,7 +1033,7 @@ void Expression::warning(const char *format, ...) } } -int Expression::rvalue() +int Expression::rvalue() { if (type && type->toBasetype()->ty == Tvoid) { error("expression %s is void and has no value", toChars()); @@ -1041,11 +1041,11 @@ int Expression::rvalue() dump(0); halt(); #endif - if (!global.gag) - type = Type::terror; - return 0; + if (!global.gag) + type = Type::terror; + return 0; } - return 1; + return 1; } Expression *Expression::combine(Expression *e1, Expression *e2) @@ -1098,11 +1098,11 @@ complex_t Expression::toComplex() #endif } -StringExp *Expression::toString() -{ - return NULL; -} - +StringExp *Expression::toString() +{ + return NULL; +} + void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(Token::toChars(op)); @@ -1190,8 +1190,8 @@ Expression *Expression::checkIntegral() Expression *Expression::checkArithmetic() { if (!type->isintegral() && !type->isfloating()) - { if (type->toBasetype() != Type::terror) - error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); + { if (type->toBasetype() != Type::terror) + error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); return new ErrorExp(); } return this; @@ -1287,12 +1287,12 @@ Expression *Expression::checkToPointer() Expression *Expression::addressOf(Scope *sc) { Expression *e; - Type *t = type; + Type *t = type; //printf("Expression::addressOf()\n"); e = toLvalue(sc, NULL); e = new AddrExp(loc, e); - e->type = t->pointerTo(); + e->type = t->pointerTo(); return e; } @@ -1354,7 +1354,7 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps) { a = new Expressions(); a->setDim(exps->dim); - for (size_t i = 0; i < a->dim; i++) + for (size_t i = 0; i < a->dim; i++) { Expression *e = (Expression *)exps->data[i]; e = e->syntaxCopy(); @@ -1561,18 +1561,18 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) break; } case Tchar: - { - unsigned o = buf->offset; + { + unsigned o = buf->offset; if (v == '\'') buf->writestring("'\\''"); else if (isprint(v) && v != '\\') buf->printf("'%c'", (int)v); else buf->printf("'\\x%02x'", (int)v); - if (hgs->ddoc) - escapeDdocString(buf, o); + if (hgs->ddoc) + escapeDdocString(buf, o); break; - } + } case Tint8: buf->writestring("cast(byte)"); @@ -1751,11 +1751,11 @@ complex_t RealExp::toComplex() int RealEquals(real_t x1, real_t x2) { - return (Port::isNan(x1) && Port::isNan(x2)) || - /* In some cases, the REALPAD bytes get garbage in them, - * so be sure and ignore them. - */ - memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; + return (Port::isNan(x1) && Port::isNan(x2)) || + /* In some cases, the REALPAD bytes get garbage in them, + * so be sure and ignore them. + */ + memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; } int RealExp::equals(Object *o) @@ -1812,16 +1812,16 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) buf->writestring(buffer); else { - #ifdef __HAIKU__ // broken printf workaround - char buffer2[25]; - char *ptr = (char *)&value; - for(int i = 0; i < sizeof(value); i++) - snprintf(buffer2, sizeof(char), "%x", ptr[i]); - - buf->writestring(buffer2); - #else - buf->printf("%La", value); // ensure exact duplication - #endif + #ifdef __HAIKU__ // broken printf workaround + char buffer2[25]; + char *ptr = (char *)&value; + for(int i = 0; i < sizeof(value); i++) + snprintf(buffer2, sizeof(char), "%x", ptr[i]); + + buf->writestring(buffer2); + #else + buf->printf("%La", value); // ensure exact duplication + #endif } if (type) @@ -1867,7 +1867,7 @@ void realToMangleBuffer(OutBuffer *buf, real_t value) * 0X1.9P+2 => 19P2 */ - if (Port::isNan(value)) + if (Port::isNan(value)) buf->writestring("NAN"); // no -NAN bugs else { @@ -2079,9 +2079,9 @@ Expression *IdentifierExp::semantic(Scope *sc) * then replace f with the function template declaration. */ FuncDeclaration *f = s->isFuncDeclaration(); - if (f) - { TemplateDeclaration *tempdecl = getFuncTemplateDecl(f); - if (tempdecl) + if (f) + { TemplateDeclaration *tempdecl = getFuncTemplateDecl(f); + if (tempdecl) { if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's tempdecl = tempdecl->overroot; // then get the start @@ -2188,10 +2188,10 @@ Lagain: return this; if (!s->isFuncDeclaration()) // functions are checked after overloading checkDeprecated(sc, s); - Dsymbol *olds = s; + Dsymbol *olds = s; s = s->toAlias(); //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); - if (s != olds && !s->isFuncDeclaration()) + if (s != olds && !s->isFuncDeclaration()) checkDeprecated(sc, s); if (sc->func) @@ -2281,21 +2281,21 @@ Lagain: if (!f->originalType && f->scope) // semantic not yet run f->semantic(f->scope); - -#if DMDV2 - // if inferring return type, sematic3 needs to be run - if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) - { - TemplateInstance *spec = isSpeculativeFunction(f); - int olderrs = global.errors; - f->semantic3(f->scope); - // Update the template instantiation with the number - // of errors which occured. - if (spec && global.errors != olderrs) - spec->errors = global.errors - olderrs; - } -#endif - + +#if DMDV2 + // if inferring return type, sematic3 needs to be run + if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) + { + TemplateInstance *spec = isSpeculativeFunction(f); + int olderrs = global.errors; + f->semantic3(f->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } +#endif + if (f->isUnitTestDeclaration()) { error("cannot call unittest function %s", toChars()); @@ -2322,7 +2322,7 @@ Lagain: { if (!imp->pkg) { error("forward reference of import %s", imp->toChars()); - return new ErrorExp(); + return new ErrorExp(); } ScopeExp *ie = new ScopeExp(loc, imp->pkg); return ie->semantic(sc); @@ -2347,8 +2347,8 @@ Lagain: t = s->getType(); if (t) { - TypeExp *te = new TypeExp(loc, t); - return te->semantic(sc); + TypeExp *te = new TypeExp(loc, t); + return te->semantic(sc); } TupleDeclaration *tup = s->isTupleDeclaration(); @@ -2380,7 +2380,7 @@ Lagain: } error("%s '%s' is not a variable", s->kind(), s->toChars()); - return new ErrorExp(); + return new ErrorExp(); } char *DsymbolExp::toChars() @@ -2417,12 +2417,12 @@ Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) ThisExp::ThisExp(Loc loc) : Expression(loc, TOKthis, sizeof(ThisExp)) { - //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum); + //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum); var = NULL; } Expression *ThisExp::semantic(Scope *sc) -{ +{ #if LOGSEMANTIC printf("ThisExp::semantic()\n"); #endif @@ -2431,35 +2431,35 @@ Expression *ThisExp::semantic(Scope *sc) return this; } - FuncDeclaration *fd = hasThis(sc); // fd is the uplevel function with the 'this' variable - + FuncDeclaration *fd = hasThis(sc); // fd is the uplevel function with the 'this' variable + /* Special case for typeof(this) and typeof(super) since both * should work even if they are not inside a non-static member function */ - if (!fd && sc->intypeof) + if (!fd && sc->intypeof) { // Find enclosing struct or class - for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) + for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) { if (!s) { - error("%s is not in a class or struct scope", toChars()); + error("%s is not in a class or struct scope", toChars()); goto Lerr; } - ClassDeclaration *cd = s->isClassDeclaration(); + ClassDeclaration *cd = s->isClassDeclaration(); if (cd) { type = cd->type; return this; } - StructDeclaration *sd = s->isStructDeclaration(); + StructDeclaration *sd = s->isStructDeclaration(); if (sd) { -#if STRUCTTHISREF - type = sd->type; -#else +#if STRUCTTHISREF + type = sd->type; +#else type = sd->type->pointerTo(); -#endif +#endif return this; } } @@ -2478,7 +2478,7 @@ Expression *ThisExp::semantic(Scope *sc) Lerr: error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars()); - return new ErrorExp(); + return new ErrorExp(); } int ThisExp::isBool(int result) @@ -2512,7 +2512,7 @@ SuperExp::SuperExp(Loc loc) } Expression *SuperExp::semantic(Scope *sc) -{ +{ ClassDeclaration *cd; Dsymbol *s; @@ -2522,22 +2522,22 @@ Expression *SuperExp::semantic(Scope *sc) if (type) return this; - FuncDeclaration *fd = hasThis(sc); - + FuncDeclaration *fd = hasThis(sc); + /* Special case for typeof(this) and typeof(super) since both * should work even if they are not inside a non-static member function */ - if (!fd && sc->intypeof) + if (!fd && sc->intypeof) { // Find enclosing class - for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) + for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) { if (!s) { error("%s is not in a class scope", toChars()); goto Lerr; } - ClassDeclaration *cd = s->isClassDeclaration(); + ClassDeclaration *cd = s->isClassDeclaration(); if (cd) { cd = cd->baseClass; @@ -2552,7 +2552,7 @@ Expression *SuperExp::semantic(Scope *sc) } if (!fd) goto Lerr; - + assert(fd->vthis); var = fd->vthis; assert(var->parent); @@ -2573,9 +2573,9 @@ Expression *SuperExp::semantic(Scope *sc) else { type = cd->baseClass->type; -#if DMDV2 - type = type->castMod(var->type->mod); -#endif +#if DMDV2 + type = type->castMod(var->type->mod); +#endif } var->isVarDeclaration()->checkNestedReference(sc, loc); @@ -2587,7 +2587,7 @@ Expression *SuperExp::semantic(Scope *sc) Lerr: error("'super' is only allowed in non-static class member functions"); - return new ErrorExp(); + return new ErrorExp(); } void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -2621,17 +2621,17 @@ int NullExp::isBool(int result) return result ? FALSE : TRUE; } -StringExp *NullExp::toString() -{ - if (implicitConvTo(Type::tstring)) - { - StringExp *se = new StringExp(loc, (char*)mem.calloc(1, 1), 0); - se->type = Type::tstring; - return se; - } - return NULL; -} - +StringExp *NullExp::toString() +{ + if (implicitConvTo(Type::tstring)) + { + StringExp *se = new StringExp(loc, (char*)mem.calloc(1, 1), 0); + se->type = Type::tstring; + return se; + } + return NULL; +} + void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("null"); @@ -2652,7 +2652,7 @@ StringExp::StringExp(Loc loc, char *string) this->sz = 1; this->committed = 0; this->postfix = 0; - this->ownedByCtfe = false; + this->ownedByCtfe = false; } StringExp::StringExp(Loc loc, void *string, size_t len) @@ -2663,7 +2663,7 @@ StringExp::StringExp(Loc loc, void *string, size_t len) this->sz = 1; this->committed = 0; this->postfix = 0; - this->ownedByCtfe = false; + this->ownedByCtfe = false; } StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) @@ -2674,7 +2674,7 @@ StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) this->sz = 1; this->committed = 0; this->postfix = postfix; - this->ownedByCtfe = false; + this->ownedByCtfe = false; } #if 0 @@ -2687,7 +2687,7 @@ Expression *StringExp::syntaxCopy() int StringExp::equals(Object *o) { - //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars()); + //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars()); if (o && o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; @@ -2733,7 +2733,7 @@ Expression *StringExp::semantic(Scope *sc) p = utf_decodeChar((unsigned char *)string, len, &u, &c); if (p) { error("%s", p); - return new ErrorExp(); + return new ErrorExp(); } else { buffer.write4(c); @@ -2754,7 +2754,7 @@ Expression *StringExp::semantic(Scope *sc) p = utf_decodeChar((unsigned char *)string, len, &u, &c); if (p) { error("%s", p); - return new ErrorExp(); + return new ErrorExp(); } else { buffer.writeUTF16(c); @@ -2782,59 +2782,59 @@ Expression *StringExp::semantic(Scope *sc) return this; } -/********************************** - * Return length of string. - */ - -size_t StringExp::length() -{ - size_t result = 0; - dchar_t c; - const char *p; - - switch (sz) - { - case 1: - for (size_t u = 0; u < len;) - { - p = utf_decodeChar((unsigned char *)string, len, &u, &c); - if (p) - { error("%s", p); - return 0; - } - else - result++; - } - break; - - case 2: - for (size_t u = 0; u < len;) - { - p = utf_decodeWchar((unsigned short *)string, len, &u, &c); - if (p) - { error("%s", p); - return 0; - } - else - result++; - } - break; - - case 4: - result = len; - break; - - default: - assert(0); - } - return result; -} - -StringExp *StringExp::toString() -{ - return this; -} - +/********************************** + * Return length of string. + */ + +size_t StringExp::length() +{ + size_t result = 0; + dchar_t c; + const char *p; + + switch (sz) + { + case 1: + for (size_t u = 0; u < len;) + { + p = utf_decodeChar((unsigned char *)string, len, &u, &c); + if (p) + { error("%s", p); + return 0; + } + else + result++; + } + break; + + case 2: + for (size_t u = 0; u < len;) + { + p = utf_decodeWchar((unsigned short *)string, len, &u, &c); + if (p) + { error("%s", p); + return 0; + } + else + result++; + } + break; + + case 4: + result = len; + break; + + default: + assert(0); + } + return result; +} + +StringExp *StringExp::toString() +{ + return this; +} + /**************************************** * Convert string to char[]. */ @@ -2856,7 +2856,7 @@ StringExp *StringExp::toUTF8(Scope *sc) int StringExp::compare(Object *obj) { - //printf("StringExp::compare()\n"); + //printf("StringExp::compare()\n"); // Used to sort case statement expressions so we can do an efficient lookup StringExp *se2 = (StringExp *)(obj); @@ -2870,7 +2870,7 @@ int StringExp::compare(Object *obj) int len1 = len; int len2 = se2->len; - //printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2); + //printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2); if (len1 == len2) { switch (sz) @@ -2915,12 +2915,12 @@ int StringExp::isBool(int result) return result ? TRUE : FALSE; } -#if DMDV2 -int StringExp::isLvalue() -{ - return 1; -} -#endif +#if DMDV2 +int StringExp::isLvalue() +{ + return 1; +} +#endif unsigned StringExp::charAt(size_t i) { unsigned value; @@ -2948,7 +2948,7 @@ unsigned StringExp::charAt(size_t i) void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('"'); - unsigned o = buf->offset; + unsigned o = buf->offset; for (size_t i = 0; i < len; i++) { unsigned c = charAt(i); @@ -2973,8 +2973,8 @@ void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) break; } } - if (hgs->ddoc) - escapeDdocString(buf, o); + if (hgs->ddoc) + escapeDdocString(buf, o); buf->writeByte('"'); if (postfix) buf->writeByte(postfix); @@ -3026,19 +3026,19 @@ void StringExp::toMangleBuffer(OutBuffer *buf) default: assert(0); } - buf->reserve(1 + 11 + 2 * qlen); + buf->reserve(1 + 11 + 2 * qlen); buf->writeByte(m); - buf->printf("%d_", qlen); // nbytes <= 11 - - for (unsigned char *p = buf->data + buf->offset, *pend = p + 2 * qlen; - p < pend; p += 2, ++q) - { - unsigned char hi = *q >> 4 & 0xF; - p[0] = (hi < 10 ? hi + '0' : hi - 10 + 'a'); - unsigned char lo = *q & 0xF; - p[1] = (lo < 10 ? lo + '0' : lo - 10 + 'a'); - } - buf->offset += 2 * qlen; + buf->printf("%d_", qlen); // nbytes <= 11 + + for (unsigned char *p = buf->data + buf->offset, *pend = p + 2 * qlen; + p < pend; p += 2, ++q) + { + unsigned char hi = *q >> 4 & 0xF; + p[0] = (hi < 10 ? hi + '0' : hi - 10 + 'a'); + unsigned char lo = *q & 0xF; + p[1] = (lo < 10 ? lo + '0' : lo - 10 + 'a'); + } + buf->offset += 2 * qlen; } /************************ ArrayLiteralExp ************************************/ @@ -3049,7 +3049,7 @@ ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) { this->elements = elements; - this->ownedByCtfe = false; + this->ownedByCtfe = false; } ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) @@ -3075,13 +3075,13 @@ Expression *ArrayLiteralExp::semantic(Scope *sc) return this; // Run semantic() on each element - for (size_t i = 0; i < elements->dim; i++) + for (size_t i = 0; i < elements->dim; i++) { e = (Expression *)elements->data[i]; e = e->semantic(sc); elements->data[i] = (void *)e; } expandTuples(elements); - for (size_t i = 0; i < elements->dim; i++) + for (size_t i = 0; i < elements->dim; i++) { e = (Expression *)elements->data[i]; if (!e->type) @@ -3112,15 +3112,15 @@ Expression *ArrayLiteralExp::semantic(Scope *sc) if (!t0) t0 = Type::tvoid; - + type = new TypeSArray(t0, new IntegerExp(elements->dim)); type = type->semantic(loc, sc); - - /* Disallow array literals of type void being used. - */ - if (elements->dim > 0 && t0->ty == Tvoid) - error("%s of type %s has no value", toChars(), type->toChars()); - + + /* Disallow array literals of type void being used. + */ + if (elements->dim > 0 && t0->ty == Tvoid) + error("%s of type %s has no value", toChars(), type->toChars()); + return this; } @@ -3128,9 +3128,9 @@ int ArrayLiteralExp::checkSideEffect(int flag) { int f = 0; for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = elements->tdata()[i]; - f |= e->hasSideEffect(); + f |= e->hasSideEffect(); } if (flag == 0 && f == 0) Expression::checkSideEffect(0); @@ -3150,35 +3150,35 @@ int ArrayLiteralExp::canThrow() } #endif -StringExp *ArrayLiteralExp::toString() -{ - TY telem = type->nextOf()->toBasetype()->ty; - - if (telem == Tchar || telem == Twchar || telem == Tdchar || - (telem == Tvoid && (!elements || elements->dim == 0))) - { - OutBuffer buf; - if (elements) - for (int i = 0; i < elements->dim; ++i) - { - Expression *ch = elements->tdata()[i]; - if (ch->op != TOKint64) - return NULL; - buf.writedchar(ch->toInteger()); - } - buf.writebyte(0); - - char prefix = 'c'; - if (telem == Twchar) prefix = 'w'; - else if (telem == Tdchar) prefix = 'd'; - - StringExp *se = new StringExp(loc, buf.extractData(), buf.size - 1, prefix); - se->type = type; - return se; - } - return NULL; -} - +StringExp *ArrayLiteralExp::toString() +{ + TY telem = type->nextOf()->toBasetype()->ty; + + if (telem == Tchar || telem == Twchar || telem == Tdchar || + (telem == Tvoid && (!elements || elements->dim == 0))) + { + OutBuffer buf; + if (elements) + for (int i = 0; i < elements->dim; ++i) + { + Expression *ch = elements->tdata()[i]; + if (ch->op != TOKint64) + return NULL; + buf.writedchar(ch->toInteger()); + } + buf.writebyte(0); + + char prefix = 'c'; + if (telem == Twchar) prefix = 'w'; + else if (telem == Tdchar) prefix = 'd'; + + StringExp *se = new StringExp(loc, buf.extractData(), buf.size - 1, prefix); + se->type = type; + return se; + } + return NULL; +} + void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('['); @@ -3191,7 +3191,7 @@ void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) size_t dim = elements ? elements->dim : 0; buf->printf("A%zu", dim); for (size_t i = 0; i < dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = elements->tdata()[i]; e->toMangleBuffer(buf); } } @@ -3207,7 +3207,7 @@ AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, assert(keys->dim == values->dim); this->keys = keys; this->values = values; - this->ownedByCtfe = false; + this->ownedByCtfe = false; } Expression *AssocArrayLiteralExp::syntaxCopy() @@ -3217,7 +3217,7 @@ Expression *AssocArrayLiteralExp::syntaxCopy() } Expression *AssocArrayLiteralExp::semantic(Scope *sc) -{ +{ #if LOGSEMANTIC printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); #endif @@ -3251,8 +3251,8 @@ int AssocArrayLiteralExp::checkSideEffect(int flag) { Expression *key = (Expression *)keys->data[i]; Expression *value = (Expression *)values->data[i]; - f |= key->hasSideEffect(); - f |= value->hasSideEffect(); + f |= key->hasSideEffect(); + f |= value->hasSideEffect(); } if (flag == 0 && f == 0) Expression::checkSideEffect(0); @@ -3305,12 +3305,12 @@ void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) // sd( e1, e2, e3, ... ) -StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype) +StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype) : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) { this->sd = sd; this->elements = elements; - this->stype = stype; + this->stype = stype; #if IN_DMD this->sym = NULL; #endif @@ -3323,7 +3323,7 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * Expression *StructLiteralExp::syntaxCopy() { - return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype); + return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype); } Expression *StructLiteralExp::semantic(Scope *sc) @@ -3351,9 +3351,9 @@ Expression *StructLiteralExp::semantic(Scope *sc) continue; if (!e->type) - { error("%s has no value", e->toChars()); - return new ErrorExp(); - } + { error("%s has no value", e->toChars()); + return new ErrorExp(); + } e = resolveProperties(sc, e); if (i >= sd->fields.dim) { error("more initializers than fields of %s", sd->toChars()); @@ -3393,26 +3393,26 @@ Expression *StructLiteralExp::semantic(Scope *sc) else { if (v->init) - { if (v->init->isVoidInitializer()) - e = NULL; - else + { if (v->init->isVoidInitializer()) + e = NULL; + else { e = v->init->toExpression(); if (!e) { error("cannot make expression out of initializer for %s", v->toChars()); - return new ErrorExp(); + return new ErrorExp(); } else if (v->scope) - { // Do deferred semantic analysis + { // Do deferred semantic analysis Initializer *i2 = v->init->syntaxCopy(); - i2 = i2->semantic(v->scope, v->type, WANTinterpret); + i2 = i2->semantic(v->scope, v->type, WANTinterpret); e = i2->toExpression(); - // remove v->scope (see bug 3426) - // but not if gagged, for we might be called again. - if (!global.gag) + // remove v->scope (see bug 3426) + // but not if gagged, for we might be called again. + if (!global.gag) v->scope = NULL; } } - } + } else e = v->type->defaultInitLiteral(loc); offset = v->offset + v->type->size(); @@ -3420,7 +3420,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) elements->push(e); } - type = stype ? stype : sd->type; + type = stype ? stype : sd->type; return this; } @@ -3520,7 +3520,7 @@ int StructLiteralExp::checkSideEffect(int flag) if (!e) continue; - f |= e->hasSideEffect(); + f |= e->hasSideEffect(); } if (flag == 0 && f == 0) Expression::checkSideEffect(0); @@ -3658,18 +3658,18 @@ Lagain: } //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } - if (global.errors) - return new ErrorExp(); + if (global.errors) + return new ErrorExp(); } else { //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); //printf("\tparent = '%s'\n", sds->parent->toChars()); sds->semantic(sc); - - AggregateDeclaration *ad = sds->isAggregateDeclaration(); - if (ad) - return (new TypeExp(loc, ad->type))->semantic(sc); + + AggregateDeclaration *ad = sds->isAggregateDeclaration(); + if (ad) + return (new TypeExp(loc, ad->type))->semantic(sc); } type = Type::tvoid; //printf("-2ScopeExp::semantic() %s\n", toChars()); @@ -3682,14 +3682,14 @@ void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { sds->toCBuffer(buf, hgs); } - else if (hgs != NULL && hgs->ddoc) - { // fixes bug 6491 - Module *module = sds->isModule(); - if (module) - buf->writestring(module->md->toChars()); - else - buf->writestring(sds->toChars()); - } + else if (hgs != NULL && hgs->ddoc) + { // fixes bug 6491 + Module *module = sds->isModule(); + if (module) + buf->writestring(module->md->toChars()); + else + buf->writestring(sds->toChars()); + } else { buf->writestring(sds->kind()); @@ -3714,10 +3714,10 @@ void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(td->toChars()); } -int TemplateExp::rvalue() +int TemplateExp::rvalue() { error("template %s has no value", toChars()); - return 0; + return 0; } /********************** NewExp **************************************/ @@ -3747,7 +3747,7 @@ Expression *NewExp::syntaxCopy() Expression *NewExp::semantic(Scope *sc) -{ +{ Type *tb; ClassDeclaration *cdthis = NULL; @@ -3773,7 +3773,7 @@ Lagain: else { error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); - goto Lerr; + goto Lerr; } } else @@ -3788,9 +3788,9 @@ Lagain: preFunctionParameters(loc, sc, arguments); if (thisexp && tb->ty != Tclass) - { error("e.new is only for allocating nested classes, not %s", tb->toChars()); - goto Lerr; - } + { error("e.new is only for allocating nested classes, not %s", tb->toChars()); + goto Lerr; + } if (tb->ty == Tclass) { TypeFunction *tf; @@ -3798,17 +3798,17 @@ Lagain: TypeClass *tc = (TypeClass *)(tb); ClassDeclaration *cd = tc->sym->isClassDeclaration(); if (cd->isInterfaceDeclaration()) - { error("cannot create instance of interface %s", cd->toChars()); - goto Lerr; - } + { error("cannot create instance of interface %s", cd->toChars()); + goto Lerr; + } else if (cd->isAbstract()) { error("cannot create instance of abstract class %s", cd->toChars()); - for (size_t i = 0; i < cd->vtbl.dim; i++) - { FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration(); + for (size_t i = 0; i < cd->vtbl.dim; i++) + { FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration(); if (fd && fd->isAbstract()) error("function %s is abstract", fd->toChars()); } - goto Lerr; + goto Lerr; } checkDeprecated(sc, cd); if (cd->isNested()) @@ -3830,7 +3830,7 @@ Lagain: { if (!sp) { error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); - goto Lerr; + goto Lerr; } ClassDeclaration *cdp = sp->isClassDeclaration(); if (!cdp) @@ -3847,9 +3847,9 @@ Lagain: { //printf("cdthis = %s\n", cdthis->toChars()); if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) - { error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); - goto Lerr; - } + { error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); + goto Lerr; + } } #if 0 else @@ -3859,7 +3859,7 @@ Lagain: if (!sf) { error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); - goto Lerr; + goto Lerr; } printf("sf = %s\n", sf->toChars()); AggregateDeclaration *ad = sf->isThis(); @@ -3870,9 +3870,9 @@ Lagain: #endif } else if (thisexp) - { error("e.new is only for allocating nested classes"); - goto Lerr; - } + { error("e.new is only for allocating nested classes"); + goto Lerr; + } else if (fdn) { // make sure the parent context fdn of cd is reachable from sc @@ -3884,15 +3884,15 @@ Lagain: if (!sp || (fsp && fsp->isStatic())) { error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars()); - goto Lerr; + goto Lerr; } } } } else if (thisexp) - { error("e.new is only for allocating nested classes"); - goto Lerr; - } + { error("e.new is only for allocating nested classes"); + goto Lerr; + } FuncDeclaration *f = cd->ctor; if (f) @@ -3910,18 +3910,18 @@ Lagain: if (!arguments) arguments = new Expressions(); - unsigned olderrors = global.errors; + unsigned olderrors = global.errors; functionParameters(loc, sc, tf, arguments); - if (olderrors != global.errors) - return new ErrorExp(); - + if (olderrors != global.errors) + return new ErrorExp(); + } else { if (arguments && arguments->dim) - { error("no constructor for %s", cd->toChars()); - goto Lerr; - } + { error("no constructor for %s", cd->toChars()); + goto Lerr; + } } if (cd->aggNew) @@ -3937,18 +3937,18 @@ Lagain: assert(allocator); tf = (TypeFunction *)f->type; - unsigned olderrors = global.errors; + unsigned olderrors = global.errors; functionParameters(loc, sc, tf, newargs); - if (olderrors != global.errors) - return new ErrorExp(); - + if (olderrors != global.errors) + return new ErrorExp(); + } else { if (newargs && newargs->dim) - { error("no allocator for %s", cd->toChars()); - goto Lerr; - } + { error("no allocator for %s", cd->toChars()); + goto Lerr; + } } } else if (tb->ty == Tstruct) @@ -3976,10 +3976,10 @@ Lagain: assert(allocator); tf = (TypeFunction *)f->type; - unsigned olderrors = global.errors; + unsigned olderrors = global.errors; functionParameters(loc, sc, tf, newargs); - if (olderrors != global.errors) - return new ErrorExp(); + if (olderrors != global.errors) + return new ErrorExp(); e = new VarExp(loc, f); e = new CallExp(loc, e, newargs); @@ -3996,42 +3996,42 @@ Lagain: { if (tb->ty != Tarray) { error("too many arguments for array"); - goto Lerr; + goto Lerr; } - Expression *arg = arguments->tdata()[i]; + Expression *arg = arguments->tdata()[i]; arg = resolveProperties(sc, arg); arg = arg->implicitCastTo(sc, Type::tsize_t); if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) - { error("negative array index %s", arg->toChars()); - goto Lerr; - } - arguments->tdata()[i] = arg; + { error("negative array index %s", arg->toChars()); + goto Lerr; + } + arguments->tdata()[i] = arg; tb = ((TypeDArray *)tb)->next->toBasetype(); } } else if (tb->isscalar()) { if (arguments && arguments->dim) - { error("no constructor for %s", type->toChars()); - goto Lerr; - } + { error("no constructor for %s", type->toChars()); + goto Lerr; + } type = type->pointerTo(); } else { error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); - goto Lerr; + goto Lerr; } //printf("NewExp: '%s'\n", toChars()); //printf("NewExp:type '%s'\n", type->toChars()); return this; - -Lerr: - return new ErrorExp(); + +Lerr: + return new ErrorExp(); } int NewExp::checkSideEffect(int flag) @@ -4040,29 +4040,29 @@ int NewExp::checkSideEffect(int flag) } #if DMDV2 -int NewExp::canThrow(bool mustNotThrow) +int NewExp::canThrow(bool mustNotThrow) { - if (arrayExpressionCanThrow(newargs, mustNotThrow) || - arrayExpressionCanThrow(arguments, mustNotThrow)) - return 1; - if (member) - { - // See if constructor call can throw - Type *t = member->type->toBasetype(); - if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow) - { - if (mustNotThrow) - error("constructor %s is not nothrow", member->toChars()); - return 1; - } - } - // regard storage allocation failures as not recoverable - return 0; + if (arrayExpressionCanThrow(newargs, mustNotThrow) || + arrayExpressionCanThrow(arguments, mustNotThrow)) + return 1; + if (member) + { + // See if constructor call can throw + Type *t = member->type->toBasetype(); + if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow) + { + if (mustNotThrow) + error("constructor %s is not nothrow", member->toChars()); + return 1; + } + } + // regard storage allocation failures as not recoverable + return 0; } #endif void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ +{ if (thisexp) { expToCBuffer(buf, hgs, thisexp, PREC_primary); buf->writeByte('.'); @@ -4135,7 +4135,7 @@ int NewAnonClassExp::canThrow() #endif void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ +{ if (thisexp) { expToCBuffer(buf, hgs, thisexp, PREC_primary); buf->writeByte('.'); @@ -4254,7 +4254,7 @@ int VarExp::equals(Object *o) } Expression *VarExp::semantic(Scope *sc) -{ +{ #if LOGSEMANTIC printf("VarExp::semantic(%s)\n", toChars()); #endif @@ -4468,7 +4468,7 @@ TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) exps->reserve(tup->objects->dim); for (size_t i = 0; i < tup->objects->dim; i++) - { Object *o = tup->objects->tdata()[i]; + { Object *o = tup->objects->tdata()[i]; if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; @@ -4495,7 +4495,7 @@ TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) } int TupleExp::equals(Object *o) -{ +{ if (this == o) return 1; if (((Expression *)o)->op == TOKtuple) @@ -4504,8 +4504,8 @@ int TupleExp::equals(Object *o) if (exps->dim != te->exps->dim) return 0; for (size_t i = 0; i < exps->dim; i++) - { Expression *e1 = (*exps)[i]; - Expression *e2 = (*te->exps)[i]; + { Expression *e1 = (*exps)[i]; + Expression *e2 = (*te->exps)[i]; if (!e1->equals(e2)) return 0; @@ -4530,14 +4530,14 @@ Expression *TupleExp::semantic(Scope *sc) // Run semantic() on each argument for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; + { Expression *e = (*exps)[i]; e = e->semantic(sc); if (!e->type) { error("%s has no value", e->toChars()); - e = new ErrorExp(); + e = new ErrorExp(); } - (*exps)[i] = e; + (*exps)[i] = e; } expandTuples(exps); @@ -4557,10 +4557,10 @@ void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) int TupleExp::checkSideEffect(int flag) { int f = 0; - for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; + for (size_t i = 0; i < exps->dim; i++) + { Expression *e = (*exps)[i]; - f |= e->hasSideEffect(); + f |= e->hasSideEffect(); } if (flag == 0 && f == 0) Expression::checkSideEffect(0); @@ -4568,16 +4568,16 @@ int TupleExp::checkSideEffect(int flag) } #if DMDV2 -int TupleExp::canThrow(bool mustNotThrow) +int TupleExp::canThrow(bool mustNotThrow) { - return arrayExpressionCanThrow(exps, mustNotThrow); + return arrayExpressionCanThrow(exps, mustNotThrow); } #endif void TupleExp::checkEscape() { for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; + { Expression *e = (*exps)[i]; e->checkEscape(); } } @@ -4602,28 +4602,28 @@ Expression *FuncExp::semantic(Scope *sc) #endif if (!type) { - unsigned olderrors = global.errors; + unsigned olderrors = global.errors; fd->semantic(sc); fd->parent = sc->parent; - if (olderrors != global.errors) + if (olderrors != global.errors) { } else { fd->semantic2(sc); - if ( (olderrors == global.errors) || + if ( (olderrors == global.errors) || // need to infer return type (fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())) { fd->semantic3(sc); - if ( (olderrors == global.errors) && global.params.useInline) + if ( (olderrors == global.errors) && global.params.useInline) fd->inlineScan(); } } // need to infer return type - if ((olderrors != global.errors) && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()) + if ((olderrors != global.errors) && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()) ((TypeFunction *)fd->type)->next = Type::terror; // Type is a "delegate to" or "pointer to" the function literal @@ -4674,8 +4674,8 @@ Expression *DeclarationExp::semantic(Scope *sc) printf("DeclarationExp::semantic() %s\n", toChars()); #endif - unsigned olderrors = global.errors; - + unsigned olderrors = global.errors; + /* This is here to support extern(linkage) declaration, * where the extern(linkage) winds up being an AttribDeclaration * wrapper. @@ -4686,7 +4686,7 @@ Expression *DeclarationExp::semantic(Scope *sc) if (ad) { if (ad->decl && ad->decl->dim == 1) - s = ad->decl->tdata()[0]; + s = ad->decl->tdata()[0]; } if (s->isVarDeclaration()) @@ -4741,14 +4741,14 @@ Expression *DeclarationExp::semantic(Scope *sc) sc2->pop(); s->parent = sc->parent; } - if (global.errors == olderrors) + if (global.errors == olderrors) { declaration->semantic2(sc); - if (global.errors == olderrors) + if (global.errors == olderrors) { declaration->semantic3(sc); - if ((global.errors == olderrors) && global.params.useInline) + if ((global.errors == olderrors) && global.params.useInline) declaration->inlineScan(); } } @@ -4845,7 +4845,7 @@ void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(ident->toChars()); if (args) { - for (size_t i = 0; i < args->dim; i++) + for (size_t i = 0; i < args->dim; i++) { buf->writeByte(','); Object *oarg = (Object *)args->data[i]; @@ -4916,9 +4916,9 @@ Expression *IsExp::semantic(Scope *sc) if (id && !(sc->flags & SCOPEstaticif)) error("can only declare type aliases within static if conditionals"); - unsigned errors_save = global.startGagging(); + unsigned errors_save = global.startGagging(); targ = targ->semantic(loc, sc); - if (global.endGagging(errors_save)) // if any errors happened + if (global.endGagging(errors_save)) // if any errors happened { // then condition is false goto Lno; } @@ -5065,10 +5065,10 @@ Expression *IsExp::semantic(Scope *sc) parameters.data[0] = (void *)&tp; Objects dedtypes; - dedtypes.setDim(parameters.dim); - dedtypes.zero(); + dedtypes.setDim(parameters.dim); + dedtypes.zero(); - MATCH m = targ->deduceType(sc, tspec, ¶meters, &dedtypes); + MATCH m = targ->deduceType(sc, tspec, ¶meters, &dedtypes); if (m == MATCHnomatch || (m != MATCHexact && tok == TOKequal)) { @@ -5087,8 +5087,8 @@ Expression *IsExp::semantic(Scope *sc) /* Declare trailing parameters */ - for (size_t i = 1; i < parameters->dim; i++) - { TemplateParameter *tp = (*parameters)[i]; + for (size_t i = 1; i < parameters->dim; i++) + { TemplateParameter *tp = (*parameters)[i]; Declaration *s = NULL; m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s); @@ -5118,8 +5118,8 @@ Expression *IsExp::semantic(Scope *sc) * is(targ : tspec) */ tspec = tspec->semantic(loc, sc); - //printf("targ = %s, %s\n", targ->toChars(), targ->deco); - //printf("tspec = %s, %s\n", tspec->toChars(), tspec->deco); + //printf("targ = %s, %s\n", targ->toChars(), targ->deco); + //printf("tspec = %s, %s\n", tspec->toChars(), tspec->deco); if (tok == TOKcolon) { if (targ->implicitConvTo(tspec)) goto Lyes; @@ -5137,18 +5137,18 @@ Expression *IsExp::semantic(Scope *sc) Lyes: if (id) { - Dsymbol *s; - Tuple *tup = isTuple(tded); - if (tup) - s = new TupleDeclaration(loc, id, &(tup->objects)); - else - s = new AliasDeclaration(loc, id, tded); + Dsymbol *s; + Tuple *tup = isTuple(tded); + if (tup) + s = new TupleDeclaration(loc, id, &(tup->objects)); + else + s = new AliasDeclaration(loc, id, tded); s->semantic(sc); - /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there. - * More investigation is needed. - */ - if (!tup && !sc->insert(s)) - error("declaration %s is already defined", s->toChars()); + /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there. + * More investigation is needed. + */ + if (!tup && !sc->insert(s)) + error("declaration %s is already defined", s->toChars()); if (sc->sd) s->addMember(sc, sc->sd, 1); } @@ -5177,7 +5177,7 @@ void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) #if DMDV2 if (parameters) { // First parameter is already output, so start with second - for (size_t i = 1; i < parameters->dim; i++) + for (size_t i = 1; i < parameters->dim; i++) { buf->writeByte(','); TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; @@ -5470,16 +5470,16 @@ Expression *CompileExp::semantic(Scope *sc) #endif UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); - if (e1->op == TOKerror) - return e1; + if (e1->op == TOKerror) + return e1; if (!e1->type->isString()) { error("argument to mixin must be a string type, not %s\n", e1->type->toChars()); return new ErrorExp(); } e1 = e1->optimize(WANTvalue | WANTinterpret); - StringExp *se = e1->toString(); - if (!se) + StringExp *se = e1->toString(); + if (!se) { error("argument to mixin must be a string, not (%s)", e1->toChars()); return new ErrorExp(); } @@ -5517,7 +5517,7 @@ Expression *FileExp::semantic(Scope *sc) #endif UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); - e1 = e1->optimize(WANTvalue | WANTinterpret); + e1 = e1->optimize(WANTvalue | WANTinterpret); if (e1->op != TOKstring) { error("file name argument must be a string, not (%s)", e1->toChars()); goto Lerror; @@ -5536,7 +5536,7 @@ Expression *FileExp::semantic(Scope *sc) * http://cwe.mitre.org/data/definitions/22.html */ - name = FileName::safeSearchPath((Strings *)global.filePath, name); + name = FileName::safeSearchPath((Strings *)global.filePath, name); if (!name) { error("file %s cannot be found or not in a path specified with -J", se->toChars()); goto Lerror; @@ -5559,7 +5559,7 @@ Expression *FileExp::semantic(Scope *sc) return se->semantic(sc); Lerror: - return new ErrorExp(); + return new ErrorExp(); } void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -5719,22 +5719,22 @@ Expression *DotIdExp::semantic(Scope *sc) UnaExp::semantic(sc); - if (ident == Id::mangleof) - { // symbol.mangleof - Dsymbol *ds; - switch (e1->op) - { - case TOKimport: ds = ((ScopeExp *)e1)->sds; goto L1; - case TOKvar: ds = ((VarExp *)e1)->var; goto L1; - case TOKdotvar: ds = ((DotVarExp *)e1)->var; goto L1; - L1: - char* s = ds->mangle(); - e = new StringExp(loc, s, strlen(s), 'c'); - e = e->semantic(sc); - return e; - } - } - + if (ident == Id::mangleof) + { // symbol.mangleof + Dsymbol *ds; + switch (e1->op) + { + case TOKimport: ds = ((ScopeExp *)e1)->sds; goto L1; + case TOKvar: ds = ((VarExp *)e1)->var; goto L1; + case TOKdotvar: ds = ((DotVarExp *)e1)->var; goto L1; + L1: + char* s = ds->mangle(); + e = new StringExp(loc, s, strlen(s), 'c'); + e = e->semantic(sc); + return e; + } + } + if (e1->op == TOKdotexp) { DotExp *de = (DotExp *)e1; @@ -5743,7 +5743,7 @@ Expression *DotIdExp::semantic(Scope *sc) } else { - if (e1->op != TOKtype) + if (e1->op != TOKtype) e1 = resolveProperties(sc, e1); eleft = NULL; eright = e1; @@ -5755,7 +5755,7 @@ Expression *DotIdExp::semantic(Scope *sc) TupleExp *te = (TupleExp *)e1; Expressions *exps = new Expressions(); exps->setDim(te->exps->dim); - for (size_t i = 0; i < exps->dim; i++) + for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)te->exps->data[i]; e = e->semantic(sc); e = new DotIdExp(e->loc, e, Id::offsetof); @@ -5798,12 +5798,12 @@ Expression *DotIdExp::semantic(Scope *sc) (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0); if (s) { - /* Check for access before resolving aliases because public - * aliases to private symbols are public. - */ - if (Declaration *d = s->isDeclaration()) - accessCheck(loc, sc, 0, d); - + /* Check for access before resolving aliases because public + * aliases to private symbols are public. + */ + if (Declaration *d = s->isDeclaration()) + accessCheck(loc, sc, 0, d); + s = s->toAlias(); checkDeprecated(sc, s); @@ -5971,10 +5971,10 @@ Expression *DotIdExp::semantic(Scope *sc) * as: * .ident(e1) */ - unsigned errors = global.startGagging(); + unsigned errors = global.startGagging(); Type *t1 = e1->type; e = e1->type->dotExp(sc, e1, ident); - if (global.endGagging(errors)) // if failed to find the property + if (global.endGagging(errors)) // if failed to find the property { e1->type = t1; // kludge to restore type e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident); @@ -6142,7 +6142,7 @@ Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) if (fd && ((fd->isCtorDeclaration() && var->storage_class & STCfield) || (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && - fd->toParent2() == var->toParent() && + fd->toParent2() == var->toParent() && e1->op == TOKthis ) { @@ -6222,8 +6222,8 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc) Expression *e = new DotIdExp(loc, e1, ti->name); L1: e = e->semantic(sc); - if (e->op == TOKerror) - return e; + if (e->op == TOKerror) + return e; if (e->op == TOKdottd) { if (global.errors) @@ -6232,14 +6232,14 @@ L1: TemplateDeclaration *td = dte->td; eleft = dte->e1; ti->tempdecl = td; -#if DMDV2 - if (ti->needsTypeInference(sc)) - { - e = new CallExp(loc, this); - return e->semantic(sc); - } - else -#endif +#if DMDV2 + if (ti->needsTypeInference(sc)) + { + e = new CallExp(loc, this); + return e->semantic(sc); + } + else +#endif ti->semantic(sc); if (!ti->inst) // if template failed to expand return new ErrorExp(); @@ -6630,9 +6630,9 @@ Expression *CallExp::semantic(Scope *sc) * If not, go with partial explicit specialization. */ ti->semanticTiargs(sc); - unsigned errors = global.startGagging(); + unsigned errors = global.startGagging(); ti->semantic(sc); - if (global.endGagging(errors)) + if (global.endGagging(errors)) { /* Didn't work, go with partial explicit specialization */ @@ -6655,9 +6655,9 @@ Expression *CallExp::semantic(Scope *sc) */ ti->semanticTiargs(sc); Expression *etmp; - unsigned errors = global.startGagging(); + unsigned errors = global.startGagging(); etmp = e1->semantic(sc); - if (global.endGagging(errors)) + if (global.endGagging(errors)) { targsi = ti->tiargs; e1 = new DotIdExp(loc, se->e1, ti->name); @@ -6678,15 +6678,15 @@ Lagain: } else { - static int nest; - if (++nest > 500) - { - error("recursive evaluation of %s", toChars()); - --nest; - return new ErrorExp(); - } + static int nest; + if (++nest > 500) + { + error("recursive evaluation of %s", toChars()); + --nest; + return new ErrorExp(); + } UnaExp::semantic(sc); - --nest; + --nest; /* Look for e1 being a lazy parameter */ @@ -6707,14 +6707,14 @@ Lagain: e1 = new DsymbolExp(loc, se->sds); e1 = e1->semantic(sc); } -#if DMDV2 - else if (e1->op == TOKsymoff && ((SymOffExp *)e1)->hasOverloads) - { - SymOffExp *se = (SymOffExp *)e1; - e1 = new VarExp(se->loc, se->var, 1); - e1 = e1->semantic(sc); - } -#endif +#if DMDV2 + else if (e1->op == TOKsymoff && ((SymOffExp *)e1)->hasOverloads) + { + SymOffExp *se = (SymOffExp *)e1; + e1 = new VarExp(se->loc, se->var, 1); + e1 = e1->semantic(sc); + } +#endif #if 1 // patch for #540 by Oskar Linde else if (e1->op == TOKdotexp) { @@ -6842,7 +6842,7 @@ Lagain: arguments = new Expressions(); f = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); if (!f) - return new ErrorExp(); + return new ErrorExp(); ad = td->toParent()->isAggregateDeclaration(); } if (f->needThis()) @@ -6859,36 +6859,36 @@ Lagain: ) { error("cannot call public/export function %s from invariant", f->toChars()); - return new ErrorExp(); + return new ErrorExp(); } checkDeprecated(sc, f); #if DMDV2 checkPurity(sc, f); - checkSafety(sc, f); + checkSafety(sc, f); #endif accessCheck(loc, sc, ue->e1, f); if (!f->needThis()) { VarExp *ve = new VarExp(loc, f); - if ((ue->e1)->op == TOKtype) // just a FQN - e1 = ve; - else // things like (new Foo).bar() - e1 = new CommaExp(loc, ue->e1, ve); + if ((ue->e1)->op == TOKtype) // just a FQN + e1 = ve; + else // things like (new Foo).bar() + e1 = new CommaExp(loc, ue->e1, ve); e1->type = f->type; } else { if (e1->op == TOKdotvar) - { + { dve->var = f; - e1->type = f->type; - } + e1->type = f->type; + } else - { + { e1 = new DotVarExp(loc, dte->e1, f); - e1 = e1->semantic(sc); - } + e1 = e1->semantic(sc); + } // See if we need to adjust the 'this' pointer AggregateDeclaration *ad = f->isThis(); @@ -6912,14 +6912,14 @@ Lagain: if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) { error("super class constructor call must be in a constructor"); - return new ErrorExp(); + return new ErrorExp(); } else { f = cd->baseClass->ctor; if (!f) { error("no super class constructor for %s", cd->baseClass->toChars()); - return new ErrorExp(); + return new ErrorExp(); } else { @@ -6937,11 +6937,11 @@ Lagain: } f = f->overloadResolve(loc, NULL, arguments, sc->module); - accessCheck(loc, sc, NULL, f); + accessCheck(loc, sc, NULL, f); checkDeprecated(sc, f); #if DMDV2 checkPurity(sc, f); - checkSafety(sc, f); + checkSafety(sc, f); #endif e1 = new DotVarExp(e1->loc, e1, f); e1 = e1->semantic(sc); @@ -6959,7 +6959,7 @@ Lagain: if (!cd || !sc->func->isCtorDeclaration()) { error("class constructor call must be in a constructor"); - return new ErrorExp(); + return new ErrorExp(); } else { @@ -6981,7 +6981,7 @@ Lagain: checkDeprecated(sc, f); #if DMDV2 checkPurity(sc, f); - checkSafety(sc, f); + checkSafety(sc, f); #endif e1 = new DotVarExp(e1->loc, e1, f); e1 = e1->semantic(sc); @@ -6990,15 +6990,15 @@ Lagain: // BUG: this should really be done by checking the static // call graph if (f == sc->func) - { error("cyclic constructor call"); - return new ErrorExp(); - } + { error("cyclic constructor call"); + return new ErrorExp(); + } } } else if (!t1) { error("function expected before (), not '%s'", e1->toChars()); - return new ErrorExp(); + return new ErrorExp(); } else if (t1->ty != Tfunction) { @@ -7009,8 +7009,8 @@ Lagain: goto Lcheckargs; } else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) - { - Expression *e = new PtrExp(loc, e1); + { + Expression *e = new PtrExp(loc, e1); t1 = ((TypePointer *)t1)->next; e->type = t1; e1 = e; @@ -7020,8 +7020,8 @@ Lagain: TemplateExp *te = (TemplateExp *)e1; f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); if (!f) - { - return new ErrorExp(); + { + return new ErrorExp(); } if (f->needThis() && hasThis(sc)) { @@ -7037,7 +7037,7 @@ Lagain: } else { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); - return new ErrorExp(); + return new ErrorExp(); } } else if (e1->op == TOKvar) @@ -7075,7 +7075,7 @@ Lagain: checkDeprecated(sc, f); #if DMDV2 checkPurity(sc, f); - checkSafety(sc, f); + checkSafety(sc, f); #endif if (f->needThis() && hasThis(sc)) @@ -7102,16 +7102,16 @@ Lcheckargs: if (!arguments) arguments = new Expressions(); - int olderrors = global.errors; + int olderrors = global.errors; functionParameters(loc, sc, tf, arguments); - if (olderrors != global.errors) - return new ErrorExp(); + if (olderrors != global.errors) + return new ErrorExp(); - if (!type) - { - error("forward reference to inferred return type of function call %s", toChars()); - return new ErrorExp(); - } + if (!type) + { + error("forward reference to inferred return type of function call %s", toChars()); + return new ErrorExp(); + } if (f && f->tintro) { @@ -7132,43 +7132,43 @@ Lcheckargs: int CallExp::checkSideEffect(int flag) { #if DMDV2 - int result = 1; + int result = 1; - /* Calling a function or delegate that is pure nothrow - * has no side effects. - */ - if (e1->type) - { - Type *t = e1->type->toBasetype(); - if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak && - ((TypeFunction *)t)->isnothrow) - || - (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak && - ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) - ) - { - result = 0; - //if (flag == 0) - //warning("pure nothrow function %s has no effect", e1->toChars()); - } - else - result = 1; - } - - result |= e1->checkSideEffect(1); + /* Calling a function or delegate that is pure nothrow + * has no side effects. + */ + if (e1->type) + { + Type *t = e1->type->toBasetype(); + if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak && + ((TypeFunction *)t)->isnothrow) + || + (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak && + ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) + ) + { + result = 0; + //if (flag == 0) + //warning("pure nothrow function %s has no effect", e1->toChars()); + } + else + result = 1; + } + + result |= e1->checkSideEffect(1); /* If any of the arguments have side effects, this expression does */ for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = arguments->tdata()[i]; - result |= e->checkSideEffect(1); + result |= e->checkSideEffect(1); } - return result; -#else + return result; +#else return 1; -#endif +#endif } #if DMDV2 @@ -7274,11 +7274,11 @@ Expression *AddrExp::semantic(Scope *sc) { m = sc->module; UnaExp::semantic(sc); - if (e1->type == Type::terror) - return new ErrorExp(); + if (e1->type == Type::terror) + return new ErrorExp(); e1 = e1->toLvalue(sc, NULL); - if (e1->op == TOKerror) - return e1; + if (e1->op == TOKerror) + return e1; if (!e1->type) { error("cannot take address of %s", e1->toChars()); @@ -7324,8 +7324,8 @@ Expression *AddrExp::semantic(Scope *sc) } if (f && f->isNested()) - { - Expression *e = new DelegateExp(loc, e1, f); + { + Expression *e = new DelegateExp(loc, e1, f); e = e->semantic(sc); return e; } @@ -7375,14 +7375,14 @@ Expression *PtrExp::semantic(Scope *sc) switch (tb->ty) { case Tpointer: - type = ((TypePointer *)tb)->next; + type = ((TypePointer *)tb)->next; break; case Tsarray: case Tarray: - if (!global.params.useDeprecated) - error("using * on an array is deprecated; use *(%s).ptr instead", e1->toChars()); - type = ((TypeArray *)tb)->next; + if (!global.params.useDeprecated) + error("using * on an array is deprecated; use *(%s).ptr instead", e1->toChars()); + type = ((TypeArray *)tb)->next; e1 = e1->castTo(sc, type->pointerTo()); break; @@ -7391,8 +7391,8 @@ Expression *PtrExp::semantic(Scope *sc) case Terror: return new ErrorExp(); } - if (!rvalue()) - return new ErrorExp(); + if (!rvalue()) + return new ErrorExp(); } return this; } @@ -7580,8 +7580,8 @@ Expression *DeleteExp::semantic(Scope *sc) UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); e1 = e1->toLvalue(sc, NULL); - if (e1->op == TOKerror) - return e1; + if (e1->op == TOKerror) + return e1; type = Type::tvoid; tb = e1->type->toBasetype(); @@ -7629,7 +7629,7 @@ Expression *DeleteExp::semantic(Scope *sc) break; } error("cannot delete type %s", e1->type->toChars()); - return new ErrorExp(); + return new ErrorExp(); } if (e1->op == TOKindex) @@ -7653,7 +7653,7 @@ int DeleteExp::checkSideEffect(int flag) Expression *DeleteExp::checkToBoolean() { error("delete does not give a boolean result"); - return new ErrorExp(); + return new ErrorExp(); } void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -7738,9 +7738,9 @@ Expression *CastExp::semantic(Scope *sc) } // Struct casts are possible only when the sizes match - // Same with static array -> static array - if (tob->ty == Tstruct || t1b->ty == Tstruct || - (tob->ty == Tsarray && t1b->ty == Tsarray)) + // Same with static array -> static array + if (tob->ty == Tstruct || t1b->ty == Tstruct || + (tob->ty == Tsarray && t1b->ty == Tsarray)) { size_t fromsize = t1b->size(loc); size_t tosize = tob->size(loc); @@ -7902,34 +7902,34 @@ Expression *SliceExp::semantic(Scope *sc) else goto Lerror; - { - Scope *sc2 = sc; + { + Scope *sc2 = sc; if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) { sym = new ArrayScopeSymbol(this); sym->loc = loc; sym->parent = sc->scopesym; - sc2 = sc->push(sym); + sc2 = sc->push(sym); } if (lwr) - { lwr = lwr->semantic(sc2); - lwr = resolveProperties(sc2, lwr); - lwr = lwr->implicitCastTo(sc2, Type::tsize_t); + { lwr = lwr->semantic(sc2); + lwr = resolveProperties(sc2, lwr); + lwr = lwr->implicitCastTo(sc2, Type::tsize_t); if (lwr->type == Type::terror) goto Lerr; } if (upr) - { upr = upr->semantic(sc2); - upr = resolveProperties(sc2, upr); - upr = upr->implicitCastTo(sc2, Type::tsize_t); - if (upr->type == Type::terror) + { upr = upr->semantic(sc2); + upr = resolveProperties(sc2, upr); + upr = upr->implicitCastTo(sc2, Type::tsize_t); + if (upr->type == Type::terror) goto Lerr; } - if (sc2 != sc) - sc2->pop(); - } + if (sc2 != sc) + sc2->pop(); + } if (t->ty == Ttuple) { @@ -8035,11 +8035,11 @@ Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) return this; } -int SliceExp::isBool(int result) -{ - return e1->isBool(result); -} - +int SliceExp::isBool(int result) +{ + return e1->isBool(result); +} + void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { expToCBuffer(buf, hgs, e1, precedence[op]); @@ -8059,13 +8059,13 @@ void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writeByte(']'); } -int SliceExp::canThrow() -{ - return UnaExp::canThrow() - || (lwr != NULL && lwr->canThrow()) - || (upr != NULL && upr->canThrow()); -} - +int SliceExp::canThrow() +{ + return UnaExp::canThrow() + || (lwr != NULL && lwr->canThrow()) + || (upr != NULL && upr->canThrow()); +} + /********************** ArrayLength **************************************/ ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) @@ -8274,7 +8274,7 @@ int CommaExp::isBool(int result) int CommaExp::checkSideEffect(int flag) { if (flag == 2) - return e1->hasSideEffect() || e2->hasSideEffect(); + return e1->hasSideEffect() || e2->hasSideEffect(); else { // Don't check e1 until we cast(void) the a,b code generation @@ -8329,8 +8329,8 @@ Expression *IndexExp::semantic(Scope *sc) error("%s has no value", e2->toChars()); goto Lerr; } - if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix - e2 = (*((TupleExp *)e2)->exps)[0]; + if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix + e2 = (*((TupleExp *)e2)->exps)[0]; e2 = resolveProperties(sc, e2); if (e2->type == Type::terror) goto Lerr; @@ -8651,7 +8651,7 @@ Expression *AssignExp::semantic(Scope *sc) { Expressions *exps = new Expressions; exps->setDim(dim); - for (size_t i = 0; i < dim; i++) + for (size_t i = 0; i < dim; i++) { Expression *ex1 = (Expression *)tup1->exps->data[i]; Expression *ex2 = (Expression *)tup2->exps->data[i]; exps->data[i] = (void *) new AssignExp(loc, ex1, ex2); @@ -8693,8 +8693,8 @@ Expression *AssignExp::semantic(Scope *sc) } } - if (!e2->rvalue()) - return new ErrorExp(); + if (!e2->rvalue()) + return new ErrorExp(); if (e1->op == TOKarraylength) { @@ -8737,22 +8737,22 @@ Expression *AssignExp::semantic(Scope *sc) e2->op == TOKmul || e2->op == TOKdiv || e2->op == TOKmod || e2->op == TOKxor || e2->op == TOKand || e2->op == TOKor || -#if DMDV2 - e2->op == TOKpow || -#endif +#if DMDV2 + e2->op == TOKpow || +#endif e2->op == TOKtilde || e2->op == TOKneg)) { type = e1->type; return arrayOp(sc); } - if (e1->op == TOKvar && - (((VarExp *)e1)->var->storage_class & STCscope) && - op == TOKassign) - { - error("cannot rebind scope variables"); - } - + if (e1->op == TOKvar && + (((VarExp *)e1)->var->storage_class & STCscope) && + op == TOKassign) + { + error("cannot rebind scope variables"); + } + type = e1->type; assert(type); return this; @@ -8764,8 +8764,8 @@ Expression *AssignExp::checkToBoolean() // if (a = b) ... // are usually mistakes. - error("assignment cannot be used as a condition, perhaps == was meant?"); - return new ErrorExp(); + error("assignment cannot be used as a condition, perhaps == was meant?"); + return new ErrorExp(); } /************************************************************/ @@ -8972,8 +8972,8 @@ Expression *CatAssignExp::semantic(Scope *sc) Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); - if (!e2->rvalue()) - return new ErrorExp(); + if (!e2->rvalue()) + return new ErrorExp(); Type *tb1next = tb1->nextOf(); @@ -8994,7 +8994,7 @@ Expression *CatAssignExp::semantic(Scope *sc) else if (tb1->ty == Tarray && (tb1next->ty == Tchar || tb1next->ty == Twchar) && - e2->type->ty != tb1next->ty && + e2->type->ty != tb1next->ty && e2->implicitConvTo(Type::tdchar) ) { // Append dchar to char[] or wchar[] @@ -9456,15 +9456,15 @@ Expression *MinExp::semantic(Scope *sc) else if (t2->isintegral()) e = scaleFactor(sc); else - { error("can't subtract %s from pointer", t2->toChars()); - return new ErrorExp(); + { error("can't subtract %s from pointer", t2->toChars()); + return new ErrorExp(); } } else if (t2->ty == Tpointer) { type = e2->type; error("can't subtract pointer from %s", e1->type->toChars()); - return new ErrorExp(); + return new ErrorExp(); } else { @@ -9978,19 +9978,19 @@ Expression *OrOrExp::semantic(Scope *sc) if (e2->type->ty == Tvoid) type = Type::tvoid; - else - { - e2 = e2->checkToBoolean(); - type = Type::tboolean; - } + else + { + e2 = e2->checkToBoolean(); + type = Type::tboolean; + } if (e2->op == TOKtype || e2->op == TOKimport) - { error("%s is not an expression", e2->toChars()); - return new ErrorExp(); - } - if (e1->op == TOKerror) - return e1; - if (e2->op == TOKerror) - return e2; + { error("%s is not an expression", e2->toChars()); + return new ErrorExp(); + } + if (e1->op == TOKerror) + return e1; + if (e2->op == TOKerror) + return e2; return this; } @@ -10009,7 +10009,7 @@ int OrOrExp::checkSideEffect(int flag) { if (flag == 2) { - return e1->hasSideEffect() || e2->hasSideEffect(); + return e1->hasSideEffect() || e2->hasSideEffect(); } else { e1->checkSideEffect(1); @@ -10053,19 +10053,19 @@ Expression *AndAndExp::semantic(Scope *sc) if (e2->type->ty == Tvoid) type = Type::tvoid; - else - { - e2 = e2->checkToBoolean(); - type = Type::tboolean; - } + else + { + e2 = e2->checkToBoolean(); + type = Type::tboolean; + } if (e2->op == TOKtype || e2->op == TOKimport) - { error("%s is not an expression", e2->toChars()); - return new ErrorExp(); - } - if (e1->op == TOKerror) - return e1; - if (e2->op == TOKerror) - return e2; + { error("%s is not an expression", e2->toChars()); + return new ErrorExp(); + } + if (e1->op == TOKerror) + return e1; + if (e2->op == TOKerror) + return e2; return this; } @@ -10084,7 +10084,7 @@ int AndAndExp::checkSideEffect(int flag) { if (flag == 2) { - return e1->hasSideEffect() || e2->hasSideEffect(); + return e1->hasSideEffect() || e2->hasSideEffect(); } else { @@ -10542,9 +10542,9 @@ int CondExp::checkSideEffect(int flag) { if (flag == 2) { - return econd->hasSideEffect() || - e1->hasSideEffect() || - e2->hasSideEffect(); + return econd->hasSideEffect() || + e1->hasSideEffect() || + e2->hasSideEffect(); } else { diff --git a/dmd/expression.h b/dmd/expression.h index 74933f1e..ffc095ca 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -44,8 +44,8 @@ struct BinExp; struct AssignExp; struct InterState; struct OverloadSet; -struct Initializer; -struct StringExp; +struct Initializer; +struct StringExp; enum TOK; @@ -74,8 +74,8 @@ namespace llvm { void initPrecedence(); -typedef int (*apply_fp_t)(Expression *, void *); - +typedef int (*apply_fp_t)(Expression *, void *); + Expression *resolveProperties(Scope *sc, Expression *e); void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d); Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid); @@ -86,17 +86,17 @@ void expandTuples(Expressions *exps); FuncDeclaration *hasThis(Scope *sc); Expression *fromConstInitializer(int result, Expression *e); int arrayExpressionCanThrow(Expressions *exps); -TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); - -/* Interpreter: what form of return value expression is required? - */ -enum CtfeGoal -{ ctfeNeedRvalue, // Must return an Rvalue - ctfeNeedLvalue, // Must return an Lvalue - ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue - ctfeNeedLvalueRef,// Must return a reference to an Lvalue (for ref types) - ctfeNeedNothing // The return value is not required -}; +TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); + +/* Interpreter: what form of return value expression is required? + */ +enum CtfeGoal +{ ctfeNeedRvalue, // Must return an Rvalue + ctfeNeedLvalue, // Must return an Lvalue + ctfeNeedAnyValue, // Can return either an Rvalue or an Lvalue + ctfeNeedLvalueRef,// Must return a reference to an Lvalue (for ref types) + ctfeNeedNothing // The return value is not required +}; struct IntRange { uinteger_t imin; @@ -113,9 +113,9 @@ struct Expression : Object Expression(Loc loc, enum TOK op, int size); Expression *copy(); virtual Expression *syntaxCopy(); - virtual int apply(apply_fp_t fp, void *param); + virtual int apply(apply_fp_t fp, void *param); virtual Expression *semantic(Scope *sc); - Expression *trySemantic(Scope *sc); + Expression *trySemantic(Scope *sc); int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression() @@ -124,7 +124,7 @@ struct Expression : Object virtual void dump(int indent); void error(const char *format, ...) IS_PRINTF(2); void warning(const char *format, ...) IS_PRINTF(2); - virtual int rvalue(); + virtual int rvalue(); static Expression *combine(Expression *e1, Expression *e2); static Expressions *arraySyntaxCopy(Expressions *exps); @@ -134,7 +134,7 @@ struct Expression : Object virtual real_t toReal(); virtual real_t toImaginary(); virtual complex_t toComplex(); - virtual StringExp *toString(); + virtual StringExp *toString(); virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); virtual void toMangleBuffer(OutBuffer *buf); virtual Expression *toLvalue(Scope *sc, Expression *e); @@ -160,21 +160,21 @@ struct Expression : Object virtual Expression *optimize(int result); #define WANTflags 1 #define WANTvalue 2 - // A compile-time result is required. Give an error if not possible + // A compile-time result is required. Give an error if not possible #define WANTinterpret 4 - // Same as WANTvalue, but also expand variables as far as possible - #define WANTexpand 8 + // Same as WANTvalue, but also expand variables as far as possible + #define WANTexpand 8 - virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); virtual int isConst(); virtual int isBool(int result); virtual int isBit(); - bool hasSideEffect(); + bool hasSideEffect(); virtual int checkSideEffect(int flag); virtual int canThrow(); - virtual int inlineCost3(InlineCostState *ics); + virtual int inlineCost3(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); virtual Expression *inlineScan(InlineScanState *iss); Expression *inlineCopy(Scope *sc); @@ -215,7 +215,7 @@ struct IntegerExp : Expression IntegerExp(dinteger_t value); int equals(Object *o); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); char *toChars(); void dump(int indent); dinteger_t toInteger(); @@ -242,7 +242,7 @@ struct ErrorExp : IntegerExp ErrorExp(); Expression *implicitCastTo(Scope *sc, Type *t); - Expression *castTo(Scope *sc, Type *t); + Expression *castTo(Scope *sc, Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -253,7 +253,7 @@ struct RealExp : Expression RealExp(Loc loc, real_t value, Type *type); int equals(Object *o); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); char *toChars(); dinteger_t toInteger(); uinteger_t toUInteger(); @@ -281,7 +281,7 @@ struct ComplexExp : Expression ComplexExp(Loc loc, complex_t value, Type *type); int equals(Object *o); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); char *toChars(); dinteger_t toInteger(); uinteger_t toUInteger(); @@ -341,12 +341,12 @@ struct ThisExp : Expression ThisExp(Loc loc); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *toLvalue(Scope *sc, Expression *e); - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); //Expression *inlineScan(InlineScanState *iss); @@ -377,12 +377,12 @@ struct NullExp : Expression Expression *semantic(Scope *sc); int isBool(int result); int isConst(); - StringExp *toString(); + StringExp *toString(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); #if IN_DMD elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); @@ -399,7 +399,7 @@ struct StringExp : Expression unsigned char sz; // 1: char, 2: wchar, 4: dchar unsigned char committed; // !=0 if type is committed unsigned char postfix; // 'c', 'w', 'd' - bool ownedByCtfe; // true = created in CTFE + bool ownedByCtfe; // true = created in CTFE StringExp(Loc loc, char *s); StringExp(Loc loc, void *s, size_t len); @@ -408,9 +408,9 @@ struct StringExp : Expression int equals(Object *o); char *toChars(); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); - size_t length(); - StringExp *toString(); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + size_t length(); + StringExp *toString(); StringExp *toUTF8(Scope *sc); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); @@ -437,14 +437,14 @@ struct TupleExp : Expression TupleExp(Loc loc, Expressions *exps); TupleExp(Loc loc, TupleDeclaration *tup); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); int equals(Object *o); Expression *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void checkEscape(); int checkSideEffect(int flag); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *castTo(Scope *sc, Type *t); #if IN_DMD elem *toElem(IRState *irs); @@ -461,21 +461,21 @@ struct TupleExp : Expression struct ArrayLiteralExp : Expression { Expressions *elements; - bool ownedByCtfe; // true = created in CTFE + bool ownedByCtfe; // true = created in CTFE ArrayLiteralExp(Loc loc, Expressions *elements); ArrayLiteralExp(Loc loc, Expression *e); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); int isBool(int result); int checkSideEffect(int flag); - StringExp *toString(); + StringExp *toString(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); @@ -495,12 +495,12 @@ struct AssocArrayLiteralExp : Expression { Expressions *keys; Expressions *values; - bool ownedByCtfe; // true = created in CTFE + bool ownedByCtfe; // true = created in CTFE AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); int isBool(int result); #if IN_DMD @@ -510,7 +510,7 @@ struct AssocArrayLiteralExp : Expression void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); @@ -528,19 +528,19 @@ struct StructLiteralExp : Expression StructDeclaration *sd; // which aggregate this is for Expressions *elements; // parallels sd->fields[] with // NULL entries for fields to skip - Type *stype; // final type of result (can be different from sd's type) + Type *stype; // final type of result (can be different from sd's type) #if IN_DMD Symbol *sym; // back end symbol to initialize with literal #endif size_t soffset; // offset from start of s int fillHoles; // fill alignment 'holes' with zero - bool ownedByCtfe; // true = created in CTFE + bool ownedByCtfe; // true = created in CTFE - StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); + StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *getField(Type *type, unsigned offset); int getFieldIndex(Type *type, unsigned offset); @@ -548,10 +548,10 @@ struct StructLiteralExp : Expression void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *toLvalue(Scope *sc, Expression *e); - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -611,7 +611,7 @@ struct TemplateExp : Expression TemplateDeclaration *td; TemplateExp(Loc loc, TemplateDeclaration *td); - int rvalue(); + int rvalue(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -631,9 +631,9 @@ struct NewExp : Expression NewExp(Loc loc, Expression *thisexp, Expressions *newargs, Type *newtype, Expressions *arguments); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *optimize(int result); #if IN_DMD elem *toElem(IRState *irs); @@ -641,7 +641,7 @@ struct NewExp : Expression int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - //int inlineCost3(InlineCostState *ics); + //int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); //Expression *inlineScan(InlineScanState *iss); @@ -662,7 +662,7 @@ struct NewAnonClassExp : Expression NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs, ClassDeclaration *cd, Expressions *arguments); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -690,7 +690,7 @@ struct SymOffExp : Expression SymOffExp(Loc loc, Declaration *var, unsigned offset); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int isConst(); @@ -719,7 +719,7 @@ struct VarExp : Expression int equals(Object *o); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void dump(int indent); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -765,15 +765,15 @@ struct FuncExp : Expression FuncExp(Loc loc, FuncLiteralDeclaration *fd); Expression *syntaxCopy(); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); + dt_t **toDt(dt_t **pdt); #endif - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); //Expression *doInline(InlineDoState *ids); //Expression *inlineScan(InlineScanState *iss); @@ -792,14 +792,14 @@ struct DeclarationExp : Expression DeclarationExp(Loc loc, Dsymbol *declaration); Expression *syntaxCopy(); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); #endif - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -872,12 +872,12 @@ struct UnaExp : Expression UnaExp(Loc loc, enum TOK op, int size, Expression *e1); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); void dump(int indent); - Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)); + Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -892,7 +892,7 @@ struct BinExp : Expression BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *semanticp(Scope *sc); Expression *commonSemanticAssign(Scope *sc); @@ -907,12 +907,12 @@ struct BinExp : Expression int isunsigned(); void incompatibleTypes(); void dump(int indent); - Expression *interpretCommon(InterState *istate, CtfeGoal goal, - Expression *(*fp)(Type *, Expression *, Expression *)); - Expression *interpretCommon2(InterState *istate, CtfeGoal goal, - Expression *(*fp)(TOK, Type *, Expression *, Expression *)); - Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal, - Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); + Expression *interpretCommon(InterState *istate, CtfeGoal goal, + Expression *(*fp)(Type *, Expression *, Expression *)); + Expression *interpretCommon2(InterState *istate, CtfeGoal goal, + Expression *(*fp)(TOK, Type *, Expression *, Expression *)); + Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal, + Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); Expression *arrayOp(Scope *sc); Expression *doInline(InlineDoState *ids); @@ -953,9 +953,9 @@ struct AssertExp : UnaExp AssertExp(Loc loc, Expression *e, Expression *msg = NULL); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -998,7 +998,7 @@ struct DotVarExp : UnaExp Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); #if IN_DMD @@ -1029,13 +1029,13 @@ struct DelegateExp : UnaExp DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); #if IN_DMD elem *toElem(IRState *irs); #endif @@ -1071,10 +1071,10 @@ struct CallExp : UnaExp CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); @@ -1084,7 +1084,7 @@ struct CallExp : UnaExp Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); - int inlineCost3(InlineCostState *ics); + int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -1107,7 +1107,7 @@ struct AddrExp : UnaExp MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); #if IN_LLVM DValue* toElem(IRState* irs); @@ -1127,7 +1127,7 @@ struct PtrExp : UnaExp elem *toElem(IRState *irs); #endif Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); #if IN_LLVM DValue* toElem(IRState* irs); @@ -1140,7 +1140,7 @@ struct NegExp : UnaExp NegExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1170,7 +1170,7 @@ struct ComExp : UnaExp ComExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1191,7 +1191,7 @@ struct NotExp : UnaExp NotExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); #if IN_DMD elem *toElem(IRState *irs); @@ -1207,7 +1207,7 @@ struct BoolExp : UnaExp BoolExp(Loc loc, Expression *e, Type *type); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); #if IN_DMD elem *toElem(IRState *irs); @@ -1243,7 +1243,7 @@ struct CastExp : UnaExp Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -1271,23 +1271,23 @@ struct SliceExp : UnaExp SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); void checkEscape(); void checkEscapeRef(); Expression *toLvalue(Scope *sc, Expression *e); Expression *modifiableLvalue(Scope *sc, Expression *e); - int isBool(int result); + int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void dump(int indent); #if IN_DMD elem *toElem(IRState *irs); #endif void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); - int canThrow(); + int canThrow(); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -1303,7 +1303,7 @@ struct ArrayLengthExp : UnaExp ArrayLengthExp(Loc loc, Expression *e1); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); @@ -1322,7 +1322,7 @@ struct ArrayExp : UnaExp ArrayExp(Loc loc, Expression *e1, Expressions *arguments); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *toLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -1354,7 +1354,7 @@ struct CommaExp : BinExp int isBool(int result); int checkSideEffect(int flag); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); #if IN_DMD elem *toElem(IRState *irs); #endif @@ -1376,7 +1376,7 @@ struct IndexExp : BinExp Expression *modifiableLvalue(Scope *sc, Expression *e); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *doInline(InlineDoState *ids); #if IN_DMD @@ -1394,7 +1394,7 @@ struct PostExp : BinExp { PostExp(enum TOK op, Loc loc, Expression *e); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Identifier *opId(); // For operator overloading #if IN_DMD @@ -1412,7 +1412,7 @@ struct AssignExp : BinExp AssignExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *checkToBoolean(); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Identifier *opId(); // For operator overloading void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1445,7 +1445,7 @@ struct op##AssignExp : BinExp \ { \ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ Expression *semantic(Scope *sc); \ - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ X(Expression *buildArrayLoop(Parameters *fparams);) \ \ @@ -1481,7 +1481,7 @@ struct AddExp : BinExp AddExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1505,7 +1505,7 @@ struct MinExp : BinExp MinExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1528,7 +1528,7 @@ struct CatExp : BinExp CatExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); // For operator overloading Identifier *opId(); @@ -1548,7 +1548,7 @@ struct MulExp : BinExp MulExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1571,7 +1571,7 @@ struct DivExp : BinExp DivExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1593,7 +1593,7 @@ struct ModExp : BinExp ModExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1627,7 +1627,7 @@ struct ShlExp : BinExp ShlExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); // For operator overloading Identifier *opId(); @@ -1647,7 +1647,7 @@ struct ShrExp : BinExp ShrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); // For operator overloading Identifier *opId(); @@ -1667,7 +1667,7 @@ struct UshrExp : BinExp UshrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); // For operator overloading Identifier *opId(); @@ -1687,7 +1687,7 @@ struct AndExp : BinExp AndExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1710,7 +1710,7 @@ struct OrExp : BinExp OrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1733,7 +1733,7 @@ struct XorExp : BinExp XorExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1758,7 +1758,7 @@ struct OrOrExp : BinExp Expression *checkToBoolean(); int isBit(); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); #if IN_DMD elem *toElem(IRState *irs); @@ -1776,7 +1776,7 @@ struct AndAndExp : BinExp Expression *checkToBoolean(); int isBit(); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int checkSideEffect(int flag); #if IN_DMD elem *toElem(IRState *irs); @@ -1792,7 +1792,7 @@ struct CmpExp : BinExp CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); // For operator overloading @@ -1812,7 +1812,7 @@ struct InExp : BinExp { InExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); // For operator overloading @@ -1831,7 +1831,7 @@ struct InExp : BinExp struct RemoveExp : BinExp { RemoveExp(Loc loc, Expression *e1, Expression *e2); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); @@ -1849,7 +1849,7 @@ struct EqualExp : BinExp EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); // For operator overloading @@ -1873,7 +1873,7 @@ struct IdentityExp : BinExp Expression *semantic(Scope *sc); int isBit(); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); #if IN_DMD elem *toElem(IRState *irs); #endif @@ -1891,10 +1891,10 @@ struct CondExp : BinExp CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2); Expression *syntaxCopy(); - int apply(apply_fp_t fp, void *param); + int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *optimize(int result); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void checkEscape(); void checkEscapeRef(); Expression *toLvalue(Scope *sc, Expression *e); @@ -2006,11 +2006,11 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2); Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr); -// Const-folding functions used by CTFE - -void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex); -void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex); -void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex); - - +// Const-folding functions used by CTFE + +void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex); +void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex); +void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex); + + #endif /* DMD_EXPRESSION_H */ diff --git a/dmd/func.c b/dmd/func.c index 29f45e58..e61c93f5 100644 --- a/dmd/func.c +++ b/dmd/func.c @@ -61,13 +61,13 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla vtblIndex = -1; hasReturnExp = 0; naked = 0; - inlineStatusExp = ILSuninitialized; - inlineStatusStmt = ILSuninitialized; + inlineStatusExp = ILSuninitialized; + inlineStatusStmt = ILSuninitialized; inlineNest = 0; inlineAsm = 0; - isArrayOp = 0; + isArrayOp = 0; semanticRun = PASSinit; - semantic3Errors = 0; + semantic3Errors = 0; #if DMDV1 nestedFrameRef = 0; #endif @@ -88,7 +88,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla #if DMDV2 builtin = BUILTINunknown; tookAddressOf = 0; - flags = 0; + flags = 0; #endif #if IN_LLVM @@ -221,10 +221,10 @@ void FuncDeclaration::semantic(Scope *sc) if (isAbstract() && !isVirtual()) error("non-virtual functions cannot be abstract"); - // https://github.com/donc/dmd/commit/9f7b2f8cfe5d7482f2de7f9678c176d54abe237f#commitcomment-321724 - //if (isOverride() && !isVirtual()) - //error("cannot override a non-virtual function"); - + // https://github.com/donc/dmd/commit/9f7b2f8cfe5d7482f2de7f9678c176d54abe237f#commitcomment-321724 + //if (isOverride() && !isVirtual()) + //error("cannot override a non-virtual function"); + if (isAbstract() && isFinal()) error("cannot be both final and abstract"); #if 0 @@ -320,7 +320,7 @@ void FuncDeclaration::semantic(Scope *sc) // ctor = (CtorDeclaration *)this; // if (!cd->ctor) // cd->ctor = ctor; - goto Ldone; + goto Ldone; } #if 0 @@ -411,7 +411,7 @@ void FuncDeclaration::semantic(Scope *sc) return; default: - { FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl[vi]; + { FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl[vi]; // This function is covariant with fdv if (fdv->isFinal()) error("cannot override final function %s", fdv->toPrettyChars()); @@ -421,17 +421,17 @@ void FuncDeclaration::semantic(Scope *sc) warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars()); #endif - FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration(); - if (fdc->toParent() == parent) + FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration(); + if (fdc->toParent() == parent) { // If both are mixins, then error. - // If either is not, the one that is not overrides the other. - - // if (this is mixin) && (fdc is not mixin) then fdc overrides - if (!this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration()) + // If either is not, the one that is not overrides the other. + + // if (this is mixin) && (fdc is not mixin) then fdc overrides + if (!this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration()) break; - - if (!this->parent->isClassDeclaration() // if both are mixins then error + + if (!this->parent->isClassDeclaration() // if both are mixins then error #if !BREAKABI && !isDtorDeclaration() #endif @@ -441,7 +441,7 @@ void FuncDeclaration::semantic(Scope *sc) ) error("multiple overrides of same function"); } - cd->vtbl[vi] = this; + cd->vtbl[vi] = this; vtblIndex = vi; /* Remember which functions this overrides @@ -506,10 +506,10 @@ void FuncDeclaration::semantic(Scope *sc) /* Only need to have a tintro if the vptr * offsets differ */ - unsigned errors = global.startGagging(); // suppress printing of error messages + unsigned errors = global.startGagging(); // suppress printing of error messages int offset; int baseOf = fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset); - if (global.endGagging(errors)) + if (global.endGagging(errors)) { // any error in isBaseOf() is a forward reference error, so we bail out cd->sizeok = 2; // can't finish due to forward reference @@ -647,7 +647,7 @@ void FuncDeclaration::semantic(Scope *sc) FuncDeclaration *fd = new FuncDeclaration(loc, loc, Id::require, STCundefined, tf); fd->fbody = frequire; - Statement *s1 = new ExpStatement(loc, fd); + Statement *s1 = new ExpStatement(loc, fd); Expression *e = new CallExp(loc, new VarExp(loc, fd), (Expressions *)NULL); Statement *s2 = new ExpStatement(loc, e); frequire = new CompoundStatement(loc, s1, s2); @@ -674,7 +674,7 @@ void FuncDeclaration::semantic(Scope *sc) FuncDeclaration *fd = new FuncDeclaration(loc, loc, Id::ensure, STCundefined, tf); fd->fbody = fensure; - Statement *s1 = new ExpStatement(loc, fd); + Statement *s1 = new ExpStatement(loc, fd); Expression *eresult = NULL; if (outId) eresult = new IdentifierExp(loc, outId); @@ -689,7 +689,7 @@ Ldone: Module::dprogress++; //LDC relies on semanticRun variable not being reset here if(semanticRun < PASSsemanticdone) - semanticRun = PASSsemanticdone; + semanticRun = PASSsemanticdone; /* Save scope for possible later use (if we need the * function internals) @@ -731,7 +731,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (semanticRun >= PASSsemantic3) return; semanticRun = PASSsemantic3; - semantic3Errors = 0; + semantic3Errors = 0; #if IN_LLVM if (!global.params.useAvailableExternally) @@ -754,20 +754,20 @@ void FuncDeclaration::semantic3(Scope *sc) } } - if (frequire) - { - for (int i = 0; i < foverrides.dim; i++) - { - FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i]; - - if (fdv->fbody && !fdv->frequire) - { - error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars()); - break; - } - } - } - + if (frequire) + { + for (int i = 0; i < foverrides.dim; i++) + { + FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i]; + + if (fdv->fbody && !fdv->frequire) + { + error("cannot have an in contract when overriden function %s does not have an in contract", fdv->toPrettyChars()); + break; + } + } + } + frequire = mergeFrequire(frequire); fensure = mergeFensure(fensure); @@ -790,10 +790,10 @@ void FuncDeclaration::semantic3(Scope *sc) sc2->sw = NULL; sc2->fes = fes; sc2->linkage = LINKd; - sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | - STCdeprecated | STCoverride | - STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | - STCproperty | STCsafe | STCtrusted | STCsystem); + sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | + STCdeprecated | STCoverride | + STC_TYPECTOR | STCfinal | STCtls | STCgshared | STCref | + STCproperty | STCsafe | STCtrusted | STCsystem); sc2->protection = PROTpublic; sc2->explicitProtection = 0; sc2->structalign = 8; @@ -848,24 +848,24 @@ void FuncDeclaration::semantic3(Scope *sc) #else Type *t; - if (global.params.is64bit) - { // Declare save area for varargs registers - Type *t = new TypeIdentifier(loc, Id::va_argsave_t); - t = t->semantic(loc, sc); - if (t == Type::terror) - { - error("must import std.c.stdarg to use variadic functions"); - return; - } - else - { - v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL); - v_argsave->semantic(sc2); - sc2->insert(v_argsave); - v_argsave->parent = this; - } - } - + if (global.params.is64bit) + { // Declare save area for varargs registers + Type *t = new TypeIdentifier(loc, Id::va_argsave_t); + t = t->semantic(loc, sc); + if (t == Type::terror) + { + error("must import std.c.stdarg to use variadic functions"); + return; + } + else + { + v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL); + v_argsave->semantic(sc2); + sc2->insert(v_argsave); + v_argsave->parent = this; + } + } + if (f->linkage == LINKd) { // Declare _arguments[] #if BREAKABI @@ -889,7 +889,7 @@ void FuncDeclaration::semantic3(Scope *sc) v_arguments->parent = this; #endif } - if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) + if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) { // Declare _argptr #if IN_GCC t = d_gcc_builtin_va_list_d_type; @@ -954,7 +954,7 @@ void FuncDeclaration::semantic3(Scope *sc) { /* parameters[] has all the tuples removed, as the back end * doesn't know about tuples */ - parameters = new VarDeclarations(); + parameters = new VarDeclarations(); parameters->reserve(nparams); for (size_t i = 0; i < nparams; i++) { @@ -1186,7 +1186,7 @@ void FuncDeclaration::semantic3(Scope *sc) f = (TypeFunction *)type; } - int offend = fbody ? fbody->blockExit(FALSE) & BEfallthru : TRUE; + int offend = fbody ? fbody->blockExit(FALSE) & BEfallthru : TRUE; if (isStaticCtorDeclaration()) { /* It's a static constructor. Ensure that all @@ -1233,16 +1233,16 @@ void FuncDeclaration::semantic3(Scope *sc) Expression *e1 = new SuperExp(0); Expression *e = new CallExp(0, e1); - e = e->trySemantic(sc2); - if (!e) + e = e->trySemantic(sc2); + if (!e) error("no match for implicit super() call in constructor"); - else - { + else + { Statement *s = new ExpStatement(0, e); fbody = new CompoundStatement(0, s, fbody); } } - } + } else if (fes) { // For foreach(){} body, append a return 0; Expression *e = new IntegerExp(0); @@ -1329,17 +1329,17 @@ void FuncDeclaration::semantic3(Scope *sc) v_argptr->init = new VoidInitializer(loc); #else Type *t = argptr->type; - if (global.params.is64bit) - { // Initialize _argptr to point to v_argsave - Expression *e1 = new VarExp(0, argptr); - Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16); - e->type = argptr->type; - e = new AssignExp(0, e1, e); - e = e->semantic(sc); - a->push(new ExpStatement(0, e)); - } - else - { // Initialize _argptr to point past non-variadic arg + if (global.params.is64bit) + { // Initialize _argptr to point to v_argsave + Expression *e1 = new VarExp(0, argptr); + Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16); + e->type = argptr->type; + e = new AssignExp(0, e1, e); + e = e->semantic(sc); + a->push(new ExpStatement(0, e)); + } + else + { // Initialize _argptr to point past non-variadic arg VarDeclaration *p; unsigned offset = 0; @@ -1531,7 +1531,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (isSynchronized()) { AggregateDeclaration *ad = isThis(); - ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration(); + ClassDeclaration *cd = ad ? ad->isClassDeclaration() : parent->isClassDeclaration(); Expression *sync; if (isStatic()) @@ -1569,12 +1569,12 @@ void FuncDeclaration::semantic3(Scope *sc) if (global.gag && global.errors != nerrors) semanticRun = PASSsemanticdone; // Ensure errors get reported again else - { + { semanticRun = PASSsemantic3done; - semantic3Errors = global.errors - nerrors; - } - //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); - //fflush(stdout); + semantic3Errors = global.errors - nerrors; + } + //printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); + //fflush(stdout); } void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -1589,7 +1589,7 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (fbody && - (!hgs->hdrgen || hgs->tpltMember || canInline(1,1,1)) + (!hgs->hdrgen || hgs->tpltMember || canInline(1,1,1)) ) { buf->writenl(); @@ -1669,7 +1669,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf) } sf = fdv->mergeFrequire(sf); - if (sf && fdv->fdrequire) + if (sf && fdv->fdrequire) { //printf("fdv->frequire: %s\n", fdv->frequire->toChars()); /* Make the call: @@ -1680,13 +1680,13 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf) Expression *e = new CallExp(loc, new VarExp(loc, fdv->fdrequire), eresult); Statement *s2 = new ExpStatement(loc, e); - Catch *c = new Catch(loc, NULL, NULL, sf); - Catches *catches = new Catches(); - catches->push(c); - sf = new TryCatchStatement(loc, s2, catches); - } - else - return NULL; + Catch *c = new Catch(loc, NULL, NULL, sf); + Catches *catches = new Catches(); + catches->push(c); + sf = new TryCatchStatement(loc, s2, catches); + } + else + return NULL; } return sf; } @@ -2462,21 +2462,21 @@ int FuncDeclaration::isVirtual() toParent()->isClassDeclaration(); } -// Determine if a function is pedantically virtual - -int FuncDeclaration::isVirtualMethod() -{ - //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars()); - if (!isVirtual()) - return 0; - // If it's a final method, and does not override anything, then it is not virtual - if (isFinal() && foverrides.dim == 0) - { - return 0; - } - return 1; -} - +// Determine if a function is pedantically virtual + +int FuncDeclaration::isVirtualMethod() +{ + //printf("FuncDeclaration::isVirtualMethod() %s\n", toChars()); + if (!isVirtual()) + return 0; + // If it's a final method, and does not override anything, then it is not virtual + if (isFinal() && foverrides.dim == 0) + { + return 0; + } + return 1; +} + int FuncDeclaration::isFinal() { ClassDeclaration *cd; @@ -2651,43 +2651,43 @@ Lyes: } #endif -/*********************************************** - * Determine if function's variables are referenced by a function - * nested within it. - */ - -int FuncDeclaration::hasNestedFrameRefs() -{ -#if DMDV2 - if (closureVars.dim) -#else - if (nestedFrameRef) -#endif - return 1; - - /* If a virtual method has contracts, assume its variables are referenced - * by those contracts, even if they aren't. Because they might be referenced - * by the overridden or overriding function's contracts. - * This can happen because frequire and fensure are implemented as nested functions, - * and they can be called directly by an overriding function and the overriding function's - * context had better match, or Bugzilla 7337 will bite. - */ - if ((fdrequire || fdensure) && isVirtualMethod()) - return 1; - - if (foverrides.dim && isVirtualMethod()) - { - for (size_t i = 0; i < foverrides.dim; i++) - { - FuncDeclaration *fdv = foverrides.tdata()[i]; - if (fdv->hasNestedFrameRefs()) - return 1; - } - } - - return 0; -} - +/*********************************************** + * Determine if function's variables are referenced by a function + * nested within it. + */ + +int FuncDeclaration::hasNestedFrameRefs() +{ +#if DMDV2 + if (closureVars.dim) +#else + if (nestedFrameRef) +#endif + return 1; + + /* If a virtual method has contracts, assume its variables are referenced + * by those contracts, even if they aren't. Because they might be referenced + * by the overridden or overriding function's contracts. + * This can happen because frequire and fensure are implemented as nested functions, + * and they can be called directly by an overriding function and the overriding function's + * context had better match, or Bugzilla 7337 will bite. + */ + if ((fdrequire || fdensure) && isVirtualMethod()) + return 1; + + if (foverrides.dim && isVirtualMethod()) + { + for (size_t i = 0; i < foverrides.dim; i++) + { + FuncDeclaration *fdv = foverrides.tdata()[i]; + if (fdv->hasNestedFrameRefs()) + return 1; + } + } + + return 0; +} + /********************************************* * Return the function's parameter list, and whether * it is variadic or not. @@ -3112,7 +3112,7 @@ void StaticCtorDeclaration::semantic(Scope *sc) VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); v->storage_class = STCstatic; Statements *sa = new Statements(); - Statement *s = new ExpStatement(0, v); + Statement *s = new ExpStatement(0, v); sa->push(s); Expression *e = new IdentifierExp(0, id); e = new AddAssignExp(0, e, new IntegerExp(1)); @@ -3154,11 +3154,11 @@ int StaticCtorDeclaration::isVirtual() return FALSE; } -bool StaticCtorDeclaration::hasStaticCtorOrDtor() -{ - return TRUE; -} - +bool StaticCtorDeclaration::hasStaticCtorOrDtor() +{ + return TRUE; +} + int StaticCtorDeclaration::addPreInvariant() { return FALSE; @@ -3223,7 +3223,7 @@ void StaticDtorDeclaration::semantic(Scope *sc) VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); v->storage_class = STCstatic; Statements *sa = new Statements(); - Statement *s = new ExpStatement(0, v); + Statement *s = new ExpStatement(0, v); sa->push(s); Expression *e = new IdentifierExp(0, id); e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1)); @@ -3266,11 +3266,11 @@ int StaticDtorDeclaration::isVirtual() return FALSE; } -bool StaticDtorDeclaration::hasStaticCtorOrDtor() -{ - return TRUE; -} - +bool StaticDtorDeclaration::hasStaticCtorOrDtor() +{ + return TRUE; +} + int StaticDtorDeclaration::addPreInvariant() { return FALSE; diff --git a/dmd/hdrgen.c b/dmd/hdrgen.c index 87c9ffee..6fa5af42 100644 --- a/dmd/hdrgen.c +++ b/dmd/hdrgen.c @@ -1,100 +1,100 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// Initial header generation implementation by Dave Fladebo -// 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. - -// Routines to emit header files - -#define PRETTY_PRINT -#define TEST_EMIT_ALL 0 // For Testing - -#define LOG 0 - -#include -#include -#include -#if __DMC__ -#include -#endif - -#include "rmem.h" - -#include "id.h" -#include "init.h" - -#include "attrib.h" -#include "cond.h" -#include "enum.h" -#include "import.h" -#include "module.h" -#include "mtype.h" -#include "scope.h" -#include "staticassert.h" -#include "template.h" -#include "utf.h" -#include "version.h" - -#include "declaration.h" -#include "aggregate.h" -#include "expression.h" -#include "statement.h" -#include "mtype.h" -#include "hdrgen.h" - -void argsToCBuffer(OutBuffer *buf, Array *arguments, HdrGenState *hgs); - -void Module::genhdrfile() -{ - OutBuffer hdrbufr; - - hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars()); - hdrbufr.writenl(); - - HdrGenState hgs; - memset(&hgs, 0, sizeof(hgs)); - hgs.hdrgen = 1; - - toCBuffer(&hdrbufr, &hgs); - - // Transfer image to file - hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset); - hdrbufr.data = NULL; - - char *pt = FileName::path(hdrfile->toChars()); - if (*pt) - FileName::ensurePathExists(pt); - mem.free(pt); - hdrfile->writev(); -} - - -void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - if (md) - { - buf->writestring("module "); - buf->writestring(md->toChars()); - buf->writebyte(';'); - buf->writenl(); - } - - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = (Dsymbol *)members->data[i]; - - s->toHBuffer(buf, hgs); - } -} - - -void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - toCBuffer(buf, hgs); -} - - -/*************************************/ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// Initial header generation implementation by Dave Fladebo +// 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. + +// Routines to emit header files + +#define PRETTY_PRINT +#define TEST_EMIT_ALL 0 // For Testing + +#define LOG 0 + +#include +#include +#include +#if __DMC__ +#include +#endif + +#include "rmem.h" + +#include "id.h" +#include "init.h" + +#include "attrib.h" +#include "cond.h" +#include "enum.h" +#include "import.h" +#include "module.h" +#include "mtype.h" +#include "scope.h" +#include "staticassert.h" +#include "template.h" +#include "utf.h" +#include "version.h" + +#include "declaration.h" +#include "aggregate.h" +#include "expression.h" +#include "statement.h" +#include "mtype.h" +#include "hdrgen.h" + +void argsToCBuffer(OutBuffer *buf, Array *arguments, HdrGenState *hgs); + +void Module::genhdrfile() +{ + OutBuffer hdrbufr; + + hdrbufr.printf("// D import file generated from '%s'", srcfile->toChars()); + hdrbufr.writenl(); + + HdrGenState hgs; + memset(&hgs, 0, sizeof(hgs)); + hgs.hdrgen = 1; + + toCBuffer(&hdrbufr, &hgs); + + // Transfer image to file + hdrfile->setbuffer(hdrbufr.data, hdrbufr.offset); + hdrbufr.data = NULL; + + char *pt = FileName::path(hdrfile->toChars()); + if (*pt) + FileName::ensurePathExists(pt); + mem.free(pt); + hdrfile->writev(); +} + + +void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + if (md) + { + buf->writestring("module "); + buf->writestring(md->toChars()); + buf->writebyte(';'); + buf->writenl(); + } + + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (Dsymbol *)members->data[i]; + + s->toHBuffer(buf, hgs); + } +} + + +void Dsymbol::toHBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + toCBuffer(buf, hgs); +} + + +/*************************************/ diff --git a/dmd/hdrgen.h b/dmd/hdrgen.h index 6e007ed7..79cfb732 100644 --- a/dmd/hdrgen.h +++ b/dmd/hdrgen.h @@ -1,34 +1,34 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// initial header generation implementation by Dave Fladebo -// 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. - - -struct HdrGenState -{ - int hdrgen; // 1 if generating header file - int ddoc; // 1 if generating Ddoc file - int console; // 1 if writing to console - int tpltMember; - int inCallExp; - int inPtrExp; - int inSlcExp; - int inDotExp; - int inBinExp; - int inArrExp; - int emitInst; - struct - { - int init; - int decl; - } FLinit; - - HdrGenState() { memset(this, 0, sizeof(HdrGenState)); } -}; - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// initial header generation implementation by Dave Fladebo +// 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. + + +struct HdrGenState +{ + int hdrgen; // 1 if generating header file + int ddoc; // 1 if generating Ddoc file + int console; // 1 if writing to console + int tpltMember; + int inCallExp; + int inPtrExp; + int inSlcExp; + int inDotExp; + int inBinExp; + int inArrExp; + int emitInst; + struct + { + int init; + int decl; + } FLinit; + + HdrGenState() { memset(this, 0, sizeof(HdrGenState)); } +}; + + diff --git a/dmd/html.c b/dmd/html.c index ee708cdd..0e2f0ab7 100644 --- a/dmd/html.c +++ b/dmd/html.c @@ -1,718 +1,718 @@ - -// 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. - - -/* HTML parser - */ - -#include -#include -#include -#include -#include -#include - -#include "mars.h" -#include "html.h" - -#include -#include "root.h" - -extern int HtmlNamedEntity(unsigned char *p, int length); - -static int isLineSeparator(const unsigned char* p); - -/********************************** - * Determine if beginning of tag identifier - * or a continuation of a tag identifier. - */ - -inline int istagstart(int c) -{ - return (isalpha(c) || c == '_'); -} - -inline int istag(int c) -{ - return (isalnum(c) || c == '_'); -} - -/********************************************** - */ - -Html::Html(const char *sourcename, unsigned char *base, unsigned length) -{ - //printf("Html::Html()\n"); - this->sourcename = sourcename; - this->base = base; - p = base; - end = base + length; - linnum = 1; - dbuf = NULL; - inCode = 0; -} - -/********************************************** - * Print error & quit. - */ - -void Html::error(const char *format, ...) -{ - if (!global.gag) - { - printf("%s(%d) : HTML Error: ", sourcename, linnum); - - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); - } - - global.errors++; -} - -/********************************************** - * Extract all the code from an HTML file, - * concatenate it all together, and store in buf. - */ - -void Html::extractCode(OutBuffer *buf) -{ - //printf("Html::extractCode()\n"); - dbuf = buf; // save for other routines - buf->reserve(end - p); - inCode = 0; - while (1) - { - //printf("p = %p, *p = x%x\n", p, *p); - switch (*p) - { -#if 0 // strings are not recognized outside of tags - case '"': - case '\'': - skipString(); - continue; -#endif - case '<': - if (p[1] == '!' && isCommentStart()) - { // Comments start with - * Netscape: comments nest - * w3c: whitespace can appear between -- and > of comment close - */ - -void Html::scanComment() -{ - // Most of the complexity is dealing with the case that - // an arbitrary amount of whitespace can appear between - // the -- and the > of a comment close. - int scangt = 0; - - //printf("scanComment()\n"); - if (*p == '\n') - { linnum++; - // Always extract new lines, so that D lexer counts the - // lines right. - dbuf->writeByte(*p); - } - while (1) - { - //scangt = 1; // IE 5.0 compatibility - p++; - switch (*p) - { - case '-': - if (p[1] == '-') - { - if (p[2] == '>') // optimize for most common case - { - p += 3; - break; - } - p++; - scangt = 1; - } - else - scangt = 0; - continue; - - case '>': - if (scangt) - { // found --> - p++; - break; - } - continue; - - case ' ': - case '\t': - case '\f': - case '\v': - // skip white space - continue; - - case '\r': - if (p[1] == '\n') - goto Ldefault; - case '\n': - linnum++; // remember to count lines - // Always extract new lines, so that D lexer counts the - // lines right. - dbuf->writeByte(*p); - continue; - - case 0: - case 0x1a: - error("end of file before closing --> of comment"); - break; - - default: - Ldefault: - scangt = 0; // it's not --> - continue; - } - break; - } - //printf("*p = '%c'\n", *p); -} - -/******************************************** - * Determine if we are at the start of a comment. - * Input: - * p is on the opening '<' - * Returns: - * 0 if not start of a comment - * 1 if start of a comment, p is adjusted to point past -- - */ - -int Html::isCommentStart() -#ifdef __DMC__ - __out(result) - { - if (result == 0) - ; - else if (result == 1) - { - assert(p[-2] == '-' && p[-1] == '-'); - } - else - assert(0); - } - __body -#endif /* __DMC__ */ - { unsigned char *s; - - if (p[0] == '<' && p[1] == '!') - { - for (s = p + 2; 1; s++) - { - switch (*s) - { - case ' ': - case '\t': - case '\r': - case '\f': - case '\v': - // skip white space, even though spec says no - // white space is allowed - continue; - - case '-': - if (s[1] == '-') - { - p = s + 2; - return 1; - } - goto No; - - default: - goto No; - } - } - } - No: - return 0; - } - -int Html::isCDATAStart() -{ - const char * CDATA_START_MARKER = "0) - { - /* Always extract new lines, so that D lexer counts the lines - * right. - */ - linnum++; - dbuf->writeUTF8('\n'); - p += lineSepLength; - continue; - } - else if (p[0] == ']' && p[1] == ']' && p[2] == '>') - { - /* end of CDATA section */ - p += 3; - return; - } - else if (inCode) - { - /* this CDATA section contains D code */ - dbuf->writeByte(*p); - } - - p++; - } -} - -/******************************************** - * Convert an HTML character entity into a character. - * Forms are: - * &name; named entity - * &#ddd; decimal - * &#xhhhh; hex - * Input: - * p is on the & - */ - -int Html::charEntity() -{ int c = 0; - int v; - int hex; - unsigned char *pstart = p; - - //printf("Html::charEntity('%c')\n", *p); - if (p[1] == '#') - { - p++; - if (p[1] == 'x' || p[1] == 'X') - { p++; - hex = 1; - } - else - hex = 0; - if (p[1] == ';') - goto Linvalid; - while (1) - { - p++; - switch (*p) - { - case 0: - case 0x1a: - error("end of file before end of character entity"); - goto Lignore; - - case '\n': - case '\r': - case '<': // tag start - // Termination is assumed - break; - - case ';': - // Termination is explicit - p++; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - v = *p - '0'; - goto Lvalue; - - case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': - if (!hex) - goto Linvalid; - v = (*p - 'a') + 10; - goto Lvalue; - - case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': - if (!hex) - goto Linvalid; - v = (*p - 'A') + 10; - goto Lvalue; - - Lvalue: - if (hex) - c = (c << 4) + v; - else - c = (c * 10) + v; - if (c > 0x10FFFF) - { - error("character entity out of range"); - goto Lignore; - } - continue; - - default: - Linvalid: - error("invalid numeric character reference"); - goto Lignore; - } - break; - } - } - else - { - // It's a named entity; gather all characters until ; - unsigned char *idstart = p + 1; - - while (1) - { - p++; - switch (*p) - { - case 0: - case 0x1a: - error("end of file before end of character entity"); - break; - - case '\n': - case '\r': - case '<': // tag start - // Termination is assumed - c = HtmlNamedEntity(idstart, p - idstart); - if (c == -1) - goto Lignore; - break; - - case ';': - // Termination is explicit - c = HtmlNamedEntity(idstart, p - idstart); - if (c == -1) - goto Lignore; - p++; - break; - - default: - continue; - } - break; - } - } - - // Kludge to convert non-breaking space to ascii space - if (c == 160) - c = ' '; - - return c; - -Lignore: - //printf("Lignore\n"); - p = pstart + 1; - return '&'; -} - -/** - * identify DOS, Linux, Mac, Next and Unicode line endings - * 0 if this is no line separator - * >0 the length of the separator - * Note: input has to be UTF-8 - */ -static int isLineSeparator(const unsigned char* p) -{ - // Linux - if( p[0]=='\n') - return 1; - - // Mac & Dos - if( p[0]=='\r') - return (p[1]=='\n') ? 2 : 1; - - // Unicode (line || paragraph sep.) - if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9)) - return 3; - - // Next - if( p[0]==0xC2 && p[1]==0x85) - return 2; - - return 0; -} - + +// 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. + + +/* HTML parser + */ + +#include +#include +#include +#include +#include +#include + +#include "mars.h" +#include "html.h" + +#include +#include "root.h" + +extern int HtmlNamedEntity(unsigned char *p, int length); + +static int isLineSeparator(const unsigned char* p); + +/********************************** + * Determine if beginning of tag identifier + * or a continuation of a tag identifier. + */ + +inline int istagstart(int c) +{ + return (isalpha(c) || c == '_'); +} + +inline int istag(int c) +{ + return (isalnum(c) || c == '_'); +} + +/********************************************** + */ + +Html::Html(const char *sourcename, unsigned char *base, unsigned length) +{ + //printf("Html::Html()\n"); + this->sourcename = sourcename; + this->base = base; + p = base; + end = base + length; + linnum = 1; + dbuf = NULL; + inCode = 0; +} + +/********************************************** + * Print error & quit. + */ + +void Html::error(const char *format, ...) +{ + if (!global.gag) + { + printf("%s(%d) : HTML Error: ", sourcename, linnum); + + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + + printf("\n"); + fflush(stdout); + } + + global.errors++; +} + +/********************************************** + * Extract all the code from an HTML file, + * concatenate it all together, and store in buf. + */ + +void Html::extractCode(OutBuffer *buf) +{ + //printf("Html::extractCode()\n"); + dbuf = buf; // save for other routines + buf->reserve(end - p); + inCode = 0; + while (1) + { + //printf("p = %p, *p = x%x\n", p, *p); + switch (*p) + { +#if 0 // strings are not recognized outside of tags + case '"': + case '\'': + skipString(); + continue; +#endif + case '<': + if (p[1] == '!' && isCommentStart()) + { // Comments start with + * Netscape: comments nest + * w3c: whitespace can appear between -- and > of comment close + */ + +void Html::scanComment() +{ + // Most of the complexity is dealing with the case that + // an arbitrary amount of whitespace can appear between + // the -- and the > of a comment close. + int scangt = 0; + + //printf("scanComment()\n"); + if (*p == '\n') + { linnum++; + // Always extract new lines, so that D lexer counts the + // lines right. + dbuf->writeByte(*p); + } + while (1) + { + //scangt = 1; // IE 5.0 compatibility + p++; + switch (*p) + { + case '-': + if (p[1] == '-') + { + if (p[2] == '>') // optimize for most common case + { + p += 3; + break; + } + p++; + scangt = 1; + } + else + scangt = 0; + continue; + + case '>': + if (scangt) + { // found --> + p++; + break; + } + continue; + + case ' ': + case '\t': + case '\f': + case '\v': + // skip white space + continue; + + case '\r': + if (p[1] == '\n') + goto Ldefault; + case '\n': + linnum++; // remember to count lines + // Always extract new lines, so that D lexer counts the + // lines right. + dbuf->writeByte(*p); + continue; + + case 0: + case 0x1a: + error("end of file before closing --> of comment"); + break; + + default: + Ldefault: + scangt = 0; // it's not --> + continue; + } + break; + } + //printf("*p = '%c'\n", *p); +} + +/******************************************** + * Determine if we are at the start of a comment. + * Input: + * p is on the opening '<' + * Returns: + * 0 if not start of a comment + * 1 if start of a comment, p is adjusted to point past -- + */ + +int Html::isCommentStart() +#ifdef __DMC__ + __out(result) + { + if (result == 0) + ; + else if (result == 1) + { + assert(p[-2] == '-' && p[-1] == '-'); + } + else + assert(0); + } + __body +#endif /* __DMC__ */ + { unsigned char *s; + + if (p[0] == '<' && p[1] == '!') + { + for (s = p + 2; 1; s++) + { + switch (*s) + { + case ' ': + case '\t': + case '\r': + case '\f': + case '\v': + // skip white space, even though spec says no + // white space is allowed + continue; + + case '-': + if (s[1] == '-') + { + p = s + 2; + return 1; + } + goto No; + + default: + goto No; + } + } + } + No: + return 0; + } + +int Html::isCDATAStart() +{ + const char * CDATA_START_MARKER = "0) + { + /* Always extract new lines, so that D lexer counts the lines + * right. + */ + linnum++; + dbuf->writeUTF8('\n'); + p += lineSepLength; + continue; + } + else if (p[0] == ']' && p[1] == ']' && p[2] == '>') + { + /* end of CDATA section */ + p += 3; + return; + } + else if (inCode) + { + /* this CDATA section contains D code */ + dbuf->writeByte(*p); + } + + p++; + } +} + +/******************************************** + * Convert an HTML character entity into a character. + * Forms are: + * &name; named entity + * &#ddd; decimal + * &#xhhhh; hex + * Input: + * p is on the & + */ + +int Html::charEntity() +{ int c = 0; + int v; + int hex; + unsigned char *pstart = p; + + //printf("Html::charEntity('%c')\n", *p); + if (p[1] == '#') + { + p++; + if (p[1] == 'x' || p[1] == 'X') + { p++; + hex = 1; + } + else + hex = 0; + if (p[1] == ';') + goto Linvalid; + while (1) + { + p++; + switch (*p) + { + case 0: + case 0x1a: + error("end of file before end of character entity"); + goto Lignore; + + case '\n': + case '\r': + case '<': // tag start + // Termination is assumed + break; + + case ';': + // Termination is explicit + p++; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + v = *p - '0'; + goto Lvalue; + + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + if (!hex) + goto Linvalid; + v = (*p - 'a') + 10; + goto Lvalue; + + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': + if (!hex) + goto Linvalid; + v = (*p - 'A') + 10; + goto Lvalue; + + Lvalue: + if (hex) + c = (c << 4) + v; + else + c = (c * 10) + v; + if (c > 0x10FFFF) + { + error("character entity out of range"); + goto Lignore; + } + continue; + + default: + Linvalid: + error("invalid numeric character reference"); + goto Lignore; + } + break; + } + } + else + { + // It's a named entity; gather all characters until ; + unsigned char *idstart = p + 1; + + while (1) + { + p++; + switch (*p) + { + case 0: + case 0x1a: + error("end of file before end of character entity"); + break; + + case '\n': + case '\r': + case '<': // tag start + // Termination is assumed + c = HtmlNamedEntity(idstart, p - idstart); + if (c == -1) + goto Lignore; + break; + + case ';': + // Termination is explicit + c = HtmlNamedEntity(idstart, p - idstart); + if (c == -1) + goto Lignore; + p++; + break; + + default: + continue; + } + break; + } + } + + // Kludge to convert non-breaking space to ascii space + if (c == 160) + c = ' '; + + return c; + +Lignore: + //printf("Lignore\n"); + p = pstart + 1; + return '&'; +} + +/** + * identify DOS, Linux, Mac, Next and Unicode line endings + * 0 if this is no line separator + * >0 the length of the separator + * Note: input has to be UTF-8 + */ +static int isLineSeparator(const unsigned char* p) +{ + // Linux + if( p[0]=='\n') + return 1; + + // Mac & Dos + if( p[0]=='\r') + return (p[1]=='\n') ? 2 : 1; + + // Unicode (line || paragraph sep.) + if( p[0]==0xE2 && p[1]==0x80 && (p[2]==0xA8 || p[2]==0xA9)) + return 3; + + // Next + if( p[0]==0xC2 && p[1]==0x85) + return 2; + + return 0; +} + diff --git a/dmd/html.h b/dmd/html.h index 451a1954..f1956847 100644 --- a/dmd/html.h +++ b/dmd/html.h @@ -1,43 +1,43 @@ - -// 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. - -#ifndef DMD_HTML_H -#define DMD_HTML_H 1 - -struct OutBuffer; - -struct Html -{ - const char *sourcename; - - unsigned char *base; // pointer to start of buffer - unsigned char *end; // past end of buffer - unsigned char *p; // current character - unsigned linnum; // current line number - OutBuffer *dbuf; // code source buffer - int inCode; // !=0 if in code - - - Html(const char *sourcename, unsigned char *base, unsigned length); - - void error(const char *format, ...) IS_PRINTF(2); - void extractCode(OutBuffer *buf); - void skipTag(); - void skipString(); - unsigned char *skipWhite(unsigned char *q); - void scanComment(); - int isCommentStart(); - void scanCDATA(); - int isCDATAStart(); - int charEntity(); - static int namedEntity(unsigned char *p, int length); -}; - -#endif + +// 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. + +#ifndef DMD_HTML_H +#define DMD_HTML_H 1 + +struct OutBuffer; + +struct Html +{ + const char *sourcename; + + unsigned char *base; // pointer to start of buffer + unsigned char *end; // past end of buffer + unsigned char *p; // current character + unsigned linnum; // current line number + OutBuffer *dbuf; // code source buffer + int inCode; // !=0 if in code + + + Html(const char *sourcename, unsigned char *base, unsigned length); + + void error(const char *format, ...) IS_PRINTF(2); + void extractCode(OutBuffer *buf); + void skipTag(); + void skipString(); + unsigned char *skipWhite(unsigned char *q); + void scanComment(); + int isCommentStart(); + void scanCDATA(); + int isCDATAStart(); + int charEntity(); + static int namedEntity(unsigned char *p, int length); +}; + +#endif diff --git a/dmd/identifier.c b/dmd/identifier.c index 2a7606fd..01413859 100644 --- a/dmd/identifier.c +++ b/dmd/identifier.c @@ -1,101 +1,101 @@ - -// 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 -#include - -#include "root.h" -#include "identifier.h" -#include "mars.h" -#include "lexer.h" -#include "id.h" - -Identifier::Identifier(const char *string, int value) -{ - //printf("Identifier('%s', %d)\n", string, value); - this->string = string; - this->value = value; - this->len = strlen(string); -} - -hash_t Identifier::hashCode() -{ - return String::calcHash(string); -} - -int Identifier::equals(Object *o) -{ - return this == o || memcmp(string,o->toChars(),len+1) == 0; -} - -int Identifier::compare(Object *o) -{ - return memcmp(string, o->toChars(), len + 1); -} - -char *Identifier::toChars() -{ - return (char *)string; -} - -const char *Identifier::toHChars2() -{ - const char *p = NULL; - - if (this == Id::ctor) p = "this"; - else if (this == Id::dtor) p = "~this"; - else if (this == Id::classInvariant) p = "invariant"; - else if (this == Id::unitTest) p = "unittest"; - else if (this == Id::dollar) p = "$"; - else if (this == Id::withSym) p = "with"; - else if (this == Id::result) p = "result"; - else if (this == Id::returnLabel) p = "return"; - else - { p = toChars(); - if (*p == '_') - { - if (memcmp(p, "_staticCtor", 11) == 0) - p = "static this"; - else if (memcmp(p, "_staticDtor", 11) == 0) - p = "static ~this"; - } - } - - return p; -} - -void Identifier::print() -{ - fprintf(stdmsg, "%s",string); -} - -int Identifier::dyncast() -{ - return DYNCAST_IDENTIFIER; -} - - -Identifier *Identifier::generateId(const char *prefix) -{ - static size_t i; - - return generateId(prefix, ++i); -} - -Identifier *Identifier::generateId(const char *prefix, size_t i) -{ OutBuffer buf; - - buf.writestring(prefix); - buf.printf("%zu", i); - - char *id = buf.toChars(); - buf.data = NULL; - return Lexer::idPool(id); -} + +// 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 +#include + +#include "root.h" +#include "identifier.h" +#include "mars.h" +#include "lexer.h" +#include "id.h" + +Identifier::Identifier(const char *string, int value) +{ + //printf("Identifier('%s', %d)\n", string, value); + this->string = string; + this->value = value; + this->len = strlen(string); +} + +hash_t Identifier::hashCode() +{ + return String::calcHash(string); +} + +int Identifier::equals(Object *o) +{ + return this == o || memcmp(string,o->toChars(),len+1) == 0; +} + +int Identifier::compare(Object *o) +{ + return memcmp(string, o->toChars(), len + 1); +} + +char *Identifier::toChars() +{ + return (char *)string; +} + +const char *Identifier::toHChars2() +{ + const char *p = NULL; + + if (this == Id::ctor) p = "this"; + else if (this == Id::dtor) p = "~this"; + else if (this == Id::classInvariant) p = "invariant"; + else if (this == Id::unitTest) p = "unittest"; + else if (this == Id::dollar) p = "$"; + else if (this == Id::withSym) p = "with"; + else if (this == Id::result) p = "result"; + else if (this == Id::returnLabel) p = "return"; + else + { p = toChars(); + if (*p == '_') + { + if (memcmp(p, "_staticCtor", 11) == 0) + p = "static this"; + else if (memcmp(p, "_staticDtor", 11) == 0) + p = "static ~this"; + } + } + + return p; +} + +void Identifier::print() +{ + fprintf(stdmsg, "%s",string); +} + +int Identifier::dyncast() +{ + return DYNCAST_IDENTIFIER; +} + + +Identifier *Identifier::generateId(const char *prefix) +{ + static size_t i; + + return generateId(prefix, ++i); +} + +Identifier *Identifier::generateId(const char *prefix, size_t i) +{ OutBuffer buf; + + buf.writestring(prefix); + buf.printf("%zu", i); + + char *id = buf.toChars(); + buf.data = NULL; + return Lexer::idPool(id); +} diff --git a/dmd/idgen.c b/dmd/idgen.c index 1036378f..3d048ab5 100644 --- a/dmd/idgen.c +++ b/dmd/idgen.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -60,7 +60,7 @@ Msgtable msgtable[] = { "typeinfo" }, { "outer" }, { "Exception" }, - { "Error" }, + { "Error" }, { "withSym", "__withSym" }, { "result", "__result" }, { "returnLabel", "__returnLabel" }, @@ -250,31 +250,31 @@ Msgtable msgtable[] = { "main" }, { "WinMain" }, { "DllMain" }, - - // varargs implementation - { "va_argsave_t", "__va_argsave_t" }, - { "va_argsave", "__va_argsave" }, - - // Builtin functions - { "std" }, - { "core" }, - { "math" }, - { "sin" }, - { "cos" }, - { "tan" }, - { "_sqrt", "sqrt" }, - { "_pow", "pow" }, - { "atan2" }, - { "rndtol" }, - { "expm1" }, - { "exp2" }, - { "yl2x" }, - { "yl2xp1" }, - { "fabs" }, - { "bitop" }, - { "bsf" }, - { "bsr" }, - { "bswap" }, + + // varargs implementation + { "va_argsave_t", "__va_argsave_t" }, + { "va_argsave", "__va_argsave" }, + + // Builtin functions + { "std" }, + { "core" }, + { "math" }, + { "sin" }, + { "cos" }, + { "tan" }, + { "_sqrt", "sqrt" }, + { "_pow", "pow" }, + { "atan2" }, + { "rndtol" }, + { "expm1" }, + { "exp2" }, + { "yl2x" }, + { "yl2xp1" }, + { "fabs" }, + { "bitop" }, + { "bsf" }, + { "bsr" }, + { "bswap" }, }; diff --git a/dmd/impcnvgen.c b/dmd/impcnvgen.c index 3701eeab..6e7a1993 100644 --- a/dmd/impcnvgen.c +++ b/dmd/impcnvgen.c @@ -1,457 +1,457 @@ - -// 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 -#include - -#include "mtype.h" - -enum TY impcnvResult[TMAX][TMAX]; -enum TY impcnvType1[TMAX][TMAX]; -enum TY impcnvType2[TMAX][TMAX]; -int impcnvWarn[TMAX][TMAX]; - -int integral_promotion(int t) -{ - switch (t) - { - case Tchar: - case Twchar: - case Tbit: - case Tbool: - case Tint8: - case Tuns8: - case Tint16: - case Tuns16: return Tint32; - case Tdchar: return Tuns32; - default: return t; - } -} - -void init() -{ int i, j; - - // Set conversion tables - for (i = 0; i < TMAX; i++) - for (j = 0; j < TMAX; j++) - { impcnvResult[i][j] = Terror; - impcnvType1[i][j] = Terror; - impcnvType2[i][j] = Terror; - impcnvWarn[i][j] = 0; - } - -#define X(t1,t2, nt1,nt2, rt) \ - impcnvResult[t1][t2] = rt; \ - impcnvType1[t1][t2] = nt1; \ - impcnvType2[t1][t2] = nt2; - - /* ======================= */ - - X(Tbit,Tbit, Tint32,Tint32, Tint32) - X(Tbit,Tint8, Tint32,Tint32, Tint32) - X(Tbit,Tuns8, Tint32,Tint32, Tint32) - X(Tbit,Tint16, Tint32,Tint32, Tint32) - X(Tbit,Tuns16, Tint32,Tint32, Tint32) - X(Tbit,Tint32, Tint32,Tint32, Tint32) - X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tbit,Tint64, Tint64,Tint64, Tint64) - X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tbool,Tbool, Tbool,Tbool, Tbool) - X(Tbool,Tint8, Tint32,Tint32, Tint32) - X(Tbool,Tuns8, Tint32,Tint32, Tint32) - X(Tbool,Tint16, Tint32,Tint32, Tint32) - X(Tbool,Tuns16, Tint32,Tint32, Tint32) - X(Tbool,Tint32, Tint32,Tint32, Tint32) - X(Tbool,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tbool,Tint64, Tint64,Tint64, Tint64) - X(Tbool,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tbool,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tbool,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tbool,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tbool,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tbool,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tbool,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tbool,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tbool,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tbool,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint8,Tint8, Tint32,Tint32, Tint32) - X(Tint8,Tuns8, Tint32,Tint32, Tint32) - X(Tint8,Tint16, Tint32,Tint32, Tint32) - X(Tint8,Tuns16, Tint32,Tint32, Tint32) - X(Tint8,Tint32, Tint32,Tint32, Tint32) - X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint8,Tint64, Tint64,Tint64, Tint64) - X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns8,Tuns8, Tint32,Tint32, Tint32) - X(Tuns8,Tint16, Tint32,Tint32, Tint32) - X(Tuns8,Tuns16, Tint32,Tint32, Tint32) - X(Tuns8,Tint32, Tint32,Tint32, Tint32) - X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns8,Tint64, Tint64,Tint64, Tint64) - X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint16,Tint16, Tint32,Tint32, Tint32) - X(Tint16,Tuns16, Tint32,Tint32, Tint32) - X(Tint16,Tint32, Tint32,Tint32, Tint32) - X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint16,Tint64, Tint64,Tint64, Tint64) - X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns16,Tuns16, Tint32,Tint32, Tint32) - X(Tuns16,Tint32, Tint32,Tint32, Tint32) - X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns16,Tint64, Tint64,Tint64, Tint64) - X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint32,Tint32, Tint32,Tint32, Tint32) - X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tint32,Tint64, Tint64,Tint64, Tint64) - X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32) - X(Tuns32,Tint64, Tint64,Tint64, Tint64) - X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tint64,Tint64, Tint64,Tint64, Tint64) - X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64) - - X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) - X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) - X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) - X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) - X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) - X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) - X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80) - - X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80) - X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80) - X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80) - - X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80) - X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80) - X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32) - X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64) - X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32) - X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64) - X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) - X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80) - - X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80) - X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80) - X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32) - X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) - X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) - X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - - /* ======================= */ - - X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) - -#undef X - -#define Y(t1,t2) impcnvWarn[t1][t2] = 1; - Y(Tint8, Tbit) - Y(Tuns8, Tbit) - Y(Tint16, Tbit) - Y(Tuns16, Tbit) - Y(Tint32, Tbit) - Y(Tuns32, Tbit) - Y(Tint64, Tbit) - Y(Tuns64, Tbit) - - Y(Tuns8, Tint8) - Y(Tint16, Tint8) - Y(Tuns16, Tint8) - Y(Tint32, Tint8) - Y(Tuns32, Tint8) - Y(Tint64, Tint8) - Y(Tuns64, Tint8) - - Y(Tint8, Tuns8) - Y(Tint16, Tuns8) - Y(Tuns16, Tuns8) - Y(Tint32, Tuns8) - Y(Tuns32, Tuns8) - Y(Tint64, Tuns8) - Y(Tuns64, Tuns8) - - Y(Tint8, Tchar) - Y(Tint16, Tchar) - Y(Tuns16, Tchar) - Y(Tint32, Tchar) - Y(Tuns32, Tchar) - Y(Tint64, Tchar) - Y(Tuns64, Tchar) - - Y(Tuns16, Tint16) - Y(Tint32, Tint16) - Y(Tuns32, Tint16) - Y(Tint64, Tint16) - Y(Tuns64, Tint16) - - Y(Tint16, Tuns16) - Y(Tint32, Tuns16) - Y(Tuns32, Tuns16) - Y(Tint64, Tuns16) - Y(Tuns64, Tuns16) - - Y(Tint16, Twchar) - Y(Tint32, Twchar) - Y(Tuns32, Twchar) - Y(Tint64, Twchar) - Y(Tuns64, Twchar) - -// Y(Tuns32, Tint32) - Y(Tint64, Tint32) - Y(Tuns64, Tint32) - -// Y(Tint32, Tuns32) - Y(Tint64, Tuns32) - Y(Tuns64, Tuns32) - - Y(Tint64, Tdchar) - Y(Tuns64, Tdchar) - -// Y(Tint64, Tuns64) -// Y(Tuns64, Tint64) - - for (i = 0; i < TMAX; i++) - for (j = 0; j < TMAX; j++) - { - if (impcnvResult[i][j] == Terror) - { - impcnvResult[i][j] = impcnvResult[j][i]; - impcnvType1[i][j] = impcnvType2[j][i]; - impcnvType2[i][j] = impcnvType1[j][i]; - } - } -} - -int main() -{ FILE *fp; - int i; - int j; - - init(); - - fp = fopen("impcnvtab.c","w"); - - fprintf(fp,"// This file is generated by impcnvgen.c\n"); - fprintf(fp,"#include \"mtype.h\"\n"); - - fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvResult[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvType1[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvType2[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n"); - for (i = 0; i < TMAX; i++) - { - for (j = 0; j < TMAX; j++) - { - fprintf(fp, "%d,",impcnvWarn[i][j]); - } - fprintf(fp, "\n"); - } - fprintf(fp,"};\n"); - - fclose(fp); - return EXIT_SUCCESS; -} + +// 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 +#include + +#include "mtype.h" + +enum TY impcnvResult[TMAX][TMAX]; +enum TY impcnvType1[TMAX][TMAX]; +enum TY impcnvType2[TMAX][TMAX]; +int impcnvWarn[TMAX][TMAX]; + +int integral_promotion(int t) +{ + switch (t) + { + case Tchar: + case Twchar: + case Tbit: + case Tbool: + case Tint8: + case Tuns8: + case Tint16: + case Tuns16: return Tint32; + case Tdchar: return Tuns32; + default: return t; + } +} + +void init() +{ int i, j; + + // Set conversion tables + for (i = 0; i < TMAX; i++) + for (j = 0; j < TMAX; j++) + { impcnvResult[i][j] = Terror; + impcnvType1[i][j] = Terror; + impcnvType2[i][j] = Terror; + impcnvWarn[i][j] = 0; + } + +#define X(t1,t2, nt1,nt2, rt) \ + impcnvResult[t1][t2] = rt; \ + impcnvType1[t1][t2] = nt1; \ + impcnvType2[t1][t2] = nt2; + + /* ======================= */ + + X(Tbit,Tbit, Tint32,Tint32, Tint32) + X(Tbit,Tint8, Tint32,Tint32, Tint32) + X(Tbit,Tuns8, Tint32,Tint32, Tint32) + X(Tbit,Tint16, Tint32,Tint32, Tint32) + X(Tbit,Tuns16, Tint32,Tint32, Tint32) + X(Tbit,Tint32, Tint32,Tint32, Tint32) + X(Tbit,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tbit,Tint64, Tint64,Tint64, Tint64) + X(Tbit,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tbit,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tbit,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tbit,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tbit,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tbit,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tbit,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tbit,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tbit,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tbit,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tbool,Tbool, Tbool,Tbool, Tbool) + X(Tbool,Tint8, Tint32,Tint32, Tint32) + X(Tbool,Tuns8, Tint32,Tint32, Tint32) + X(Tbool,Tint16, Tint32,Tint32, Tint32) + X(Tbool,Tuns16, Tint32,Tint32, Tint32) + X(Tbool,Tint32, Tint32,Tint32, Tint32) + X(Tbool,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tbool,Tint64, Tint64,Tint64, Tint64) + X(Tbool,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tbool,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tbool,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tbool,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tbool,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tbool,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tbool,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tbool,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tbool,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tbool,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tint8,Tint8, Tint32,Tint32, Tint32) + X(Tint8,Tuns8, Tint32,Tint32, Tint32) + X(Tint8,Tint16, Tint32,Tint32, Tint32) + X(Tint8,Tuns16, Tint32,Tint32, Tint32) + X(Tint8,Tint32, Tint32,Tint32, Tint32) + X(Tint8,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tint8,Tint64, Tint64,Tint64, Tint64) + X(Tint8,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tint8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tint8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tint8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tint8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tint8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tint8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tint8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tint8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tint8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tuns8,Tuns8, Tint32,Tint32, Tint32) + X(Tuns8,Tint16, Tint32,Tint32, Tint32) + X(Tuns8,Tuns16, Tint32,Tint32, Tint32) + X(Tuns8,Tint32, Tint32,Tint32, Tint32) + X(Tuns8,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tuns8,Tint64, Tint64,Tint64, Tint64) + X(Tuns8,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tuns8,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tuns8,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tuns8,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tuns8,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tuns8,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tuns8,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tuns8,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tuns8,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tuns8,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tint16,Tint16, Tint32,Tint32, Tint32) + X(Tint16,Tuns16, Tint32,Tint32, Tint32) + X(Tint16,Tint32, Tint32,Tint32, Tint32) + X(Tint16,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tint16,Tint64, Tint64,Tint64, Tint64) + X(Tint16,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tint16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tint16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tint16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tint16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tint16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tint16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tint16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tint16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tint16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tuns16,Tuns16, Tint32,Tint32, Tint32) + X(Tuns16,Tint32, Tint32,Tint32, Tint32) + X(Tuns16,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tuns16,Tint64, Tint64,Tint64, Tint64) + X(Tuns16,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tuns16,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tuns16,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tuns16,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tuns16,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tuns16,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tuns16,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tuns16,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tuns16,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tuns16,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tint32,Tint32, Tint32,Tint32, Tint32) + X(Tint32,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tint32,Tint64, Tint64,Tint64, Tint64) + X(Tint32,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tint32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tint32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tint32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tint32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tint32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tint32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tint32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tint32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tint32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tuns32,Tuns32, Tuns32,Tuns32, Tuns32) + X(Tuns32,Tint64, Tint64,Tint64, Tint64) + X(Tuns32,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tuns32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tuns32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tuns32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tuns32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tuns32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tuns32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tuns32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tuns32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tuns32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tint64,Tint64, Tint64,Tint64, Tint64) + X(Tint64,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tint64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tint64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tint64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tint64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tint64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tint64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tint64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tint64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tint64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tuns64,Tuns64, Tuns64,Tuns64, Tuns64) + + X(Tuns64,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tuns64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tuns64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + X(Tuns64,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tuns64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tuns64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + X(Tuns64,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tuns64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tuns64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tfloat32,Tfloat32, Tfloat32,Tfloat32, Tfloat32) + X(Tfloat32,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tfloat32,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + + X(Tfloat32,Timaginary32, Tfloat32,Timaginary32, Tfloat32) + X(Tfloat32,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tfloat32,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + + X(Tfloat32,Tcomplex32, Tfloat32,Tcomplex32, Tcomplex32) + X(Tfloat32,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tfloat32,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tfloat64,Tfloat64, Tfloat64,Tfloat64, Tfloat64) + X(Tfloat64,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + + X(Tfloat64,Timaginary32, Tfloat64,Timaginary64, Tfloat64) + X(Tfloat64,Timaginary64, Tfloat64,Timaginary64, Tfloat64) + X(Tfloat64,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + + X(Tfloat64,Tcomplex32, Tfloat64,Tcomplex64, Tcomplex64) + X(Tfloat64,Tcomplex64, Tfloat64,Tcomplex64, Tcomplex64) + X(Tfloat64,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tfloat80,Tfloat80, Tfloat80,Tfloat80, Tfloat80) + + X(Tfloat80,Timaginary32, Tfloat80,Timaginary80, Tfloat80) + X(Tfloat80,Timaginary64, Tfloat80,Timaginary80, Tfloat80) + X(Tfloat80,Timaginary80, Tfloat80,Timaginary80, Tfloat80) + + X(Tfloat80,Tcomplex32, Tfloat80,Tcomplex80, Tcomplex80) + X(Tfloat80,Tcomplex64, Tfloat80,Tcomplex80, Tcomplex80) + X(Tfloat80,Tcomplex80, Tfloat80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Timaginary32,Timaginary32, Timaginary32,Timaginary32, Timaginary32) + X(Timaginary32,Timaginary64, Timaginary64,Timaginary64, Timaginary64) + X(Timaginary32,Timaginary80, Timaginary80,Timaginary80, Timaginary80) + + X(Timaginary32,Tcomplex32, Timaginary32,Tcomplex32, Tcomplex32) + X(Timaginary32,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) + X(Timaginary32,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Timaginary64,Timaginary64, Timaginary64,Timaginary64, Timaginary64) + X(Timaginary64,Timaginary80, Timaginary80,Timaginary80, Timaginary80) + + X(Timaginary64,Tcomplex32, Timaginary64,Tcomplex64, Tcomplex64) + X(Timaginary64,Tcomplex64, Timaginary64,Tcomplex64, Tcomplex64) + X(Timaginary64,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Timaginary80,Timaginary80, Timaginary80,Timaginary80, Timaginary80) + + X(Timaginary80,Tcomplex32, Timaginary80,Tcomplex80, Tcomplex80) + X(Timaginary80,Tcomplex64, Timaginary80,Tcomplex80, Tcomplex80) + X(Timaginary80,Tcomplex80, Timaginary80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tcomplex32,Tcomplex32, Tcomplex32,Tcomplex32, Tcomplex32) + X(Tcomplex32,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) + X(Tcomplex32,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tcomplex64,Tcomplex64, Tcomplex64,Tcomplex64, Tcomplex64) + X(Tcomplex64,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) + + /* ======================= */ + + X(Tcomplex80,Tcomplex80, Tcomplex80,Tcomplex80, Tcomplex80) + +#undef X + +#define Y(t1,t2) impcnvWarn[t1][t2] = 1; + Y(Tint8, Tbit) + Y(Tuns8, Tbit) + Y(Tint16, Tbit) + Y(Tuns16, Tbit) + Y(Tint32, Tbit) + Y(Tuns32, Tbit) + Y(Tint64, Tbit) + Y(Tuns64, Tbit) + + Y(Tuns8, Tint8) + Y(Tint16, Tint8) + Y(Tuns16, Tint8) + Y(Tint32, Tint8) + Y(Tuns32, Tint8) + Y(Tint64, Tint8) + Y(Tuns64, Tint8) + + Y(Tint8, Tuns8) + Y(Tint16, Tuns8) + Y(Tuns16, Tuns8) + Y(Tint32, Tuns8) + Y(Tuns32, Tuns8) + Y(Tint64, Tuns8) + Y(Tuns64, Tuns8) + + Y(Tint8, Tchar) + Y(Tint16, Tchar) + Y(Tuns16, Tchar) + Y(Tint32, Tchar) + Y(Tuns32, Tchar) + Y(Tint64, Tchar) + Y(Tuns64, Tchar) + + Y(Tuns16, Tint16) + Y(Tint32, Tint16) + Y(Tuns32, Tint16) + Y(Tint64, Tint16) + Y(Tuns64, Tint16) + + Y(Tint16, Tuns16) + Y(Tint32, Tuns16) + Y(Tuns32, Tuns16) + Y(Tint64, Tuns16) + Y(Tuns64, Tuns16) + + Y(Tint16, Twchar) + Y(Tint32, Twchar) + Y(Tuns32, Twchar) + Y(Tint64, Twchar) + Y(Tuns64, Twchar) + +// Y(Tuns32, Tint32) + Y(Tint64, Tint32) + Y(Tuns64, Tint32) + +// Y(Tint32, Tuns32) + Y(Tint64, Tuns32) + Y(Tuns64, Tuns32) + + Y(Tint64, Tdchar) + Y(Tuns64, Tdchar) + +// Y(Tint64, Tuns64) +// Y(Tuns64, Tint64) + + for (i = 0; i < TMAX; i++) + for (j = 0; j < TMAX; j++) + { + if (impcnvResult[i][j] == Terror) + { + impcnvResult[i][j] = impcnvResult[j][i]; + impcnvType1[i][j] = impcnvType2[j][i]; + impcnvType2[i][j] = impcnvType1[j][i]; + } + } +} + +int main() +{ FILE *fp; + int i; + int j; + + init(); + + fp = fopen("impcnvtab.c","w"); + + fprintf(fp,"// This file is generated by impcnvgen.c\n"); + fprintf(fp,"#include \"mtype.h\"\n"); + + fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n"); + for (i = 0; i < TMAX; i++) + { + for (j = 0; j < TMAX; j++) + { + fprintf(fp, "%d,",impcnvResult[i][j]); + } + fprintf(fp, "\n"); + } + fprintf(fp,"};\n"); + + fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n"); + for (i = 0; i < TMAX; i++) + { + for (j = 0; j < TMAX; j++) + { + fprintf(fp, "%d,",impcnvType1[i][j]); + } + fprintf(fp, "\n"); + } + fprintf(fp,"};\n"); + + fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n"); + for (i = 0; i < TMAX; i++) + { + for (j = 0; j < TMAX; j++) + { + fprintf(fp, "%d,",impcnvType2[i][j]); + } + fprintf(fp, "\n"); + } + fprintf(fp,"};\n"); + + fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n"); + for (i = 0; i < TMAX; i++) + { + for (j = 0; j < TMAX; j++) + { + fprintf(fp, "%d,",impcnvWarn[i][j]); + } + fprintf(fp, "\n"); + } + fprintf(fp,"};\n"); + + fclose(fp); + return EXIT_SUCCESS; +} diff --git a/dmd/imphint.c b/dmd/imphint.c index c52ffb96..96b1b88a 100644 --- a/dmd/imphint.c +++ b/dmd/imphint.c @@ -1,82 +1,82 @@ - - -// Compiler implementation of the D programming language -// Copyright (c) 2010 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 -#include -#include -#include -#include - -/****************************************** - * Looks for undefined identifier s to see - * if it might be undefined because an import - * was not specified. - * Not meant to be a comprehensive list of names in each module, - * just the most common ones. - */ - -const char *importHint(const char *s) -{ -#if DMDV1 - static const char *modules[] = - { "tango.stdc.stdio", - "tango.io.Stdout", - "tango.math.Math", - }; - static const char *names[] = - { - "printf", NULL, - "Stdout", NULL, - "sin", "cos", "sqrt", "abs", NULL, - }; -#else - static const char *modules[] = - { "core.stdc.stdio", - "std.stdio", - "std.math", - }; - static const char *names[] = - { - "printf", NULL, - "writeln", NULL, - "sin", "cos", "sqrt", "fabs", NULL, - }; -#endif - int m = 0; - for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) - { - const char *p = names[n]; - if (p == NULL) - { m++; - continue; - } - assert(m < sizeof(modules)/sizeof(modules[0])); - if (strcmp(s, p) == 0) - return modules[m]; - } - return NULL; // didn't find it -} - -#if UNITTEST - -void unittest_importHint() -{ - const char *p; - - p = importHint("printf"); - assert(p); - p = importHint("fabs"); - assert(p); - p = importHint("xxxxx"); - assert(!p); -} - -#endif + + +// Compiler implementation of the D programming language +// Copyright (c) 2010 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 +#include +#include +#include +#include + +/****************************************** + * Looks for undefined identifier s to see + * if it might be undefined because an import + * was not specified. + * Not meant to be a comprehensive list of names in each module, + * just the most common ones. + */ + +const char *importHint(const char *s) +{ +#if DMDV1 + static const char *modules[] = + { "tango.stdc.stdio", + "tango.io.Stdout", + "tango.math.Math", + }; + static const char *names[] = + { + "printf", NULL, + "Stdout", NULL, + "sin", "cos", "sqrt", "abs", NULL, + }; +#else + static const char *modules[] = + { "core.stdc.stdio", + "std.stdio", + "std.math", + }; + static const char *names[] = + { + "printf", NULL, + "writeln", NULL, + "sin", "cos", "sqrt", "fabs", NULL, + }; +#endif + int m = 0; + for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) + { + const char *p = names[n]; + if (p == NULL) + { m++; + continue; + } + assert(m < sizeof(modules)/sizeof(modules[0])); + if (strcmp(s, p) == 0) + return modules[m]; + } + return NULL; // didn't find it +} + +#if UNITTEST + +void unittest_importHint() +{ + const char *p; + + p = importHint("printf"); + assert(p); + p = importHint("fabs"); + assert(p); + p = importHint("xxxxx"); + assert(!p); +} + +#endif diff --git a/dmd/import.c b/dmd/import.c index add1f094..7cbed18f 100644 --- a/dmd/import.c +++ b/dmd/import.c @@ -25,9 +25,9 @@ /********************************* Import ****************************/ -Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, +Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, int isstatic) - : Dsymbol() + : Dsymbol() { assert(id); this->loc = loc; @@ -63,11 +63,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s) { assert(!s); - Import *si = new Import(loc, packages, id, aliasId, isstatic); + Import *si = new Import(loc, packages, id, aliasId, isstatic); for (size_t i = 0; i < names.dim; i++) { - si->addAlias(names[i], aliases[i]); + si->addAlias(names[i], aliases[i]); } return si; @@ -135,12 +135,12 @@ void Import::importAll(Scope *sc) load(sc); mod->importAll(0); - /* Default to private importing - */ - enum PROT prot = sc->protection; - if (!sc->explicitProtection) - prot = PROTprivate; - sc->scopesym->importScope(this, prot); + /* Default to private importing + */ + enum PROT prot = sc->protection; + if (!sc->explicitProtection) + prot = PROTprivate; + sc->scopesym->importScope(this, prot); } } @@ -172,29 +172,29 @@ void Import::semantic(Scope *sc) /* Default to private importing */ - enum PROT prot = sc->protection; + enum PROT prot = sc->protection; if (!sc->explicitProtection) - prot = PROTprivate; - for (Scope *scd = sc; scd; scd = scd->enclosing) + prot = PROTprivate; + for (Scope *scd = sc; scd; scd = scd->enclosing) { - if (scd->scopesym) - { - scd->scopesym->importScope(this, prot); - break; - } + if (scd->scopesym) + { + scd->scopesym->importScope(this, prot); + break; + } } mod->semantic(); if (mod->needmoduleinfo) - { //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars()); + { //printf("module4 %s because of %s\n", sc->module->toChars(), mod->toChars()); sc->module->needmoduleinfo = 1; - } + } - if (aliasId) - { - AliasDeclaration *ad = new AliasDeclaration(loc, aliasId, mod); - sc->insert(ad); + if (aliasId) + { + AliasDeclaration *ad = new AliasDeclaration(loc, aliasId, mod); + sc->insert(ad); ad->semantic(sc); } } @@ -231,7 +231,7 @@ void Import::semantic(Scope *sc) { for (size_t i = 0; i < packages->dim; i++) { - Identifier *pid = (*packages)[i]; + Identifier *pid = (*packages)[i]; ob->printf("%s.", pid->toChars()); } } @@ -251,8 +251,8 @@ void Import::semantic(Scope *sc) else ob->writebyte(','); - Identifier *name = names[i]; - Identifier *alias = aliases[i]; + Identifier *name = names[i]; + Identifier *alias = aliases[i]; if (!alias) { @@ -277,7 +277,7 @@ void Import::semantic2(Scope *sc) //printf("Import::semantic2('%s')\n", toChars()); mod->semantic2(); if (mod->needmoduleinfo) - { //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars()); + { //printf("module5 %s because of %s\n", sc->module->toChars(), mod->toChars()); sc->module->needmoduleinfo = 1; } } @@ -291,50 +291,50 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags) mod->semantic(); } - if (names.dim) // selective import - { - for (size_t i = 0; i < names.dim; i++) - { - Identifier *name = (Identifier *)names[i]; - Identifier *alias = (Identifier *)aliases[i]; + if (names.dim) // selective import + { + for (size_t i = 0; i < names.dim; i++) + { + Identifier *name = (Identifier *)names[i]; + Identifier *alias = (Identifier *)aliases[i]; - if (!alias) - alias = name; - - if (alias->equals(ident)) - return mod->search(loc, name, flags); - } - - // What should happen when renamed and selective imports are mixed? - // This makes the whole module available with the renamed id. - if (aliasId && aliasId->equals(ident)) - return mod; - } - else // non-selective import - { - // For renamed imports, only the alias name is visible. - if (aliasId) - { - if (aliasId->equals(ident)) - return mod; - return 0; - } - - // For non-static imports, prefer symbols in the module over the module name. - if (!isstatic) - { - Dsymbol *s = mod->search(loc, ident, flags); - if (s) - return s; - } - - // Make the start of the package name available. - if (pkg->ident->equals(ident)) - { - return pkg; - } - } - return 0; + if (!alias) + alias = name; + + if (alias->equals(ident)) + return mod->search(loc, name, flags); + } + + // What should happen when renamed and selective imports are mixed? + // This makes the whole module available with the renamed id. + if (aliasId && aliasId->equals(ident)) + return mod; + } + else // non-selective import + { + // For renamed imports, only the alias name is visible. + if (aliasId) + { + if (aliasId->equals(ident)) + return mod; + return 0; + } + + // For non-static imports, prefer symbols in the module over the module name. + if (!isstatic) + { + Dsymbol *s = mod->search(loc, ident, flags); + if (s) + return s; + } + + // Make the start of the package name available. + if (pkg->ident->equals(ident)) + { + return pkg; + } + } + return 0; } void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -352,7 +352,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (packages && packages->dim) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = (*packages)[i]; + { Identifier *pid = (*packages)[i]; buf->printf("%s.", pid->toChars()); } @@ -381,7 +381,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); } -char *Import::toChars() -{ - return id->toChars(); -} +char *Import::toChars() +{ + return id->toChars(); +} diff --git a/dmd/import.h b/dmd/import.h index 872e1301..e054bbb7 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -28,21 +28,21 @@ struct HdrGenState; struct Import : Dsymbol { - // isstatic import aliasId = packages.id; - Identifiers *packages; // array of Identifier's representing packages + // isstatic import aliasId = packages.id; + Identifiers *packages; // array of Identifier's representing packages Identifier *id; // module Identifier Identifier *aliasId; int isstatic; // !=0 if static import enum PROT protection; // Pairs of alias=name to bind into current namespace - Identifiers names; - Identifiers aliases; + Identifiers names; + Identifiers aliases; Module *mod; Package *pkg; // leftmost package/module - Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, + Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId, int isstatic); void addAlias(Identifier *name, Identifier *alias); @@ -55,7 +55,7 @@ struct Import : Dsymbol void semantic2(Scope *sc); Dsymbol *search(Loc loc, Identifier *ident, int flags); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - char *toChars(); + char *toChars(); Import *isImport() { return this; } }; diff --git a/dmd/init.c b/dmd/init.c index 9fdda975..9c269790 100644 --- a/dmd/init.c +++ b/dmd/init.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -34,7 +34,7 @@ Initializer *Initializer::syntaxCopy() return this; } -Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret) { return this; } @@ -52,7 +52,7 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai) { a = new Initializers(); a->setDim(ai->dim); - for (size_t i = 0; i < a->dim; i++) + for (size_t i = 0; i < a->dim; i++) { Initializer *e = (Initializer *)ai->data[i]; e = e->syntaxCopy(); @@ -87,7 +87,7 @@ Initializer *VoidInitializer::syntaxCopy() } -Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret) { //printf("VoidInitializer::semantic(t = %p)\n", t); type = t; @@ -126,7 +126,7 @@ Initializer *StructInitializer::syntaxCopy() assert(field.dim == value.dim); ai->field.setDim(field.dim); ai->value.setDim(value.dim); - for (size_t i = 0; i < field.dim; i++) + for (size_t i = 0; i < field.dim; i++) { ai->field.data[i] = field.data[i]; @@ -144,7 +144,7 @@ void StructInitializer::addInit(Identifier *field, Initializer *value) this->value.push(value); } -Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) { int errors = 0; @@ -152,35 +152,35 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) vars.setDim(field.dim); t = t->toBasetype(); if (t->ty == Tstruct) - { + { unsigned fieldi = 0; - TypeStruct *ts = (TypeStruct *)t; + TypeStruct *ts = (TypeStruct *)t; ad = ts->sym; - size_t nfields = ad->fields.dim; -#if DMDV2 - if (((StructDeclaration *)ad)->isnested) - nfields--; // don't count pointer to outer -#endif - for (size_t i = 0; i < field.dim; i++) + size_t nfields = ad->fields.dim; +#if DMDV2 + if (((StructDeclaration *)ad)->isnested) + nfields--; // don't count pointer to outer +#endif + for (size_t i = 0; i < field.dim; i++) { - Identifier *id = field[i]; - Initializer *val = value[i]; + Identifier *id = field[i]; + Initializer *val = value[i]; Dsymbol *s; VarDeclaration *v; if (id == NULL) { - if (fieldi >= nfields) + if (fieldi >= nfields) { error(loc, "too many initializers for %s", ad->toChars()); - errors = 1; + errors = 1; field.remove(i); i--; continue; } else { - s = ad->fields[fieldi]; + s = ad->fields[fieldi]; } } else @@ -190,28 +190,28 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) if (!s) { error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); - errors = 1; + errors = 1; continue; } - s = s->toAlias(); + s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { - if (fieldi >= nfields) + if (fieldi >= nfields) { - error(loc, "%s.%s is not a per-instance initializable field", - t->toChars(), s->toChars()); - errors = 1; + error(loc, "%s.%s is not a per-instance initializable field", + t->toChars(), s->toChars()); + errors = 1; break; } - if (s == ad->fields[fieldi]) + if (s == ad->fields[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { - val = val->semantic(sc, v->type, needInterpret); + val = val->semantic(sc, v->type, needInterpret); value.data[i] = (void *)val; vars.data[i] = (void *)v; } @@ -232,7 +232,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) fd->endloc = loc; Expression *e = new FuncExp(loc, fd); ExpInitializer *ie = new ExpInitializer(loc, e); - return ie->semantic(sc, t, needInterpret); + return ie->semantic(sc, t, needInterpret); } else { @@ -265,97 +265,97 @@ Expression *StructInitializer::toExpression() if (!sd) return NULL; Expressions *elements = new Expressions(); - size_t nfields = ad->fields.dim; -#if DMDV2 - if (sd->isnested) - nfields--; -#endif - elements->setDim(nfields); - for (size_t i = 0; i < elements->dim; i++) - { - elements->data[i] = NULL; - } - unsigned fieldi = 0; + size_t nfields = ad->fields.dim; +#if DMDV2 + if (sd->isnested) + nfields--; +#endif + elements->setDim(nfields); + for (size_t i = 0; i < elements->dim; i++) + { + elements->data[i] = NULL; + } + unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) { - Identifier *id = field[i]; - if (id) - { - Dsymbol * s = ad->search(loc, id, 0); - if (!s) - { - error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); - goto Lno; - } - s = s->toAlias(); - - // Find out which field index it is - for (fieldi = 0; 1; fieldi++) - { - if (fieldi >= nfields) - { - s->error("is not a per-instance initializable field"); - goto Lno; - } - if (s == ad->fields[fieldi]) - break; - } - } - else if (fieldi >= nfields) - { error(loc, "too many initializers for '%s'", ad->toChars()); + Identifier *id = field[i]; + if (id) + { + Dsymbol * s = ad->search(loc, id, 0); + if (!s) + { + error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); + goto Lno; + } + s = s->toAlias(); + + // Find out which field index it is + for (fieldi = 0; 1; fieldi++) + { + if (fieldi >= nfields) + { + s->error("is not a per-instance initializable field"); + goto Lno; + } + if (s == ad->fields[fieldi]) + break; + } + } + else if (fieldi >= nfields) + { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; - } + } Initializer *iz = (Initializer *)value.data[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; - if (elements->data[fieldi]) - { error(loc, "duplicate initializer for field '%s'", - ((Dsymbol *)ad->fields.data[fieldi])->toChars()); - goto Lno; - } - elements->data[fieldi] = ex; - ++fieldi; - } - // Now, fill in any missing elements with default initializers. - // We also need to validate any anonymous unions - for (size_t i = 0; i < elements->dim; ) - { - VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration(); - int unionSize = ad->numFieldsInUnion(i); - if (unionSize == 1) - { // Not a union -- default initialize if missing - if (!elements->data[i]) - elements->data[i] = vd->type->defaultInit(); - } - else - { // anonymous union -- check for errors - int found = -1; // index of the first field with an initializer - for (int j = i; j < i + unionSize; ++j) - { - if (!elements->data[j]) - continue; - if (found >= 0) - { - VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration(); - VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration(); - error(loc, "%s cannot have initializers for fields %s and %s in same union", - ad->toChars(), - v1->toChars(), v->toChars()); - goto Lno; - } - found = j; - } - if (found == -1) - { - error(loc, "no initializer for union that contains field %s", - vd->toChars()); - goto Lno; - } - } - i += unionSize; + if (elements->data[fieldi]) + { error(loc, "duplicate initializer for field '%s'", + ((Dsymbol *)ad->fields.data[fieldi])->toChars()); + goto Lno; + } + elements->data[fieldi] = ex; + ++fieldi; + } + // Now, fill in any missing elements with default initializers. + // We also need to validate any anonymous unions + for (size_t i = 0; i < elements->dim; ) + { + VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration(); + int unionSize = ad->numFieldsInUnion(i); + if (unionSize == 1) + { // Not a union -- default initialize if missing + if (!elements->data[i]) + elements->data[i] = vd->type->defaultInit(); + } + else + { // anonymous union -- check for errors + int found = -1; // index of the first field with an initializer + for (int j = i; j < i + unionSize; ++j) + { + if (!elements->data[j]) + continue; + if (found >= 0) + { + VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration(); + VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration(); + error(loc, "%s cannot have initializers for fields %s and %s in same union", + ad->toChars(), + v1->toChars(), v->toChars()); + goto Lno; + } + found = j; + } + if (found == -1) + { + error(loc, "no initializer for union that contains field %s", + vd->toChars()); + goto Lno; + } + } + i += unionSize; } e = new StructLiteralExp(loc, sd, elements); e->type = sd->type; @@ -371,7 +371,7 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { //printf("StructInitializer::toCBuffer()\n"); buf->writebyte('{'); - for (size_t i = 0; i < field.dim; i++) + for (size_t i = 0; i < field.dim; i++) { if (i > 0) buf->writebyte(','); @@ -407,7 +407,7 @@ Initializer *ArrayInitializer::syntaxCopy() assert(index.dim == value.dim); ai->index.setDim(index.dim); ai->value.setDim(value.dim); - for (size_t i = 0; i < ai->value.dim; i++) + for (size_t i = 0; i < ai->value.dim; i++) { Expression *e = (Expression *)index.data[i]; if (e) e = e->syntaxCopy(); @@ -428,7 +428,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value) type = NULL; } -Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) { unsigned i; unsigned length; const unsigned amax = 0x80000000; @@ -454,17 +454,17 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) length = 0; for (i = 0; i < index.dim; i++) { - Expression *idx = index[i]; + Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); - index[i] = idx; + index[i] = idx; length = idx->toInteger(); } - Initializer *val = value[i]; - val = val->semantic(sc, t->nextOf(), needInterpret); - value[i] = val; + Initializer *val = value[i]; + val = val->semantic(sc, t->nextOf(), needInterpret); + value[i] = val; length++; if (length == 0) { error(loc, "array dimension overflow"); @@ -531,8 +531,8 @@ Expression *ArrayInitializer::toExpression() edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index[i]) - j = (index[i])->toInteger(); + if (index[i]) + j = (index[i])->toInteger(); if (j >= edim) edim = j + 1; } @@ -542,10 +542,10 @@ Expression *ArrayInitializer::toExpression() elements->setDim(edim); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index[i]) - j = (index[i])->toInteger(); + if (index[i]) + j = (index[i])->toInteger(); assert(j < edim); - Initializer *iz = value[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); @@ -553,7 +553,7 @@ Expression *ArrayInitializer::toExpression() { goto Lno; } - (*elements)[j] = ex; + (*elements)[j] = ex; } /* Fill in any missing elements with the default initializer @@ -562,13 +562,13 @@ Expression *ArrayInitializer::toExpression() Expression *init = NULL; for (size_t i = 0; i < edim; i++) { - if (!(*elements)[i]) + if (!(*elements)[i]) { if (!type) goto Lno; if (!init) init = t->next->defaultInit(); - (*elements)[i] = init; + (*elements)[i] = init; } } @@ -588,30 +588,30 @@ Lno: */ Initializer *ArrayInitializer::toAssocArrayInitializer() -{ +{ Expression *e; //printf("ArrayInitializer::toAssocArrayInitializer()\n"); //static int i; if (++i == 2) halt(); - Expressions *keys = new Expressions(); + Expressions *keys = new Expressions(); keys->setDim(value.dim); - Expressions *values = new Expressions(); + Expressions *values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { - e = index.tdata()[i]; + e = index.tdata()[i]; if (!e) goto Lno; - keys->tdata()[i] = e; + keys->tdata()[i] = e; - Initializer *iz = value.tdata()[i]; + Initializer *iz = value.tdata()[i]; if (!iz) goto Lno; e = iz->toExpression(); if (!e) goto Lno; - values->tdata()[i] = e; + values->tdata()[i] = e; } e = new AssocArrayLiteralExp(loc, keys, values); return new ExpInitializer(loc, e); @@ -663,17 +663,17 @@ Laa: void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writebyte('['); - for (size_t i = 0; i < index.dim; i++) + for (size_t i = 0; i < index.dim; i++) { if (i > 0) buf->writebyte(','); - Expression *ex = index.tdata()[i]; + Expression *ex = index.tdata()[i]; if (ex) { ex->toCBuffer(buf, hgs); buf->writebyte(':'); } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value.tdata()[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -694,19 +694,19 @@ Initializer *ExpInitializer::syntaxCopy() return new ExpInitializer(loc, exp->syntaxCopy()); } -Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) { //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); exp = exp->semantic(sc); - int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue; - - int olderrors = global.errors; - exp = exp->optimize(wantOptimize); - if (!global.gag && olderrors != global.errors) - return this; // Failed, suppress duplicate error messages - - if (exp->op == TOKtype) - error("initializer must be an expression, not '%s'", exp->toChars()); + int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue; + + int olderrors = global.errors; + exp = exp->optimize(wantOptimize); + if (!global.gag && olderrors != global.errors) + return this; // Failed, suppress duplicate error messages + + if (exp->op == TOKtype) + error("initializer must be an expression, not '%s'", exp->toChars()); Type *tb = t->toBasetype(); /* Look for case of initializing a static array with a too-short @@ -739,7 +739,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) exp = exp->implicitCastTo(sc, t); L1: - exp = exp->optimize(wantOptimize); + exp = exp->optimize(wantOptimize); //printf("-ExpInitializer::semantic(): "); exp->print(); return this; } diff --git a/dmd/init.h b/dmd/init.h index b695380d..35e314e2 100644 --- a/dmd/init.h +++ b/dmd/init.h @@ -1,148 +1,148 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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. - -#ifndef INIT_H -#define INIT_H - -#include "root.h" - -#include "mars.h" -#include "arraytypes.h" - -struct Identifier; -struct Expression; -struct Scope; -struct Type; -struct dt_t; -struct AggregateDeclaration; -struct VoidInitializer; -struct StructInitializer; -struct ArrayInitializer; -struct ExpInitializer; -struct HdrGenState; - - -#if IN_LLVM -namespace llvm { - class StructType; -} -#endif - -struct Initializer : Object -{ - Loc loc; - - Initializer(Loc loc); - virtual Initializer *syntaxCopy(); - // needInterpret is WANTinterpret if must be a manifest constant, 0 if not. - virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret); - virtual Type *inferType(Scope *sc); - virtual Expression *toExpression() = 0; - virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; - char *toChars(); - - static Initializers *arraySyntaxCopy(Initializers *ai); - -#if IN_DMD - virtual dt_t *toDt(); -#endif - - virtual VoidInitializer *isVoidInitializer() { return NULL; } - virtual StructInitializer *isStructInitializer() { return NULL; } - virtual ArrayInitializer *isArrayInitializer() { return NULL; } - virtual ExpInitializer *isExpInitializer() { return NULL; } -}; - -struct VoidInitializer : Initializer -{ - Type *type; // type that this will initialize to - - VoidInitializer(Loc loc); - Initializer *syntaxCopy(); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - -#if IN_DMD - dt_t *toDt(); -#endif - - virtual VoidInitializer *isVoidInitializer() { return this; } -}; - -struct StructInitializer : Initializer -{ - Identifiers field; // of Identifier *'s - Initializers value; // parallel array of Initializer *'s - - VarDeclarations vars; // parallel array of VarDeclaration *'s - AggregateDeclaration *ad; // which aggregate this is for - - StructInitializer(Loc loc); - Initializer *syntaxCopy(); - void addInit(Identifier *field, Initializer *value); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - -#if IN_DMD - dt_t *toDt(); -#endif - - StructInitializer *isStructInitializer() { return this; } -#if IN_LLVM - llvm::StructType *ltype; -#endif -}; - -struct ArrayInitializer : Initializer -{ - Expressions index; // indices - Initializers value; // of Initializer *'s - unsigned dim; // length of array being initialized - Type *type; // type that array will be used to initialize - int sem; // !=0 if semantic() is run - - ArrayInitializer(Loc loc); - Initializer *syntaxCopy(); - void addInit(Expression *index, Initializer *value); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); - Type *inferType(Scope *sc); - Expression *toExpression(); - Initializer *toAssocArrayInitializer(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - -#if IN_DMD - dt_t *toDt(); - dt_t *toDtBit(); // for bit arrays -#endif - - ArrayInitializer *isArrayInitializer() { return this; } -}; - -struct ExpInitializer : Initializer -{ - Expression *exp; - - ExpInitializer(Loc loc, Expression *exp); - Initializer *syntaxCopy(); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); - Type *inferType(Scope *sc); - Expression *toExpression(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - -#if IN_DMD - dt_t *toDt(); -#endif - - virtual ExpInitializer *isExpInitializer() { return this; } -}; - -#endif + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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. + +#ifndef INIT_H +#define INIT_H + +#include "root.h" + +#include "mars.h" +#include "arraytypes.h" + +struct Identifier; +struct Expression; +struct Scope; +struct Type; +struct dt_t; +struct AggregateDeclaration; +struct VoidInitializer; +struct StructInitializer; +struct ArrayInitializer; +struct ExpInitializer; +struct HdrGenState; + + +#if IN_LLVM +namespace llvm { + class StructType; +} +#endif + +struct Initializer : Object +{ + Loc loc; + + Initializer(Loc loc); + virtual Initializer *syntaxCopy(); + // needInterpret is WANTinterpret if must be a manifest constant, 0 if not. + virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret); + virtual Type *inferType(Scope *sc); + virtual Expression *toExpression() = 0; + virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; + char *toChars(); + + static Initializers *arraySyntaxCopy(Initializers *ai); + +#if IN_DMD + virtual dt_t *toDt(); +#endif + + virtual VoidInitializer *isVoidInitializer() { return NULL; } + virtual StructInitializer *isStructInitializer() { return NULL; } + virtual ArrayInitializer *isArrayInitializer() { return NULL; } + virtual ExpInitializer *isExpInitializer() { return NULL; } +}; + +struct VoidInitializer : Initializer +{ + Type *type; // type that this will initialize to + + VoidInitializer(Loc loc); + Initializer *syntaxCopy(); + Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Expression *toExpression(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + +#if IN_DMD + dt_t *toDt(); +#endif + + virtual VoidInitializer *isVoidInitializer() { return this; } +}; + +struct StructInitializer : Initializer +{ + Identifiers field; // of Identifier *'s + Initializers value; // parallel array of Initializer *'s + + VarDeclarations vars; // parallel array of VarDeclaration *'s + AggregateDeclaration *ad; // which aggregate this is for + + StructInitializer(Loc loc); + Initializer *syntaxCopy(); + void addInit(Identifier *field, Initializer *value); + Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Expression *toExpression(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + +#if IN_DMD + dt_t *toDt(); +#endif + + StructInitializer *isStructInitializer() { return this; } +#if IN_LLVM + llvm::StructType *ltype; +#endif +}; + +struct ArrayInitializer : Initializer +{ + Expressions index; // indices + Initializers value; // of Initializer *'s + unsigned dim; // length of array being initialized + Type *type; // type that array will be used to initialize + int sem; // !=0 if semantic() is run + + ArrayInitializer(Loc loc); + Initializer *syntaxCopy(); + void addInit(Expression *index, Initializer *value); + Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Type *inferType(Scope *sc); + Expression *toExpression(); + Initializer *toAssocArrayInitializer(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + +#if IN_DMD + dt_t *toDt(); + dt_t *toDtBit(); // for bit arrays +#endif + + ArrayInitializer *isArrayInitializer() { return this; } +}; + +struct ExpInitializer : Initializer +{ + Expression *exp; + + ExpInitializer(Loc loc, Expression *exp); + Initializer *syntaxCopy(); + Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Type *inferType(Scope *sc); + Expression *toExpression(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + +#if IN_DMD + dt_t *toDt(); +#endif + + virtual ExpInitializer *isExpInitializer() { return this; } +}; + +#endif diff --git a/dmd/inline.c b/dmd/inline.c index 93b65b05..3fe2f825 100644 --- a/dmd/inline.c +++ b/dmd/inline.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -39,44 +39,44 @@ struct InlineCostState }; const int COST_MAX = 250; -const int STATEMENT_COST = 0x1000; -const int STATEMENT_COST_MAX = 250 * 0x1000; - -// STATEMENT_COST be power of 2 and greater than COST_MAX -//static assert((STATEMENT_COST & (STATEMENT_COST - 1)) == 0); -//static assert(STATEMENT_COST > COST_MAX); - -bool tooCostly(int cost) { return ((cost & (STATEMENT_COST - 1)) >= COST_MAX); } - -int expressionInlineCost(Expression *e, InlineCostState *ics); +const int STATEMENT_COST = 0x1000; +const int STATEMENT_COST_MAX = 250 * 0x1000; + +// STATEMENT_COST be power of 2 and greater than COST_MAX +//static assert((STATEMENT_COST & (STATEMENT_COST - 1)) == 0); +//static assert(STATEMENT_COST > COST_MAX); + +bool tooCostly(int cost) { return ((cost & (STATEMENT_COST - 1)) >= COST_MAX); } + +int expressionInlineCost(Expression *e, InlineCostState *ics); int Statement::inlineCost(InlineCostState *ics) { - //printf("Statement::inlineCost = %d\n", COST_MAX); - //printf("%p\n", isScopeStatement()); - //printf("%s\n", toChars()); + //printf("Statement::inlineCost = %d\n", COST_MAX); + //printf("%p\n", isScopeStatement()); + //printf("%s\n", toChars()); return COST_MAX; // default is we can't inline it } int ExpStatement::inlineCost(InlineCostState *ics) { - return expressionInlineCost(exp, ics); - //return exp ? exp->inlineCost(ics) : 0; + return expressionInlineCost(exp, ics); + //return exp ? exp->inlineCost(ics) : 0; } int CompoundStatement::inlineCost(InlineCostState *ics) { int cost = 0; for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { cost += s->inlineCost(ics); - if (tooCostly(cost)) + if (tooCostly(cost)) break; } } - //printf("CompoundStatement::inlineCost = %d\n", cost); + //printf("CompoundStatement::inlineCost = %d\n", cost); return cost; } @@ -84,22 +84,22 @@ int UnrolledLoopStatement::inlineCost(InlineCostState *ics) { int cost = 0; for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { cost += s->inlineCost(ics); - if (tooCostly(cost)) + if (tooCostly(cost)) break; } } return cost; } -int ScopeStatement::inlineCost(InlineCostState *ics) -{ - return statement ? 1 + statement->inlineCost(ics) : 1; -} - +int ScopeStatement::inlineCost(InlineCostState *ics) +{ + return statement ? 1 + statement->inlineCost(ics) : 1; +} + int IfStatement::inlineCost(InlineCostState *ics) { int cost; @@ -112,7 +112,7 @@ int IfStatement::inlineCost(InlineCostState *ics) return COST_MAX; #endif - cost = expressionInlineCost(condition, ics); + cost = expressionInlineCost(condition, ics); #if !IN_LLVM /* Specifically allow: @@ -141,7 +141,7 @@ int IfStatement::inlineCost(InlineCostState *ics) cost += elsebody->inlineCost(ics); ics->nested -= 1; } - //printf("IfStatement::inlineCost = %d\n", cost); + //printf("IfStatement::inlineCost = %d\n", cost); return cost; } @@ -152,67 +152,67 @@ int ReturnStatement::inlineCost(InlineCostState *ics) if (ics->nested) return COST_MAX; #endif - return expressionInlineCost(exp, ics); + return expressionInlineCost(exp, ics); } -#if DMDV2 -int ImportStatement::inlineCost(InlineCostState *ics) -{ - return 0; -} -#endif +#if DMDV2 +int ImportStatement::inlineCost(InlineCostState *ics) +{ + return 0; +} +#endif -int ForStatement::inlineCost(InlineCostState *ics) -{ - //return COST_MAX; - int cost = STATEMENT_COST; - if (init) - cost += init->inlineCost(ics); - if (condition) - cost += expressionInlineCost(condition, ics); - if (increment) - cost += expressionInlineCost(increment, ics); - if (body) - cost += body->inlineCost(ics); - //printf("ForStatement: inlineCost = %d\n", cost); +int ForStatement::inlineCost(InlineCostState *ics) +{ + //return COST_MAX; + int cost = STATEMENT_COST; + if (init) + cost += init->inlineCost(ics); + if (condition) + cost += expressionInlineCost(condition, ics); + if (increment) + cost += expressionInlineCost(increment, ics); + if (body) + cost += body->inlineCost(ics); + //printf("ForStatement: inlineCost = %d\n", cost); return cost; } - -/* -------------------------- */ - -struct ICS2 + +/* -------------------------- */ + +struct ICS2 { - int cost; - InlineCostState *ics; -}; - -int lambdaInlineCost(Expression *e, void *param) -{ - ICS2 *ics2 = (ICS2 *)param; - ics2->cost += e->inlineCost3(ics2->ics); - return (ics2->cost >= COST_MAX); + int cost; + InlineCostState *ics; +}; + +int lambdaInlineCost(Expression *e, void *param) +{ + ICS2 *ics2 = (ICS2 *)param; + ics2->cost += e->inlineCost3(ics2->ics); + return (ics2->cost >= COST_MAX); } -int expressionInlineCost(Expression *e, InlineCostState *ics) +int expressionInlineCost(Expression *e, InlineCostState *ics) { - ICS2 ics2; - ics2.cost = 0; - ics2.ics = ics; - if (e) - e->apply(&lambdaInlineCost, &ics2); - return ics2.cost; + ICS2 ics2; + ics2.cost = 0; + ics2.ics = ics; + if (e) + e->apply(&lambdaInlineCost, &ics2); + return ics2.cost; } -int Expression::inlineCost3(InlineCostState *ics) +int Expression::inlineCost3(InlineCostState *ics) { return 1; } -int ThisExp::inlineCost3(InlineCostState *ics) +int ThisExp::inlineCost3(InlineCostState *ics) { #if !IN_LLVM - //printf("ThisExp::inlineCost3() %s\n", toChars()); + //printf("ThisExp::inlineCost3() %s\n", toChars()); FuncDeclaration *fd = ics->fd; if (!fd) return COST_MAX; @@ -223,38 +223,38 @@ int ThisExp::inlineCost3(InlineCostState *ics) return 1; } -int StructLiteralExp::inlineCost3(InlineCostState *ics) +int StructLiteralExp::inlineCost3(InlineCostState *ics) { - //printf("StructLiteralExp::inlineCost3() %s\n", toChars()); -#if DMDV2 - if (sd->isnested) - return COST_MAX; -#endif - return 1; + //printf("StructLiteralExp::inlineCost3() %s\n", toChars()); +#if DMDV2 + if (sd->isnested) + return COST_MAX; +#endif + return 1; } -int FuncExp::inlineCost3(InlineCostState *ics) +int FuncExp::inlineCost3(InlineCostState *ics) { - //printf("FuncExp::inlineCost3()\n"); + //printf("FuncExp::inlineCost3()\n"); // This breaks on LDC too, since nested functions have internal linkage // and thus can't be referenced from other objects. // Right now, this makes the function be output to the .obj file twice. return COST_MAX; } -int DelegateExp::inlineCost3(InlineCostState *ics) +int DelegateExp::inlineCost3(InlineCostState *ics) { - //printf("DelegateExp::inlineCost3()\n"); + //printf("DelegateExp::inlineCost3()\n"); // This breaks on LDC too, since nested functions have internal linkage // and thus can't be referenced from other objects. return COST_MAX; } -int DeclarationExp::inlineCost3(InlineCostState *ics) +int DeclarationExp::inlineCost3(InlineCostState *ics) { int cost = 0; VarDeclaration *vd; - //printf("DeclarationExp::inlineCost3()\n"); + //printf("DeclarationExp::inlineCost3()\n"); vd = declaration->isVarDeclaration(); if (vd) { @@ -265,7 +265,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) return COST_MAX; // finish DeclarationExp::doInline #else for (size_t i = 0; i < td->objects->dim; i++) - { Object *o = (*td->objects)[i]; + { Object *o = (*td->objects)[i]; if (o->dyncast() != DYNCAST_EXPRESSION) return COST_MAX; Expression *eo = (Expression *)o; @@ -281,10 +281,10 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) return COST_MAX; cost += 1; -#if DMDV2 - if (vd->edtor) // if destructor required - return COST_MAX; // needs work to make this work -#endif +#if DMDV2 + if (vd->edtor) // if destructor required + return COST_MAX; // needs work to make this work +#endif // Scan initializer (vd->init) if (vd->init) { @@ -292,7 +292,7 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) if (ie) { - cost += expressionInlineCost(ie->exp, ics); + cost += expressionInlineCost(ie->exp, ics); } } } @@ -304,157 +304,157 @@ int DeclarationExp::inlineCost3(InlineCostState *ics) declaration->isClassDeclaration() || declaration->isFuncDeclaration() || declaration->isTypedefDeclaration() || -#if DMDV2 - declaration->isAttribDeclaration() || -#endif +#if DMDV2 + declaration->isAttribDeclaration() || +#endif declaration->isTemplateMixin()) return COST_MAX; - //printf("DeclarationExp::inlineCost3('%s')\n", toChars()); + //printf("DeclarationExp::inlineCost3('%s')\n", toChars()); return cost; } -int CallExp::inlineCost3(InlineCostState *ics) +int CallExp::inlineCost3(InlineCostState *ics) { - //printf("CallExp::inlineCost3() %s\n", toChars()); - // Bugzilla 3500: super.func() calls must be devirtualized, and the inliner - // can't handle that at present. - if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper) - return COST_MAX; - - return 1; + //printf("CallExp::inlineCost3() %s\n", toChars()); + // Bugzilla 3500: super.func() calls must be devirtualized, and the inliner + // can't handle that at present. + if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper) + return COST_MAX; + + return 1; } - -/* ======================== Perform the inlining ============================== */ - -/* Inlining is done by: - * o Converting to an Expression - * o Copying the trees of the function to be inlined - * o Renaming the variables - */ - -struct InlineDoState -{ - VarDeclaration *vthis; - Dsymbols from; // old Dsymbols - Dsymbols to; // parallel array of new Dsymbols - Dsymbol *parent; // new parent -}; - -/* -------------------------------------------------------------------- */ -Statement *Statement::doInlineStatement(InlineDoState *ids) +/* ======================== Perform the inlining ============================== */ + +/* Inlining is done by: + * o Converting to an Expression + * o Copying the trees of the function to be inlined + * o Renaming the variables + */ + +struct InlineDoState { - assert(0); - return NULL; // default is we can't inline it + VarDeclaration *vthis; + Dsymbols from; // old Dsymbols + Dsymbols to; // parallel array of new Dsymbols + Dsymbol *parent; // new parent +}; + +/* -------------------------------------------------------------------- */ + +Statement *Statement::doInlineStatement(InlineDoState *ids) +{ + assert(0); + return NULL; // default is we can't inline it } -Statement *ExpStatement::doInlineStatement(InlineDoState *ids) +Statement *ExpStatement::doInlineStatement(InlineDoState *ids) { -#if LOG - if (exp) printf("ExpStatement::doInlineStatement() '%s'\n", exp->toChars()); -#endif - return new ExpStatement(loc, exp ? exp->doInline(ids) : NULL); +#if LOG + if (exp) printf("ExpStatement::doInlineStatement() '%s'\n", exp->toChars()); +#endif + return new ExpStatement(loc, exp ? exp->doInline(ids) : NULL); } -Statement *CompoundStatement::doInlineStatement(InlineDoState *ids) -{ - //printf("CompoundStatement::doInlineStatement() %d\n", statements->dim); - Statements *as = new Statements(); - as->reserve(statements->dim); - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - if (s) - { - as->push(s->doInlineStatement(ids)); - if (s->isReturnStatement()) - break; +Statement *CompoundStatement::doInlineStatement(InlineDoState *ids) +{ + //printf("CompoundStatement::doInlineStatement() %d\n", statements->dim); + Statements *as = new Statements(); + as->reserve(statements->dim); + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; + if (s) + { + as->push(s->doInlineStatement(ids)); + if (s->isReturnStatement()) + break; - /* Check for: - * if (condition) - * return exp1; - * else - * return exp2; - */ - IfStatement *ifs = s->isIfStatement(); - if (ifs && ifs->elsebody && ifs->ifbody && - ifs->ifbody->isReturnStatement() && - ifs->elsebody->isReturnStatement() - ) - break; - } - else - as->push(NULL); - } - return new CompoundStatement(loc, as); + /* Check for: + * if (condition) + * return exp1; + * else + * return exp2; + */ + IfStatement *ifs = s->isIfStatement(); + if (ifs && ifs->elsebody && ifs->ifbody && + ifs->ifbody->isReturnStatement() && + ifs->elsebody->isReturnStatement() + ) + break; + } + else + as->push(NULL); + } + return new CompoundStatement(loc, as); } -Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids) +Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids) { - //printf("UnrolledLoopStatement::doInlineStatement() %d\n", statements->dim); - Statements *as = new Statements(); - as->reserve(statements->dim); - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - if (s) - { - as->push(s->doInlineStatement(ids)); - if (s->isReturnStatement()) - break; - } - else - as->push(NULL); - } - return new UnrolledLoopStatement(loc, as); + //printf("UnrolledLoopStatement::doInlineStatement() %d\n", statements->dim); + Statements *as = new Statements(); + as->reserve(statements->dim); + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; + if (s) + { + as->push(s->doInlineStatement(ids)); + if (s->isReturnStatement()) + break; + } + else + as->push(NULL); + } + return new UnrolledLoopStatement(loc, as); } -Statement *ScopeStatement::doInlineStatement(InlineDoState *ids) +Statement *ScopeStatement::doInlineStatement(InlineDoState *ids) { - //printf("ScopeStatement::doInlineStatement() %d\n", statements->dim); - return statement ? new ScopeStatement(loc, statement->doInlineStatement(ids)) : this; + //printf("ScopeStatement::doInlineStatement() %d\n", statements->dim); + return statement ? new ScopeStatement(loc, statement->doInlineStatement(ids)) : this; } -Statement *IfStatement::doInlineStatement(InlineDoState *ids) -{ - assert(!arg); - - Expression *condition = this->condition ? this->condition->doInline(ids) : NULL; - Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(ids) : NULL; - Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL; - - return new IfStatement(loc, arg, condition, ifbody, elsebody); -} - -Statement *ReturnStatement::doInlineStatement(InlineDoState *ids) +Statement *IfStatement::doInlineStatement(InlineDoState *ids) { - //printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : ""); - return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL); -} - -#if DMDV2 -Statement *ImportStatement::doInlineStatement(InlineDoState *ids) -{ - return NULL; -} -#endif - -Statement *ForStatement::doInlineStatement(InlineDoState *ids) -{ - //printf("ForStatement::doInlineStatement()\n"); - Statement *init = this->init ? this->init->doInlineStatement(ids) : NULL; - Expression *condition = this->condition ? this->condition->doInline(ids) : NULL; - Expression *increment = this->increment ? this->increment->doInline(ids) : NULL; - Statement *body = this->body ? this->body->doInlineStatement(ids) : NULL; - return new ForStatement(loc, init, condition, increment, body); -} - -/* -------------------------------------------------------------------- */ + assert(!arg); + + Expression *condition = this->condition ? this->condition->doInline(ids) : NULL; + Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(ids) : NULL; + Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL; + + return new IfStatement(loc, arg, condition, ifbody, elsebody); +} + +Statement *ReturnStatement::doInlineStatement(InlineDoState *ids) +{ + //printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : ""); + return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL); +} + +#if DMDV2 +Statement *ImportStatement::doInlineStatement(InlineDoState *ids) +{ + return NULL; +} +#endif + +Statement *ForStatement::doInlineStatement(InlineDoState *ids) +{ + //printf("ForStatement::doInlineStatement()\n"); + Statement *init = this->init ? this->init->doInlineStatement(ids) : NULL; + Expression *condition = this->condition ? this->condition->doInline(ids) : NULL; + Expression *increment = this->increment ? this->increment->doInline(ids) : NULL; + Statement *body = this->body ? this->body->doInlineStatement(ids) : NULL; + return new ForStatement(loc, init, condition, increment, body); +} + +/* -------------------------------------------------------------------- */ Expression *Statement::doInline(InlineDoState *ids) { - printf("Statement::doInline()\n%s\n", toChars()); - fflush(stdout); + printf("Statement::doInline()\n%s\n", toChars()); + fflush(stdout); assert(0); return NULL; // default is we can't inline it } @@ -473,7 +473,7 @@ Expression *CompoundStatement::doInline(InlineDoState *ids) //printf("CompoundStatement::doInline() %d\n", statements->dim); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { Expression *e2 = s->doInline(ids); @@ -505,7 +505,7 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids) //printf("UnrolledLoopStatement::doInline() %d\n", statements->dim); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { Expression *e2 = s->doInline(ids); @@ -517,11 +517,11 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids) return e; } -Expression *ScopeStatement::doInline(InlineDoState *ids) -{ - return statement ? statement->doInline(ids) : NULL; -} - +Expression *ScopeStatement::doInline(InlineDoState *ids) +{ + return statement ? statement->doInline(ids) : NULL; +} + Expression *IfStatement::doInline(InlineDoState *ids) { Expression *econd; @@ -568,13 +568,13 @@ Expression *ReturnStatement::doInline(InlineDoState *ids) return exp ? exp->doInline(ids) : 0; } -#if DMDV2 -Expression *ImportStatement::doInline(InlineDoState *ids) -{ - return NULL; -} -#endif - +#if DMDV2 +Expression *ImportStatement::doInline(InlineDoState *ids) +{ + return NULL; +} +#endif + /* --------------------------------------------------------------- */ /****************************** @@ -589,12 +589,12 @@ Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) newa = new Expressions(); newa->setDim(a->dim); - for (size_t i = 0; i < a->dim; i++) - { Expression *e = a->tdata()[i]; + for (size_t i = 0; i < a->dim; i++) + { Expression *e = a->tdata()[i]; if (e) e = e->doInline(ids); - newa->tdata()[i] = e; + newa->tdata()[i] = e; } } return newa; @@ -609,13 +609,13 @@ Expression *Expression::doInline(InlineDoState *ids) Expression *SymOffExp::doInline(InlineDoState *ids) { //printf("SymOffExp::doInline(%s)\n", toChars()); - for (size_t i = 0; i < ids->from.dim; i++) + for (size_t i = 0; i < ids->from.dim; i++) { - if (var == ids->from.tdata()[i]) + if (var == ids->from.tdata()[i]) { SymOffExp *se = (SymOffExp *)copy(); - se->var = (Declaration *)ids->to.tdata()[i]; + se->var = (Declaration *)ids->to.tdata()[i]; return se; } } @@ -625,13 +625,13 @@ Expression *SymOffExp::doInline(InlineDoState *ids) Expression *VarExp::doInline(InlineDoState *ids) { //printf("VarExp::doInline(%s)\n", toChars()); - for (size_t i = 0; i < ids->from.dim; i++) + for (size_t i = 0; i < ids->from.dim; i++) { - if (var == ids->from.tdata()[i]) + if (var == ids->from.tdata()[i]) { VarExp *ve = (VarExp *)copy(); - ve->var = (Declaration *)ids->to.tdata()[i]; + ve->var = (Declaration *)ids->to.tdata()[i]; return ve; } } @@ -675,7 +675,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids) if (td) { for (size_t i = 0; i < td->objects->dim; i++) - { DsymbolExp *se = td->objects->tdata()[i]; + { DsymbolExp *se = td->objects->tdata()[i]; assert(se->op == TOKdsymbol); se->s; } @@ -795,7 +795,7 @@ Expression *IndexExp::doInline(InlineDoState *ids) ids->from.push(vd); ids->to.push(vto); - if (vd->init && !vd->init->isVoidInitializer()) + if (vd->init && !vd->init->isVoidInitializer()) { ie = vd->init->isExpInitializer(); assert(ie); @@ -834,7 +834,7 @@ Expression *SliceExp::doInline(InlineDoState *ids) ids->from.push(vd); ids->to.push(vto); - if (vd->init && !vd->init->isVoidInitializer()) + if (vd->init && !vd->init->isVoidInitializer()) { ie = vd->init->isExpInitializer(); assert(ie); @@ -937,38 +937,38 @@ Statement *ExpStatement::inlineScan(InlineScanState *iss) printf("ExpStatement::inlineScan(%s)\n", toChars()); #endif if (exp) - { + { exp = exp->inlineScan(iss); - - /* See if we can inline as a statement rather than as - * an Expression. - */ - if (exp && exp->op == TOKcall) - { - CallExp *ce = (CallExp *)exp; - if (ce->e1->op == TOKvar) - { - VarExp *ve = (VarExp *)ce->e1; - FuncDeclaration *fd = ve->var->isFuncDeclaration(); - - if (fd && fd != iss->fd && fd->canInline(0, 0, 1)) - { - Statement *s; - fd->expandInline(iss, NULL, ce->arguments, &s); - return s; - } - } - } - } + + /* See if we can inline as a statement rather than as + * an Expression. + */ + if (exp && exp->op == TOKcall) + { + CallExp *ce = (CallExp *)exp; + if (ce->e1->op == TOKvar) + { + VarExp *ve = (VarExp *)ce->e1; + FuncDeclaration *fd = ve->var->isFuncDeclaration(); + + if (fd && fd != iss->fd && fd->canInline(0, 0, 1)) + { + Statement *s; + fd->expandInline(iss, NULL, ce->arguments, &s); + return s; + } + } + } + } return this; } Statement *CompoundStatement::inlineScan(InlineScanState *iss) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) - (*statements)[i] = s->inlineScan(iss); + (*statements)[i] = s->inlineScan(iss); } return this; } @@ -976,9 +976,9 @@ Statement *CompoundStatement::inlineScan(InlineScanState *iss) Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) - (*statements)[i] = s->inlineScan(iss); + (*statements)[i] = s->inlineScan(iss); } return this; } @@ -1061,11 +1061,11 @@ Statement *SwitchStatement::inlineScan(InlineScanState *iss) sdefault = (DefaultStatement *)sdefault->inlineScan(iss); if (cases) { - for (size_t i = 0; i < cases->dim; i++) - { CaseStatement *s; + for (size_t i = 0; i < cases->dim; i++) + { CaseStatement *s; - s = cases->tdata()[i]; - cases->tdata()[i] = (CaseStatement *)s->inlineScan(iss); + s = cases->tdata()[i]; + cases->tdata()[i] = (CaseStatement *)s->inlineScan(iss); } } return this; @@ -1127,8 +1127,8 @@ Statement *TryCatchStatement::inlineScan(InlineScanState *iss) body = body->inlineScan(iss); if (catches) { - for (size_t i = 0; i < catches->dim; i++) - { Catch *c = catches->tdata()[i]; + for (size_t i = 0; i < catches->dim; i++) + { Catch *c = catches->tdata()[i]; if (c->handler) c->handler = c->handler->inlineScan(iss); @@ -1173,17 +1173,17 @@ Statement *LabelStatement::inlineScan(InlineScanState *iss) /* -------------------------- */ -void arrayInlineScan(InlineScanState *iss, Expressions *arguments) +void arrayInlineScan(InlineScanState *iss, Expressions *arguments) { if (arguments) { - for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + for (size_t i = 0; i < arguments->dim; i++) + { Expression *e = arguments->tdata()[i]; if (e) { e = e->inlineScan(iss); - arguments->tdata()[i] = e; + arguments->tdata()[i] = e; } } } @@ -1203,7 +1203,7 @@ void scanVar(Dsymbol *s, InlineScanState *iss) if (td) { for (size_t i = 0; i < td->objects->dim; i++) - { DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i]; + { DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i]; assert(se->op == TOKdsymbol); scanVar(se->s, iss); } @@ -1290,9 +1290,9 @@ Expression *CallExp::inlineScan(InlineScanState *iss) VarExp *ve = (VarExp *)e1; FuncDeclaration *fd = ve->var->isFuncDeclaration(); - if (fd && fd != iss->fd && fd->canInline(0, 0, 0)) + if (fd && fd != iss->fd && fd->canInline(0, 0, 0)) { - e = fd->expandInline(iss, NULL, arguments, NULL); + e = fd->expandInline(iss, NULL, arguments, NULL); } } else if (e1->op == TOKdotvar) @@ -1300,7 +1300,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss) DotVarExp *dve = (DotVarExp *)e1; FuncDeclaration *fd = dve->var->isFuncDeclaration(); - if (fd && fd != iss->fd && fd->canInline(1, 0, 0)) + if (fd && fd != iss->fd && fd->canInline(1, 0, 0)) { if (dve->e1->op == TOKcall && dve->e1->type->toBasetype()->ty == Tstruct) @@ -1312,7 +1312,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss) ; } else - e = fd->expandInline(iss, dve->e1, arguments, NULL); + e = fd->expandInline(iss, dve->e1, arguments, NULL); } } @@ -1403,7 +1403,7 @@ void FuncDeclaration::inlineScan() #endif memset(&iss, 0, sizeof(iss)); iss.fd = this; - if (fbody && !naked) + if (fbody && !naked) { inlineNest++; fbody = fbody->inlineScan(&iss); @@ -1411,7 +1411,7 @@ void FuncDeclaration::inlineScan() } } -int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) +int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) { InlineCostState ics; int cost; @@ -1419,7 +1419,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) #define CANINLINE_LOG 0 #if CANINLINE_LOG - printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toChars()); + printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toChars()); #endif if (needThis() && !hasthis) @@ -1433,7 +1433,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) return 0; } - switch (statementsToo ? inlineStatusStmt : inlineStatusExp) + switch (statementsToo ? inlineStatusStmt : inlineStatusExp) { case ILSyes: #if CANINLINE_LOG @@ -1466,10 +1466,10 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) /* Don't inline a function that returns non-void, but has * no return expression. - * No statement inlining for non-voids. + * No statement inlining for non-voids. */ if (tf->next && tf->next->ty != Tvoid && - (!(hasReturnExp & 1) || statementsToo) && + (!(hasReturnExp & 1) || statementsToo) && !hdrscan) goto Lno; } @@ -1485,7 +1485,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) if ( !fbody || - ident == Id::ensure || // ensure() has magic properties the inliner loses + ident == Id::ensure || // ensure() has magic properties the inliner loses !hdrscan && ( #if 0 @@ -1497,7 +1497,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) isSynchronized() || isImportedSymbol() || #if !IN_LLVM - hasNestedFrameRefs() || // no nested references to this frame + hasNestedFrameRefs() || // no nested references to this frame #endif // !IN_LLVM (isVirtual() && !isFinal()) )) @@ -1512,10 +1512,10 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) */ if (parameters) { - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { - VarDeclaration *v = parameters->tdata()[i]; - if (v->type->toBasetype()->ty == Tsarray) + VarDeclaration *v = parameters->tdata()[i]; + if (v->type->toBasetype()->ty == Tsarray) goto Lno; } } @@ -1528,47 +1528,47 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) ics.hdrscan = hdrscan; cost = fbody->inlineCost(&ics); #if CANINLINE_LOG - printf("cost = %d for %s\n", cost, toChars()); + printf("cost = %d for %s\n", cost, toChars()); #endif - if (tooCostly(cost)) - goto Lno; - if (!statementsToo && cost > COST_MAX) + if (tooCostly(cost)) + goto Lno; + if (!statementsToo && cost > COST_MAX) goto Lno; - if (!hdrscan) - { - // Don't modify inlineStatus for header content scan - if (statementsToo) - inlineStatusStmt = ILSyes; - else - inlineStatusExp = ILSyes; - + if (!hdrscan) + { + // Don't modify inlineStatus for header content scan + if (statementsToo) + inlineStatusStmt = ILSyes; + else + inlineStatusExp = ILSyes; + #if !IN_LLVM - inlineScan(); // Don't scan recursively for header content scan + inlineScan(); // Don't scan recursively for header content scan #endif - if (inlineStatusExp == ILSuninitialized) - { - // Need to redo cost computation, as some statements or expressions have been inlined - memset(&ics, 0, sizeof(ics)); - ics.hasthis = hasthis; - ics.fd = this; - ics.hdrscan = hdrscan; - cost = fbody->inlineCost(&ics); - #if CANINLINE_LOG - printf("recomputed cost = %d for %s\n", cost, toChars()); - #endif - if (tooCostly(cost)) - goto Lno; - if (!statementsToo && cost > COST_MAX) - goto Lno; - - if (statementsToo) - inlineStatusStmt = ILSyes; - else - inlineStatusExp = ILSyes; - } - } + if (inlineStatusExp == ILSuninitialized) + { + // Need to redo cost computation, as some statements or expressions have been inlined + memset(&ics, 0, sizeof(ics)); + ics.hasthis = hasthis; + ics.fd = this; + ics.hdrscan = hdrscan; + cost = fbody->inlineCost(&ics); + #if CANINLINE_LOG + printf("recomputed cost = %d for %s\n", cost, toChars()); + #endif + if (tooCostly(cost)) + goto Lno; + if (!statementsToo && cost > COST_MAX) + goto Lno; + + if (statementsToo) + inlineStatusStmt = ILSyes; + else + inlineStatusExp = ILSyes; + } + } #if CANINLINE_LOG printf("\t2: yes %s\n", toChars()); #endif @@ -1576,34 +1576,34 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) Lno: if (!hdrscan) // Don't modify inlineStatus for header content scan - { if (statementsToo) - inlineStatusStmt = ILSno; - else - inlineStatusExp = ILSno; - } + { if (statementsToo) + inlineStatusStmt = ILSno; + else + inlineStatusExp = ILSno; + } #if CANINLINE_LOG printf("\t2: no %s\n", toChars()); #endif return 0; } -Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps) +Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps) { InlineDoState ids; DeclarationExp *de; Expression *e = NULL; - Statements *as = NULL; + Statements *as = NULL; -#if LOG || CANINLINE_LOG - printf("FuncDeclaration::expandInline('%s')\n", toChars()); +#if LOG || CANINLINE_LOG + printf("FuncDeclaration::expandInline('%s')\n", toChars()); #endif memset(&ids, 0, sizeof(ids)); ids.parent = iss->fd; - if (ps) - as = new Statements(); - + if (ps) + as = new Statements(); + // Set up vthis if (ethis) { @@ -1659,19 +1659,19 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi { e = new DeclarationExp(0, ids.vthis); e->type = Type::tvoid; - if (as) - as->push(new ExpStatement(e->loc, e)); + if (as) + as->push(new ExpStatement(e->loc, e)); } if (arguments && arguments->dim) { assert(parameters->dim == arguments->dim); - for (size_t i = 0; i < arguments->dim; i++) + for (size_t i = 0; i < arguments->dim; i++) { - VarDeclaration *vfrom = parameters->tdata()[i]; + VarDeclaration *vfrom = parameters->tdata()[i]; VarDeclaration *vto; - Expression *arg = arguments->tdata()[i]; + Expression *arg = arguments->tdata()[i]; ExpInitializer *ei; VarExp *ve; @@ -1701,31 +1701,31 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi de = new DeclarationExp(0, vto); de->type = Type::tvoid; - if (as) - as->push(new ExpStatement(0, de)); - else - e = Expression::combine(e, de); + if (as) + as->push(new ExpStatement(0, de)); + else + e = Expression::combine(e, de); } } - if (ps) - { - inlineNest++; - Statement *s = fbody->doInlineStatement(&ids); - as->push(s); - *ps = new ScopeStatement(0, new CompoundStatement(0, as)); - inlineNest--; - } - else - { - inlineNest++; - Expression *eb = fbody->doInline(&ids); - e = Expression::combine(e, eb); - inlineNest--; - //eb->type->print(); - //eb->print(); - //eb->dump(0); - } + if (ps) + { + inlineNest++; + Statement *s = fbody->doInlineStatement(&ids); + as->push(s); + *ps = new ScopeStatement(0, new CompoundStatement(0, as)); + inlineNest--; + } + else + { + inlineNest++; + Expression *eb = fbody->doInline(&ids); + e = Expression::combine(e, eb); + inlineNest--; + //eb->type->print(); + //eb->print(); + //eb->dump(0); + } /* There's a problem if what the function returns is used subsequently as an * lvalue, as in a struct return that is then used as a 'this'. @@ -1737,7 +1737,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi * See Bugzilla 2127 for an example. */ TypeFunction *tf = (TypeFunction*)type; - if (!ps && tf->next->ty == Tstruct) + if (!ps && tf->next->ty == Tstruct) { /* Generate a new variable to hold the result and initialize it with the * inlined body of the function: @@ -1768,9 +1768,9 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi //fprintf(stderr, "CallExp::inlineScan: e = "); e->print(); } - // Need to reevaluate whether parent can now be inlined - // in expressions, as we might have inlined statements - iss->fd->inlineStatusExp = ILSuninitialized; + // Need to reevaluate whether parent can now be inlined + // in expressions, as we might have inlined statements + iss->fd->inlineStatusExp = ILSuninitialized; return e; } @@ -1790,7 +1790,7 @@ Expression *Expression::inlineCopy(Scope *sc) memset(&ics, 0, sizeof(ics)); ics.hdrscan = 1; // so DeclarationExp:: will work on 'statics' which are not - int cost = expressionInlineCost(this, &ics); + int cost = expressionInlineCost(this, &ics); if (cost >= COST_MAX) { error("cannot inline default argument %s", toChars()); return new ErrorExp(); diff --git a/dmd/interpret.c b/dmd/interpret.c index 3536542a..e1000c98 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -24,145 +24,145 @@ #include "declaration.h" #include "aggregate.h" #include "id.h" -#include "utf.h" -#include "attrib.h" // for AttribDeclaration - -#include "template.h" -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd); - +#include "utf.h" +#include "attrib.h" // for AttribDeclaration + +#include "template.h" +TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd); + #define LOG 0 -#define LOGASSIGN 0 -#define SHOWPERFORMANCE 0 - -// Maximum allowable recursive function calls in CTFE -#define CTFE_RECURSION_LIMIT 1000 - -// The values of all CTFE variables. -struct CtfeStack -{ -private: - /* The stack. Every declaration we encounter is pushed here, - together with the VarDeclaration, and the previous - stack address of that variable, so that we can restore it - when we leave the stack frame. - Ctfe Stack addresses are just 0-based integers, but we save - them as 'void *' because ArrayBase can only do pointers. - */ - Expressions values; // values on the stack - VarDeclarations vars; // corresponding variables - ArrayBase savedId; // id of the previous state of that var - - /* Global constants get saved here after evaluation, so we never - * have to redo them. This saves a lot of time and memory. - */ - Expressions globalValues; // values of global constants - size_t framepointer; // current frame pointer - size_t maxStackPointer; // most stack we've ever used -public: - CtfeStack() : framepointer(0) - { - } - size_t stackPointer() - { - return values.dim; - } - // Largest number of stack positions we've used - size_t maxStackUsage() - { - return maxStackPointer; - } - // return the previous frame - size_t startFrame() - { - size_t oldframe = framepointer; - framepointer = stackPointer(); - return oldframe; - } - void endFrame(size_t oldframe) - { - popAll(framepointer); - framepointer = oldframe; - } - Expression *getValue(VarDeclaration *v) - { - if (v->isDataseg() && !v->isCTFE()) - { - assert(v->ctfeAdrOnStack >= 0 && - v->ctfeAdrOnStack < globalValues.dim); - return globalValues.tdata()[v->ctfeAdrOnStack]; - } - assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); - return values.tdata()[v->ctfeAdrOnStack]; - } - void setValue(VarDeclaration *v, Expression *e) - { - assert(!v->isDataseg() || v->isCTFE()); - assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); - values.tdata()[v->ctfeAdrOnStack] = e; - } - void push(VarDeclaration *v) - { - assert(!v->isDataseg() || v->isCTFE()); - if (v->ctfeAdrOnStack!= (size_t)-1 - && v->ctfeAdrOnStack >= framepointer) - { // Already exists in this frame, reuse it. - values.tdata()[v->ctfeAdrOnStack] = NULL; - return; - } - savedId.push((void *)(v->ctfeAdrOnStack)); - v->ctfeAdrOnStack = values.dim; - vars.push(v); - values.push(NULL); - } - void pop(VarDeclaration *v) - { - assert(!v->isDataseg() || v->isCTFE()); - assert(!(v->storage_class & (STCref | STCout))); - int oldid = v->ctfeAdrOnStack; - v->ctfeAdrOnStack = (size_t)(savedId.tdata()[oldid]); - if (v->ctfeAdrOnStack == values.dim - 1) - { - values.pop(); - vars.pop(); - savedId.pop(); - } - } - void popAll(size_t stackpointer) - { - if (stackPointer() > maxStackPointer) - maxStackPointer = stackPointer(); - assert(values.dim >= stackpointer && stackpointer >= 0); - for (size_t i = stackpointer; i < values.dim; ++i) - { - VarDeclaration *v = vars.tdata()[i]; - v->ctfeAdrOnStack = (size_t)(savedId.tdata()[i]); - } - values.setDim(stackpointer); - vars.setDim(stackpointer); - savedId.setDim(stackpointer); - } - void saveGlobalConstant(VarDeclaration *v, Expression *e) - { - assert(v->isDataseg() && !v->isCTFE()); - v->ctfeAdrOnStack = globalValues.dim; - globalValues.push(e); - } -}; - -CtfeStack ctfeStack; - +#define LOGASSIGN 0 +#define SHOWPERFORMANCE 0 + +// Maximum allowable recursive function calls in CTFE +#define CTFE_RECURSION_LIMIT 1000 + +// The values of all CTFE variables. +struct CtfeStack +{ +private: + /* The stack. Every declaration we encounter is pushed here, + together with the VarDeclaration, and the previous + stack address of that variable, so that we can restore it + when we leave the stack frame. + Ctfe Stack addresses are just 0-based integers, but we save + them as 'void *' because ArrayBase can only do pointers. + */ + Expressions values; // values on the stack + VarDeclarations vars; // corresponding variables + ArrayBase savedId; // id of the previous state of that var + + /* Global constants get saved here after evaluation, so we never + * have to redo them. This saves a lot of time and memory. + */ + Expressions globalValues; // values of global constants + size_t framepointer; // current frame pointer + size_t maxStackPointer; // most stack we've ever used +public: + CtfeStack() : framepointer(0) + { + } + size_t stackPointer() + { + return values.dim; + } + // Largest number of stack positions we've used + size_t maxStackUsage() + { + return maxStackPointer; + } + // return the previous frame + size_t startFrame() + { + size_t oldframe = framepointer; + framepointer = stackPointer(); + return oldframe; + } + void endFrame(size_t oldframe) + { + popAll(framepointer); + framepointer = oldframe; + } + Expression *getValue(VarDeclaration *v) + { + if (v->isDataseg() && !v->isCTFE()) + { + assert(v->ctfeAdrOnStack >= 0 && + v->ctfeAdrOnStack < globalValues.dim); + return globalValues.tdata()[v->ctfeAdrOnStack]; + } + assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); + return values.tdata()[v->ctfeAdrOnStack]; + } + void setValue(VarDeclaration *v, Expression *e) + { + assert(!v->isDataseg() || v->isCTFE()); + assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); + values.tdata()[v->ctfeAdrOnStack] = e; + } + void push(VarDeclaration *v) + { + assert(!v->isDataseg() || v->isCTFE()); + if (v->ctfeAdrOnStack!= (size_t)-1 + && v->ctfeAdrOnStack >= framepointer) + { // Already exists in this frame, reuse it. + values.tdata()[v->ctfeAdrOnStack] = NULL; + return; + } + savedId.push((void *)(v->ctfeAdrOnStack)); + v->ctfeAdrOnStack = values.dim; + vars.push(v); + values.push(NULL); + } + void pop(VarDeclaration *v) + { + assert(!v->isDataseg() || v->isCTFE()); + assert(!(v->storage_class & (STCref | STCout))); + int oldid = v->ctfeAdrOnStack; + v->ctfeAdrOnStack = (size_t)(savedId.tdata()[oldid]); + if (v->ctfeAdrOnStack == values.dim - 1) + { + values.pop(); + vars.pop(); + savedId.pop(); + } + } + void popAll(size_t stackpointer) + { + if (stackPointer() > maxStackPointer) + maxStackPointer = stackPointer(); + assert(values.dim >= stackpointer && stackpointer >= 0); + for (size_t i = stackpointer; i < values.dim; ++i) + { + VarDeclaration *v = vars.tdata()[i]; + v->ctfeAdrOnStack = (size_t)(savedId.tdata()[i]); + } + values.setDim(stackpointer); + vars.setDim(stackpointer); + savedId.setDim(stackpointer); + } + void saveGlobalConstant(VarDeclaration *v, Expression *e) + { + assert(v->isDataseg() && !v->isCTFE()); + v->ctfeAdrOnStack = globalValues.dim; + globalValues.push(e); + } +}; + +CtfeStack ctfeStack; + struct InterState { InterState *caller; // calling function's InterState FuncDeclaration *fd; // function being interpreted - size_t framepointer; // frame pointer of previous frame + size_t framepointer; // frame pointer of previous frame Statement *start; // if !=NULL, start execution at this statement - Statement *gotoTarget; /* target of EXP_GOTO_INTERPRET result; also - * target of labelled EXP_BREAK_INTERPRET or - * EXP_CONTINUE_INTERPRET. (NULL if no label). - */ + Statement *gotoTarget; /* target of EXP_GOTO_INTERPRET result; also + * target of labelled EXP_BREAK_INTERPRET or + * EXP_CONTINUE_INTERPRET. (NULL if no label). + */ Expression *localThis; // value of 'this', or NULL if none bool awaitingLvalueReturn; // Support for ref return values: // Any return to this function should return an lvalue. @@ -174,281 +174,281 @@ InterState::InterState() memset(this, 0, sizeof(InterState)); } -// Global status of the CTFE engine -struct CtfeStatus -{ - static int callDepth; // current number of recursive calls - static int stackTraceCallsToSuppress; /* When printing a stack trace, - * suppress this number of calls - */ - static int maxCallDepth; // highest number of recursive calls - static int numArrayAllocs; // Number of allocated arrays - static int numAssignments; // total number of assignments executed -}; - -int CtfeStatus::callDepth = 0; -int CtfeStatus::stackTraceCallsToSuppress = 0; -int CtfeStatus::maxCallDepth = 0; -int CtfeStatus::numArrayAllocs = 0; -int CtfeStatus::numAssignments = 0; - -// CTFE diagnostic information -void printCtfePerformanceStats() -{ -#if SHOWPERFORMANCE - printf(" ---- CTFE Performance ----\n"); - printf("max call depth = %d\tmax stack = %d\n", CtfeStatus::maxCallDepth, ctfeStack.maxStackUsage()); - printf("array allocs = %d\tassignments = %d\n\n", CtfeStatus::numArrayAllocs, CtfeStatus::numAssignments); -#endif -} +// Global status of the CTFE engine +struct CtfeStatus +{ + static int callDepth; // current number of recursive calls + static int stackTraceCallsToSuppress; /* When printing a stack trace, + * suppress this number of calls + */ + static int maxCallDepth; // highest number of recursive calls + static int numArrayAllocs; // Number of allocated arrays + static int numAssignments; // total number of assignments executed +}; + +int CtfeStatus::callDepth = 0; +int CtfeStatus::stackTraceCallsToSuppress = 0; +int CtfeStatus::maxCallDepth = 0; +int CtfeStatus::numArrayAllocs = 0; +int CtfeStatus::numAssignments = 0; + +// CTFE diagnostic information +void printCtfePerformanceStats() +{ +#if SHOWPERFORMANCE + printf(" ---- CTFE Performance ----\n"); + printf("max call depth = %d\tmax stack = %d\n", CtfeStatus::maxCallDepth, ctfeStack.maxStackUsage()); + printf("array allocs = %d\tassignments = %d\n\n", CtfeStatus::numArrayAllocs, CtfeStatus::numAssignments); +#endif +} -Expression * resolveReferences(Expression *e, Expression *thisval); -Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal); +Expression * resolveReferences(Expression *e, Expression *thisval); +Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal); VarDeclaration *findParentVar(Expression *e, Expression *thisval); -bool needToCopyLiteral(Expression *expr); -Expression *copyLiteral(Expression *e); -Expression *paintTypeOntoLiteral(Type *type, Expression *lit); -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2); -Expression *evaluateIfBuiltin(InterState *istate, Loc loc, - FuncDeclaration *fd, Expressions *arguments, Expression *pthis); -Expression *scrubReturnValue(Loc loc, Expression *e); -bool isAssocArray(Type *t); -bool isPointer(Type *t); - -// CTFE only expressions -#define TOKclassreference ((TOK)(TOKMAX+1)) -#define TOKthrownexception ((TOK)(TOKMAX+2)) - -// Reference to a class, or an interface. We need this when we -// point to a base class (we must record what the type is). -struct ClassReferenceExp : Expression -{ - StructLiteralExp *value; - ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type) : Expression(loc, TOKclassreference, sizeof(ClassReferenceExp)) - { - assert(lit && lit->sd && lit->sd->isClassDeclaration()); - this->value = lit; - this->type = type; - } - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) - { - //printf("ClassReferenceExp::interpret() %s\n", value->toChars()); - return this; - } - char *toChars() - { - return value->toChars(); - } - ClassDeclaration *originalClass() - { - return value->sd->isClassDeclaration(); - } - // Return index of the field, or -1 if not found - int getFieldIndex(Type *fieldtype, size_t fieldoffset) - { - ClassDeclaration *cd = originalClass(); - size_t fieldsSoFar = 0; - for (size_t j = 0; j < value->elements->dim; j++) - { while (j - fieldsSoFar >= cd->fields.dim) - { fieldsSoFar += cd->fields.dim; - cd = cd->baseClass; - } - Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; - VarDeclaration *v2 = s->isVarDeclaration(); - if (fieldoffset == v2->offset && - fieldtype->size() == v2->type->size()) - { return value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar); - } - } - return -1; - } - // Return index of the field, or -1 if not found - // Same as getFieldIndex, but checks for a direct match with the VarDeclaration - int findFieldIndexByName(VarDeclaration *v) - { - ClassDeclaration *cd = originalClass(); - size_t fieldsSoFar = 0; - for (size_t j = 0; j < value->elements->dim; j++) - { while (j - fieldsSoFar >= cd->fields.dim) - { fieldsSoFar += cd->fields.dim; - cd = cd->baseClass; - } - Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; - VarDeclaration *v2 = s->isVarDeclaration(); - if (v == v2) - { return value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar); - } - } - return -1; - } -}; - -// Return index of the field, or -1 if not found -// Same as getFieldIndex, but checks for a direct match with the VarDeclaration -int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) -{ - for (int i = 0; i < sd->fields.dim; ++i) - { - if (sd->fields.tdata()[i] == v) - return i; - } - return -1; -} - -// Fake class which holds the thrown exception. Used for implementing exception handling. -struct ThrownExceptionExp : Expression -{ - ClassReferenceExp *thrown; // the thing being tossed - ThrownExceptionExp(Loc loc, ClassReferenceExp *victim) : Expression(loc, TOKthrownexception, sizeof(ThrownExceptionExp)) - { - this->thrown = victim; - this->type = type; - } - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) - { - assert(0); // This should never be interpreted - return this; - } - char *toChars() - { - return (char *)"CTFE ThrownException"; - } - // Generate an error message when this exception is not caught - void generateUncaughtError() - { - thrown->error("Uncaught CTFE exception %s(%s)", thrown->type->toChars(), - thrown->value->elements->tdata()[0]->toChars()); - /* Also give the line where the throw statement was. We won't have it - * in the case where the ThrowStatement is generated internally - * (eg, in ScopeStatement) - */ - if (loc.filename && !loc.equals(thrown->loc)) - errorSupplemental(loc, "thrown from here"); - } -}; - -// True if 'e' is EXP_CANT_INTERPRET, or an exception -bool exceptionOrCantInterpret(Expression *e) -{ - if (e == EXP_CANT_INTERPRET) return true; - if (!e || e == EXP_GOTO_INTERPRET || e == EXP_VOID_INTERPRET - || e == EXP_BREAK_INTERPRET || e == EXP_CONTINUE_INTERPRET) - return false; - return e->op == TOKthrownexception; -} - - -// Used for debugging only -void showCtfeExpr(Expression *e, int level = 0) -{ - for (int i = level; i>0; --i) printf(" "); - Expressions *elements = NULL; - // We need the struct definition to detect block assignment - StructDeclaration *sd = NULL; - ClassDeclaration *cd = NULL; - if (e->op == TOKstructliteral) - { elements = ((StructLiteralExp *)e)->elements; - sd = ((StructLiteralExp *)e)->sd; - printf("STRUCT type = %s %p:\n", e->type->toChars(), - e); - } - else if (e->op == TOKclassreference) - { elements = ((ClassReferenceExp *)e)->value->elements; - cd = ((ClassReferenceExp *)e)->originalClass(); - printf("CLASS type = %s %p:\n", e->type->toChars(), - ((ClassReferenceExp *)e)->value); - } - else if (e->op == TOKarrayliteral) - { - elements = ((ArrayLiteralExp *)e)->elements; - printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(), - e); - } - else if (e->op == TOKassocarrayliteral) - { - printf("AA LITERAL type=%s %p:\n", e->type->toChars(), - e); - } - else if (e->op == TOKstring) - { - printf("STRING %s %p\n", e->toChars(), - ((StringExp *)e)->string); - } - else if (e->op == TOKslice) - { - printf("SLICE %p: %s\n", e, e->toChars()); - showCtfeExpr(((SliceExp *)e)->e1, level + 1); - } - else if (e->op == TOKvar) - { - printf("VAR %p %s\n", e, e->toChars()); - VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration(); - if (v && v->getValue()) - showCtfeExpr(v->getValue(), level + 1); - } - else if (isPointer(e->type)) - { - // This is potentially recursive. We mustn't try to print the thing we're pointing to. - if (e->op == TOKindex) - printf("POINTER %p into %p [%s]\n", e, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2->toChars()); - else if (e->op == TOKdotvar) - printf("POINTER %p to %p .%s\n", e, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var->toChars()); - else - printf("POINTER %p: %s\n", e, e->toChars()); - } - else - printf("VALUE %p: %s\n", e, e->toChars()); - - if (elements) - { - size_t fieldsSoFar = 0; - for (size_t i = 0; i < elements->dim; i++) - { Expression *z = NULL; - Dsymbol *s = NULL; - if (i > 15) { - printf("...(total %d elements)\n", elements->dim); - return; - } - if (sd) - { s = sd->fields.tdata()[i]; - z = elements->tdata()[i]; - } - else if (cd) - { while (i - fieldsSoFar >= cd->fields.dim) - { fieldsSoFar += cd->fields.dim; - cd = cd->baseClass; - for (int j = level; j>0; --j) printf(" "); - printf(" BASE CLASS: %s\n", cd->toChars()); - } - s = cd->fields.tdata()[i - fieldsSoFar]; - size_t indx = (elements->dim - fieldsSoFar)- cd->fields.dim + i; - assert(indx >= 0); - assert(indx < elements->dim); - z = elements->tdata()[indx]; - } - if (!z) { - for (int j = level; j>0; --j) printf(" "); - printf(" void\n"); - continue; - } - - if (s) - { - VarDeclaration *v = s->isVarDeclaration(); - assert(v); - // If it is a void assignment, use the default initializer - if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray) - { - for (int j = level; --j;) printf(" "); - printf(" field: block initalized static array\n"); - continue; - } - } - showCtfeExpr(z, level + 1); - } - } -} +bool needToCopyLiteral(Expression *expr); +Expression *copyLiteral(Expression *e); +Expression *paintTypeOntoLiteral(Type *type, Expression *lit); +Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2); +Expression *evaluateIfBuiltin(InterState *istate, Loc loc, + FuncDeclaration *fd, Expressions *arguments, Expression *pthis); +Expression *scrubReturnValue(Loc loc, Expression *e); +bool isAssocArray(Type *t); +bool isPointer(Type *t); + +// CTFE only expressions +#define TOKclassreference ((TOK)(TOKMAX+1)) +#define TOKthrownexception ((TOK)(TOKMAX+2)) + +// Reference to a class, or an interface. We need this when we +// point to a base class (we must record what the type is). +struct ClassReferenceExp : Expression +{ + StructLiteralExp *value; + ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type) : Expression(loc, TOKclassreference, sizeof(ClassReferenceExp)) + { + assert(lit && lit->sd && lit->sd->isClassDeclaration()); + this->value = lit; + this->type = type; + } + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) + { + //printf("ClassReferenceExp::interpret() %s\n", value->toChars()); + return this; + } + char *toChars() + { + return value->toChars(); + } + ClassDeclaration *originalClass() + { + return value->sd->isClassDeclaration(); + } + // Return index of the field, or -1 if not found + int getFieldIndex(Type *fieldtype, size_t fieldoffset) + { + ClassDeclaration *cd = originalClass(); + size_t fieldsSoFar = 0; + for (size_t j = 0; j < value->elements->dim; j++) + { while (j - fieldsSoFar >= cd->fields.dim) + { fieldsSoFar += cd->fields.dim; + cd = cd->baseClass; + } + Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; + VarDeclaration *v2 = s->isVarDeclaration(); + if (fieldoffset == v2->offset && + fieldtype->size() == v2->type->size()) + { return value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar); + } + } + return -1; + } + // Return index of the field, or -1 if not found + // Same as getFieldIndex, but checks for a direct match with the VarDeclaration + int findFieldIndexByName(VarDeclaration *v) + { + ClassDeclaration *cd = originalClass(); + size_t fieldsSoFar = 0; + for (size_t j = 0; j < value->elements->dim; j++) + { while (j - fieldsSoFar >= cd->fields.dim) + { fieldsSoFar += cd->fields.dim; + cd = cd->baseClass; + } + Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; + VarDeclaration *v2 = s->isVarDeclaration(); + if (v == v2) + { return value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar); + } + } + return -1; + } +}; + +// Return index of the field, or -1 if not found +// Same as getFieldIndex, but checks for a direct match with the VarDeclaration +int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) +{ + for (int i = 0; i < sd->fields.dim; ++i) + { + if (sd->fields.tdata()[i] == v) + return i; + } + return -1; +} + +// Fake class which holds the thrown exception. Used for implementing exception handling. +struct ThrownExceptionExp : Expression +{ + ClassReferenceExp *thrown; // the thing being tossed + ThrownExceptionExp(Loc loc, ClassReferenceExp *victim) : Expression(loc, TOKthrownexception, sizeof(ThrownExceptionExp)) + { + this->thrown = victim; + this->type = type; + } + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) + { + assert(0); // This should never be interpreted + return this; + } + char *toChars() + { + return (char *)"CTFE ThrownException"; + } + // Generate an error message when this exception is not caught + void generateUncaughtError() + { + thrown->error("Uncaught CTFE exception %s(%s)", thrown->type->toChars(), + thrown->value->elements->tdata()[0]->toChars()); + /* Also give the line where the throw statement was. We won't have it + * in the case where the ThrowStatement is generated internally + * (eg, in ScopeStatement) + */ + if (loc.filename && !loc.equals(thrown->loc)) + errorSupplemental(loc, "thrown from here"); + } +}; + +// True if 'e' is EXP_CANT_INTERPRET, or an exception +bool exceptionOrCantInterpret(Expression *e) +{ + if (e == EXP_CANT_INTERPRET) return true; + if (!e || e == EXP_GOTO_INTERPRET || e == EXP_VOID_INTERPRET + || e == EXP_BREAK_INTERPRET || e == EXP_CONTINUE_INTERPRET) + return false; + return e->op == TOKthrownexception; +} + + +// Used for debugging only +void showCtfeExpr(Expression *e, int level = 0) +{ + for (int i = level; i>0; --i) printf(" "); + Expressions *elements = NULL; + // We need the struct definition to detect block assignment + StructDeclaration *sd = NULL; + ClassDeclaration *cd = NULL; + if (e->op == TOKstructliteral) + { elements = ((StructLiteralExp *)e)->elements; + sd = ((StructLiteralExp *)e)->sd; + printf("STRUCT type = %s %p:\n", e->type->toChars(), + e); + } + else if (e->op == TOKclassreference) + { elements = ((ClassReferenceExp *)e)->value->elements; + cd = ((ClassReferenceExp *)e)->originalClass(); + printf("CLASS type = %s %p:\n", e->type->toChars(), + ((ClassReferenceExp *)e)->value); + } + else if (e->op == TOKarrayliteral) + { + elements = ((ArrayLiteralExp *)e)->elements; + printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(), + e); + } + else if (e->op == TOKassocarrayliteral) + { + printf("AA LITERAL type=%s %p:\n", e->type->toChars(), + e); + } + else if (e->op == TOKstring) + { + printf("STRING %s %p\n", e->toChars(), + ((StringExp *)e)->string); + } + else if (e->op == TOKslice) + { + printf("SLICE %p: %s\n", e, e->toChars()); + showCtfeExpr(((SliceExp *)e)->e1, level + 1); + } + else if (e->op == TOKvar) + { + printf("VAR %p %s\n", e, e->toChars()); + VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration(); + if (v && v->getValue()) + showCtfeExpr(v->getValue(), level + 1); + } + else if (isPointer(e->type)) + { + // This is potentially recursive. We mustn't try to print the thing we're pointing to. + if (e->op == TOKindex) + printf("POINTER %p into %p [%s]\n", e, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2->toChars()); + else if (e->op == TOKdotvar) + printf("POINTER %p to %p .%s\n", e, ((DotVarExp *)e)->e1, ((DotVarExp *)e)->var->toChars()); + else + printf("POINTER %p: %s\n", e, e->toChars()); + } + else + printf("VALUE %p: %s\n", e, e->toChars()); + + if (elements) + { + size_t fieldsSoFar = 0; + for (size_t i = 0; i < elements->dim; i++) + { Expression *z = NULL; + Dsymbol *s = NULL; + if (i > 15) { + printf("...(total %d elements)\n", elements->dim); + return; + } + if (sd) + { s = sd->fields.tdata()[i]; + z = elements->tdata()[i]; + } + else if (cd) + { while (i - fieldsSoFar >= cd->fields.dim) + { fieldsSoFar += cd->fields.dim; + cd = cd->baseClass; + for (int j = level; j>0; --j) printf(" "); + printf(" BASE CLASS: %s\n", cd->toChars()); + } + s = cd->fields.tdata()[i - fieldsSoFar]; + size_t indx = (elements->dim - fieldsSoFar)- cd->fields.dim + i; + assert(indx >= 0); + assert(indx < elements->dim); + z = elements->tdata()[indx]; + } + if (!z) { + for (int j = level; j>0; --j) printf(" "); + printf(" void\n"); + continue; + } + + if (s) + { + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + // If it is a void assignment, use the default initializer + if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray) + { + for (int j = level; --j;) printf(" "); + printf(" field: block initalized static array\n"); + continue; + } + } + showCtfeExpr(z, level + 1); + } + } +} /************************************* * Attempt to interpret a function given the arguments. @@ -457,7 +457,7 @@ void showCtfeExpr(Expression *e, int level = 0) * arguments function arguments * thisarg 'this', if a needThis() function, NULL if not. * - * Return result expression if successful, EXP_CANT_INTERPRET if not. + * Return result expression if successful, EXP_CANT_INTERPRET if not. */ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) @@ -465,32 +465,32 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument #if LOG printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); #endif - if (semanticRun == PASSsemantic3) - return EXP_CANT_INTERPRET; + if (semanticRun == PASSsemantic3) + return EXP_CANT_INTERPRET; if (semanticRun < PASSsemantic3 && scope) { - /* Forward reference - we need to run semantic3 on this function. - * If errors are gagged, and it's not part of a speculative - * template instance, we need to temporarily ungag errors. - */ - int olderrors = global.errors; - int oldgag = global.gag; - TemplateInstance *spec = isSpeculativeFunction(this); - if (global.gag && !spec) - global.gag = 0; + /* Forward reference - we need to run semantic3 on this function. + * If errors are gagged, and it's not part of a speculative + * template instance, we need to temporarily ungag errors. + */ + int olderrors = global.errors; + int oldgag = global.gag; + TemplateInstance *spec = isSpeculativeFunction(this); + if (global.gag && !spec) + global.gag = 0; semantic3(scope); - global.gag = oldgag; // regag errors - - // If it is a speculatively-instantiated template, and errors occur, - // we need to mark the template as having errors. - if (spec && global.errors != olderrors) - spec->errors = global.errors - olderrors; - if (olderrors != global.errors) // if errors compiling this function - return EXP_CANT_INTERPRET; + global.gag = oldgag; // regag errors + + // If it is a speculatively-instantiated template, and errors occur, + // we need to mark the template as having errors. + if (spec && global.errors != olderrors) + spec->errors = global.errors - olderrors; + if (olderrors != global.errors) // if errors compiling this function + return EXP_CANT_INTERPRET; } if (semanticRun < PASSsemantic3done) - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; Type *tb = type->toBasetype(); assert(tb->ty == Tfunction); @@ -498,37 +498,37 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument Type *tret = tf->next->toBasetype(); if (tf->varargs && arguments && ((parameters && arguments->dim != parameters->dim) || (!parameters && arguments->dim))) - { + { error("C-style variadic functions are not yet implemented in CTFE"); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } - // Nested functions always inherit the 'this' pointer from the parent, - // except for delegates. (Note that the 'this' pointer may be null). - // Func literals report isNested() even if they are in global scope, - // so we need to check that the parent is a function. - if (isNested() && toParent2()->isFuncDeclaration() && !thisarg && istate) - thisarg = istate->localThis; - + // Nested functions always inherit the 'this' pointer from the parent, + // except for delegates. (Note that the 'this' pointer may be null). + // Func literals report isNested() even if they are in global scope, + // so we need to check that the parent is a function. + if (isNested() && toParent2()->isFuncDeclaration() && !thisarg && istate) + thisarg = istate->localThis; + InterState istatex; istatex.caller = istate; istatex.fd = this; istatex.localThis = thisarg; - istatex.framepointer = ctfeStack.startFrame(); + istatex.framepointer = ctfeStack.startFrame(); Expressions vsave; // place to save previous parameter values size_t dim = 0; if (needThis() && !thisarg) - { // error, no this. Prevent segfault. + { // error, no this. Prevent segfault. error("need 'this' to access member %s", toChars()); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } if (thisarg && !istate) { // Check that 'this' aleady has a value if (thisarg->interpret(istate) == EXP_CANT_INTERPRET) - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } - static int evaluatingArgs = 0; + static int evaluatingArgs = 0; if (arguments) { dim = arguments->dim; @@ -541,22 +541,22 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument Expressions eargs; eargs.setDim(dim); for (size_t i = 0; i < dim; i++) - { Expression *earg = arguments->tdata()[i]; + { Expression *earg = arguments->tdata()[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); if (arg->storageClass & (STCout | STCref)) { - if (!istate && (arg->storageClass & STCout)) - { // initializing an out parameter involves writing to it. - earg->error("global %s cannot be passed as an 'out' parameter at compile time", earg->toChars()); - return EXP_CANT_INTERPRET; + if (!istate && (arg->storageClass & STCout)) + { // initializing an out parameter involves writing to it. + earg->error("global %s cannot be passed as an 'out' parameter at compile time", earg->toChars()); + return EXP_CANT_INTERPRET; } - // Convert all reference arguments into lvalue references - ++evaluatingArgs; - earg = earg->interpret(istate, ctfeNeedLvalueRef); - --evaluatingArgs; - if (earg == EXP_CANT_INTERPRET) - return earg; + // Convert all reference arguments into lvalue references + ++evaluatingArgs; + earg = earg->interpret(istate, ctfeNeedLvalueRef); + --evaluatingArgs; + if (earg == EXP_CANT_INTERPRET) + return earg; } else if (arg->storageClass & STClazy) { @@ -572,78 +572,78 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument */ earg = ((AddrExp *)earg)->e1; } - ++evaluatingArgs; - earg = earg->interpret(istate); - --evaluatingArgs; + ++evaluatingArgs; + earg = earg->interpret(istate); + --evaluatingArgs; if (earg == EXP_CANT_INTERPRET) - return earg; - } - if (earg->op == TOKthrownexception) - { - if (istate) - return earg; - ((ThrownExceptionExp *)earg)->generateUncaughtError(); - return EXP_CANT_INTERPRET; + return earg; } - eargs.tdata()[i] = earg; + if (earg->op == TOKthrownexception) + { + if (istate) + return earg; + ((ThrownExceptionExp *)earg)->generateUncaughtError(); + return EXP_CANT_INTERPRET; + } + eargs.tdata()[i] = earg; } for (size_t i = 0; i < dim; i++) - { Expression *earg = eargs.tdata()[i]; + { Expression *earg = eargs.tdata()[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); - VarDeclaration *v = parameters->tdata()[i]; + VarDeclaration *v = parameters->tdata()[i]; #if LOG printf("arg[%d] = %s\n", i, earg->toChars()); #endif - if (arg->storageClass & (STCout | STCref) && earg->op == TOKvar) - { - VarExp *ve = (VarExp *)earg; - VarDeclaration *v2 = ve->var->isVarDeclaration(); - if (!v2) - { - error("cannot interpret %s as a ref parameter", ve->toChars()); - return EXP_CANT_INTERPRET; + if (arg->storageClass & (STCout | STCref) && earg->op == TOKvar) + { + VarExp *ve = (VarExp *)earg; + VarDeclaration *v2 = ve->var->isVarDeclaration(); + if (!v2) + { + error("cannot interpret %s as a ref parameter", ve->toChars()); + return EXP_CANT_INTERPRET; } - /* The push() isn't a variable we'll use, it's just a place - * to save the old value of v. - * Note that v might be v2! So we need to save v2's index - * before pushing. - */ - size_t oldadr = v2->ctfeAdrOnStack; - ctfeStack.push(v); - v->ctfeAdrOnStack = oldadr; - assert(v2->hasValue()); - } + /* The push() isn't a variable we'll use, it's just a place + * to save the old value of v. + * Note that v might be v2! So we need to save v2's index + * before pushing. + */ + size_t oldadr = v2->ctfeAdrOnStack; + ctfeStack.push(v); + v->ctfeAdrOnStack = oldadr; + assert(v2->hasValue()); + } else { // Value parameters and non-trivial references - ctfeStack.push(v); - v->setValueWithoutChecking(earg); + ctfeStack.push(v); + v->setValueWithoutChecking(earg); } -#if LOG || LOGASSIGN +#if LOG || LOGASSIGN printf("interpreted arg[%d] = %s\n", i, earg->toChars()); - showCtfeExpr(earg); + showCtfeExpr(earg); #endif } } - if (vresult) - ctfeStack.push(vresult); - - // Enter the function - ++CtfeStatus::callDepth; - if (CtfeStatus::callDepth > CtfeStatus::maxCallDepth) - CtfeStatus::maxCallDepth = CtfeStatus::callDepth; + if (vresult) + ctfeStack.push(vresult); + + // Enter the function + ++CtfeStatus::callDepth; + if (CtfeStatus::callDepth > CtfeStatus::maxCallDepth) + CtfeStatus::maxCallDepth = CtfeStatus::callDepth; Expression *e = NULL; while (1) { - if (CtfeStatus::callDepth > CTFE_RECURSION_LIMIT) - { // This is a compiler error. It must not be suppressed. - global.gag = 0; - error("CTFE recursion limit exceeded"); - e = EXP_CANT_INTERPRET; - break; - } + if (CtfeStatus::callDepth > CTFE_RECURSION_LIMIT) + { // This is a compiler error. It must not be suppressed. + global.gag = 0; + error("CTFE recursion limit exceeded"); + e = EXP_CANT_INTERPRET; + break; + } e = fbody->interpret(&istatex); if (e == EXP_CANT_INTERPRET) { @@ -666,28 +666,28 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument else break; } - assert(e != EXP_CONTINUE_INTERPRET && e != EXP_BREAK_INTERPRET); + assert(e != EXP_CONTINUE_INTERPRET && e != EXP_BREAK_INTERPRET); - // Leave the function - --CtfeStatus::callDepth; - - ctfeStack.endFrame(istatex.framepointer); - - // If fell off the end of a void function, return void - if (!e && type->toBasetype()->nextOf()->ty == Tvoid) - return EXP_VOID_INTERPRET; - // If it generated an exception, return it - if (exceptionOrCantInterpret(e)) - { - if (istate || e == EXP_CANT_INTERPRET) - return e; - ((ThrownExceptionExp *)e)->generateUncaughtError(); - return EXP_CANT_INTERPRET; - } - if (!istate && !evaluatingArgs) - { - e = scrubReturnValue(loc, e); - } + // Leave the function + --CtfeStatus::callDepth; + + ctfeStack.endFrame(istatex.framepointer); + + // If fell off the end of a void function, return void + if (!e && type->toBasetype()->nextOf()->ty == Tvoid) + return EXP_VOID_INTERPRET; + // If it generated an exception, return it + if (exceptionOrCantInterpret(e)) + { + if (istate || e == EXP_CANT_INTERPRET) + return e; + ((ThrownExceptionExp *)e)->generateUncaughtError(); + return EXP_CANT_INTERPRET; + } + if (!istate && !evaluatingArgs) + { + e = scrubReturnValue(loc, e); + } return e; } @@ -705,7 +705,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument * Returns: * NULL continue to next statement * EXP_CANT_INTERPRET cannot interpret statement at compile time - * !NULL expression from return statement, or thrown exception + * !NULL expression from return statement, or thrown exception */ Expression *Statement::interpret(InterState *istate) @@ -726,14 +726,14 @@ Expression *ExpStatement::interpret(InterState *istate) START() if (exp) { - Expression *e = exp->interpret(istate, ctfeNeedNothing); + Expression *e = exp->interpret(istate, ctfeNeedNothing); if (e == EXP_CANT_INTERPRET) { //printf("-ExpStatement::interpret(): %p\n", e); return EXP_CANT_INTERPRET; } - if (e && e!= EXP_VOID_INTERPRET && e->op == TOKthrownexception) - return e; + if (e && e!= EXP_VOID_INTERPRET && e->op == TOKthrownexception) + return e; } return NULL; } @@ -749,7 +749,7 @@ Expression *CompoundStatement::interpret(InterState *istate) if (statements) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = statements->tdata()[i]; + { Statement *s = statements->tdata()[i]; if (s) { @@ -776,26 +776,26 @@ Expression *UnrolledLoopStatement::interpret(InterState *istate) if (statements) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = statements->tdata()[i]; + { Statement *s = statements->tdata()[i]; e = s->interpret(istate); if (e == EXP_CANT_INTERPRET) break; if (e == EXP_CONTINUE_INTERPRET) - { - if (istate->gotoTarget && istate->gotoTarget != this) - break; // continue at higher level - istate->gotoTarget = NULL; - e = NULL; + { + if (istate->gotoTarget && istate->gotoTarget != this) + break; // continue at higher level + istate->gotoTarget = NULL; + e = NULL; continue; } if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; + e = NULL; + } // else break at a higher level break; } if (e) @@ -805,13 +805,13 @@ Expression *UnrolledLoopStatement::interpret(InterState *istate) return e; } -// For CTFE only. Returns true if 'e' is TRUE or a non-null pointer. -int isTrueBool(Expression *e) -{ - return e->isBool(TRUE) || ((e->type->ty == Tpointer || e->type->ty == Tclass) - && e->op != TOKnull); -} - +// For CTFE only. Returns true if 'e' is TRUE or a non-null pointer. +int isTrueBool(Expression *e) +{ + return e->isBool(TRUE) || ((e->type->ty == Tpointer || e->type->ty == Tclass) + && e->op != TOKnull); +} + Expression *IfStatement::interpret(InterState *istate) { #if LOG @@ -825,8 +825,8 @@ Expression *IfStatement::interpret(InterState *istate) Expression *e = NULL; if (ifbody) e = ifbody->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; + if (exceptionOrCantInterpret(e)) + return e; if (istate->start && elsebody) e = elsebody->interpret(istate); return e; @@ -835,9 +835,9 @@ Expression *IfStatement::interpret(InterState *istate) Expression *e = condition->interpret(istate); assert(e); //if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n"); - if (e != EXP_CANT_INTERPRET && (e && e->op != TOKthrownexception)) + if (e != EXP_CANT_INTERPRET && (e && e->op != TOKthrownexception)) { - if (isTrueBool(e)) + if (isTrueBool(e)) e = ifbody ? ifbody->interpret(istate) : NULL; else if (e->isBool(FALSE)) e = elsebody ? elsebody->interpret(istate) : NULL; @@ -859,177 +859,177 @@ Expression *ScopeStatement::interpret(InterState *istate) return statement ? statement->interpret(istate) : NULL; } -Expression *resolveSlice(Expression *e) +Expression *resolveSlice(Expression *e) { - if ( ((SliceExp *)e)->e1->op == TOKnull) - return ((SliceExp *)e)->e1; - return Slice(e->type, ((SliceExp *)e)->e1, - ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); -} - -/* Determine the array length, without interpreting it. - * e must be an array literal, or a slice - * It's very wasteful to resolve the slice when we only - * need the length. - */ -uinteger_t resolveArrayLength(Expression *e) -{ - if (e->op == TOKnull) - return 0; - if (e->op == TOKslice) - { uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger(); - uinteger_t iup = ((SliceExp *)e)->upr->toInteger(); - return iup - ilo; - } - if (e->op == TOKstring) - { return ((StringExp *)e)->len; - } - if (e->op == TOKarrayliteral) - { ArrayLiteralExp *ale = (ArrayLiteralExp *)e; - return ale->elements ? ale->elements->dim : 0; - } - if (e->op == TOKassocarrayliteral) - { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e; - return ale->keys->dim; - } - assert(0); - return 0; -} - -// As Equal, but resolves slices before comparing -Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) -{ - if (e1->op == TOKslice) - e1 = resolveSlice(e1); - if (e2->op == TOKslice) - e2 = resolveSlice(e2); - return Equal(op, type, e1, e2); -} - -Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) -{ - Loc loc = e1->loc; - Type *t1 = e1->type->toBasetype(); - Type *t2 = e2->type->toBasetype(); - Expression *e; - if (e2->op == TOKstring && e1->op == TOKarrayliteral && - t1->nextOf()->isintegral()) - { - // [chars] ~ string => string (only valid for CTFE) - StringExp *es1 = (StringExp *)e2; - ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1; - size_t len = es1->len + es2->elements->dim; - int sz = es1->sz; - - void *s = mem.malloc((len + 1) * sz); - memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz); - for (size_t i = 0; i < es2->elements->dim; i++) - { Expression *es2e = es2->elements->tdata()[i]; - if (es2e->op != TOKint64) - return EXP_CANT_INTERPRET; - dinteger_t v = es2e->toInteger(); - memcpy((unsigned char *)s + i * sz, &v, sz); - } - - // Add terminating 0 - memset((unsigned char *)s + len * sz, 0, sz); - - StringExp *es = new StringExp(loc, s, len); - es->sz = sz; - es->committed = 0; - es->type = type; - e = es; - return e; - } - else if (e1->op == TOKstring && e2->op == TOKarrayliteral && - t2->nextOf()->isintegral()) - { - // string ~ [chars] => string (only valid for CTFE) - // Concatenate the strings - StringExp *es1 = (StringExp *)e1; - ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; - size_t len = es1->len + es2->elements->dim; - int sz = es1->sz; - - void *s = mem.malloc((len + 1) * sz); - memcpy(s, es1->string, es1->len * sz); - for (size_t i = 0; i < es2->elements->dim; i++) - { Expression *es2e = es2->elements->tdata()[i]; - if (es2e->op != TOKint64) - return EXP_CANT_INTERPRET; - dinteger_t v = es2e->toInteger(); - memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz); - } - - // Add terminating 0 - memset((unsigned char *)s + len * sz, 0, sz); - - StringExp *es = new StringExp(loc, s, len); - es->sz = sz; - es->committed = 0; //es1->committed; - es->type = type; - e = es; - return e; - } - return Cat(type, e1, e2); -} - -void scrubArray(Loc loc, Expressions *elems); - -/* All results destined for use outside of CTFE need to have their CTFE-specific - * features removed. - * In particular, all slices must be resolved. - */ -Expression *scrubReturnValue(Loc loc, Expression *e) -{ - if (e->op == TOKclassreference) - { - error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); - return EXP_CANT_INTERPRET; - } - if (e->op == TOKslice) - { - e = resolveSlice(e); - } - if (e->op == TOKstructliteral) - { - StructLiteralExp *se = (StructLiteralExp *)e; - se->ownedByCtfe = false; - scrubArray(loc, se->elements); - } - if (e->op == TOKstring) - { - ((StringExp *)e)->ownedByCtfe = false; - } - if (e->op == TOKarrayliteral) - { - ((ArrayLiteralExp *)e)->ownedByCtfe = false; - scrubArray(loc, ((ArrayLiteralExp *)e)->elements); - } - if (e->op == TOKassocarrayliteral) - { - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; - aae->ownedByCtfe = false; - scrubArray(loc, aae->keys); - scrubArray(loc, aae->values); - } - return e; -} - -// Scrub all members of an array -void scrubArray(Loc loc, Expressions *elems) -{ - for (size_t i = 0; i < elems->dim; i++) - { - Expression *m = elems->tdata()[i]; - if (!m) - continue; - m = scrubReturnValue(loc, m); - elems->tdata()[i] = m; - } + if ( ((SliceExp *)e)->e1->op == TOKnull) + return ((SliceExp *)e)->e1; + return Slice(e->type, ((SliceExp *)e)->e1, + ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); } - +/* Determine the array length, without interpreting it. + * e must be an array literal, or a slice + * It's very wasteful to resolve the slice when we only + * need the length. + */ +uinteger_t resolveArrayLength(Expression *e) +{ + if (e->op == TOKnull) + return 0; + if (e->op == TOKslice) + { uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger(); + uinteger_t iup = ((SliceExp *)e)->upr->toInteger(); + return iup - ilo; + } + if (e->op == TOKstring) + { return ((StringExp *)e)->len; + } + if (e->op == TOKarrayliteral) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e; + return ale->elements ? ale->elements->dim : 0; + } + if (e->op == TOKassocarrayliteral) + { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e; + return ale->keys->dim; + } + assert(0); + return 0; +} + +// As Equal, but resolves slices before comparing +Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) +{ + if (e1->op == TOKslice) + e1 = resolveSlice(e1); + if (e2->op == TOKslice) + e2 = resolveSlice(e2); + return Equal(op, type, e1, e2); +} + +Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) +{ + Loc loc = e1->loc; + Type *t1 = e1->type->toBasetype(); + Type *t2 = e2->type->toBasetype(); + Expression *e; + if (e2->op == TOKstring && e1->op == TOKarrayliteral && + t1->nextOf()->isintegral()) + { + // [chars] ~ string => string (only valid for CTFE) + StringExp *es1 = (StringExp *)e2; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1; + size_t len = es1->len + es2->elements->dim; + int sz = es1->sz; + + void *s = mem.malloc((len + 1) * sz); + memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz); + for (size_t i = 0; i < es2->elements->dim; i++) + { Expression *es2e = es2->elements->tdata()[i]; + if (es2e->op != TOKint64) + return EXP_CANT_INTERPRET; + dinteger_t v = es2e->toInteger(); + memcpy((unsigned char *)s + i * sz, &v, sz); + } + + // Add terminating 0 + memset((unsigned char *)s + len * sz, 0, sz); + + StringExp *es = new StringExp(loc, s, len); + es->sz = sz; + es->committed = 0; + es->type = type; + e = es; + return e; + } + else if (e1->op == TOKstring && e2->op == TOKarrayliteral && + t2->nextOf()->isintegral()) + { + // string ~ [chars] => string (only valid for CTFE) + // Concatenate the strings + StringExp *es1 = (StringExp *)e1; + ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; + size_t len = es1->len + es2->elements->dim; + int sz = es1->sz; + + void *s = mem.malloc((len + 1) * sz); + memcpy(s, es1->string, es1->len * sz); + for (size_t i = 0; i < es2->elements->dim; i++) + { Expression *es2e = es2->elements->tdata()[i]; + if (es2e->op != TOKint64) + return EXP_CANT_INTERPRET; + dinteger_t v = es2e->toInteger(); + memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz); + } + + // Add terminating 0 + memset((unsigned char *)s + len * sz, 0, sz); + + StringExp *es = new StringExp(loc, s, len); + es->sz = sz; + es->committed = 0; //es1->committed; + es->type = type; + e = es; + return e; + } + return Cat(type, e1, e2); +} + +void scrubArray(Loc loc, Expressions *elems); + +/* All results destined for use outside of CTFE need to have their CTFE-specific + * features removed. + * In particular, all slices must be resolved. + */ +Expression *scrubReturnValue(Loc loc, Expression *e) +{ + if (e->op == TOKclassreference) + { + error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); + return EXP_CANT_INTERPRET; + } + if (e->op == TOKslice) + { + e = resolveSlice(e); + } + if (e->op == TOKstructliteral) + { + StructLiteralExp *se = (StructLiteralExp *)e; + se->ownedByCtfe = false; + scrubArray(loc, se->elements); + } + if (e->op == TOKstring) + { + ((StringExp *)e)->ownedByCtfe = false; + } + if (e->op == TOKarrayliteral) + { + ((ArrayLiteralExp *)e)->ownedByCtfe = false; + scrubArray(loc, ((ArrayLiteralExp *)e)->elements); + } + if (e->op == TOKassocarrayliteral) + { + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; + aae->ownedByCtfe = false; + scrubArray(loc, aae->keys); + scrubArray(loc, aae->values); + } + return e; +} + +// Scrub all members of an array +void scrubArray(Loc loc, Expressions *elems) +{ + for (size_t i = 0; i < elems->dim; i++) + { + Expression *m = elems->tdata()[i]; + if (!m) + continue; + m = scrubReturnValue(loc, m); + elems->tdata()[i] = m; + } +} + + Expression *ReturnStatement::interpret(InterState *istate) { #if LOG @@ -1047,8 +1047,8 @@ Expression *ReturnStatement::interpret(InterState *istate) { TypeFunction *tf = (TypeFunction *)istate->fd->type; if (tf->isref && istate->caller && istate->caller->awaitingLvalueReturn) - { // We need to return an lvalue - Expression *e = exp->interpret(istate, ctfeNeedLvalue); + { // We need to return an lvalue + Expression *e = exp->interpret(istate, ctfeNeedLvalue); if (e == EXP_CANT_INTERPRET) error("ref return %s is not yet supported in CTFE", exp->toChars()); return e; @@ -1062,21 +1062,21 @@ Expression *ReturnStatement::interpret(InterState *istate) } } #endif - // We need to treat pointers specially, because TOKsymoff can be used to - // return a value OR a pointer - Expression *e; - if ( isPointer(exp->type) ) - e = exp->interpret(istate, ctfeNeedLvalue); - else - e = exp->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - if (needToCopyLiteral(e)) - e = copyLiteral(e); -#if LOGASSIGN - printf("RETURN %s\n", loc.toChars()); - showCtfeExpr(e); -#endif + // We need to treat pointers specially, because TOKsymoff can be used to + // return a value OR a pointer + Expression *e; + if ( isPointer(exp->type) ) + e = exp->interpret(istate, ctfeNeedLvalue); + else + e = exp->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + if (needToCopyLiteral(e)) + e = copyLiteral(e); +#if LOGASSIGN + printf("RETURN %s\n", loc.toChars()); + showCtfeExpr(e); +#endif return e; } @@ -1087,21 +1087,21 @@ Expression *BreakStatement::interpret(InterState *istate) #endif START() if (ident) - { LabelDsymbol *label = istate->fd->searchLabel(ident); - assert(label && label->statement); - Statement *s = label->statement; - if (s->isLabelStatement()) - s = s->isLabelStatement()->statement; - if (s->isScopeStatement()) - s = s->isScopeStatement()->statement; - istate->gotoTarget = s; + { LabelDsymbol *label = istate->fd->searchLabel(ident); + assert(label && label->statement); + Statement *s = label->statement; + if (s->isLabelStatement()) + s = s->isLabelStatement()->statement; + if (s->isScopeStatement()) + s = s->isScopeStatement()->statement; + istate->gotoTarget = s; return EXP_BREAK_INTERPRET; - } - else - { - istate->gotoTarget = NULL; - return EXP_BREAK_INTERPRET; - } + } + else + { + istate->gotoTarget = NULL; + return EXP_BREAK_INTERPRET; + } } Expression *ContinueStatement::interpret(InterState *istate) @@ -1111,16 +1111,16 @@ Expression *ContinueStatement::interpret(InterState *istate) #endif START() if (ident) - { LabelDsymbol *label = istate->fd->searchLabel(ident); - assert(label && label->statement); - Statement *s = label->statement; - if (s->isLabelStatement()) - s = s->isLabelStatement()->statement; - if (s->isScopeStatement()) - s = s->isScopeStatement()->statement; - istate->gotoTarget = s; - return EXP_CONTINUE_INTERPRET; - } + { LabelDsymbol *label = istate->fd->searchLabel(ident); + assert(label && label->statement); + Statement *s = label->statement; + if (s->isLabelStatement()) + s = s->isLabelStatement()->statement; + if (s->isScopeStatement()) + s = s->isScopeStatement()->statement; + istate->gotoTarget = s; + return EXP_CONTINUE_INTERPRET; + } else return EXP_CONTINUE_INTERPRET; } @@ -1151,21 +1151,21 @@ Expression *DoStatement::interpret(InterState *istate) if (e == EXP_CANT_INTERPRET) return e; if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level - return e; - } + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; + e = NULL; + } // else break at a higher level + return e; + } if (e == EXP_CONTINUE_INTERPRET) - if (!istate->gotoTarget || istate->gotoTarget == this) - { + if (!istate->gotoTarget || istate->gotoTarget == this) + { goto Lcontinue; - } - else // else continue at a higher level - return e; + } + else // else continue at a higher level + return e; if (e) return e; } @@ -1176,29 +1176,29 @@ Expression *DoStatement::interpret(InterState *istate) if (e == EXP_CANT_INTERPRET) break; if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; + e = NULL; + } // else break at a higher level break; } if (e && e != EXP_CONTINUE_INTERPRET) break; - if (istate->gotoTarget && istate->gotoTarget != this) - break; // continue at a higher level + if (istate->gotoTarget && istate->gotoTarget != this) + break; // continue at a higher level Lcontinue: - istate->gotoTarget = NULL; + istate->gotoTarget = NULL; e = condition->interpret(istate); - if (exceptionOrCantInterpret(e)) + if (exceptionOrCantInterpret(e)) break; if (!e->isConst()) { e = EXP_CANT_INTERPRET; break; } - if (isTrueBool(e)) + if (isTrueBool(e)) { } else if (e->isBool(FALSE)) @@ -1223,7 +1223,7 @@ Expression *ForStatement::interpret(InterState *istate) if (init) { e = init->interpret(istate); - if (exceptionOrCantInterpret(e)) + if (exceptionOrCantInterpret(e)) return e; assert(!e); } @@ -1236,21 +1236,21 @@ Expression *ForStatement::interpret(InterState *istate) if (e == EXP_CANT_INTERPRET) return e; if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; return NULL; - } // else break at a higher level - } + } // else break at a higher level + } if (e == EXP_CONTINUE_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; goto Lcontinue; - } // else continue at a higher level - } + } // else continue at a higher level + } if (e) return e; } @@ -1260,33 +1260,33 @@ Expression *ForStatement::interpret(InterState *istate) if (!condition) goto Lhead; e = condition->interpret(istate); - if (exceptionOrCantInterpret(e)) + if (exceptionOrCantInterpret(e)) break; if (!e->isConst()) { e = EXP_CANT_INTERPRET; break; } - if (isTrueBool(e)) + if (isTrueBool(e)) { Lhead: e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) break; if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; + e = NULL; + } // else break at a higher level break; } if (e && e != EXP_CONTINUE_INTERPRET) break; - if (istate->gotoTarget && istate->gotoTarget != this) - break; // continue at a higher level + if (istate->gotoTarget && istate->gotoTarget != this) + break; // continue at a higher level Lcontinue: - istate->gotoTarget = NULL; + istate->gotoTarget = NULL; if (increment) { e = increment->interpret(istate); @@ -1335,35 +1335,35 @@ Expression *SwitchStatement::interpret(InterState *istate) if (e == EXP_CANT_INTERPRET) return e; if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; return NULL; - } // else break at a higher level - } + } // else break at a higher level + } return e; } Expression *econdition = condition->interpret(istate); - if (exceptionOrCantInterpret(econdition)) - return econdition; - if (econdition->op == TOKslice) - econdition = resolveSlice(econdition); + if (exceptionOrCantInterpret(econdition)) + return econdition; + if (econdition->op == TOKslice) + econdition = resolveSlice(econdition); Statement *s = NULL; if (cases) { for (size_t i = 0; i < cases->dim; i++) { - CaseStatement *cs = cases->tdata()[i]; - Expression * caseExp = cs->exp->interpret(istate); - if (exceptionOrCantInterpret(caseExp)) - return caseExp; - e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp); - if (exceptionOrCantInterpret(e)) - return e; + CaseStatement *cs = cases->tdata()[i]; + Expression * caseExp = cs->exp->interpret(istate); + if (exceptionOrCantInterpret(caseExp)) + return caseExp; + e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp); + if (exceptionOrCantInterpret(e)) + return e; if (e->isBool(TRUE)) { s = cs; break; @@ -1381,13 +1381,13 @@ Expression *SwitchStatement::interpret(InterState *istate) e = body ? body->interpret(istate) : NULL; assert(!istate->start); if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level - } + { + if (!istate->gotoTarget || istate->gotoTarget == this) + { + istate->gotoTarget = NULL; + e = NULL; + } // else break at a higher level + } return e; } @@ -1467,69 +1467,69 @@ Expression *TryCatchStatement::interpret(InterState *istate) printf("TryCatchStatement::interpret()\n"); #endif START() - Expression *e = body ? body->interpret(istate) : NULL; - if (e == EXP_CANT_INTERPRET) - return e; - if (!exceptionOrCantInterpret(e)) - return e; - // An exception was thrown - ThrownExceptionExp *ex = (ThrownExceptionExp *)e; - Type *extype = ex->thrown->originalClass()->type; - // Search for an appropriate catch clause. - for (size_t i = 0; i < catches->dim; i++) - { -#if DMDV1 - Catch *ca = (Catch *)catches->data[i]; -#else - Catch *ca = catches->tdata()[i]; -#endif - Type *catype = ca->type; - - if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) - { // Execute the handler - if (ca->var) - { - ctfeStack.push(ca->var); - ca->var->setValue(ex->thrown); - } - return ca->handler->interpret(istate); - } - } - return e; -} - -bool isAnErrorException(ClassDeclaration *cd) -{ - return cd == ClassDeclaration::errorException || ClassDeclaration::errorException->isBaseOf(cd, NULL); -} - -ThrownExceptionExp *chainExceptions(ThrownExceptionExp *oldest, ThrownExceptionExp *newest) -{ -#if LOG - printf("Collided exceptions %s %s\n", oldest->thrown->toChars(), newest->thrown->toChars()); -#endif -#if DMDV2 - // Little sanity check to make sure it's really a Throwable - ClassReferenceExp *boss = oldest->thrown; - assert(boss->value->elements->tdata()[4]->type->ty == Tclass); - ClassReferenceExp *collateral = newest->thrown; - if (isAnErrorException(collateral->originalClass()) - && !isAnErrorException(boss->originalClass())) - { // The new exception bypass the existing chain - assert(collateral->value->elements->tdata()[5]->type->ty == Tclass); - collateral->value->elements->tdata()[5] = boss; - return newest; - } - while (boss->value->elements->tdata()[4]->op == TOKclassreference) - { - boss = (ClassReferenceExp *)(boss->value->elements->tdata()[4]); - } - boss->value->elements->tdata()[4] = collateral; - return oldest; -#else - // for D1, the newest exception just clobbers the older one - return newest; -#endif + Expression *e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + return e; + if (!exceptionOrCantInterpret(e)) + return e; + // An exception was thrown + ThrownExceptionExp *ex = (ThrownExceptionExp *)e; + Type *extype = ex->thrown->originalClass()->type; + // Search for an appropriate catch clause. + for (size_t i = 0; i < catches->dim; i++) + { +#if DMDV1 + Catch *ca = (Catch *)catches->data[i]; +#else + Catch *ca = catches->tdata()[i]; +#endif + Type *catype = ca->type; + + if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) + { // Execute the handler + if (ca->var) + { + ctfeStack.push(ca->var); + ca->var->setValue(ex->thrown); + } + return ca->handler->interpret(istate); + } + } + return e; +} + +bool isAnErrorException(ClassDeclaration *cd) +{ + return cd == ClassDeclaration::errorException || ClassDeclaration::errorException->isBaseOf(cd, NULL); +} + +ThrownExceptionExp *chainExceptions(ThrownExceptionExp *oldest, ThrownExceptionExp *newest) +{ +#if LOG + printf("Collided exceptions %s %s\n", oldest->thrown->toChars(), newest->thrown->toChars()); +#endif +#if DMDV2 + // Little sanity check to make sure it's really a Throwable + ClassReferenceExp *boss = oldest->thrown; + assert(boss->value->elements->tdata()[4]->type->ty == Tclass); + ClassReferenceExp *collateral = newest->thrown; + if (isAnErrorException(collateral->originalClass()) + && !isAnErrorException(boss->originalClass())) + { // The new exception bypass the existing chain + assert(collateral->value->elements->tdata()[5]->type->ty == Tclass); + collateral->value->elements->tdata()[5] = boss; + return newest; + } + while (boss->value->elements->tdata()[4]->op == TOKclassreference) + { + boss = (ClassReferenceExp *)(boss->value->elements->tdata()[4]); + } + boss->value->elements->tdata()[4] = collateral; + return oldest; +#else + // for D1, the newest exception just clobbers the older one + return newest; +#endif } @@ -1539,20 +1539,20 @@ Expression *TryFinallyStatement::interpret(InterState *istate) printf("TryFinallyStatement::interpret()\n"); #endif START() - Expression *e = body ? body->interpret(istate) : NULL; - if (e == EXP_CANT_INTERPRET) - return e; - Expression *second = finalbody ? finalbody->interpret(istate) : NULL; - if (second == EXP_CANT_INTERPRET) - return second; - if (exceptionOrCantInterpret(second)) - { // Check for collided exceptions - if (exceptionOrCantInterpret(e)) - e = chainExceptions((ThrownExceptionExp *)e, (ThrownExceptionExp *)second); - else - e = second; - } - return e; + Expression *e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + return e; + Expression *second = finalbody ? finalbody->interpret(istate) : NULL; + if (second == EXP_CANT_INTERPRET) + return second; + if (exceptionOrCantInterpret(second)) + { // Check for collided exceptions + if (exceptionOrCantInterpret(e)) + e = chainExceptions((ThrownExceptionExp *)e, (ThrownExceptionExp *)second); + else + e = second; + } + return e; } Expression *ThrowStatement::interpret(InterState *istate) @@ -1561,16 +1561,16 @@ Expression *ThrowStatement::interpret(InterState *istate) printf("ThrowStatement::interpret()\n"); #endif START() - Expression *e = exp->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - assert(e->op == TOKclassreference); - return new ThrownExceptionExp(loc, (ClassReferenceExp *)e); + Expression *e = exp->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + assert(e->op == TOKclassreference); + return new ThrownExceptionExp(loc, (ClassReferenceExp *)e); } Expression *OnScopeStatement::interpret(InterState *istate) { - assert(0); + assert(0); return EXP_CANT_INTERPRET; } @@ -1580,19 +1580,19 @@ Expression *WithStatement::interpret(InterState *istate) printf("WithStatement::interpret()\n"); #endif START() - Expression *e = exp->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - if (wthis->type->ty == Tpointer && exp->type->ty != Tpointer) - { - e = new AddrExp(loc, e); - e->type = wthis->type; - } - ctfeStack.push(wthis); - wthis->setValue(e); - e = body ? body->interpret(istate) : EXP_VOID_INTERPRET; - ctfeStack.pop(wthis); - return e; + Expression *e = exp->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + if (wthis->type->ty == Tpointer && exp->type->ty != Tpointer) + { + e = new AddrExp(loc, e); + e->type = wthis->type; + } + ctfeStack.push(wthis); + wthis->setValue(e); + e = body ? body->interpret(istate) : EXP_VOID_INTERPRET; + ctfeStack.pop(wthis); + return e; } Expression *AsmStatement::interpret(InterState *istate) @@ -1605,20 +1605,20 @@ Expression *AsmStatement::interpret(InterState *istate) return EXP_CANT_INTERPRET; } -#if DMDV2 -Expression *ImportStatement::interpret(InterState *istate) -{ -#if LOG - printf("ImportStatement::interpret()\n"); -#endif - START(); - return NULL; -} -#endif - +#if DMDV2 +Expression *ImportStatement::interpret(InterState *istate) +{ +#if LOG + printf("ImportStatement::interpret()\n"); +#endif + START(); + return NULL; +} +#endif + /******************************** Expression ***************************/ -Expression *Expression::interpret(InterState *istate, CtfeGoal goal) +Expression *Expression::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("Expression::interpret() %s\n", toChars()); @@ -1629,24 +1629,24 @@ Expression *Expression::interpret(InterState *istate, CtfeGoal goal) return EXP_CANT_INTERPRET; } -Expression *ThisExp::interpret(InterState *istate, CtfeGoal goal) +Expression *ThisExp::interpret(InterState *istate, CtfeGoal goal) { - while (istate && !istate->localThis) - istate = istate->caller; - if (istate && istate->localThis && istate->localThis->op == TOKstructliteral) - return istate->localThis; + while (istate && !istate->localThis) + istate = istate->caller; + if (istate && istate->localThis && istate->localThis->op == TOKstructliteral) + return istate->localThis; if (istate && istate->localThis) - return istate->localThis->interpret(istate, goal); + return istate->localThis->interpret(istate, goal); error("value of 'this' is not known at compile time"); return EXP_CANT_INTERPRET; } -Expression *NullExp::interpret(InterState *istate, CtfeGoal goal) +Expression *NullExp::interpret(InterState *istate, CtfeGoal goal) { return this; } -Expression *IntegerExp::interpret(InterState *istate, CtfeGoal goal) +Expression *IntegerExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("IntegerExp::interpret() %s\n", toChars()); @@ -1654,7 +1654,7 @@ Expression *IntegerExp::interpret(InterState *istate, CtfeGoal goal) return this; } -Expression *RealExp::interpret(InterState *istate, CtfeGoal goal) +Expression *RealExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("RealExp::interpret() %s\n", toChars()); @@ -1662,35 +1662,35 @@ Expression *RealExp::interpret(InterState *istate, CtfeGoal goal) return this; } -Expression *ComplexExp::interpret(InterState *istate, CtfeGoal goal) +Expression *ComplexExp::interpret(InterState *istate, CtfeGoal goal) { return this; } -Expression *StringExp::interpret(InterState *istate, CtfeGoal goal) +Expression *StringExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("StringExp::interpret() %s\n", toChars()); #endif - /* In both D1 and D2, attempts to modify string literals are prevented - * in BinExp::interpretAssignCommon. - * In D2, we also disallow casts of read-only literals to mutable, - * though it isn't strictly necessary. - */ -#if DMDV2 - // Fixed-length char arrays always get duped later anyway. - if (type->ty == Tsarray) - return this; - if (!(((TypeNext *)type)->next->mod & (MODconst | MODimmutable))) - { // It seems this happens only when there has been an explicit cast - error("cannot cast a read-only string literal to mutable in CTFE"); - return EXP_CANT_INTERPRET; - } -#endif + /* In both D1 and D2, attempts to modify string literals are prevented + * in BinExp::interpretAssignCommon. + * In D2, we also disallow casts of read-only literals to mutable, + * though it isn't strictly necessary. + */ +#if DMDV2 + // Fixed-length char arrays always get duped later anyway. + if (type->ty == Tsarray) + return this; + if (!(((TypeNext *)type)->next->mod & (MODconst | MODimmutable))) + { // It seems this happens only when there has been an explicit cast + error("cannot cast a read-only string literal to mutable in CTFE"); + return EXP_CANT_INTERPRET; + } +#endif return this; } -Expression *FuncExp::interpret(InterState *istate, CtfeGoal goal) +Expression *FuncExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("FuncExp::interpret() %s\n", toChars()); @@ -1698,28 +1698,28 @@ Expression *FuncExp::interpret(InterState *istate, CtfeGoal goal) return this; } -/* Is it safe to convert from srcPointee* to destPointee* ? - * srcPointee is the genuine type (never void). - * destPointee may be void. - */ -bool isSafePointerCast(Type *srcPointee, Type *destPointee) -{ // It's OK if both are the same (modulo const) -#if DMDV2 - if (srcPointee->castMod(0) == destPointee->castMod(0)) - return true; -#else - if (srcPointee == destPointee) - return true; -#endif - // it's OK to cast to void* - if (destPointee->ty == Tvoid) - return true; - // It's OK if they are the same size integers, eg int* and uint* - return srcPointee->isintegral() && destPointee->isintegral() - && srcPointee->size() == destPointee->size(); -} - -Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) +/* Is it safe to convert from srcPointee* to destPointee* ? + * srcPointee is the genuine type (never void). + * destPointee may be void. + */ +bool isSafePointerCast(Type *srcPointee, Type *destPointee) +{ // It's OK if both are the same (modulo const) +#if DMDV2 + if (srcPointee->castMod(0) == destPointee->castMod(0)) + return true; +#else + if (srcPointee == destPointee) + return true; +#endif + // it's OK to cast to void* + if (destPointee->ty == Tvoid) + return true; + // It's OK if they are the same size integers, eg int* and uint* + return srcPointee->isintegral() && destPointee->isintegral() + && srcPointee->size() == destPointee->size(); +} + +Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("SymOffExp::interpret() %s\n", toChars()); @@ -1728,103 +1728,103 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) { return this; } - if (type->ty != Tpointer) - { // Probably impossible + if (type->ty != Tpointer) + { // Probably impossible error("Cannot interpret %s at compile time", toChars()); return EXP_CANT_INTERPRET; - } - Type *pointee = ((TypePointer *)type)->next; - Expression *val = getVarExp(loc, istate, var, goal); - if (val->type->ty == Tarray || val->type->ty == Tsarray) - { - // Check for unsupported type painting operations - Type *elemtype = ((TypeArray *)(val->type))->next; - - // It's OK to cast from fixed length to dynamic array, eg &int[3] to int[]* - if (val->type->ty == Tsarray && pointee->ty == Tarray - && elemtype->size() == pointee->nextOf()->size()) - { - Expression *e = new AddrExp(loc, val); - e->type = type; - return e; - } - if ( !isSafePointerCast(elemtype, pointee) ) - { // It's also OK to cast from &string to string*. - if ( offset == 0 && isSafePointerCast(var->type, pointee) ) - { - VarExp *ve = new VarExp(loc, var); - ve->type = type; - return ve; - } - error("reinterpreting cast from %s to %s is not supported in CTFE", - val->type->toChars(), type->toChars()); - return EXP_CANT_INTERPRET; - } - - TypeArray *tar = (TypeArray *)val->type; - dinteger_t sz = pointee->size(); - dinteger_t indx = offset/sz; - assert(sz * indx == offset); - Expression *aggregate = NULL; - if (val->op == TOKarrayliteral || val->op == TOKstring) - aggregate = val; - else if (val->op == TOKslice) - { - aggregate = ((SliceExp *)val)->e1; - Expression *lwr = ((SliceExp *)val)->lwr->interpret(istate); - indx += lwr->toInteger(); - } - if (aggregate) - { - IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); - IndexExp *ie = new IndexExp(loc, aggregate, ofs); - ie->type = type; - return ie; - } - } - else if ( offset == 0 && isSafePointerCast(var->type, pointee) ) - { - VarExp *ve = new VarExp(loc, var); - ve->type = type; - return ve; - } - - error("Cannot convert &%s to %s at compile time", var->type->toChars(), type->toChars()); - return EXP_CANT_INTERPRET; + } + Type *pointee = ((TypePointer *)type)->next; + Expression *val = getVarExp(loc, istate, var, goal); + if (val->type->ty == Tarray || val->type->ty == Tsarray) + { + // Check for unsupported type painting operations + Type *elemtype = ((TypeArray *)(val->type))->next; + + // It's OK to cast from fixed length to dynamic array, eg &int[3] to int[]* + if (val->type->ty == Tsarray && pointee->ty == Tarray + && elemtype->size() == pointee->nextOf()->size()) + { + Expression *e = new AddrExp(loc, val); + e->type = type; + return e; + } + if ( !isSafePointerCast(elemtype, pointee) ) + { // It's also OK to cast from &string to string*. + if ( offset == 0 && isSafePointerCast(var->type, pointee) ) + { + VarExp *ve = new VarExp(loc, var); + ve->type = type; + return ve; + } + error("reinterpreting cast from %s to %s is not supported in CTFE", + val->type->toChars(), type->toChars()); + return EXP_CANT_INTERPRET; + } + + TypeArray *tar = (TypeArray *)val->type; + dinteger_t sz = pointee->size(); + dinteger_t indx = offset/sz; + assert(sz * indx == offset); + Expression *aggregate = NULL; + if (val->op == TOKarrayliteral || val->op == TOKstring) + aggregate = val; + else if (val->op == TOKslice) + { + aggregate = ((SliceExp *)val)->e1; + Expression *lwr = ((SliceExp *)val)->lwr->interpret(istate); + indx += lwr->toInteger(); + } + if (aggregate) + { + IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); + IndexExp *ie = new IndexExp(loc, aggregate, ofs); + ie->type = type; + return ie; + } + } + else if ( offset == 0 && isSafePointerCast(var->type, pointee) ) + { + VarExp *ve = new VarExp(loc, var); + ve->type = type; + return ve; + } + + error("Cannot convert &%s to %s at compile time", var->type->toChars(), type->toChars()); + return EXP_CANT_INTERPRET; } -Expression *AddrExp::interpret(InterState *istate, CtfeGoal goal) +Expression *AddrExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG - printf("AddrExp::interpret() %s\n", toChars()); + printf("AddrExp::interpret() %s\n", toChars()); #endif - // For reference types, we need to return an lvalue ref. - TY tb = e1->type->toBasetype()->ty; - bool needRef = (tb == Tarray || tb == Taarray || tb == Tclass); - Expression *e = e1->interpret(istate, needRef ? ctfeNeedLvalueRef : ctfeNeedLvalue); - if (exceptionOrCantInterpret(e)) - return e; - // Return a simplified address expression - e = new AddrExp(loc, e); - e->type = type; - return e; + // For reference types, we need to return an lvalue ref. + TY tb = e1->type->toBasetype()->ty; + bool needRef = (tb == Tarray || tb == Taarray || tb == Tclass); + Expression *e = e1->interpret(istate, needRef ? ctfeNeedLvalueRef : ctfeNeedLvalue); + if (exceptionOrCantInterpret(e)) + return e; + // Return a simplified address expression + e = new AddrExp(loc, e); + e->type = type; + return e; } -Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) -{ -#if LOG - printf("DelegateExp::interpret() %s\n", toChars()); -#endif - return this; -} - - -// ------------------------------------------------------------- +Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) +{ +#if LOG + printf("DelegateExp::interpret() %s\n", toChars()); +#endif + return this; +} + + +// ------------------------------------------------------------- // Remove out, ref, and this // ------------------------------------------------------------- // The variable used in a dotvar, index, or slice expression, // after 'out', 'ref', and 'this' have been removed. -Expression * resolveReferences(Expression *e, Expression *thisval) +Expression * resolveReferences(Expression *e, Expression *thisval) { for(;;) { @@ -1835,26 +1835,26 @@ Expression * resolveReferences(Expression *e, Expression *thisval) e = thisval; continue; } - if (e->op == TOKvar) - { + if (e->op == TOKvar) + { VarExp *ve = (VarExp *)e; VarDeclaration *v = ve->var->isVarDeclaration(); - if (v->type->ty == Tpointer) - break; - if (v->ctfeAdrOnStack == (size_t)-1) // If not on the stack, can't possibly be a ref. - break; - if (v && v->getValue() && (v->getValue()->op == TOKslice)) - { - SliceExp *se = (SliceExp *)v->getValue(); - if (se->e1->op == TOKarrayliteral || se->e1->op == TOKassocarrayliteral || se->e1->op == TOKstring) - break; - e = v->getValue(); - continue; - } - else if (v && v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar - || v->getValue()->op == TOKthis )) + if (v->type->ty == Tpointer) + break; + if (v->ctfeAdrOnStack == (size_t)-1) // If not on the stack, can't possibly be a ref. + break; + if (v && v->getValue() && (v->getValue()->op == TOKslice)) { - e = v->getValue(); + SliceExp *se = (SliceExp *)v->getValue(); + if (se->e1->op == TOKarrayliteral || se->e1->op == TOKassocarrayliteral || se->e1->op == TOKstring) + break; + e = v->getValue(); + continue; + } + else if (v && v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar + || v->getValue()->op == TOKthis )) + { + e = v->getValue(); continue; } } @@ -1863,15 +1863,15 @@ Expression * resolveReferences(Expression *e, Expression *thisval) return e; } -Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal) +Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal) { Expression *e = EXP_CANT_INTERPRET; VarDeclaration *v = d->isVarDeclaration(); -#if IN_LLVM +#if IN_LLVM StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); -#else - SymbolDeclaration *s = d->isSymbolDeclaration(); -#endif +#else + SymbolDeclaration *s = d->isSymbolDeclaration(); +#endif if (v) { #if DMDV2 @@ -1879,44 +1879,44 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal */ if (v->ident == Id::ctfe) return new IntegerExp(loc, 1, Type::tbool); - if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->hasValue()) + if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->hasValue()) #else if (v->isConst() && v->init) #endif { e = v->init->toExpression(); - if (e && (e->op == TOKconstruct || e->op == TOKblit)) - { AssignExp *ae = (AssignExp *)e; - e = ae->e2; - v->inuse++; - e = e->interpret(istate, ctfeNeedAnyValue); - v->inuse--; - if (e == EXP_CANT_INTERPRET && !global.gag && !CtfeStatus::stackTraceCallsToSuppress) - errorSupplemental(loc, "while evaluating %s.init", v->toChars()); - if (exceptionOrCantInterpret(e)) - return e; - e->type = v->type; - } - else - { + if (e && (e->op == TOKconstruct || e->op == TOKblit)) + { AssignExp *ae = (AssignExp *)e; + e = ae->e2; + v->inuse++; + e = e->interpret(istate, ctfeNeedAnyValue); + v->inuse--; + if (e == EXP_CANT_INTERPRET && !global.gag && !CtfeStatus::stackTraceCallsToSuppress) + errorSupplemental(loc, "while evaluating %s.init", v->toChars()); + if (exceptionOrCantInterpret(e)) + return e; + e->type = v->type; + } + else + { if (e && !e->type) e->type = v->type; - if (e) - e = e->interpret(istate, ctfeNeedAnyValue); - if (e == EXP_CANT_INTERPRET && !global.gag && !CtfeStatus::stackTraceCallsToSuppress) - errorSupplemental(loc, "while evaluating %s.init", v->toChars()); - } - if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) - { - e = copyLiteral(e); - if (v->isDataseg()) - ctfeStack.saveGlobalConstant(v, e); - else - v->setValueWithoutChecking(e); - } - } - else if (v->isCTFE() && !v->hasValue()) + if (e) + e = e->interpret(istate, ctfeNeedAnyValue); + if (e == EXP_CANT_INTERPRET && !global.gag && !CtfeStatus::stackTraceCallsToSuppress) + errorSupplemental(loc, "while evaluating %s.init", v->toChars()); + } + if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) + { + e = copyLiteral(e); + if (v->isDataseg()) + ctfeStack.saveGlobalConstant(v, e); + else + v->setValueWithoutChecking(e); + } + } + else if (v->isCTFE() && !v->hasValue()) { - if (v->init && v->type->size() != 0) + if (v->init && v->type->size() != 0) { if (v->init->isVoidInitializer()) { @@ -1929,90 +1929,90 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal else e = v->type->defaultInitLiteral(loc); } - else if (!v->isDataseg() && !v->isCTFE() && !istate) - { error(loc, "variable %s cannot be read at compile time", v->toChars()); + else if (!v->isDataseg() && !v->isCTFE() && !istate) + { error(loc, "variable %s cannot be read at compile time", v->toChars()); return EXP_CANT_INTERPRET; } else - { e = v->hasValue() ? v->getValue() : NULL; - if (!e && !v->isCTFE() && v->isDataseg()) + { e = v->hasValue() ? v->getValue() : NULL; + if (!e && !v->isCTFE() && v->isDataseg()) { error(loc, "static variable %s cannot be read at compile time", v->toChars()); e = EXP_CANT_INTERPRET; } else if (!e) error(loc, "variable %s is used before initialization", v->toChars()); - else if (exceptionOrCantInterpret(e)) - return e; - else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex) - { // If it is a foreach ref, resolve the index into a constant - IndexExp *ie = (IndexExp *)e; - Expression *w = ie->e2->interpret(istate); - if (w != ie->e2) - { - e = new IndexExp(ie->loc, ie->e1, w); - e->type = ie->type; - } - return e; - } - else if ((goal == ctfeNeedLvalue) - || e->op == TOKstring || e->op == TOKstructliteral || e->op == TOKarrayliteral - || e->op == TOKassocarrayliteral || e->op == TOKslice - || e->type->toBasetype()->ty == Tpointer) - return e; // it's already an Lvalue - else - e = e->interpret(istate, goal); + else if (exceptionOrCantInterpret(e)) + return e; + else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex) + { // If it is a foreach ref, resolve the index into a constant + IndexExp *ie = (IndexExp *)e; + Expression *w = ie->e2->interpret(istate); + if (w != ie->e2) + { + e = new IndexExp(ie->loc, ie->e1, w); + e->type = ie->type; + } + return e; + } + else if ((goal == ctfeNeedLvalue) + || e->op == TOKstring || e->op == TOKstructliteral || e->op == TOKarrayliteral + || e->op == TOKassocarrayliteral || e->op == TOKslice + || e->type->toBasetype()->ty == Tpointer) + return e; // it's already an Lvalue + else + e = e->interpret(istate, goal); } if (!e) e = EXP_CANT_INTERPRET; } else if (s) { -#if !IN_LLVM - // Struct static initializers, for example - if (s->dsym->toInitializer() == s->sym) - { -#endif - e = s->dsym->type->defaultInitLiteral(); - e = e->semantic(NULL); - if (e->op == TOKerror) - e = EXP_CANT_INTERPRET; -#if !IN_LLVM - } - else - error(loc, "cannot interpret symbol %s at compile time", v->toChars()); -#endif - } - else - error(loc, "cannot interpret declaration %s at compile time", d->toChars()); +#if !IN_LLVM + // Struct static initializers, for example + if (s->dsym->toInitializer() == s->sym) + { +#endif + e = s->dsym->type->defaultInitLiteral(); + e = e->semantic(NULL); + if (e->op == TOKerror) + e = EXP_CANT_INTERPRET; +#if !IN_LLVM + } + else + error(loc, "cannot interpret symbol %s at compile time", v->toChars()); +#endif + } + else + error(loc, "cannot interpret declaration %s at compile time", d->toChars()); return e; } -Expression *VarExp::interpret(InterState *istate, CtfeGoal goal) +Expression *VarExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("VarExp::interpret() %s\n", toChars()); #endif - if (goal == ctfeNeedLvalueRef) - { - VarDeclaration *v = var->isVarDeclaration(); - if (v && !v->isDataseg() && !v->isCTFE() && !istate) - { error("variable %s cannot be referenced at compile time", v->toChars()); - return EXP_CANT_INTERPRET; - } - else if (v && !v->hasValue() && !v->isCTFE() && v->isDataseg()) - { error("static variable %s cannot be referenced at compile time", v->toChars()); - return EXP_CANT_INTERPRET; - } - return this; - } - Expression *e = getVarExp(loc, istate, var, goal); - // A VarExp may include an implicit cast. It must be done explicitly. - if (e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) - e = paintTypeOntoLiteral(type, e); - return e; + if (goal == ctfeNeedLvalueRef) + { + VarDeclaration *v = var->isVarDeclaration(); + if (v && !v->isDataseg() && !v->isCTFE() && !istate) + { error("variable %s cannot be referenced at compile time", v->toChars()); + return EXP_CANT_INTERPRET; + } + else if (v && !v->hasValue() && !v->isCTFE() && v->isDataseg()) + { error("static variable %s cannot be referenced at compile time", v->toChars()); + return EXP_CANT_INTERPRET; + } + return this; + } + Expression *e = getVarExp(loc, istate, var, goal); + // A VarExp may include an implicit cast. It must be done explicitly. + if (e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) + e = paintTypeOntoLiteral(type, e); + return e; } -Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) +Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("DeclarationExp::interpret() %s\n", toChars()); @@ -2021,24 +2021,24 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) VarDeclaration *v = declaration->isVarDeclaration(); if (v) { - if (v->toAlias()->isTupleDeclaration()) - { // Reserve stack space for all tuple members - TupleDeclaration *td =v->toAlias()->isTupleDeclaration(); - if (!td->objects) - return NULL; - for(int i= 0; i < td->objects->dim; ++i) - { - Object * o = td->objects->tdata()[i]; - Expression *ex = isExpression(o); - DsymbolExp *s = (ex && ex->op == TOKdsymbol) ? (DsymbolExp *)ex : NULL; - VarDeclaration *v2 = s ? s->s->isVarDeclaration() : NULL; - assert(v2); - if (!v2->isDataseg() || v2->isCTFE()) - ctfeStack.push(v2); - } - } - if (!v->isDataseg() || v->isCTFE()) - ctfeStack.push(v); + if (v->toAlias()->isTupleDeclaration()) + { // Reserve stack space for all tuple members + TupleDeclaration *td =v->toAlias()->isTupleDeclaration(); + if (!td->objects) + return NULL; + for(int i= 0; i < td->objects->dim; ++i) + { + Object * o = td->objects->tdata()[i]; + Expression *ex = isExpression(o); + DsymbolExp *s = (ex && ex->op == TOKdsymbol) ? (DsymbolExp *)ex : NULL; + VarDeclaration *v2 = s ? s->s->isVarDeclaration() : NULL; + assert(v2); + if (!v2->isDataseg() || v2->isCTFE()) + ctfeStack.push(v2); + } + } + if (!v->isDataseg() || v->isCTFE()) + ctfeStack.push(v); Dsymbol *s = v->toAlias(); if (s == v && !v->isStatic() && v->init) { @@ -2053,10 +2053,10 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) e = EXP_CANT_INTERPRET; } } - else if (s == v && !v->init && v->type->size()==0) - { // Zero-length arrays don't need an initializer - e = v->type->defaultInitLiteral(loc); - } + else if (s == v && !v->init && v->type->size()==0) + { // Zero-length arrays don't need an initializer + e = v->type->defaultInitLiteral(loc); + } #if DMDV2 else if (s == v && (v->isConst() || v->isImmutable()) && v->init) #else @@ -2070,24 +2070,24 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) } else if (s->isTupleDeclaration() && !v->init) e = NULL; - else if (v->isStatic() && !v->init) - e = NULL; // Just ignore static variables which aren't read or written yet + else if (v->isStatic() && !v->init) + e = NULL; // Just ignore static variables which aren't read or written yet else - { - error("Static variable %s cannot be modified at compile time", v->toChars()); - e = EXP_CANT_INTERPRET; - } + { + error("Static variable %s cannot be modified at compile time", v->toChars()); + e = EXP_CANT_INTERPRET; + } } else if (declaration->isAttribDeclaration() || declaration->isTemplateMixin() || declaration->isTupleDeclaration()) - { // Check for static struct declarations, which aren't executable - AttribDeclaration *ad = declaration->isAttribDeclaration(); - if (ad && ad->decl && ad->decl->dim == 1 - && ad->decl->tdata()[0]->isAggregateDeclaration()) - return NULL; // static struct declaration. Nothing to do. - - // These can be made to work, too lazy now + { // Check for static struct declarations, which aren't executable + AttribDeclaration *ad = declaration->isAttribDeclaration(); + if (ad && ad->decl && ad->decl->dim == 1 + && ad->decl->tdata()[0]->isAggregateDeclaration()) + return NULL; // static struct declaration. Nothing to do. + + // These can be made to work, too lazy now error("Declaration %s is not yet implemented in CTFE", toChars()); e = EXP_CANT_INTERPRET; } @@ -2101,7 +2101,7 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) return e; } -Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) +Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("TupleExp::interpret() %s\n", toChars()); @@ -2109,38 +2109,38 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) Expressions *expsx = NULL; for (size_t i = 0; i < exps->dim; i++) - { Expression *e = exps->tdata()[i]; + { Expression *e = exps->tdata()[i]; Expression *ex; ex = e->interpret(istate); - if (exceptionOrCantInterpret(ex)) + if (exceptionOrCantInterpret(ex)) { delete expsx; return ex; } - // A tuple of assignments can contain void (Bug 5676). - if (goal == ctfeNeedNothing) - continue; - if (ex == EXP_VOID_INTERPRET) - { - error("ICE: void element %s in tuple", e->toChars()); - assert(0); - } - + // A tuple of assignments can contain void (Bug 5676). + if (goal == ctfeNeedNothing) + continue; + if (ex == EXP_VOID_INTERPRET) + { + error("ICE: void element %s in tuple", e->toChars()); + assert(0); + } + /* If any changes, do Copy On Write */ if (ex != e) { if (!expsx) { expsx = new Expressions(); - ++CtfeStatus::numArrayAllocs; + ++CtfeStatus::numArrayAllocs; expsx->setDim(exps->dim); for (size_t j = 0; j < i; j++) { - expsx->tdata()[j] = exps->tdata()[j]; + expsx->tdata()[j] = exps->tdata()[j]; } } - expsx->tdata()[i] = ex; + expsx->tdata()[i] = ex; } } if (expsx) @@ -2152,27 +2152,27 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) return this; } -Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) +Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) { Expressions *expsx = NULL; #if LOG printf("ArrayLiteralExp::interpret() %s\n", toChars()); #endif - if (ownedByCtfe) // We've already interpreted all the elements - return copyLiteral(this); + if (ownedByCtfe) // We've already interpreted all the elements + return copyLiteral(this); if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = elements->tdata()[i]; Expression *ex; - if (e->op == TOKindex) // segfault bug 6250 - assert( ((IndexExp*)e)->e1 != this); + if (e->op == TOKindex) // segfault bug 6250 + assert( ((IndexExp*)e)->e1 != this); ex = e->interpret(istate); if (ex == EXP_CANT_INTERPRET) goto Lerror; - if (ex->op == TOKthrownexception) - return ex; + if (ex->op == TOKthrownexception) + return ex; /* If any changes, do Copy On Write */ @@ -2180,14 +2180,14 @@ Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) { if (!expsx) { expsx = new Expressions(); - ++CtfeStatus::numArrayAllocs; + ++CtfeStatus::numArrayAllocs; expsx->setDim(elements->dim); for (size_t j = 0; j < elements->dim; j++) { - expsx->tdata()[j] = elements->tdata()[j]; + expsx->tdata()[j] = elements->tdata()[j]; } } - expsx->tdata()[i] = ex; + expsx->tdata()[i] = ex; } } } @@ -2198,15 +2198,15 @@ Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) goto Lerror; ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx); ae->type = type; - return copyLiteral(ae); + return copyLiteral(ae); } -#if DMDV2 - if (((TypeNext *)type)->next->mod & (MODconst | MODimmutable)) - { // If it's immutable, we don't need to dup it +#if DMDV2 + if (((TypeNext *)type)->next->mod & (MODconst | MODimmutable)) + { // If it's immutable, we don't need to dup it return this; - } -#endif - return copyLiteral(this); + } +#endif + return copyLiteral(this); Lerror: if (expsx) @@ -2215,26 +2215,26 @@ Lerror: return EXP_CANT_INTERPRET; } -Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) +Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) { Expressions *keysx = keys; Expressions *valuesx = values; #if LOG printf("AssocArrayLiteralExp::interpret() %s\n", toChars()); #endif - if (ownedByCtfe) // We've already interpreted all the elements - return copyLiteral(this); + if (ownedByCtfe) // We've already interpreted all the elements + return copyLiteral(this); for (size_t i = 0; i < keys->dim; i++) - { Expression *ekey = keys->tdata()[i]; - Expression *evalue = values->tdata()[i]; + { Expression *ekey = keys->tdata()[i]; + Expression *evalue = values->tdata()[i]; Expression *ex; ex = ekey->interpret(istate); if (ex == EXP_CANT_INTERPRET) goto Lerr; - if (ex->op == TOKthrownexception) - return ex; - + if (ex->op == TOKthrownexception) + return ex; + /* If any changes, do Copy On Write */ @@ -2242,14 +2242,14 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) { if (keysx == keys) keysx = (Expressions *)keys->copy(); - keysx->tdata()[i] = ex; + keysx->tdata()[i] = ex; } ex = evalue->interpret(istate); if (ex == EXP_CANT_INTERPRET) goto Lerr; - if (ex->op == TOKthrownexception) - return ex; + if (ex->op == TOKthrownexception) + return ex; /* If any changes, do Copy On Write */ @@ -2257,7 +2257,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) { if (valuesx == values) valuesx = (Expressions *)values->copy(); - valuesx->tdata()[i] = ex; + valuesx->tdata()[i] = ex; } } if (keysx != keys) @@ -2270,12 +2270,12 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) /* Remove duplicate keys */ for (size_t i = 1; i < keysx->dim; i++) - { Expression *ekey = keysx->tdata()[i - 1]; - if (ekey->op == TOKslice) - ekey = resolveSlice(ekey); + { Expression *ekey = keysx->tdata()[i - 1]; + if (ekey->op == TOKslice) + ekey = resolveSlice(ekey); for (size_t j = i; j < keysx->dim; j++) - { Expression *ekey2 = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); + { Expression *ekey2 = keysx->tdata()[j]; + Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); if (ex == EXP_CANT_INTERPRET) goto Lerr; if (ex->isBool(TRUE)) // if a match @@ -2298,7 +2298,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) AssocArrayLiteralExp *ae; ae = new AssocArrayLiteralExp(loc, keysx, valuesx); ae->type = type; - ae->ownedByCtfe = true; + ae->ownedByCtfe = true; return ae; } return this; @@ -2311,7 +2311,7 @@ Lerr: return EXP_CANT_INTERPRET; } -Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) +Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) { Expressions *expsx = NULL; #if LOG @@ -2323,20 +2323,20 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) { error("Unions with overlapping fields are not yet supported in CTFE"); return EXP_CANT_INTERPRET; } - if (ownedByCtfe) - return copyLiteral(this); + if (ownedByCtfe) + return copyLiteral(this); if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = elements->tdata()[i]; if (!e) continue; Expression *ex = e->interpret(istate); - if (exceptionOrCantInterpret(ex)) + if (exceptionOrCantInterpret(ex)) { delete expsx; - return ex; + return ex; } /* If any changes, do Copy On Write @@ -2345,14 +2345,14 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) { if (!expsx) { expsx = new Expressions(); - ++CtfeStatus::numArrayAllocs; + ++CtfeStatus::numArrayAllocs; expsx->setDim(elements->dim); for (size_t j = 0; j < elements->dim; j++) { - expsx->tdata()[j] = elements->tdata()[j]; + expsx->tdata()[j] = elements->tdata()[j]; } } - expsx->tdata()[i] = ex; + expsx->tdata()[i] = ex; } } } @@ -2365,178 +2365,178 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) } StructLiteralExp *se = new StructLiteralExp(loc, sd, expsx); se->type = type; - se->ownedByCtfe = true; + se->ownedByCtfe = true; return se; } - return copyLiteral(this); -} - -/****************************** - * Helper for NewExp - * Create an array literal consisting of 'elem' duplicated 'dim' times. - */ -ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, - Expression *elem, size_t dim) -{ - Expressions *elements = new Expressions(); - elements->setDim(dim); - bool mustCopy = needToCopyLiteral(elem); - for (size_t i = 0; i < dim; i++) - { if (mustCopy) - elem = copyLiteral(elem); - elements->tdata()[i] = elem; - } - ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); - ae->type = type; - ae->ownedByCtfe = true; - return ae; -} - -/****************************** - * Helper for NewExp - * Create a string literal consisting of 'value' duplicated 'dim' times. - */ -StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, - unsigned value, size_t dim, int sz) -{ - unsigned char *s; - s = (unsigned char *)mem.calloc(dim + 1, sz); - for (size_t elemi=0; elemitype = type; - se->sz = sz; - se->committed = true; - se->ownedByCtfe = true; - return se; -} - -// Create an array literal of type 'newtype' with dimensions given by -// 'arguments'[argnum..$] -Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *istate, - Expressions *arguments, int argnum) -{ - Expression *lenExpr = ((arguments->tdata()[argnum]))->interpret(istate); - if (exceptionOrCantInterpret(lenExpr)) - return lenExpr; - size_t len = (size_t)(lenExpr->toInteger()); - Type *elemType = ((TypeArray *)newtype)->next; - if (elemType->ty == Tarray && argnum < arguments->dim - 1) - { - Expression *elem = recursivelyCreateArrayLiteral(loc, elemType, istate, - arguments, argnum + 1); - if (exceptionOrCantInterpret(elem)) - return elem; - - Expressions *elements = new Expressions(); - elements->setDim(len); - for (size_t i = 0; i < len; i++) - elements->tdata()[i] = copyLiteral(elem); - ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); - ae->type = newtype; - ae->ownedByCtfe = true; - return ae; - } - assert(argnum == arguments->dim - 1); - if (elemType->ty == Tchar || elemType->ty == Twchar - || elemType->ty == Tdchar) - return createBlockDuplicatedStringLiteral(loc, newtype, - (unsigned)(elemType->defaultInitLiteral()->toInteger()), - len, elemType->size()); - return createBlockDuplicatedArrayLiteral(loc, newtype, - elemType->defaultInitLiteral(), - len); + return copyLiteral(this); } -Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) +/****************************** + * Helper for NewExp + * Create an array literal consisting of 'elem' duplicated 'dim' times. + */ +ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, + Expression *elem, size_t dim) +{ + Expressions *elements = new Expressions(); + elements->setDim(dim); + bool mustCopy = needToCopyLiteral(elem); + for (size_t i = 0; i < dim; i++) + { if (mustCopy) + elem = copyLiteral(elem); + elements->tdata()[i] = elem; + } + ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); + ae->type = type; + ae->ownedByCtfe = true; + return ae; +} + +/****************************** + * Helper for NewExp + * Create a string literal consisting of 'value' duplicated 'dim' times. + */ +StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, + unsigned value, size_t dim, int sz) +{ + unsigned char *s; + s = (unsigned char *)mem.calloc(dim + 1, sz); + for (size_t elemi=0; elemitype = type; + se->sz = sz; + se->committed = true; + se->ownedByCtfe = true; + return se; +} + +// Create an array literal of type 'newtype' with dimensions given by +// 'arguments'[argnum..$] +Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *istate, + Expressions *arguments, int argnum) +{ + Expression *lenExpr = ((arguments->tdata()[argnum]))->interpret(istate); + if (exceptionOrCantInterpret(lenExpr)) + return lenExpr; + size_t len = (size_t)(lenExpr->toInteger()); + Type *elemType = ((TypeArray *)newtype)->next; + if (elemType->ty == Tarray && argnum < arguments->dim - 1) + { + Expression *elem = recursivelyCreateArrayLiteral(loc, elemType, istate, + arguments, argnum + 1); + if (exceptionOrCantInterpret(elem)) + return elem; + + Expressions *elements = new Expressions(); + elements->setDim(len); + for (size_t i = 0; i < len; i++) + elements->tdata()[i] = copyLiteral(elem); + ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); + ae->type = newtype; + ae->ownedByCtfe = true; + return ae; + } + assert(argnum == arguments->dim - 1); + if (elemType->ty == Tchar || elemType->ty == Twchar + || elemType->ty == Tdchar) + return createBlockDuplicatedStringLiteral(loc, newtype, + (unsigned)(elemType->defaultInitLiteral()->toInteger()), + len, elemType->size()); + return createBlockDuplicatedArrayLiteral(loc, newtype, + elemType->defaultInitLiteral(), + len); +} + +Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("NewExp::interpret() %s\n", toChars()); #endif - if (newtype->ty == Tarray && arguments) - return recursivelyCreateArrayLiteral(loc, newtype, istate, arguments, 0); - - if (newtype->toBasetype()->ty == Tstruct) - { - Expression *se = newtype->defaultInitLiteral(); -#if DMDV2 - if (member) + if (newtype->ty == Tarray && arguments) + return recursivelyCreateArrayLiteral(loc, newtype, istate, arguments, 0); + + if (newtype->toBasetype()->ty == Tstruct) { - int olderrors = global.errors; - member->interpret(istate, arguments, se); - if (olderrors != global.errors) - { - error("cannot evaluate %s at compile time", toChars()); + Expression *se = newtype->defaultInitLiteral(); +#if DMDV2 + if (member) + { + int olderrors = global.errors; + member->interpret(istate, arguments, se); + if (olderrors != global.errors) + { + error("cannot evaluate %s at compile time", toChars()); return EXP_CANT_INTERPRET; - } - } -#else // The above code would fail on D1 because it doesn't use STRUCTTHISREF, - // but that's OK because D1 doesn't have struct constructors anyway. - assert(!member); -#endif - Expression *e = new AddrExp(loc, copyLiteral(se)); - e->type = type; - return e; - } - if (newtype->toBasetype()->ty == Tclass) - { - ClassDeclaration *cd = ((TypeClass *)newtype->toBasetype())->sym; - size_t totalFieldCount = 0; - for (ClassDeclaration *c = cd; c; c = c->baseClass) - totalFieldCount += c->fields.dim; - Expressions *elems = new Expressions; - elems->setDim(totalFieldCount); - size_t fieldsSoFar = totalFieldCount; - for (ClassDeclaration *c = cd; c; c = c->baseClass) - { - fieldsSoFar -= c->fields.dim; - for (size_t i = 0; i < c->fields.dim; i++) - { - Dsymbol *s = c->fields.tdata()[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v); - Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(); - if (exceptionOrCantInterpret(m)) - return m; - elems->tdata()[fieldsSoFar+i] = copyLiteral(m); - } - } - // Hack: we store a ClassDeclaration instead of a StructDeclaration. - // We probably won't get away with this. - StructLiteralExp *se = new StructLiteralExp(loc, (StructDeclaration *)cd, elems, newtype); - se->ownedByCtfe = true; - Expression *e = new ClassReferenceExp(loc, se, type); - if (member) - { // Call constructor - if (!member->fbody) - { - Expression *ctorfail = evaluateIfBuiltin(istate, loc, member, arguments, e); - if (ctorfail && exceptionOrCantInterpret(ctorfail)) - return ctorfail; - if (ctorfail) - return e; - member->error("%s cannot be constructed at compile time, because the constructor has no available source code", newtype->toChars()); - return EXP_CANT_INTERPRET; - } - Expression * ctorfail = member->interpret(istate, arguments, e); - if (exceptionOrCantInterpret(ctorfail)) - return ctorfail; - } - return e; + } + } +#else // The above code would fail on D1 because it doesn't use STRUCTTHISREF, + // but that's OK because D1 doesn't have struct constructors anyway. + assert(!member); +#endif + Expression *e = new AddrExp(loc, copyLiteral(se)); + e->type = type; + return e; + } + if (newtype->toBasetype()->ty == Tclass) + { + ClassDeclaration *cd = ((TypeClass *)newtype->toBasetype())->sym; + size_t totalFieldCount = 0; + for (ClassDeclaration *c = cd; c; c = c->baseClass) + totalFieldCount += c->fields.dim; + Expressions *elems = new Expressions; + elems->setDim(totalFieldCount); + size_t fieldsSoFar = totalFieldCount; + for (ClassDeclaration *c = cd; c; c = c->baseClass) + { + fieldsSoFar -= c->fields.dim; + for (size_t i = 0; i < c->fields.dim; i++) + { + Dsymbol *s = c->fields.tdata()[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(); + if (exceptionOrCantInterpret(m)) + return m; + elems->tdata()[fieldsSoFar+i] = copyLiteral(m); + } + } + // Hack: we store a ClassDeclaration instead of a StructDeclaration. + // We probably won't get away with this. + StructLiteralExp *se = new StructLiteralExp(loc, (StructDeclaration *)cd, elems, newtype); + se->ownedByCtfe = true; + Expression *e = new ClassReferenceExp(loc, se, type); + if (member) + { // Call constructor + if (!member->fbody) + { + Expression *ctorfail = evaluateIfBuiltin(istate, loc, member, arguments, e); + if (ctorfail && exceptionOrCantInterpret(ctorfail)) + return ctorfail; + if (ctorfail) + return e; + member->error("%s cannot be constructed at compile time, because the constructor has no available source code", newtype->toChars()); + return EXP_CANT_INTERPRET; + } + Expression * ctorfail = member->interpret(istate, arguments, e); + if (exceptionOrCantInterpret(ctorfail)) + return ctorfail; + } + return e; } error("Cannot interpret %s at compile time", toChars()); return EXP_CANT_INTERPRET; } -Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)) +Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)) { Expression *e; Expression *e1; @@ -2544,16 +2544,16 @@ Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expressi printf("UnaExp::interpretCommon() %s\n", toChars()); #endif e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; + if (exceptionOrCantInterpret(e1)) + return e1; e = (*fp)(type, e1); return e; } #define UNA_INTERPRET(op) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ +Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ { \ - return interpretCommon(istate, goal, &op); \ + return interpretCommon(istate, goal, &op); \ } UNA_INTERPRET(Neg) @@ -2561,131 +2561,131 @@ UNA_INTERPRET(Com) UNA_INTERPRET(Not) UNA_INTERPRET(Bool) -Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs) -{ - *ofs = 0; - if (e->op == TOKaddress) - e = ((AddrExp *)e)->e1; - if (e->op == TOKdotvar) - { - Expression *ex = ((DotVarExp *)e)->e1; - VarDeclaration *v = ((DotVarExp *)e)->var->isVarDeclaration(); - assert(v); - StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex; - // We can't use getField, because it makes a copy - int i = -1; - if (ex->op == TOKclassreference) - i = ((ClassReferenceExp *)ex)->getFieldIndex(e->type, v->offset); - else - i = se->getFieldIndex(e->type, v->offset); - assert(i != -1); - e = se->elements->tdata()[i]; - } - if (e->op == TOKindex) - { - IndexExp *ie = (IndexExp *)e; - // Note that each AA element is part of its own memory block - if ((ie->e1->type->ty == Tarray || ie->e1->type->ty == Tsarray - || ie->e1->op == TOKstring || ie->e1->op==TOKarrayliteral) && - ie->e2->op == TOKint64) - { - *ofs = ie->e2->toInteger(); - return ie->e1; - } - } - return e; -} - -// return e1 - e2 as an integer, or error if not possible -Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2) -{ - dinteger_t ofs1, ofs2; - Expression *agg1 = getAggregateFromPointer(e1, &ofs1); - Expression *agg2 = getAggregateFromPointer(e2, &ofs2); - if (agg1 == agg2) - { - Type *pointee = ((TypePointer *)agg1->type)->next; - dinteger_t sz = pointee->size(); - return new IntegerExp(loc, (ofs1-ofs2)*sz, type); - } - else if (agg1->op == TOKstring && agg2->op == TOKstring) - { - if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string) - { - Type *pointee = ((TypePointer *)agg1->type)->next; - dinteger_t sz = pointee->size(); - return new IntegerExp(loc, (ofs1-ofs2)*sz, type); - } - } -#if LOGASSIGN - printf("FAILED POINTER DIFF\n"); - showCtfeExpr(agg1); - showCtfeExpr(agg2); -#endif - error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract " - "pointers to two different memory blocks", - e1->toChars(), e2->toChars()); - return EXP_CANT_INTERPRET; -} - -// Return eptr op e2, where eptr is a pointer, e2 is an integer, -// and op is TOKadd or TOKmin -Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, - Expression *eptr, Expression *e2) -{ - if (eptr->type->nextOf()->ty == Tvoid) - { - error(loc, "cannot perform arithmetic on void* pointers at compile time"); - return EXP_CANT_INTERPRET; - } - dinteger_t ofs1, ofs2; - if (eptr->op == TOKaddress) - eptr = ((AddrExp *)eptr)->e1; - Expression *agg1 = getAggregateFromPointer(eptr, &ofs1); - if (agg1->op != TOKstring && agg1->op != TOKarrayliteral) - { - error(loc, "cannot perform pointer arithmetic on non-arrays at compile time"); - return EXP_CANT_INTERPRET; - } - ofs2 = e2->toInteger(); - Type *pointee = ((TypePointer *)agg1->type)->next; - dinteger_t sz = pointee->size(); - Expression *dollar = ArrayLength(Type::tsize_t, agg1); - assert(dollar != EXP_CANT_INTERPRET); - dinteger_t len = dollar->toInteger(); - - Expression *val = agg1; - TypeArray *tar = (TypeArray *)val->type; - dinteger_t indx = ofs1; - if (op == TOKadd || op == TOKaddass || op == TOKplusplus) - indx = indx + ofs2/sz; - else if (op == TOKmin || op == TOKminass || op == TOKminusminus) - indx -= ofs2/sz; - else - { - error(loc, "CTFE Internal compiler error: bad pointer operation"); - return EXP_CANT_INTERPRET; - } - if (val->op != TOKarrayliteral && val->op != TOKstring) - { - error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars()); - return EXP_CANT_INTERPRET; - } - if (indx < 0 || indx > len) - { - error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); - return EXP_CANT_INTERPRET; - } - - IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); - IndexExp *ie = new IndexExp(loc, val, ofs); - ie->type = type; - return ie; -} +Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs) +{ + *ofs = 0; + if (e->op == TOKaddress) + e = ((AddrExp *)e)->e1; + if (e->op == TOKdotvar) + { + Expression *ex = ((DotVarExp *)e)->e1; + VarDeclaration *v = ((DotVarExp *)e)->var->isVarDeclaration(); + assert(v); + StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex; + // We can't use getField, because it makes a copy + int i = -1; + if (ex->op == TOKclassreference) + i = ((ClassReferenceExp *)ex)->getFieldIndex(e->type, v->offset); + else + i = se->getFieldIndex(e->type, v->offset); + assert(i != -1); + e = se->elements->tdata()[i]; + } + if (e->op == TOKindex) + { + IndexExp *ie = (IndexExp *)e; + // Note that each AA element is part of its own memory block + if ((ie->e1->type->ty == Tarray || ie->e1->type->ty == Tsarray + || ie->e1->op == TOKstring || ie->e1->op==TOKarrayliteral) && + ie->e2->op == TOKint64) + { + *ofs = ie->e2->toInteger(); + return ie->e1; + } + } + return e; +} + +// return e1 - e2 as an integer, or error if not possible +Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2) +{ + dinteger_t ofs1, ofs2; + Expression *agg1 = getAggregateFromPointer(e1, &ofs1); + Expression *agg2 = getAggregateFromPointer(e2, &ofs2); + if (agg1 == agg2) + { + Type *pointee = ((TypePointer *)agg1->type)->next; + dinteger_t sz = pointee->size(); + return new IntegerExp(loc, (ofs1-ofs2)*sz, type); + } + else if (agg1->op == TOKstring && agg2->op == TOKstring) + { + if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string) + { + Type *pointee = ((TypePointer *)agg1->type)->next; + dinteger_t sz = pointee->size(); + return new IntegerExp(loc, (ofs1-ofs2)*sz, type); + } + } +#if LOGASSIGN + printf("FAILED POINTER DIFF\n"); + showCtfeExpr(agg1); + showCtfeExpr(agg2); +#endif + error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract " + "pointers to two different memory blocks", + e1->toChars(), e2->toChars()); + return EXP_CANT_INTERPRET; +} + +// Return eptr op e2, where eptr is a pointer, e2 is an integer, +// and op is TOKadd or TOKmin +Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, + Expression *eptr, Expression *e2) +{ + if (eptr->type->nextOf()->ty == Tvoid) + { + error(loc, "cannot perform arithmetic on void* pointers at compile time"); + return EXP_CANT_INTERPRET; + } + dinteger_t ofs1, ofs2; + if (eptr->op == TOKaddress) + eptr = ((AddrExp *)eptr)->e1; + Expression *agg1 = getAggregateFromPointer(eptr, &ofs1); + if (agg1->op != TOKstring && agg1->op != TOKarrayliteral) + { + error(loc, "cannot perform pointer arithmetic on non-arrays at compile time"); + return EXP_CANT_INTERPRET; + } + ofs2 = e2->toInteger(); + Type *pointee = ((TypePointer *)agg1->type)->next; + dinteger_t sz = pointee->size(); + Expression *dollar = ArrayLength(Type::tsize_t, agg1); + assert(dollar != EXP_CANT_INTERPRET); + dinteger_t len = dollar->toInteger(); + + Expression *val = agg1; + TypeArray *tar = (TypeArray *)val->type; + dinteger_t indx = ofs1; + if (op == TOKadd || op == TOKaddass || op == TOKplusplus) + indx = indx + ofs2/sz; + else if (op == TOKmin || op == TOKminass || op == TOKminusminus) + indx -= ofs2/sz; + else + { + error(loc, "CTFE Internal compiler error: bad pointer operation"); + return EXP_CANT_INTERPRET; + } + if (val->op != TOKarrayliteral && val->op != TOKstring) + { + error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars()); + return EXP_CANT_INTERPRET; + } + if (indx < 0 || indx > len) + { + error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); + return EXP_CANT_INTERPRET; + } + + IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); + IndexExp *ie = new IndexExp(loc, val, ofs); + ie->type = type; + return ie; +} typedef Expression *(*fp_t)(Type *, Expression *, Expression *); -Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) +Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) { Expression *e; Expression *e1; Expression *e2; @@ -2693,56 +2693,56 @@ Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) #if LOG printf("BinExp::interpretCommon() %s\n", toChars()); #endif - if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer && op == TOKmin) - { - e1 = this->e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - e2 = this->e2->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e2)) - return e2; - return pointerDifference(loc, type, e1, e2); - } - if (this->e1->type->ty == Tpointer && this->e2->type->isintegral()) - { - e1 = this->e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; - return pointerArithmetic(loc, op, type, e1, e2); - } - if (this->e2->type->ty == Tpointer && this->e1->type->isintegral() && op==TOKadd) - { + if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer && op == TOKmin) + { + e1 = this->e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + e2 = this->e2->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e2)) + return e2; + return pointerDifference(loc, type, e1, e2); + } + if (this->e1->type->ty == Tpointer && this->e2->type->isintegral()) + { + e1 = this->e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + e2 = this->e2->interpret(istate); + if (exceptionOrCantInterpret(e2)) + return e2; + return pointerArithmetic(loc, op, type, e1, e2); + } + if (this->e2->type->ty == Tpointer && this->e1->type->isintegral() && op==TOKadd) + { e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - e2 = this->e2->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e2)) - return e1; - return pointerArithmetic(loc, op, type, e2, e1); - } - if (this->e1->type->ty == Tpointer || this->e2->type->ty == Tpointer) - { - error("pointer expression %s cannot be interpreted at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; + if (exceptionOrCantInterpret(e1)) + return e1; + e2 = this->e2->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e2)) + return e1; + return pointerArithmetic(loc, op, type, e2, e1); + } + if (this->e1->type->ty == Tpointer || this->e2->type->ty == Tpointer) + { + error("pointer expression %s cannot be interpreted at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + e1 = this->e1->interpret(istate); + if (exceptionOrCantInterpret(e1)) + return e1; if (e1->isConst() != 1) goto Lcant; e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; + if (exceptionOrCantInterpret(e2)) + return e2; if (e2->isConst() != 1) goto Lcant; e = (*fp)(type, e1, e2); - if (e == EXP_CANT_INTERPRET) - error("%s cannot be interpreted at compile time", toChars()); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); return e; Lcant: @@ -2750,9 +2750,9 @@ Lcant: } #define BIN_INTERPRET(op) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ +Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ { \ - return interpretCommon(istate, goal, &op); \ + return interpretCommon(istate, goal, &op); \ } BIN_INTERPRET(Add) @@ -2766,89 +2766,89 @@ BIN_INTERPRET(Ushr) BIN_INTERPRET(And) BIN_INTERPRET(Or) BIN_INTERPRET(Xor) -#if DMDV2 -BIN_INTERPRET(Pow) -#endif +#if DMDV2 +BIN_INTERPRET(Pow) +#endif typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *); -// Return EXP_CANT_INTERPRET if they point to independent memory blocks -Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) -{ - dinteger_t ofs1, ofs2; - Expression *agg1 = getAggregateFromPointer(e1, &ofs1); - Expression *agg2 = getAggregateFromPointer(e2, &ofs2); - // Note that type painting can occur with VarExp, so we - // must compare the variables being pointed to. - if (agg1 == agg2 || - (agg1->op == TOKvar && agg2->op == TOKvar && - ((VarExp *)agg1)->var == ((VarExp *)agg2)->var) - ) - { - dinteger_t cm = ofs1 - ofs2; - dinteger_t n; - dinteger_t zero = 0; - switch(op) - { - case TOKlt: n = (ofs1 < ofs2); break; - case TOKle: n = (ofs1 <= ofs2); break; - case TOKgt: n = (ofs1 > ofs2); break; - case TOKge: n = (ofs1 >= ofs2); break; - case TOKidentity: - case TOKequal: n = (ofs1 == ofs2); break; - case TOKnotidentity: - case TOKnotequal: n = (ofs1 != ofs2); break; - default: - assert(0); - } - return new IntegerExp(loc, n, type); - } - int cmp; - if (agg1->op == TOKnull) - { - cmp = (agg2->op == TOKnull); - } - else if (agg2->op == TOKnull) - { - cmp = 0; - } - else - { - switch(op) - { - case TOKidentity: - case TOKequal: - case TOKnotidentity: // 'cmp' gets inverted below - case TOKnotequal: - cmp = 0; - break; - default: - return EXP_CANT_INTERPRET; - } - } - if (op == TOKnotidentity || op == TOKnotequal) - cmp ^= 1; - return new IntegerExp(loc, cmp, type); -} - -Expression *ctfeIdentity(enum TOK op, Type *type, Expression *e1, Expression *e2) -{ - if (e1->op == TOKclassreference || e2->op == TOKclassreference) - { - int cmp = 0; - if (e1->op == TOKclassreference && e2->op == TOKclassreference && - ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value) - cmp = 1; - if (op == TOKnotidentity || op == TOKnotequal) - cmp ^= 1; - return new IntegerExp(e1->loc, cmp, type); - } - return Identity(op, type, e1, e2); -} - - -Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp) +// Return EXP_CANT_INTERPRET if they point to independent memory blocks +Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) +{ + dinteger_t ofs1, ofs2; + Expression *agg1 = getAggregateFromPointer(e1, &ofs1); + Expression *agg2 = getAggregateFromPointer(e2, &ofs2); + // Note that type painting can occur with VarExp, so we + // must compare the variables being pointed to. + if (agg1 == agg2 || + (agg1->op == TOKvar && agg2->op == TOKvar && + ((VarExp *)agg1)->var == ((VarExp *)agg2)->var) + ) + { + dinteger_t cm = ofs1 - ofs2; + dinteger_t n; + dinteger_t zero = 0; + switch(op) + { + case TOKlt: n = (ofs1 < ofs2); break; + case TOKle: n = (ofs1 <= ofs2); break; + case TOKgt: n = (ofs1 > ofs2); break; + case TOKge: n = (ofs1 >= ofs2); break; + case TOKidentity: + case TOKequal: n = (ofs1 == ofs2); break; + case TOKnotidentity: + case TOKnotequal: n = (ofs1 != ofs2); break; + default: + assert(0); + } + return new IntegerExp(loc, n, type); + } + int cmp; + if (agg1->op == TOKnull) + { + cmp = (agg2->op == TOKnull); + } + else if (agg2->op == TOKnull) + { + cmp = 0; + } + else + { + switch(op) + { + case TOKidentity: + case TOKequal: + case TOKnotidentity: // 'cmp' gets inverted below + case TOKnotequal: + cmp = 0; + break; + default: + return EXP_CANT_INTERPRET; + } + } + if (op == TOKnotidentity || op == TOKnotequal) + cmp ^= 1; + return new IntegerExp(loc, cmp, type); +} + +Expression *ctfeIdentity(enum TOK op, Type *type, Expression *e1, Expression *e2) +{ + if (e1->op == TOKclassreference || e2->op == TOKclassreference) + { + int cmp = 0; + if (e1->op == TOKclassreference && e2->op == TOKclassreference && + ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value) + cmp = 1; + if (op == TOKnotidentity || op == TOKnotequal) + cmp ^= 1; + return new IntegerExp(e1->loc, cmp, type); + } + return Identity(op, type, e1, e2); +} + + +Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp) { Expression *e; Expression *e1; Expression *e2; @@ -2856,73 +2856,73 @@ Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp #if LOG printf("BinExp::interpretCommon2() %s\n", toChars()); #endif - if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer) - { - e1 = this->e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - e2 = this->e2->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e2)) - return e2; - e = comparePointers(loc, op, type, e1, e2); - if (e == EXP_CANT_INTERPRET) - { - error("%s and %s point to independent memory blocks and " - "cannot be compared at compile time", this->e1->toChars(), - this->e2->toChars()); - } - return e; - } + if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer) + { + e1 = this->e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + e2 = this->e2->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e2)) + return e2; + e = comparePointers(loc, op, type, e1, e2); + if (e == EXP_CANT_INTERPRET) + { + error("%s and %s point to independent memory blocks and " + "cannot be compared at compile time", this->e1->toChars(), + this->e2->toChars()); + } + return e; + } e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKslice) - e1 = resolveSlice(e1); - + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKslice) + e1 = resolveSlice(e1); + if (e1->isConst() != 1 && e1->op != TOKnull && e1->op != TOKstring && e1->op != TOKarrayliteral && - e1->op != TOKstructliteral && - e1->op != TOKclassreference) - { - error("cannot compare %s at compile time", e1->toChars()); + e1->op != TOKstructliteral && + e1->op != TOKclassreference) + { + error("cannot compare %s at compile time", e1->toChars()); goto Lcant; - } + } e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; - if (e2->op == TOKslice) - e2 = resolveSlice(e2); + if (exceptionOrCantInterpret(e2)) + return e2; + if (e2->op == TOKslice) + e2 = resolveSlice(e2); if (e2->isConst() != 1 && e2->op != TOKnull && e2->op != TOKstring && e2->op != TOKarrayliteral && - e2->op != TOKstructliteral && - e2->op != TOKclassreference) - { - error("cannot compare %s at compile time", e2->toChars()); + e2->op != TOKstructliteral && + e2->op != TOKclassreference) + { + error("cannot compare %s at compile time", e2->toChars()); goto Lcant; - } + } e = (*fp)(op, type, e1, e2); - if (e == EXP_CANT_INTERPRET) - error("%s cannot be interpreted at compile time", toChars()); + if (e == EXP_CANT_INTERPRET) + error("%s cannot be interpreted at compile time", toChars()); return e; Lcant: return EXP_CANT_INTERPRET; } -#define BIN_INTERPRET2(op, opfunc) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ - return interpretCommon2(istate, goal, &opfunc); \ +#define BIN_INTERPRET2(op, opfunc) \ +Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ +{ \ + return interpretCommon2(istate, goal, &opfunc); \ } -BIN_INTERPRET2(Equal, Equal) -BIN_INTERPRET2(Identity, ctfeIdentity) -BIN_INTERPRET2(Cmp, Cmp) +BIN_INTERPRET2(Equal, Equal) +BIN_INTERPRET2(Identity, ctfeIdentity) +BIN_INTERPRET2(Cmp, Cmp) /* Helper functions for BinExp::interpretAssignCommon */ @@ -2930,23 +2930,23 @@ BIN_INTERPRET2(Cmp, Cmp) /*************************************** * Duplicate the elements array, then set field 'indexToChange' = newelem. */ -Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem) +Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem) { Expressions *expsx = new Expressions(); - ++CtfeStatus::numArrayAllocs; + ++CtfeStatus::numArrayAllocs; expsx->setDim(oldelems->dim); for (size_t j = 0; j < expsx->dim; j++) { if (j == indexToChange) - expsx->tdata()[j] = newelem; + expsx->tdata()[j] = newelem; else - expsx->tdata()[j] = oldelems->tdata()[j]; + expsx->tdata()[j] = oldelems->tdata()[j]; } return expsx; } -// Create a new struct literal, which is the same as se except that se.field[offset] = elem -Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, Expression *newval) +// Create a new struct literal, which is the same as se except that se.field[offset] = elem +Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, Expression *newval) { int fieldi = se->getFieldIndex(newval->type, offset); if (fieldi == -1) @@ -2954,9 +2954,9 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, /* Create new struct literal reflecting updated fieldi */ Expressions *expsx = changeOneElement(se->elements, fieldi, newval); - StructLiteralExp * ee = new StructLiteralExp(se->loc, se->sd, expsx); + StructLiteralExp * ee = new StructLiteralExp(se->loc, se->sd, expsx); ee->type = se->type; - ee->ownedByCtfe = 1; + ee->ownedByCtfe = 1; return ee; } @@ -2965,21 +2965,21 @@ Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, * set arr[index] = newval and return the new array. * */ -Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *index, Expression *newval) +Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *index, Expression *newval) { /* Create new associative array literal reflecting updated key/value */ Expressions *keysx = aae->keys; - Expressions *valuesx = aae->values; + Expressions *valuesx = aae->values; int updated = 0; for (size_t j = valuesx->dim; j; ) { j--; - Expression *ekey = aae->keys->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); - if (exceptionOrCantInterpret(ex)) - return ex; + Expression *ekey = aae->keys->tdata()[j]; + Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + if (exceptionOrCantInterpret(ex)) + return ex; if (ex->isBool(TRUE)) - { valuesx->tdata()[j] = newval; + { valuesx->tdata()[j] = newval; updated = 1; } } @@ -3037,588 +3037,588 @@ VarDeclaration * findParentVar(Expression *e, Expression *thisval) return v; } -// Given expr, which evaluates to an array/AA/string literal, -// return true if it needs to be copied -bool needToCopyLiteral(Expression *expr) +// Given expr, which evaluates to an array/AA/string literal, +// return true if it needs to be copied +bool needToCopyLiteral(Expression *expr) { - for (;;) + for (;;) { - switch (expr->op) - { - case TOKarrayliteral: - return !((ArrayLiteralExp *)expr)->ownedByCtfe; - case TOKassocarrayliteral: - return !((AssocArrayLiteralExp *)expr)->ownedByCtfe; - case TOKstructliteral: - return !((StructLiteralExp *)expr)->ownedByCtfe; - case TOKstring: - case TOKthis: - case TOKvar: - return false; - case TOKassign: - return false; - case TOKindex: - case TOKdotvar: - case TOKslice: - case TOKcast: - expr = ((UnaExp *)expr)->e1; - continue; - case TOKcat: - return needToCopyLiteral(((BinExp *)expr)->e1) || - needToCopyLiteral(((BinExp *)expr)->e2); - case TOKcatass: - expr = ((BinExp *)expr)->e2; - continue; - default: - return false; + switch (expr->op) + { + case TOKarrayliteral: + return !((ArrayLiteralExp *)expr)->ownedByCtfe; + case TOKassocarrayliteral: + return !((AssocArrayLiteralExp *)expr)->ownedByCtfe; + case TOKstructliteral: + return !((StructLiteralExp *)expr)->ownedByCtfe; + case TOKstring: + case TOKthis: + case TOKvar: + return false; + case TOKassign: + return false; + case TOKindex: + case TOKdotvar: + case TOKslice: + case TOKcast: + expr = ((UnaExp *)expr)->e1; + continue; + case TOKcat: + return needToCopyLiteral(((BinExp *)expr)->e1) || + needToCopyLiteral(((BinExp *)expr)->e2); + case TOKcatass: + expr = ((BinExp *)expr)->e2; + continue; + default: + return false; } - } -} - -Expressions *copyLiteralArray(Expressions *oldelems) -{ - if (!oldelems) - return oldelems; - CtfeStatus::numArrayAllocs++; - Expressions *newelems = new Expressions(); - newelems->setDim(oldelems->dim); - for (size_t i = 0; i < oldelems->dim; i++) - newelems->tdata()[i] = copyLiteral(oldelems->tdata()[i]); - return newelems; + } +} + +Expressions *copyLiteralArray(Expressions *oldelems) +{ + if (!oldelems) + return oldelems; + CtfeStatus::numArrayAllocs++; + Expressions *newelems = new Expressions(); + newelems->setDim(oldelems->dim); + for (size_t i = 0; i < oldelems->dim; i++) + newelems->tdata()[i] = copyLiteral(oldelems->tdata()[i]); + return newelems; } - -// Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral. -// This value will be used for in-place modification. -Expression *copyLiteral(Expression *e) + +// Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral. +// This value will be used for in-place modification. +Expression *copyLiteral(Expression *e) { - if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp! - { - StringExp *se = (StringExp *)e; - unsigned char *s; - s = (unsigned char *)mem.calloc(se->len + 1, se->sz); - memcpy(s, se->string, se->len * se->sz); - StringExp *se2 = new StringExp(se->loc, s, se->len); - se2->committed = se->committed; - se2->postfix = se->postfix; - se2->type = se->type; - se2->sz = se->sz; - se2->ownedByCtfe = true; - return se2; - } - else if (e->op == TOKarrayliteral) - { - ArrayLiteralExp *ae = (ArrayLiteralExp *)e; - ArrayLiteralExp *r = new ArrayLiteralExp(e->loc, - copyLiteralArray(ae->elements)); - r->type = e->type; - r->ownedByCtfe = true; - return r; - } - else if (e->op == TOKassocarrayliteral) - { - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; - AssocArrayLiteralExp *r = new AssocArrayLiteralExp(e->loc, - copyLiteralArray(aae->keys), copyLiteralArray(aae->values)); - r->type = e->type; - r->ownedByCtfe = true; - return r; - } - /* syntaxCopy doesn't work for struct literals, because of a nasty special - * case: block assignment is permitted inside struct literals, eg, - * an int[4] array can be initialized with a single int. - */ - else if (e->op == TOKstructliteral) - { - StructLiteralExp *se = (StructLiteralExp *)e; - Expressions *oldelems = se->elements; - Expressions * newelems = new Expressions(); - newelems->setDim(oldelems->dim); - for (size_t i = 0; i < newelems->dim; i++) - { - Expression *m = oldelems->tdata()[i]; - // We need the struct definition to detect block assignment - AggregateDeclaration *sd = se->sd; - Dsymbol *s = sd->fields.tdata()[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v); - // If it is a void assignment, use the default initializer - if (!m) - m = v->type->defaultInitLiteral(e->loc); - if (m->op == TOKslice) - m = resolveSlice(m); - if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) - { - // Block assignment from inside struct literals - TypeSArray *tsa = (TypeSArray *)v->type; - uinteger_t length = tsa->dim->toInteger(); - m = createBlockDuplicatedArrayLiteral(e->loc, v->type, m, (size_t)length); - } - else if (v->type->ty != Tarray && v->type->ty!=Taarray) // NOTE: do not copy array references - m = copyLiteral(m); - newelems->tdata()[i] = m; - } -#if DMDV2 - StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems, se->stype); -#else - StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems); -#endif - r->type = e->type; - r->ownedByCtfe = true; - return r; - } - else if (e->op == TOKfunction || e->op == TOKdelegate - || e->op == TOKsymoff || e->op == TOKnull - || e->op == TOKvar - || e->op == TOKint64 || e->op == TOKfloat64 - || e->op == TOKchar || e->op == TOKcomplex80) - { // Simple value types - Expression *r = e->syntaxCopy(); - r->type = e->type; - return r; - } - else if ( isPointer(e->type) ) - { // For pointers, we only do a shallow copy. - Expression *r; - if (e->op == TOKaddress) - r = new AddrExp(e->loc, ((AddrExp *)e)->e1); - else if (e->op == TOKindex) - r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2); - else if (e->op == TOKdotvar) - r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, - ((DotVarExp *)e)->var -#if DMDV2 - , ((DotVarExp *)e)->hasOverloads -#endif - ); - else - assert(0); - r->type = e->type; - return r; - } - else if (e->op == TOKslice) - { // Array slices only do a shallow copy - Expression *r = new SliceExp(e->loc, ((SliceExp *)e)->e1, - ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); - r->type = e->type; - return r; - } - else if (e->op == TOKclassreference) - return new ClassReferenceExp(e->loc, ((ClassReferenceExp *)e)->value, e->type); - else + if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp! { - e->error("Internal Compiler Error: CTFE literal %s", e->toChars()); - assert(0); + StringExp *se = (StringExp *)e; + unsigned char *s; + s = (unsigned char *)mem.calloc(se->len + 1, se->sz); + memcpy(s, se->string, se->len * se->sz); + StringExp *se2 = new StringExp(se->loc, s, se->len); + se2->committed = se->committed; + se2->postfix = se->postfix; + se2->type = se->type; + se2->sz = se->sz; + se2->ownedByCtfe = true; + return se2; + } + else if (e->op == TOKarrayliteral) + { + ArrayLiteralExp *ae = (ArrayLiteralExp *)e; + ArrayLiteralExp *r = new ArrayLiteralExp(e->loc, + copyLiteralArray(ae->elements)); + r->type = e->type; + r->ownedByCtfe = true; + return r; + } + else if (e->op == TOKassocarrayliteral) + { + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; + AssocArrayLiteralExp *r = new AssocArrayLiteralExp(e->loc, + copyLiteralArray(aae->keys), copyLiteralArray(aae->values)); + r->type = e->type; + r->ownedByCtfe = true; + return r; + } + /* syntaxCopy doesn't work for struct literals, because of a nasty special + * case: block assignment is permitted inside struct literals, eg, + * an int[4] array can be initialized with a single int. + */ + else if (e->op == TOKstructliteral) + { + StructLiteralExp *se = (StructLiteralExp *)e; + Expressions *oldelems = se->elements; + Expressions * newelems = new Expressions(); + newelems->setDim(oldelems->dim); + for (size_t i = 0; i < newelems->dim; i++) + { + Expression *m = oldelems->tdata()[i]; + // We need the struct definition to detect block assignment + AggregateDeclaration *sd = se->sd; + Dsymbol *s = sd->fields.tdata()[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + // If it is a void assignment, use the default initializer + if (!m) + m = v->type->defaultInitLiteral(e->loc); + if (m->op == TOKslice) + m = resolveSlice(m); + if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) + { + // Block assignment from inside struct literals + TypeSArray *tsa = (TypeSArray *)v->type; + uinteger_t length = tsa->dim->toInteger(); + m = createBlockDuplicatedArrayLiteral(e->loc, v->type, m, (size_t)length); + } + else if (v->type->ty != Tarray && v->type->ty!=Taarray) // NOTE: do not copy array references + m = copyLiteral(m); + newelems->tdata()[i] = m; + } +#if DMDV2 + StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems, se->stype); +#else + StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems); +#endif + r->type = e->type; + r->ownedByCtfe = true; + return r; + } + else if (e->op == TOKfunction || e->op == TOKdelegate + || e->op == TOKsymoff || e->op == TOKnull + || e->op == TOKvar + || e->op == TOKint64 || e->op == TOKfloat64 + || e->op == TOKchar || e->op == TOKcomplex80) + { // Simple value types + Expression *r = e->syntaxCopy(); + r->type = e->type; + return r; + } + else if ( isPointer(e->type) ) + { // For pointers, we only do a shallow copy. + Expression *r; + if (e->op == TOKaddress) + r = new AddrExp(e->loc, ((AddrExp *)e)->e1); + else if (e->op == TOKindex) + r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2); + else if (e->op == TOKdotvar) + r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1, + ((DotVarExp *)e)->var +#if DMDV2 + , ((DotVarExp *)e)->hasOverloads +#endif + ); + else + assert(0); + r->type = e->type; + return r; + } + else if (e->op == TOKslice) + { // Array slices only do a shallow copy + Expression *r = new SliceExp(e->loc, ((SliceExp *)e)->e1, + ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr); + r->type = e->type; + return r; + } + else if (e->op == TOKclassreference) + return new ClassReferenceExp(e->loc, ((ClassReferenceExp *)e)->value, e->type); + else + { + e->error("Internal Compiler Error: CTFE literal %s", e->toChars()); + assert(0); return e; } -} +} -/* Deal with type painting. - * Type painting is a major nuisance: we can't just set - * e->type = type, because that would change the original literal. - * But, we can't simply copy the literal either, because that would change - * the values of any pointers. - */ -Expression *paintTypeOntoLiteral(Type *type, Expression *lit) -{ - if (lit->type == type) - return lit; - Expression *e; - if (lit->op == TOKslice) +/* Deal with type painting. + * Type painting is a major nuisance: we can't just set + * e->type = type, because that would change the original literal. + * But, we can't simply copy the literal either, because that would change + * the values of any pointers. + */ +Expression *paintTypeOntoLiteral(Type *type, Expression *lit) +{ + if (lit->type == type) + return lit; + Expression *e; + if (lit->op == TOKslice) { - SliceExp *se = (SliceExp *)lit; - e = new SliceExp(lit->loc, se->e1, se->lwr, se->upr); - } - else if (lit->op == TOKindex) - { - IndexExp *ie = (IndexExp *)lit; - e = new IndexExp(lit->loc, ie->e1, ie->e2); - } - else if (lit->op == TOKarrayliteral) - { - e = new SliceExp(lit->loc, lit, - new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); + SliceExp *se = (SliceExp *)lit; + e = new SliceExp(lit->loc, se->e1, se->lwr, se->upr); } - else if (lit->op == TOKstring) - { - // For strings, we need to introduce another level of indirection - e = new SliceExp(lit->loc, lit, - new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); - } - else if (lit->op == TOKassocarrayliteral) - { - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit; - // TODO: we should be creating a reference to this AAExp, not - // just a ref to the keys and values. - bool wasOwned = aae->ownedByCtfe; - aae = new AssocArrayLiteralExp(lit->loc, aae->keys, aae->values); - aae->ownedByCtfe = wasOwned; - e = aae; - } - else - { // Can't type paint from struct to struct*; this needs another - // level of indirection - if (lit->op == TOKstructliteral && isPointer(type) ) - lit->error("CTFE internal error painting %s", type->toChars()); - e = copyLiteral(lit); - } - e->type = type; - return e; -} + else if (lit->op == TOKindex) + { + IndexExp *ie = (IndexExp *)lit; + e = new IndexExp(lit->loc, ie->e1, ie->e2); + } + else if (lit->op == TOKarrayliteral) + { + e = new SliceExp(lit->loc, lit, + new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); + } + else if (lit->op == TOKstring) + { + // For strings, we need to introduce another level of indirection + e = new SliceExp(lit->loc, lit, + new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); + } + else if (lit->op == TOKassocarrayliteral) + { + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit; + // TODO: we should be creating a reference to this AAExp, not + // just a ref to the keys and values. + bool wasOwned = aae->ownedByCtfe; + aae = new AssocArrayLiteralExp(lit->loc, aae->keys, aae->values); + aae->ownedByCtfe = wasOwned; + e = aae; + } + else + { // Can't type paint from struct to struct*; this needs another + // level of indirection + if (lit->op == TOKstructliteral && isPointer(type) ) + lit->error("CTFE internal error painting %s", type->toChars()); + e = copyLiteral(lit); + } + e->type = type; + return e; +} -Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e) -{ - if (e->op == TOKnull) - return paintTypeOntoLiteral(to, e); - if (e->op == TOKclassreference) - { // Disallow reinterpreting class casts. Do this by ensuring that - // the original class can implicitly convert to the target class - ClassDeclaration *originalClass = ((ClassReferenceExp *)e)->originalClass(); - if (originalClass->type->implicitConvTo(to)) - return paintTypeOntoLiteral(to, e); - else - return new NullExp(loc, to); - } - Expression *r = Cast(type, to, e); - if (r == EXP_CANT_INTERPRET) - error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars()); - if (e->op == TOKarrayliteral) - ((ArrayLiteralExp *)e)->ownedByCtfe = true; - if (e->op == TOKstring) - ((StringExp *)e)->ownedByCtfe = true; - return r; -} +Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e) +{ + if (e->op == TOKnull) + return paintTypeOntoLiteral(to, e); + if (e->op == TOKclassreference) + { // Disallow reinterpreting class casts. Do this by ensuring that + // the original class can implicitly convert to the target class + ClassDeclaration *originalClass = ((ClassReferenceExp *)e)->originalClass(); + if (originalClass->type->implicitConvTo(to)) + return paintTypeOntoLiteral(to, e); + else + return new NullExp(loc, to); + } + Expression *r = Cast(type, to, e); + if (r == EXP_CANT_INTERPRET) + error(loc, "cannot cast %s to %s at compile time", e->toChars(), to->toChars()); + if (e->op == TOKarrayliteral) + ((ArrayLiteralExp *)e)->ownedByCtfe = true; + if (e->op == TOKstring) + ((StringExp *)e)->ownedByCtfe = true; + return r; +} -/* Set dest = src, where both dest and src are container value literals - * (ie, struct literals, or static arrays (can be an array literal or a string) - * Assignment is recursively in-place. - * Purpose: any reference to a member of 'dest' will remain valid after the - * assignment. - */ -void assignInPlace(Expression *dest, Expression *src) -{ - assert(dest->op == TOKstructliteral || dest->op == TOKarrayliteral || - dest->op == TOKstring); - Expressions *oldelems; - Expressions *newelems; - if (dest->op == TOKstructliteral) - { - assert(dest->op == src->op); - oldelems = ((StructLiteralExp *)dest)->elements; - newelems = ((StructLiteralExp *)src)->elements; - } - else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral) - { - oldelems = ((ArrayLiteralExp *)dest)->elements; - newelems = ((ArrayLiteralExp *)src)->elements; - } - else if (dest->op == TOKstring && src->op == TOKstring) - { - sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0); - return; - } - else if (dest->op == TOKarrayliteral && src->op == TOKstring) - { - sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0); - return; - } - else if (src->op == TOKarrayliteral && dest->op == TOKstring) - { - sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0); - return; - } - else assert(0); - - assert(oldelems->dim == newelems->dim); - - for (size_t i= 0; i < oldelems->dim; ++i) - { - Expression *e = newelems->tdata()[i]; - Expression *o = oldelems->tdata()[i]; - if (e->op == TOKstructliteral) - { - assert(o->op == e->op); - assignInPlace(o, e); - } - else if (e->type->ty == Tsarray && o->type->ty == Tsarray) - { - assignInPlace(o, e); - } - else - { - oldelems->tdata()[i] = newelems->tdata()[i]; - } - } -} - -void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef) -{ - assert( ae->type->ty == Tsarray || ae->type->ty == Tarray); -#if DMDV2 - Type *desttype = ((TypeArray *)ae->type)->next->castMod(0); - bool directblk = (val->type->toBasetype()->castMod(0)) == desttype; -#else - Type *desttype = ((TypeArray *)ae->type)->next; - bool directblk = (val->type->toBasetype()) == desttype; -#endif - - bool cow = !(val->op == TOKstructliteral || val->op == TOKarrayliteral - || val->op == TOKstring); - - for (size_t k = 0; k < ae->elements->dim; k++) - { - if (!directblk && ae->elements->tdata()[k]->op == TOKarrayliteral) - { - recursiveBlockAssign((ArrayLiteralExp *)ae->elements->tdata()[k], val, wantRef); - } - else - { - if (wantRef || cow) - ae->elements->tdata()[k] = val; - else - assignInPlace(ae->elements->tdata()[k], val); - } - } -} - - -Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post) -{ -#if LOG - printf("BinExp::interpretAssignCommon() %s\n", toChars()); -#endif - Expression *returnValue = EXP_CANT_INTERPRET; - Expression *e1 = this->e1; - if (!istate) - { - error("value of %s is not known at compile time", e1->toChars()); - return returnValue; - } - ++CtfeStatus::numAssignments; - /* Before we begin, we need to know if this is a reference assignment - * (dynamic array, AA, or class) or a value assignment. - * Determining this for slice assignments are tricky: we need to know - * if it is a block assignment (a[] = e) rather than a direct slice - * assignment (a[] = b[]). Note that initializers of multi-dimensional - * static arrays can have 2D block assignments (eg, int[7][7] x = 6;). - * So we need to recurse to determine if it is a block assignment. - */ - bool isBlockAssignment = false; - if (e1->op == TOKslice) - { - // a[] = e can have const e. So we compare the naked types. - Type *desttype = e1->type->toBasetype(); -#if DMDV2 - Type *srctype = e2->type->toBasetype()->castMod(0); -#else - Type *srctype = e2->type->toBasetype(); -#endif - while ( desttype->ty == Tsarray || desttype->ty == Tarray) - { - desttype = ((TypeArray *)desttype)->next; -#if DMDV2 - if (srctype == desttype->castMod(0)) -#else - if (srctype == desttype) -#endif - { - isBlockAssignment = true; - break; - } - } - } - bool wantRef = false; - if (!fp && this->e1->type->toBasetype() == this->e2->type->toBasetype() && - (e1->type->toBasetype()->ty == Tarray || isAssocArray(e1->type)) - // e = *x is never a reference, because *x is always a value - && this->e2->op != TOKstar - ) - { -#if DMDV2 - wantRef = true; -#else - /* D1 doesn't have const in the type system. But there is still a - * vestigal const in the form of static const variables. - * Problematic code like: - * const int [] x = [1,2,3]; - * int [] y = x; - * can be dealt with by making this a non-ref assign (y = x.dup). - * Otherwise it's a big mess. - */ - VarDeclaration * targetVar = findParentVar(e2, istate->localThis); - if (!(targetVar && targetVar->isConst())) - wantRef = true; - // slice assignment of static arrays is not reference assignment - if ((e1->op==TOKslice) && ((SliceExp *)e1)->e1->type->ty == Tsarray) - wantRef = false; -#endif - // If it is assignment from a ref parameter, it's not a ref assignment - if (this->e2->op == TOKvar) - { - VarDeclaration *v = ((VarExp *)this->e2)->var->isVarDeclaration(); - if (v && (v->storage_class & (STCref | STCout))) - wantRef = false; - } - } - if (isBlockAssignment && (e2->type->toBasetype()->ty == Tarray || e2->type->toBasetype()->ty == Tsarray)) - { - wantRef = true; - } - // If it is a construction of a ref variable, it is a ref assignment - if (op == TOKconstruct && this->e1->op==TOKvar - && ((VarExp*)this->e1)->var->storage_class & STCref) - { - wantRef = true; - } - - if (fp) - { - while (e1->op == TOKcast) - { CastExp *ce = (CastExp *)e1; - e1 = ce->e1; - } - } - if (exceptionOrCantInterpret(e1)) - return e1; - - // First, deal with this = e; and call() = e; - if (e1->op == TOKthis) - { - e1 = istate->localThis; - } - if (e1->op == TOKcall) - { - bool oldWaiting = istate->awaitingLvalueReturn; - istate->awaitingLvalueReturn = true; - e1 = e1->interpret(istate); - istate->awaitingLvalueReturn = oldWaiting; - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKarrayliteral || e1->op == TOKstring) - { - // f() = e2, when f returns an array, is always a slice assignment. - // Convert into arr[0..arr.length] = e2 - e1 = new SliceExp(loc, e1, - new IntegerExp(0, 0, Type::tsize_t), - ArrayLength(Type::tsize_t, e1)); - e1->type = type; - } - } - if (e1->op == TOKstar) - { - e1 = e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - if (!(e1->op == TOKvar || e1->op == TOKdotvar || e1->op == TOKindex - || e1->op == TOKslice)) - { - error("cannot dereference invalid pointer %s", - this->e1->toChars()); - return EXP_CANT_INTERPRET; - } - } - - if (!(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar - || e1->op == TOKindex || e1->op == TOKslice)) - { - error("CTFE internal error: unsupported assignment %s", toChars()); - return EXP_CANT_INTERPRET; - } - - Expression * newval = NULL; - - if (!wantRef) - { // We need to treat pointers specially, because TOKsymoff can be used to - // return a value OR a pointer - assert(e1); - assert(e1->type); - if ( isPointer(e1->type) && (e2->op == TOKsymoff || e2->op==TOKaddress || e2->op==TOKvar)) - newval = this->e2->interpret(istate, ctfeNeedLvalue); - else - newval = this->e2->interpret(istate); - if (exceptionOrCantInterpret(newval)) - return newval; - } - // ---------------------------------------------------- - // Deal with read-modify-write assignments. - // Set 'newval' to the final assignment value - // Also determine the return value (except for slice - // assignments, which are more complicated) - // ---------------------------------------------------- - - if (fp || e1->op == TOKarraylength) - { - // If it isn't a simple assignment, we need the existing value - Expression * oldval = e1->interpret(istate); - if (exceptionOrCantInterpret(oldval)) - return oldval; - while (oldval->op == TOKvar) - { - oldval = resolveReferences(oldval, istate->localThis); - oldval = oldval->interpret(istate); - if (exceptionOrCantInterpret(oldval)) - return oldval; - } - - if (fp) - { - // ~= can create new values (see bug 6052) - if (op == TOKcatass) - { - // We need to dup it. We can skip this if it's a dynamic array, - // because it gets copied later anyway - if (newval->type->ty != Tarray) - newval = copyLiteral(newval); - if (newval->op == TOKslice) - newval = resolveSlice(newval); - // It becomes a reference assignment - wantRef = true; - } - if (oldval->op == TOKslice) - oldval = resolveSlice(oldval); - if (this->e1->type->ty == Tpointer && this->e2->type->isintegral() - && (op==TOKaddass || op == TOKminass || - op == TOKplusplus || op == TOKminusminus)) - { - oldval = this->e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(oldval)) - return oldval; - newval = this->e2->interpret(istate); - if (exceptionOrCantInterpret(newval)) - return newval; - newval = pointerArithmetic(loc, op, type, oldval, newval); - } - else if (this->e1->type->ty == Tpointer) - { - error("pointer expression %s cannot be interpreted at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - else - { - newval = (*fp)(type, oldval, newval); - } - if (newval == EXP_CANT_INTERPRET) - { - error("Cannot interpret %s at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - if (exceptionOrCantInterpret(newval)) - return newval; - // Determine the return value - returnValue = ctfeCast(loc, type, type, post ? oldval : newval); - if (exceptionOrCantInterpret(returnValue)) - return returnValue; - } - else - returnValue = newval; - if (e1->op == TOKarraylength) +/* Set dest = src, where both dest and src are container value literals + * (ie, struct literals, or static arrays (can be an array literal or a string) + * Assignment is recursively in-place. + * Purpose: any reference to a member of 'dest' will remain valid after the + * assignment. + */ +void assignInPlace(Expression *dest, Expression *src) +{ + assert(dest->op == TOKstructliteral || dest->op == TOKarrayliteral || + dest->op == TOKstring); + Expressions *oldelems; + Expressions *newelems; + if (dest->op == TOKstructliteral) + { + assert(dest->op == src->op); + oldelems = ((StructLiteralExp *)dest)->elements; + newelems = ((StructLiteralExp *)src)->elements; + } + else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral) + { + oldelems = ((ArrayLiteralExp *)dest)->elements; + newelems = ((ArrayLiteralExp *)src)->elements; + } + else if (dest->op == TOKstring && src->op == TOKstring) + { + sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0); + return; + } + else if (dest->op == TOKarrayliteral && src->op == TOKstring) + { + sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0); + return; + } + else if (src->op == TOKarrayliteral && dest->op == TOKstring) + { + sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0); + return; + } + else assert(0); + + assert(oldelems->dim == newelems->dim); + + for (size_t i= 0; i < oldelems->dim; ++i) + { + Expression *e = newelems->tdata()[i]; + Expression *o = oldelems->tdata()[i]; + if (e->op == TOKstructliteral) + { + assert(o->op == e->op); + assignInPlace(o, e); + } + else if (e->type->ty == Tsarray && o->type->ty == Tsarray) + { + assignInPlace(o, e); + } + else + { + oldelems->tdata()[i] = newelems->tdata()[i]; + } + } +} + +void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef) +{ + assert( ae->type->ty == Tsarray || ae->type->ty == Tarray); +#if DMDV2 + Type *desttype = ((TypeArray *)ae->type)->next->castMod(0); + bool directblk = (val->type->toBasetype()->castMod(0)) == desttype; +#else + Type *desttype = ((TypeArray *)ae->type)->next; + bool directblk = (val->type->toBasetype()) == desttype; +#endif + + bool cow = !(val->op == TOKstructliteral || val->op == TOKarrayliteral + || val->op == TOKstring); + + for (size_t k = 0; k < ae->elements->dim; k++) + { + if (!directblk && ae->elements->tdata()[k]->op == TOKarrayliteral) + { + recursiveBlockAssign((ArrayLiteralExp *)ae->elements->tdata()[k], val, wantRef); + } + else + { + if (wantRef || cow) + ae->elements->tdata()[k] = val; + else + assignInPlace(ae->elements->tdata()[k], val); + } + } +} + + +Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post) +{ +#if LOG + printf("BinExp::interpretAssignCommon() %s\n", toChars()); +#endif + Expression *returnValue = EXP_CANT_INTERPRET; + Expression *e1 = this->e1; + if (!istate) + { + error("value of %s is not known at compile time", e1->toChars()); + return returnValue; + } + ++CtfeStatus::numAssignments; + /* Before we begin, we need to know if this is a reference assignment + * (dynamic array, AA, or class) or a value assignment. + * Determining this for slice assignments are tricky: we need to know + * if it is a block assignment (a[] = e) rather than a direct slice + * assignment (a[] = b[]). Note that initializers of multi-dimensional + * static arrays can have 2D block assignments (eg, int[7][7] x = 6;). + * So we need to recurse to determine if it is a block assignment. + */ + bool isBlockAssignment = false; + if (e1->op == TOKslice) + { + // a[] = e can have const e. So we compare the naked types. + Type *desttype = e1->type->toBasetype(); +#if DMDV2 + Type *srctype = e2->type->toBasetype()->castMod(0); +#else + Type *srctype = e2->type->toBasetype(); +#endif + while ( desttype->ty == Tsarray || desttype->ty == Tarray) + { + desttype = ((TypeArray *)desttype)->next; +#if DMDV2 + if (srctype == desttype->castMod(0)) +#else + if (srctype == desttype) +#endif + { + isBlockAssignment = true; + break; + } + } + } + bool wantRef = false; + if (!fp && this->e1->type->toBasetype() == this->e2->type->toBasetype() && + (e1->type->toBasetype()->ty == Tarray || isAssocArray(e1->type)) + // e = *x is never a reference, because *x is always a value + && this->e2->op != TOKstar + ) + { +#if DMDV2 + wantRef = true; +#else + /* D1 doesn't have const in the type system. But there is still a + * vestigal const in the form of static const variables. + * Problematic code like: + * const int [] x = [1,2,3]; + * int [] y = x; + * can be dealt with by making this a non-ref assign (y = x.dup). + * Otherwise it's a big mess. + */ + VarDeclaration * targetVar = findParentVar(e2, istate->localThis); + if (!(targetVar && targetVar->isConst())) + wantRef = true; + // slice assignment of static arrays is not reference assignment + if ((e1->op==TOKslice) && ((SliceExp *)e1)->e1->type->ty == Tsarray) + wantRef = false; +#endif + // If it is assignment from a ref parameter, it's not a ref assignment + if (this->e2->op == TOKvar) + { + VarDeclaration *v = ((VarExp *)this->e2)->var->isVarDeclaration(); + if (v && (v->storage_class & (STCref | STCout))) + wantRef = false; + } + } + if (isBlockAssignment && (e2->type->toBasetype()->ty == Tarray || e2->type->toBasetype()->ty == Tsarray)) + { + wantRef = true; + } + // If it is a construction of a ref variable, it is a ref assignment + if (op == TOKconstruct && this->e1->op==TOKvar + && ((VarExp*)this->e1)->var->storage_class & STCref) + { + wantRef = true; + } + + if (fp) + { + while (e1->op == TOKcast) + { CastExp *ce = (CastExp *)e1; + e1 = ce->e1; + } + } + if (exceptionOrCantInterpret(e1)) + return e1; + + // First, deal with this = e; and call() = e; + if (e1->op == TOKthis) + { + e1 = istate->localThis; + } + if (e1->op == TOKcall) + { + bool oldWaiting = istate->awaitingLvalueReturn; + istate->awaitingLvalueReturn = true; + e1 = e1->interpret(istate); + istate->awaitingLvalueReturn = oldWaiting; + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKarrayliteral || e1->op == TOKstring) + { + // f() = e2, when f returns an array, is always a slice assignment. + // Convert into arr[0..arr.length] = e2 + e1 = new SliceExp(loc, e1, + new IntegerExp(0, 0, Type::tsize_t), + ArrayLength(Type::tsize_t, e1)); + e1->type = type; + } + } + if (e1->op == TOKstar) + { + e1 = e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + if (!(e1->op == TOKvar || e1->op == TOKdotvar || e1->op == TOKindex + || e1->op == TOKslice)) + { + error("cannot dereference invalid pointer %s", + this->e1->toChars()); + return EXP_CANT_INTERPRET; + } + } + + if (!(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar + || e1->op == TOKindex || e1->op == TOKslice)) + { + error("CTFE internal error: unsupported assignment %s", toChars()); + return EXP_CANT_INTERPRET; + } + + Expression * newval = NULL; + + if (!wantRef) + { // We need to treat pointers specially, because TOKsymoff can be used to + // return a value OR a pointer + assert(e1); + assert(e1->type); + if ( isPointer(e1->type) && (e2->op == TOKsymoff || e2->op==TOKaddress || e2->op==TOKvar)) + newval = this->e2->interpret(istate, ctfeNeedLvalue); + else + newval = this->e2->interpret(istate); + if (exceptionOrCantInterpret(newval)) + return newval; + } + // ---------------------------------------------------- + // Deal with read-modify-write assignments. + // Set 'newval' to the final assignment value + // Also determine the return value (except for slice + // assignments, which are more complicated) + // ---------------------------------------------------- + + if (fp || e1->op == TOKarraylength) + { + // If it isn't a simple assignment, we need the existing value + Expression * oldval = e1->interpret(istate); + if (exceptionOrCantInterpret(oldval)) + return oldval; + while (oldval->op == TOKvar) + { + oldval = resolveReferences(oldval, istate->localThis); + oldval = oldval->interpret(istate); + if (exceptionOrCantInterpret(oldval)) + return oldval; + } + + if (fp) + { + // ~= can create new values (see bug 6052) + if (op == TOKcatass) + { + // We need to dup it. We can skip this if it's a dynamic array, + // because it gets copied later anyway + if (newval->type->ty != Tarray) + newval = copyLiteral(newval); + if (newval->op == TOKslice) + newval = resolveSlice(newval); + // It becomes a reference assignment + wantRef = true; + } + if (oldval->op == TOKslice) + oldval = resolveSlice(oldval); + if (this->e1->type->ty == Tpointer && this->e2->type->isintegral() + && (op==TOKaddass || op == TOKminass || + op == TOKplusplus || op == TOKminusminus)) + { + oldval = this->e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(oldval)) + return oldval; + newval = this->e2->interpret(istate); + if (exceptionOrCantInterpret(newval)) + return newval; + newval = pointerArithmetic(loc, op, type, oldval, newval); + } + else if (this->e1->type->ty == Tpointer) + { + error("pointer expression %s cannot be interpreted at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + else + { + newval = (*fp)(type, oldval, newval); + } + if (newval == EXP_CANT_INTERPRET) + { + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + if (exceptionOrCantInterpret(newval)) + return newval; + // Determine the return value + returnValue = ctfeCast(loc, type, type, post ? oldval : newval); + if (exceptionOrCantInterpret(returnValue)) + return returnValue; + } + else + returnValue = newval; + if (e1->op == TOKarraylength) { size_t oldlen = oldval->toInteger(); size_t newlen = newval->toInteger(); if (oldlen == newlen) // no change required -- we're done! - return returnValue; + return returnValue; // Now change the assignment from arr.length = n into arr = newval e1 = ((ArrayLengthExp *)e1)->e1; if (oldlen != 0) @@ -3629,8 +3629,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ oldval = oldval->interpret(istate); } } - if (oldval->op == TOKslice) - oldval = resolveSlice(oldval); + if (oldval->op == TOKslice) + oldval = resolveSlice(oldval); Type *t = e1->type->toBasetype(); if (t->ty == Tarray) { @@ -3642,62 +3642,62 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ Expressions *elements = new Expressions(); elements->setDim(newlen); size_t copylen = oldlen < newlen ? oldlen : newlen; - if (oldval->op == TOKstring) - { - StringExp *oldse = (StringExp *)oldval; - unsigned char *s = (unsigned char *)mem.calloc(newlen + 1, oldse->sz); - memcpy(s, oldse->string, copylen * oldse->sz); - unsigned defaultValue = (unsigned)(defaultElem->toInteger()); - for (size_t elemi = copylen; elemi < newlen; ++elemi) - { - switch (oldse->sz) - { - case 1: s[elemi] = defaultValue; break; - case 2: ((unsigned short *)s)[elemi] = defaultValue; break; - case 4: ((unsigned *)s)[elemi] = defaultValue; break; - default: assert(0); - } - } - StringExp *se = new StringExp(loc, s, newlen); - se->type = t; - se->sz = oldse->sz; - se->committed = oldse->committed; - se->ownedByCtfe = true; - newval = se; - } - else - { - if (oldlen !=0) - assert(oldval->op == TOKarrayliteral); - ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval; - for (size_t i = 0; i < copylen; i++) - elements->tdata()[i] = ae->elements->tdata()[i]; - if (elemType->ty == Tstruct || elemType->ty == Tsarray) - { /* If it is an aggregate literal representing a value type, - * we need to create a unique copy for each element - */ - for (size_t i = copylen; i < newlen; i++) - elements->tdata()[i] = copyLiteral(defaultElem); - } - else - { - for (size_t i = copylen; i < newlen; i++) - elements->tdata()[i] = defaultElem; - } - ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements); - aae->type = t; - newval = aae; - aae->ownedByCtfe = true; - } - // We have changed it into a reference assignment - // Note that returnValue is still the new length. - wantRef = true; - if (e1->op == TOKstar) - { // arr.length+=n becomes (t=&arr, *(t).length=*(t).length+n); - e1 = e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - } + if (oldval->op == TOKstring) + { + StringExp *oldse = (StringExp *)oldval; + unsigned char *s = (unsigned char *)mem.calloc(newlen + 1, oldse->sz); + memcpy(s, oldse->string, copylen * oldse->sz); + unsigned defaultValue = (unsigned)(defaultElem->toInteger()); + for (size_t elemi = copylen; elemi < newlen; ++elemi) + { + switch (oldse->sz) + { + case 1: s[elemi] = defaultValue; break; + case 2: ((unsigned short *)s)[elemi] = defaultValue; break; + case 4: ((unsigned *)s)[elemi] = defaultValue; break; + default: assert(0); + } + } + StringExp *se = new StringExp(loc, s, newlen); + se->type = t; + se->sz = oldse->sz; + se->committed = oldse->committed; + se->ownedByCtfe = true; + newval = se; + } + else + { + if (oldlen !=0) + assert(oldval->op == TOKarrayliteral); + ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval; + for (size_t i = 0; i < copylen; i++) + elements->tdata()[i] = ae->elements->tdata()[i]; + if (elemType->ty == Tstruct || elemType->ty == Tsarray) + { /* If it is an aggregate literal representing a value type, + * we need to create a unique copy for each element + */ + for (size_t i = copylen; i < newlen; i++) + elements->tdata()[i] = copyLiteral(defaultElem); + } + else + { + for (size_t i = copylen; i < newlen; i++) + elements->tdata()[i] = defaultElem; + } + ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements); + aae->type = t; + newval = aae; + aae->ownedByCtfe = true; + } + // We have changed it into a reference assignment + // Note that returnValue is still the new length. + wantRef = true; + if (e1->op == TOKstar) + { // arr.length+=n becomes (t=&arr, *(t).length=*(t).length+n); + e1 = e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + } } else { @@ -3707,24 +3707,24 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } } - else if (!wantRef && e1->op != TOKslice) + else if (!wantRef && e1->op != TOKslice) { /* Look for special case of struct being initialized with 0. */ if (type->toBasetype()->ty == Tstruct && newval->op == TOKint64) { newval = type->defaultInitLiteral(loc); - if (newval->op != TOKstructliteral) - { - error("nested structs with constructors are not yet supported in CTFE (Bug 6419)"); - return EXP_CANT_INTERPRET; + if (newval->op != TOKstructliteral) + { + error("nested structs with constructors are not yet supported in CTFE (Bug 6419)"); + return EXP_CANT_INTERPRET; } } - newval = ctfeCast(loc, type, type, newval); - if (exceptionOrCantInterpret(newval)) - return newval; - returnValue = newval; - } - if (exceptionOrCantInterpret(newval)) + newval = ctfeCast(loc, type, type, newval); + if (exceptionOrCantInterpret(newval)) + return newval; + returnValue = newval; + } + if (exceptionOrCantInterpret(newval)) return newval; // ------------------------------------------------- @@ -3739,169 +3739,169 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ return EXP_CANT_INTERPRET; } - e1 = resolveReferences(e1, istate->localThis); + e1 = resolveReferences(e1, istate->localThis); // Unless we have a simple var assignment, we're // only modifying part of the variable. So we need to make sure // that the parent variable exists. - if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) - ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); + if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) + ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); - // --------------------------------------- - // Deal with reference assignment - // (We already have 'newval' for arraylength operations) - // --------------------------------------- - if (wantRef && !fp && this->e1->op != TOKarraylength) + // --------------------------------------- + // Deal with reference assignment + // (We already have 'newval' for arraylength operations) + // --------------------------------------- + if (wantRef && !fp && this->e1->op != TOKarraylength) { - newval = this->e2->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(newval)) - return newval; - // If it is an assignment from a array function parameter passed by - // reference, resolve the reference. (This should NOT happen for - // non-reference types). - if (newval->op == TOKvar && (newval->type->ty == Tarray || - newval->type->ty == Tclass)) - { - newval = newval->interpret(istate); + newval = this->e2->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(newval)) + return newval; + // If it is an assignment from a array function parameter passed by + // reference, resolve the reference. (This should NOT happen for + // non-reference types). + if (newval->op == TOKvar && (newval->type->ty == Tarray || + newval->type->ty == Tclass)) + { + newval = newval->interpret(istate); } - if (newval->op == TOKassocarrayliteral || newval->op == TOKstring || - newval->op==TOKarrayliteral) + if (newval->op == TOKassocarrayliteral || newval->op == TOKstring || + newval->op==TOKarrayliteral) { - if (needToCopyLiteral(newval)) - newval = copyLiteral(newval); + if (needToCopyLiteral(newval)) + newval = copyLiteral(newval); } - returnValue = newval; - } - - // --------------------------------------- - // Deal with AA index assignment - // --------------------------------------- - /* This needs special treatment if the AA doesn't exist yet. - * There are two special cases: - * (1) If the AA is itself an index of another AA, we may need to create - * multiple nested AA literals before we can insert the new value. - * (2) If the ultimate AA is null, no insertion happens at all. Instead, we - * create nested AA literals, and change it into a assignment. - */ - if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) - { - IndexExp *ie = (IndexExp *)e1; - int depth = 0; // how many nested AA indices are there? - while (ie->e1->op == TOKindex && ((IndexExp *)ie->e1)->e1->type->toBasetype()->ty == Taarray) - { - ie = (IndexExp *)ie->e1; - ++depth; - } - Expression *aggregate = resolveReferences(ie->e1, istate->localThis); - Expression *oldagg = aggregate; - // Get the AA to be modified. (We do an LvalueRef interpret, unless it - // is a simple ref parameter -- in which case, we just want the value) - aggregate = aggregate->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - if (aggregate->op == TOKassocarrayliteral) - { // Normal case, ultimate parent AA already exists - // We need to walk from the deepest index up, checking that an AA literal - // already exists on each level. - Expression *index = ((IndexExp *)e1)->e2->interpret(istate); - if (exceptionOrCantInterpret(index)) - return index; - if (index->op == TOKslice) // only happens with AA assignment - index = resolveSlice(index); - AssocArrayLiteralExp *existingAA = (AssocArrayLiteralExp *)aggregate; - while (depth > 0) - { // Walk the syntax tree to find the indexExp at this depth - IndexExp *xe = (IndexExp *)e1; - for (int d= 0; d < depth; ++d) - xe = (IndexExp *)xe->e1; - - Expression *indx = xe->e2->interpret(istate); - if (exceptionOrCantInterpret(indx)) - return indx; - if (indx->op == TOKslice) // only happens with AA assignment - indx = resolveSlice(indx); - - // Look up this index in it up in the existing AA, to get the next level of AA. - AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx); - if (exceptionOrCantInterpret(newAA)) - return newAA; - if (!newAA) - { // Doesn't exist yet, create an empty AA... - Expressions *valuesx = new Expressions(); - Expressions *keysx = new Expressions(); - newAA = new AssocArrayLiteralExp(loc, keysx, valuesx); - newAA->type = xe->type; - newAA->ownedByCtfe = true; - //... and insert it into the existing AA. - existingAA->keys->push(indx); - existingAA->values->push(newAA); - } - existingAA = newAA; - --depth; - } - if (assignAssocArrayElement(loc, existingAA, index, newval) == EXP_CANT_INTERPRET) - return EXP_CANT_INTERPRET; - return returnValue; - } - else - { /* The AA is currently null. 'aggregate' is actually a reference to - * whatever contains it. It could be anything: var, dotvarexp, ... - * We rewrite the assignment from: aggregate[i][j] = newval; - * into: aggregate = [i:[j: newval]]; - */ - while (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) - { - Expression *index = ((IndexExp *)e1)->e2->interpret(istate); - if (exceptionOrCantInterpret(index)) - return index; - if (index->op == TOKslice) // only happens with AA assignment - index = resolveSlice(index); - Expressions *valuesx = new Expressions(); - Expressions *keysx = new Expressions(); - valuesx->push(newval); - keysx->push(index); - AssocArrayLiteralExp *newaae = new AssocArrayLiteralExp(loc, keysx, valuesx); - newaae->ownedByCtfe = true; - newaae->type = e1->type; - newval = newaae; - e1 = ((IndexExp *)e1)->e1; - } - // We must return to the original aggregate, in case it was a reference - wantRef = true; - e1 = oldagg; - // fall through -- let the normal assignment logic take care of it - } - } + returnValue = newval; + } - // --------------------------------------- - // Deal with dotvar expressions - // --------------------------------------- - // Because structs are not reference types, dotvar expressions can be - // collapsed into a single assignment. - if (!wantRef && e1->op == TOKdotvar) - { - // Strip of all of the leading dotvars, unless we started with a call - // or a ref parameter - // (in which case, we already have the lvalue). - if (this->e1->op != TOKcall && !(this->e1->op==TOKvar - && ((VarExp*)this->e1)->var->storage_class & (STCref | STCout))) - e1 = e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKstructliteral && newval->op == TOKstructliteral) - { - assignInPlace(e1, newval); - return returnValue; + // --------------------------------------- + // Deal with AA index assignment + // --------------------------------------- + /* This needs special treatment if the AA doesn't exist yet. + * There are two special cases: + * (1) If the AA is itself an index of another AA, we may need to create + * multiple nested AA literals before we can insert the new value. + * (2) If the ultimate AA is null, no insertion happens at all. Instead, we + * create nested AA literals, and change it into a assignment. + */ + if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) + { + IndexExp *ie = (IndexExp *)e1; + int depth = 0; // how many nested AA indices are there? + while (ie->e1->op == TOKindex && ((IndexExp *)ie->e1)->e1->type->toBasetype()->ty == Taarray) + { + ie = (IndexExp *)ie->e1; + ++depth; + } + Expression *aggregate = resolveReferences(ie->e1, istate->localThis); + Expression *oldagg = aggregate; + // Get the AA to be modified. (We do an LvalueRef interpret, unless it + // is a simple ref parameter -- in which case, we just want the value) + aggregate = aggregate->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(aggregate)) + return aggregate; + if (aggregate->op == TOKassocarrayliteral) + { // Normal case, ultimate parent AA already exists + // We need to walk from the deepest index up, checking that an AA literal + // already exists on each level. + Expression *index = ((IndexExp *)e1)->e2->interpret(istate); + if (exceptionOrCantInterpret(index)) + return index; + if (index->op == TOKslice) // only happens with AA assignment + index = resolveSlice(index); + AssocArrayLiteralExp *existingAA = (AssocArrayLiteralExp *)aggregate; + while (depth > 0) + { // Walk the syntax tree to find the indexExp at this depth + IndexExp *xe = (IndexExp *)e1; + for (int d= 0; d < depth; ++d) + xe = (IndexExp *)xe->e1; + + Expression *indx = xe->e2->interpret(istate); + if (exceptionOrCantInterpret(indx)) + return indx; + if (indx->op == TOKslice) // only happens with AA assignment + indx = resolveSlice(indx); + + // Look up this index in it up in the existing AA, to get the next level of AA. + AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx); + if (exceptionOrCantInterpret(newAA)) + return newAA; + if (!newAA) + { // Doesn't exist yet, create an empty AA... + Expressions *valuesx = new Expressions(); + Expressions *keysx = new Expressions(); + newAA = new AssocArrayLiteralExp(loc, keysx, valuesx); + newAA->type = xe->type; + newAA->ownedByCtfe = true; + //... and insert it into the existing AA. + existingAA->keys->push(indx); + existingAA->values->push(newAA); + } + existingAA = newAA; + --depth; + } + if (assignAssocArrayElement(loc, existingAA, index, newval) == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + return returnValue; + } + else + { /* The AA is currently null. 'aggregate' is actually a reference to + * whatever contains it. It could be anything: var, dotvarexp, ... + * We rewrite the assignment from: aggregate[i][j] = newval; + * into: aggregate = [i:[j: newval]]; + */ + while (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) + { + Expression *index = ((IndexExp *)e1)->e2->interpret(istate); + if (exceptionOrCantInterpret(index)) + return index; + if (index->op == TOKslice) // only happens with AA assignment + index = resolveSlice(index); + Expressions *valuesx = new Expressions(); + Expressions *keysx = new Expressions(); + valuesx->push(newval); + keysx->push(index); + AssocArrayLiteralExp *newaae = new AssocArrayLiteralExp(loc, keysx, valuesx); + newaae->ownedByCtfe = true; + newaae->type = e1->type; + newval = newaae; + e1 = ((IndexExp *)e1)->e1; + } + // We must return to the original aggregate, in case it was a reference + wantRef = true; + e1 = oldagg; + // fall through -- let the normal assignment logic take care of it } } -#if LOGASSIGN - if (wantRef) - printf("REF ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); - else - printf("ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); - showCtfeExpr(newval); -#endif + + // --------------------------------------- + // Deal with dotvar expressions + // --------------------------------------- + // Because structs are not reference types, dotvar expressions can be + // collapsed into a single assignment. + if (!wantRef && e1->op == TOKdotvar) + { + // Strip of all of the leading dotvars, unless we started with a call + // or a ref parameter + // (in which case, we already have the lvalue). + if (this->e1->op != TOKcall && !(this->e1->op==TOKvar + && ((VarExp*)this->e1)->var->storage_class & (STCref | STCout))) + e1 = e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKstructliteral && newval->op == TOKstructliteral) + { + assignInPlace(e1, newval); + return returnValue; + } + } +#if LOGASSIGN + if (wantRef) + printf("REF ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); + else + printf("ASSIGN: %s=%s\n", e1->toChars(), newval->toChars()); + showCtfeExpr(newval); +#endif /* Assignment to variable of the form: * v = newval @@ -3910,260 +3910,260 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); - if (wantRef) - { - v->setValueNull(); - v->setValue(newval); - } - else if (e1->type->toBasetype()->ty == Tstruct) - { - // In-place modification - if (newval->op != TOKstructliteral) + if (wantRef) + { + v->setValueNull(); + v->setValue(newval); + } + else if (e1->type->toBasetype()->ty == Tstruct) + { + // In-place modification + if (newval->op != TOKstructliteral) { - error("CTFE internal error assigning struct"); - return EXP_CANT_INTERPRET; - } - newval = copyLiteral(newval); - if (v->getValue()) - assignInPlace(v->getValue(), newval); - else - v->setValue(newval); - } - else - { - TY tyE1 = e1->type->toBasetype()->ty; - if (tyE1 == Tarray || tyE1 == Taarray) - { // arr op= arr - v->setValue(newval); - } - else - { - v->setValue(newval); - } - } - } - else if (e1->op == TOKdotvar) - { - /* Assignment to member variable of the form: - * e.v = newval - */ - Expression *exx = ((DotVarExp *)e1)->e1; - if (wantRef && exx->op != TOKstructliteral) - { - exx = exx->interpret(istate); - if (exceptionOrCantInterpret(exx)) - return exx; - } - if (exx->op != TOKstructliteral && exx->op != TOKclassreference) - { - error("CTFE internal error: Dotvar assignment"); - return EXP_CANT_INTERPRET; - } - VarDeclaration *member = ((DotVarExp *)e1)->var->isVarDeclaration(); - if (!member) - { - error("CTFE internal error: Dotvar assignment"); - return EXP_CANT_INTERPRET; - } - StructLiteralExp *se = exx->op == TOKstructliteral - ? (StructLiteralExp *)exx - : ((ClassReferenceExp *)exx)->value; - int fieldi = exx->op == TOKstructliteral - ? se->getFieldIndex(member->type, member->offset) - : ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset); - if (fieldi == -1) - { - error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars()); - return EXP_CANT_INTERPRET; - } - assert(fieldi>=0 && fieldi < se->elements->dim); - if (newval->op == TOKstructliteral) - assignInPlace(se->elements->tdata()[fieldi], newval); - else - se->elements->tdata()[fieldi] = newval; - return returnValue; - } - else if (e1->op == TOKindex) - { - /* Assignment to array element of the form: - * aggregate[i] = newval - * aggregate is not AA (AAs were dealt with already). - */ - IndexExp *ie = (IndexExp *)e1; - assert(ie->e1->type->toBasetype()->ty != Taarray); - uinteger_t destarraylen = 0; - - // Set the $ variable, and find the array literal to modify - if (ie->e1->type->toBasetype()->ty != Tpointer) - { - Expression *oldval = ie->e1->interpret(istate); - if (oldval->op == TOKnull) - { - error("cannot index null array %s", ie->e1->toChars()); - return EXP_CANT_INTERPRET; - } - if (oldval->op != TOKarrayliteral && oldval->op != TOKstring - && oldval->op != TOKslice) - { - error("cannot determine length of %s at compile time", - ie->e1->toChars()); - return EXP_CANT_INTERPRET; - } - destarraylen = resolveArrayLength(oldval); - if (ie->lengthVar) - { - IntegerExp *dollarExp = new IntegerExp(loc, destarraylen, Type::tsize_t); - ctfeStack.push(ie->lengthVar); - ie->lengthVar->setValue(dollarExp); - } - } - Expression *index = ie->e2->interpret(istate); - if (ie->lengthVar) - ctfeStack.pop(ie->lengthVar); // $ is defined only inside [] - if (exceptionOrCantInterpret(index)) - return index; - - assert (index->op != TOKslice); // only happens with AA assignment - - ArrayLiteralExp *existingAE = NULL; - StringExp *existingSE = NULL; - - Expression *aggregate = resolveReferences(ie->e1, istate->localThis); - - // Set the index to modify, and check that it is in range - dinteger_t indexToModify = index->toInteger(); - if (ie->e1->type->toBasetype()->ty == Tpointer) - { - dinteger_t ofs; - aggregate = aggregate->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - if (aggregate->op == TOKnull) - { - error("cannot index through null pointer %s", ie->e1->toChars()); - return EXP_CANT_INTERPRET; - } - if (aggregate->op == TOKint64) - { - error("cannot index through invalid pointer %s of value %s", - ie->e1->toChars(), aggregate->toChars()); - return EXP_CANT_INTERPRET; - } - aggregate = getAggregateFromPointer(aggregate, &ofs); - indexToModify += ofs; - destarraylen = resolveArrayLength(aggregate); - } - if (indexToModify >= destarraylen) - { - error("array index %lld is out of bounds [0..%lld]", indexToModify, - destarraylen); - return EXP_CANT_INTERPRET; - } - - /* The only possible indexable LValue aggregates are array literals, and - * slices of array literals. - */ - if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || - aggregate->op == TOKslice || aggregate->op == TOKcall || - aggregate->op == TOKstar) - { - Expression *origagg = aggregate; - aggregate = aggregate->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - // The array could be an index of an AA. Resolve it if so. - if (aggregate->op == TOKindex && - ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) - { - IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); - if (!aggregate) - { - error("key %s not found in associative array %s", - ix->e2->toChars(), ix->e1->toChars()); - return EXP_CANT_INTERPRET; - } - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - } - } - if (aggregate->op == TOKvar) - { - VarExp *ve = (VarExp *)aggregate; - VarDeclaration *v = ve->var->isVarDeclaration(); - aggregate = v->getValue(); - if (aggregate->op == TOKnull) - { - // This would be a runtime segfault - error("cannot index null array %s", v->toChars()); - return EXP_CANT_INTERPRET; - } - } - if (aggregate->op == TOKslice) - { - SliceExp *sexp = (SliceExp *)aggregate; - aggregate = sexp->e1; - Expression *lwr = sexp->lwr->interpret(istate); - indexToModify += lwr->toInteger(); - } - if (aggregate->op == TOKarrayliteral) - existingAE = (ArrayLiteralExp *)aggregate; - else if (aggregate->op == TOKstring) - existingSE = (StringExp *)aggregate; - else - { - error("CTFE internal compiler error %s", aggregate->toChars()); - return EXP_CANT_INTERPRET; - } - if (!wantRef && newval->op == TOKslice) - { - newval = resolveSlice(newval); - if (newval == EXP_CANT_INTERPRET) - { - error("Compiler error: CTFE index assign %s", toChars()); - assert(0); - } - } - if (wantRef && newval->op == TOKindex - && ((IndexExp *)newval)->e1 == aggregate) - { // It's a circular reference, resolve it now - newval = newval->interpret(istate); - } + error("CTFE internal error assigning struct"); + return EXP_CANT_INTERPRET; + } + newval = copyLiteral(newval); + if (v->getValue()) + assignInPlace(v->getValue(), newval); + else + v->setValue(newval); + } + else + { + TY tyE1 = e1->type->toBasetype()->ty; + if (tyE1 == Tarray || tyE1 == Taarray) + { // arr op= arr + v->setValue(newval); + } + else + { + v->setValue(newval); + } + } + } + else if (e1->op == TOKdotvar) + { + /* Assignment to member variable of the form: + * e.v = newval + */ + Expression *exx = ((DotVarExp *)e1)->e1; + if (wantRef && exx->op != TOKstructliteral) + { + exx = exx->interpret(istate); + if (exceptionOrCantInterpret(exx)) + return exx; + } + if (exx->op != TOKstructliteral && exx->op != TOKclassreference) + { + error("CTFE internal error: Dotvar assignment"); + return EXP_CANT_INTERPRET; + } + VarDeclaration *member = ((DotVarExp *)e1)->var->isVarDeclaration(); + if (!member) + { + error("CTFE internal error: Dotvar assignment"); + return EXP_CANT_INTERPRET; + } + StructLiteralExp *se = exx->op == TOKstructliteral + ? (StructLiteralExp *)exx + : ((ClassReferenceExp *)exx)->value; + int fieldi = exx->op == TOKstructliteral + ? se->getFieldIndex(member->type, member->offset) + : ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset); + if (fieldi == -1) + { + error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars()); + return EXP_CANT_INTERPRET; + } + assert(fieldi>=0 && fieldi < se->elements->dim); + if (newval->op == TOKstructliteral) + assignInPlace(se->elements->tdata()[fieldi], newval); + else + se->elements->tdata()[fieldi] = newval; + return returnValue; + } + else if (e1->op == TOKindex) + { + /* Assignment to array element of the form: + * aggregate[i] = newval + * aggregate is not AA (AAs were dealt with already). + */ + IndexExp *ie = (IndexExp *)e1; + assert(ie->e1->type->toBasetype()->ty != Taarray); + uinteger_t destarraylen = 0; - if (existingAE) - { - if (newval->op == TOKstructliteral) - assignInPlace((Expression *)(existingAE->elements->tdata()[indexToModify]), newval); - else - existingAE->elements->tdata()[indexToModify] = newval; - return returnValue; - } - if (existingSE) - { - unsigned char *s = (unsigned char *)existingSE->string; - if (!existingSE->ownedByCtfe) - { - error("cannot modify read-only string literal %s", ie->e1->toChars()); - return EXP_CANT_INTERPRET; - } - unsigned value = newval->toInteger(); - switch (existingSE->sz) - { - case 1: s[indexToModify] = value; break; - case 2: ((unsigned short *)s)[indexToModify] = value; break; - case 4: ((unsigned *)s)[indexToModify] = value; break; - default: - assert(0); - break; - } - return returnValue; - } - else - { - error("Index assignment %s is not yet supported in CTFE ", toChars()); - return EXP_CANT_INTERPRET; - } - return returnValue; + // Set the $ variable, and find the array literal to modify + if (ie->e1->type->toBasetype()->ty != Tpointer) + { + Expression *oldval = ie->e1->interpret(istate); + if (oldval->op == TOKnull) + { + error("cannot index null array %s", ie->e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (oldval->op != TOKarrayliteral && oldval->op != TOKstring + && oldval->op != TOKslice) + { + error("cannot determine length of %s at compile time", + ie->e1->toChars()); + return EXP_CANT_INTERPRET; + } + destarraylen = resolveArrayLength(oldval); + if (ie->lengthVar) + { + IntegerExp *dollarExp = new IntegerExp(loc, destarraylen, Type::tsize_t); + ctfeStack.push(ie->lengthVar); + ie->lengthVar->setValue(dollarExp); + } + } + Expression *index = ie->e2->interpret(istate); + if (ie->lengthVar) + ctfeStack.pop(ie->lengthVar); // $ is defined only inside [] + if (exceptionOrCantInterpret(index)) + return index; + + assert (index->op != TOKslice); // only happens with AA assignment + + ArrayLiteralExp *existingAE = NULL; + StringExp *existingSE = NULL; + + Expression *aggregate = resolveReferences(ie->e1, istate->localThis); + + // Set the index to modify, and check that it is in range + dinteger_t indexToModify = index->toInteger(); + if (ie->e1->type->toBasetype()->ty == Tpointer) + { + dinteger_t ofs; + aggregate = aggregate->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(aggregate)) + return aggregate; + if (aggregate->op == TOKnull) + { + error("cannot index through null pointer %s", ie->e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (aggregate->op == TOKint64) + { + error("cannot index through invalid pointer %s of value %s", + ie->e1->toChars(), aggregate->toChars()); + return EXP_CANT_INTERPRET; + } + aggregate = getAggregateFromPointer(aggregate, &ofs); + indexToModify += ofs; + destarraylen = resolveArrayLength(aggregate); + } + if (indexToModify >= destarraylen) + { + error("array index %lld is out of bounds [0..%lld]", indexToModify, + destarraylen); + return EXP_CANT_INTERPRET; + } + + /* The only possible indexable LValue aggregates are array literals, and + * slices of array literals. + */ + if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || + aggregate->op == TOKslice || aggregate->op == TOKcall || + aggregate->op == TOKstar) + { + Expression *origagg = aggregate; + aggregate = aggregate->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(aggregate)) + return aggregate; + // The array could be an index of an AA. Resolve it if so. + if (aggregate->op == TOKindex && + ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) + { + IndexExp *ix = (IndexExp *)aggregate; + aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + if (!aggregate) + { + error("key %s not found in associative array %s", + ix->e2->toChars(), ix->e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (exceptionOrCantInterpret(aggregate)) + return aggregate; + } + } + if (aggregate->op == TOKvar) + { + VarExp *ve = (VarExp *)aggregate; + VarDeclaration *v = ve->var->isVarDeclaration(); + aggregate = v->getValue(); + if (aggregate->op == TOKnull) + { + // This would be a runtime segfault + error("cannot index null array %s", v->toChars()); + return EXP_CANT_INTERPRET; + } + } + if (aggregate->op == TOKslice) + { + SliceExp *sexp = (SliceExp *)aggregate; + aggregate = sexp->e1; + Expression *lwr = sexp->lwr->interpret(istate); + indexToModify += lwr->toInteger(); + } + if (aggregate->op == TOKarrayliteral) + existingAE = (ArrayLiteralExp *)aggregate; + else if (aggregate->op == TOKstring) + existingSE = (StringExp *)aggregate; + else + { + error("CTFE internal compiler error %s", aggregate->toChars()); + return EXP_CANT_INTERPRET; + } + if (!wantRef && newval->op == TOKslice) + { + newval = resolveSlice(newval); + if (newval == EXP_CANT_INTERPRET) + { + error("Compiler error: CTFE index assign %s", toChars()); + assert(0); + } + } + if (wantRef && newval->op == TOKindex + && ((IndexExp *)newval)->e1 == aggregate) + { // It's a circular reference, resolve it now + newval = newval->interpret(istate); + } + + if (existingAE) + { + if (newval->op == TOKstructliteral) + assignInPlace((Expression *)(existingAE->elements->tdata()[indexToModify]), newval); + else + existingAE->elements->tdata()[indexToModify] = newval; + return returnValue; + } + if (existingSE) + { + unsigned char *s = (unsigned char *)existingSE->string; + if (!existingSE->ownedByCtfe) + { + error("cannot modify read-only string literal %s", ie->e1->toChars()); + return EXP_CANT_INTERPRET; + } + unsigned value = newval->toInteger(); + switch (existingSE->sz) + { + case 1: s[indexToModify] = value; break; + case 2: ((unsigned short *)s)[indexToModify] = value; break; + case 4: ((unsigned *)s)[indexToModify] = value; break; + default: + assert(0); + break; + } + return returnValue; + } + else + { + error("Index assignment %s is not yet supported in CTFE ", toChars()); + return EXP_CANT_INTERPRET; + } + return returnValue; } else if (e1->op == TOKslice) { @@ -4172,261 +4172,261 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // aggregate[low..upp] = newval // ------------------------------ SliceExp * sexp = (SliceExp *)e1; - // Set the $ variable - Expression *oldval = sexp->e1; - bool assignmentToSlicedPointer = false; - if (isPointer(oldval->type)) - { // Slicing a pointer - oldval = oldval->interpret(istate, ctfeNeedLvalue); - dinteger_t ofs; - oldval = getAggregateFromPointer(oldval, &ofs); - assignmentToSlicedPointer = true; - } else - oldval = oldval->interpret(istate); - - if (oldval->op != TOKarrayliteral && oldval->op != TOKstring - && oldval->op != TOKslice && oldval->op != TOKnull) - { - error("CTFE ICE: cannot resolve array length"); - return EXP_CANT_INTERPRET; - } - uinteger_t dollar = resolveArrayLength(oldval); - if (sexp->lengthVar) - { - Expression *arraylen = new IntegerExp(loc, dollar, Type::tsize_t); - ctfeStack.push(sexp->lengthVar); - sexp->lengthVar->setValue(arraylen); - } - + // Set the $ variable + Expression *oldval = sexp->e1; + bool assignmentToSlicedPointer = false; + if (isPointer(oldval->type)) + { // Slicing a pointer + oldval = oldval->interpret(istate, ctfeNeedLvalue); + dinteger_t ofs; + oldval = getAggregateFromPointer(oldval, &ofs); + assignmentToSlicedPointer = true; + } else + oldval = oldval->interpret(istate); + + if (oldval->op != TOKarrayliteral && oldval->op != TOKstring + && oldval->op != TOKslice && oldval->op != TOKnull) + { + error("CTFE ICE: cannot resolve array length"); + return EXP_CANT_INTERPRET; + } + uinteger_t dollar = resolveArrayLength(oldval); + if (sexp->lengthVar) + { + Expression *arraylen = new IntegerExp(loc, dollar, Type::tsize_t); + ctfeStack.push(sexp->lengthVar); + sexp->lengthVar->setValue(arraylen); + } + Expression *upper = NULL; Expression *lower = NULL; if (sexp->upr) upper = sexp->upr->interpret(istate); - if (exceptionOrCantInterpret(upper)) - { - if (sexp->lengthVar) - ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] - return upper; + if (exceptionOrCantInterpret(upper)) + { + if (sexp->lengthVar) + ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] + return upper; } if (sexp->lwr) lower = sexp->lwr->interpret(istate); - if (sexp->lengthVar) - ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] - if (exceptionOrCantInterpret(lower)) - return lower; - - size_t dim = dollar; - size_t upperbound = upper ? upper->toInteger() : dim; - int lowerbound = lower ? lower->toInteger() : 0; - - if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim))) - { - error("Array bounds [0..%d] exceeded in slice [%d..%d]", - dim, lowerbound, upperbound); + if (sexp->lengthVar) + ctfeStack.pop(sexp->lengthVar); // $ is defined only in [L..U] + if (exceptionOrCantInterpret(lower)) + return lower; + + size_t dim = dollar; + size_t upperbound = upper ? upper->toInteger() : dim; + int lowerbound = lower ? lower->toInteger() : 0; + + if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim))) + { + error("Array bounds [0..%d] exceeded in slice [%d..%d]", + dim, lowerbound, upperbound); return EXP_CANT_INTERPRET; } - if (upperbound == lowerbound) - return newval; - - Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis); - dinteger_t firstIndex = lowerbound; - - ArrayLiteralExp *existingAE = NULL; - StringExp *existingSE = NULL; - - /* The only possible slicable LValue aggregates are array literals, - * and slices of array literals. - */ - - if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || - aggregate->op == TOKslice || - aggregate->op == TOKstar || aggregate->op == TOKcall) + if (upperbound == lowerbound) + return newval; + + Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis); + dinteger_t firstIndex = lowerbound; + + ArrayLiteralExp *existingAE = NULL; + StringExp *existingSE = NULL; + + /* The only possible slicable LValue aggregates are array literals, + * and slices of array literals. + */ + + if (aggregate->op == TOKindex || aggregate->op == TOKdotvar || + aggregate->op == TOKslice || + aggregate->op == TOKstar || aggregate->op == TOKcall) { - aggregate = aggregate->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - // The array could be an index of an AA. Resolve it if so. - if (aggregate->op == TOKindex && - ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) - { - IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); - if (!aggregate) - { - error("key %s not found in associative array %s", - ix->e2->toChars(), ix->e1->toChars()); - return EXP_CANT_INTERPRET; - } - if (exceptionOrCantInterpret(aggregate)) - return aggregate; - } - } - if (aggregate->op == TOKvar) + aggregate = aggregate->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(aggregate)) + return aggregate; + // The array could be an index of an AA. Resolve it if so. + if (aggregate->op == TOKindex && + ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) + { + IndexExp *ix = (IndexExp *)aggregate; + aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + if (!aggregate) { - VarExp *ve = (VarExp *)(aggregate); - VarDeclaration *v = ve->var->isVarDeclaration(); - aggregate = v->getValue(); - } - if (aggregate->op == TOKslice) - { // Slice of a slice --> change the bounds - SliceExp *sexpold = (SliceExp *)aggregate; - dinteger_t hi = upperbound + sexpold->lwr->toInteger(); - firstIndex = lowerbound + sexpold->lwr->toInteger(); - if (hi > sexpold->upr->toInteger()) - { - error("slice [%d..%d] exceeds array bounds [0..%jd]", - lowerbound, upperbound, - sexpold->upr->toInteger() - sexpold->lwr->toInteger()); - return EXP_CANT_INTERPRET; + error("key %s not found in associative array %s", + ix->e2->toChars(), ix->e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (exceptionOrCantInterpret(aggregate)) + return aggregate; } - aggregate = sexpold->e1; - } - if ( isPointer(aggregate->type) ) - { // Slicing a pointer --> change the bounds - aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); - dinteger_t ofs; - aggregate = getAggregateFromPointer(aggregate, &ofs); - dinteger_t hi = upperbound + ofs; - firstIndex = lowerbound + ofs; - if (firstIndex < 0 || hi > dim) + } + if (aggregate->op == TOKvar) + { + VarExp *ve = (VarExp *)(aggregate); + VarDeclaration *v = ve->var->isVarDeclaration(); + aggregate = v->getValue(); + } + if (aggregate->op == TOKslice) + { // Slice of a slice --> change the bounds + SliceExp *sexpold = (SliceExp *)aggregate; + dinteger_t hi = upperbound + sexpold->lwr->toInteger(); + firstIndex = lowerbound + sexpold->lwr->toInteger(); + if (hi > sexpold->upr->toInteger()) { - error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", - firstIndex, hi, dim); + error("slice [%d..%d] exceeds array bounds [0..%jd]", + lowerbound, upperbound, + sexpold->upr->toInteger() - sexpold->lwr->toInteger()); return EXP_CANT_INTERPRET; } - } - if (aggregate->op == TOKarrayliteral) - existingAE = (ArrayLiteralExp *)aggregate; - else if (aggregate->op == TOKstring) - existingSE = (StringExp *)aggregate; - if (existingSE && !existingSE->ownedByCtfe) - { error("cannot modify read-only string literal %s", sexp->e1->toChars()); - return EXP_CANT_INTERPRET; - } - - if (!wantRef && newval->op == TOKslice) + aggregate = sexpold->e1; + } + if ( isPointer(aggregate->type) ) + { // Slicing a pointer --> change the bounds + aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); + dinteger_t ofs; + aggregate = getAggregateFromPointer(aggregate, &ofs); + dinteger_t hi = upperbound + ofs; + firstIndex = lowerbound + ofs; + if (firstIndex < 0 || hi > dim) { - newval = resolveSlice(newval); - if (newval == EXP_CANT_INTERPRET) - { - error("Compiler error: CTFE slice %s", toChars()); - assert(0); + error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", + firstIndex, hi, dim); + return EXP_CANT_INTERPRET; } - } - if (wantRef && newval->op == TOKindex - && ((IndexExp *)newval)->e1 == aggregate) - { // It's a circular reference, resolve it now - newval = newval->interpret(istate); - } - - // For slice assignment, we check that the lengths match. + } + if (aggregate->op == TOKarrayliteral) + existingAE = (ArrayLiteralExp *)aggregate; + else if (aggregate->op == TOKstring) + existingSE = (StringExp *)aggregate; + if (existingSE && !existingSE->ownedByCtfe) + { error("cannot modify read-only string literal %s", sexp->e1->toChars()); + return EXP_CANT_INTERPRET; + } + + if (!wantRef && newval->op == TOKslice) + { + newval = resolveSlice(newval); + if (newval == EXP_CANT_INTERPRET) + { + error("Compiler error: CTFE slice %s", toChars()); + assert(0); + } + } + if (wantRef && newval->op == TOKindex + && ((IndexExp *)newval)->e1 == aggregate) + { // It's a circular reference, resolve it now + newval = newval->interpret(istate); + } + + // For slice assignment, we check that the lengths match. size_t srclen = 0; if (newval->op == TOKarrayliteral) srclen = ((ArrayLiteralExp *)newval)->elements->dim; else if (newval->op == TOKstring) srclen = ((StringExp *)newval)->len; - if (!isBlockAssignment && srclen != (upperbound - lowerbound)) + if (!isBlockAssignment && srclen != (upperbound - lowerbound)) { error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; } - - if (!isBlockAssignment && newval->op == TOKarrayliteral && existingAE) + + if (!isBlockAssignment && newval->op == TOKarrayliteral && existingAE) { - Expressions *oldelems = existingAE->elements; - Expressions *newelems = ((ArrayLiteralExp *)newval)->elements; - for (size_t j = 0; j < newelems->dim; j++) + Expressions *oldelems = existingAE->elements; + Expressions *newelems = ((ArrayLiteralExp *)newval)->elements; + for (size_t j = 0; j < newelems->dim; j++) { - oldelems->tdata()[j + firstIndex] = newelems->tdata()[j]; + oldelems->tdata()[j + firstIndex] = newelems->tdata()[j]; } return newval; } - else if (newval->op == TOKstring && existingSE) + else if (newval->op == TOKstring && existingSE) { - sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex); + sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex); return newval; } - else if (newval->op == TOKstring && existingAE - && existingAE->type->isString()) - { /* Mixed slice: it was initialized as an array literal of chars. - * Now a slice of it is being set with a string. - */ - sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex); - return newval; + else if (newval->op == TOKstring && existingAE + && existingAE->type->isString()) + { /* Mixed slice: it was initialized as an array literal of chars. + * Now a slice of it is being set with a string. + */ + sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex); + return newval; } - else if (newval->op == TOKarrayliteral && existingSE) - { /* Mixed slice: it was initialized as a string literal. - * Now a slice of it is being set with an array literal. - */ - sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex); - return newval; + else if (newval->op == TOKarrayliteral && existingSE) + { /* Mixed slice: it was initialized as a string literal. + * Now a slice of it is being set with an array literal. + */ + sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex); + return newval; } - else if (existingSE) - { // String literal block slice assign - unsigned value = newval->toInteger(); - unsigned char *s = (unsigned char *)existingSE->string; - for (size_t j = 0; j < upperbound-lowerbound; j++) + else if (existingSE) + { // String literal block slice assign + unsigned value = newval->toInteger(); + unsigned char *s = (unsigned char *)existingSE->string; + for (size_t j = 0; j < upperbound-lowerbound; j++) { - switch (existingSE->sz) - { - case 1: s[j+firstIndex] = value; break; - case 2: ((unsigned short *)s)[j+firstIndex] = value; break; - case 4: ((unsigned *)s)[j+firstIndex] = value; break; - default: - assert(0); - break; + switch (existingSE->sz) + { + case 1: s[j+firstIndex] = value; break; + case 2: ((unsigned short *)s)[j+firstIndex] = value; break; + case 4: ((unsigned *)s)[j+firstIndex] = value; break; + default: + assert(0); + break; } } - if (goal == ctfeNeedNothing) - return NULL; // avoid creating an unused literal - SliceExp *retslice = new SliceExp(loc, existingSE, - new IntegerExp(loc, firstIndex, Type::tsize_t), - new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); - retslice->type = this->type; - return retslice->interpret(istate); + if (goal == ctfeNeedNothing) + return NULL; // avoid creating an unused literal + SliceExp *retslice = new SliceExp(loc, existingSE, + new IntegerExp(loc, firstIndex, Type::tsize_t), + new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); + retslice->type = this->type; + return retslice->interpret(istate); } - else if (existingAE) + else if (existingAE) { - /* Block assignment, initialization of static arrays - * x[] = e - * x may be a multidimensional static array. (Note that this - * only happens with array literals, never with strings). + /* Block assignment, initialization of static arrays + * x[] = e + * x may be a multidimensional static array. (Note that this + * only happens with array literals, never with strings). */ - Expressions * w = existingAE->elements; - assert( existingAE->type->ty == Tsarray || - existingAE->type->ty == Tarray); -#if DMDV2 - Type *desttype = ((TypeArray *)existingAE->type)->next->castMod(0); - bool directblk = (e2->type->toBasetype()->castMod(0)) == desttype; -#else - Type *desttype = ((TypeArray *)existingAE->type)->next; - bool directblk = (e2->type->toBasetype()) == desttype; -#endif - bool cow = !(newval->op == TOKstructliteral || newval->op == TOKarrayliteral - || newval->op == TOKstring); - for (size_t j = 0; j < upperbound-lowerbound; j++) + Expressions * w = existingAE->elements; + assert( existingAE->type->ty == Tsarray || + existingAE->type->ty == Tarray); +#if DMDV2 + Type *desttype = ((TypeArray *)existingAE->type)->next->castMod(0); + bool directblk = (e2->type->toBasetype()->castMod(0)) == desttype; +#else + Type *desttype = ((TypeArray *)existingAE->type)->next; + bool directblk = (e2->type->toBasetype()) == desttype; +#endif + bool cow = !(newval->op == TOKstructliteral || newval->op == TOKarrayliteral + || newval->op == TOKstring); + for (size_t j = 0; j < upperbound-lowerbound; j++) { - if (!directblk) - // Multidimensional array block assign - recursiveBlockAssign((ArrayLiteralExp *)w->tdata()[j+firstIndex], newval, wantRef); - else + if (!directblk) + // Multidimensional array block assign + recursiveBlockAssign((ArrayLiteralExp *)w->tdata()[j+firstIndex], newval, wantRef); + else { - if (wantRef || cow) - existingAE->elements->tdata()[j+firstIndex] = newval; - else - assignInPlace(existingAE->elements->tdata()[j+firstIndex], newval); + if (wantRef || cow) + existingAE->elements->tdata()[j+firstIndex] = newval; + else + assignInPlace(existingAE->elements->tdata()[j+firstIndex], newval); } } - if (goal == ctfeNeedNothing) - return NULL; // avoid creating an unused literal - SliceExp *retslice = new SliceExp(loc, existingAE, - new IntegerExp(loc, firstIndex, Type::tsize_t), - new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); - retslice->type = this->type; - return retslice->interpret(istate); - } - else - error("Slice operation %s cannot be evaluated at compile time", toChars()); + if (goal == ctfeNeedNothing) + return NULL; // avoid creating an unused literal + SliceExp *retslice = new SliceExp(loc, existingAE, + new IntegerExp(loc, firstIndex, Type::tsize_t), + new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t)); + retslice->type = this->type; + return retslice->interpret(istate); + } + else + error("Slice operation %s cannot be evaluated at compile time", toChars()); } else { @@ -4435,25 +4435,25 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ dump(0); #endif } - return returnValue; + return returnValue; } -Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal) +Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal) { - return interpretAssignCommon(istate, goal, NULL); + return interpretAssignCommon(istate, goal, NULL); } -#define BIN_ASSIGN_INTERPRET_CTFE(op, ctfeOp) \ -Expression *op##AssignExp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ - return interpretAssignCommon(istate, goal, &ctfeOp); \ +#define BIN_ASSIGN_INTERPRET_CTFE(op, ctfeOp) \ +Expression *op##AssignExp::interpret(InterState *istate, CtfeGoal goal) \ +{ \ + return interpretAssignCommon(istate, goal, &ctfeOp); \ } -#define BIN_ASSIGN_INTERPRET(op) BIN_ASSIGN_INTERPRET_CTFE(op, op) - +#define BIN_ASSIGN_INTERPRET(op) BIN_ASSIGN_INTERPRET_CTFE(op, op) + BIN_ASSIGN_INTERPRET(Add) BIN_ASSIGN_INTERPRET(Min) -BIN_ASSIGN_INTERPRET_CTFE(Cat, ctfeCat) +BIN_ASSIGN_INTERPRET_CTFE(Cat, ctfeCat) BIN_ASSIGN_INTERPRET(Mul) BIN_ASSIGN_INTERPRET(Div) BIN_ASSIGN_INTERPRET(Mod) @@ -4463,20 +4463,20 @@ BIN_ASSIGN_INTERPRET(Ushr) BIN_ASSIGN_INTERPRET(And) BIN_ASSIGN_INTERPRET(Or) BIN_ASSIGN_INTERPRET(Xor) -#if DMDV2 -BIN_ASSIGN_INTERPRET(Pow) -#endif +#if DMDV2 +BIN_ASSIGN_INTERPRET(Pow) +#endif -Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) +Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("PostExp::interpret() %s\n", toChars()); #endif Expression *e; if (op == TOKplusplus) - e = interpretAssignCommon(istate, goal, &Add, 1); + e = interpretAssignCommon(istate, goal, &Add, 1); else - e = interpretAssignCommon(istate, goal, &Min, 1); + e = interpretAssignCommon(istate, goal, &Min, 1); #if LOG if (e == EXP_CANT_INTERPRET) printf("PostExp::interpret() CANT\n"); @@ -4484,152 +4484,152 @@ Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) return e; } -Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) +Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("AndAndExp::interpret() %s\n", toChars()); #endif Expression *e = e1->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - - int result; + if (exceptionOrCantInterpret(e)) + return e; + + int result; if (e != EXP_CANT_INTERPRET) { if (e->isBool(FALSE)) - result = 0; - else if (isTrueBool(e)) + result = 0; + else if (isTrueBool(e)) { e = e2->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - if (e == EXP_VOID_INTERPRET) - { - assert(type->ty == Tvoid); - return NULL; - } + if (exceptionOrCantInterpret(e)) + return e; + if (e == EXP_VOID_INTERPRET) + { + assert(type->ty == Tvoid); + return NULL; + } if (e != EXP_CANT_INTERPRET) { if (e->isBool(FALSE)) - result = 0; - else if (isTrueBool(e)) - result = 1; + result = 0; + else if (isTrueBool(e)) + result = 1; else - { - error("%s does not evaluate to a boolean", e->toChars()); + { + error("%s does not evaluate to a boolean", e->toChars()); e = EXP_CANT_INTERPRET; } } - } + } else - { - error("%s cannot be interpreted as a boolean", e->toChars()); + { + error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; } - } - if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) - e = new IntegerExp(loc, result, type); + } + if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) + e = new IntegerExp(loc, result, type); return e; } -Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) +Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("OrOrExp::interpret() %s\n", toChars()); #endif Expression *e = e1->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - - int result; + if (exceptionOrCantInterpret(e)) + return e; + + int result; if (e != EXP_CANT_INTERPRET) { - if (isTrueBool(e)) - result = 1; + if (isTrueBool(e)) + result = 1; else if (e->isBool(FALSE)) { e = e2->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - - if (e == EXP_VOID_INTERPRET) - { - assert(type->ty == Tvoid); - return NULL; - } + if (exceptionOrCantInterpret(e)) + return e; + + if (e == EXP_VOID_INTERPRET) + { + assert(type->ty == Tvoid); + return NULL; + } if (e != EXP_CANT_INTERPRET) { if (e->isBool(FALSE)) - result = 0; - else if (isTrueBool(e)) - result = 1; + result = 0; + else if (isTrueBool(e)) + result = 1; else - { - error("%s cannot be interpreted as a boolean", e->toChars()); + { + error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; } } - } + } else - { - error("%s cannot be interpreted as a boolean", e->toChars()); + { + error("%s cannot be interpreted as a boolean", e->toChars()); e = EXP_CANT_INTERPRET; } - } - if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) - e = new IntegerExp(loc, result, type); + } + if (e != EXP_CANT_INTERPRET && goal != ctfeNeedNothing) + e = new IntegerExp(loc, result, type); return e; } -// Print a stack trace, starting from callingExp which called fd. -// To shorten the stack trace, try to detect recursion. -void showCtfeBackTrace(InterState *istate, CallExp * callingExp, FuncDeclaration *fd) -{ - if (CtfeStatus::stackTraceCallsToSuppress > 0) - { - --CtfeStatus::stackTraceCallsToSuppress; - return; - } - errorSupplemental(callingExp->loc, "called from here: %s", callingExp->toChars()); - // Quit if it's not worth trying to compress the stack trace - if (CtfeStatus::callDepth < 6 || global.params.verbose) - return; - // Recursion happens if the current function already exists in the call stack. - int numToSuppress = 0; - int recurseCount = 0; - int depthSoFar = 0; - InterState *lastRecurse = istate; - for (InterState * cur = istate; cur; cur = cur->caller) - { - if (cur->fd == fd) - { ++recurseCount; - numToSuppress = depthSoFar; - lastRecurse = cur; - } - ++depthSoFar; - } - // We need at least three calls to the same function, to make compression worthwhile - if (recurseCount < 2) - return; - // We found a useful recursion. Print all the calls involved in the recursion - errorSupplemental(fd->loc, "%d recursive calls to function %s", recurseCount, fd->toChars()); - for (InterState *cur = istate; cur->fd != fd; cur = cur->caller) - { - errorSupplemental(cur->fd->loc, "recursively called from function %s", cur->fd->toChars()); - } - // We probably didn't enter the recursion in this function. - // Go deeper to find the real beginning. - InterState * cur = istate; - while (lastRecurse->caller && cur->fd == lastRecurse->caller->fd) - { - cur = cur->caller; - lastRecurse = lastRecurse->caller; - ++numToSuppress; - } - CtfeStatus::stackTraceCallsToSuppress = numToSuppress; -} +// Print a stack trace, starting from callingExp which called fd. +// To shorten the stack trace, try to detect recursion. +void showCtfeBackTrace(InterState *istate, CallExp * callingExp, FuncDeclaration *fd) +{ + if (CtfeStatus::stackTraceCallsToSuppress > 0) + { + --CtfeStatus::stackTraceCallsToSuppress; + return; + } + errorSupplemental(callingExp->loc, "called from here: %s", callingExp->toChars()); + // Quit if it's not worth trying to compress the stack trace + if (CtfeStatus::callDepth < 6 || global.params.verbose) + return; + // Recursion happens if the current function already exists in the call stack. + int numToSuppress = 0; + int recurseCount = 0; + int depthSoFar = 0; + InterState *lastRecurse = istate; + for (InterState * cur = istate; cur; cur = cur->caller) + { + if (cur->fd == fd) + { ++recurseCount; + numToSuppress = depthSoFar; + lastRecurse = cur; + } + ++depthSoFar; + } + // We need at least three calls to the same function, to make compression worthwhile + if (recurseCount < 2) + return; + // We found a useful recursion. Print all the calls involved in the recursion + errorSupplemental(fd->loc, "%d recursive calls to function %s", recurseCount, fd->toChars()); + for (InterState *cur = istate; cur->fd != fd; cur = cur->caller) + { + errorSupplemental(cur->fd->loc, "recursively called from function %s", cur->fd->toChars()); + } + // We probably didn't enter the recursion in this function. + // Go deeper to find the real beginning. + InterState * cur = istate; + while (lastRecurse->caller && cur->fd == lastRecurse->caller->fd) + { + cur = cur->caller; + lastRecurse = lastRecurse->caller; + ++numToSuppress; + } + CtfeStatus::stackTraceCallsToSuppress = numToSuppress; +} -Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) +Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e = EXP_CANT_INTERPRET; #if LOG @@ -4642,7 +4642,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) if (ecall->op == TOKcall) { ecall = e1->interpret(istate); - if (exceptionOrCantInterpret(ecall)) + if (exceptionOrCantInterpret(ecall)) return ecall; } if (ecall->op == TOKstar) @@ -4650,36 +4650,36 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) Expression * pe = ((PtrExp*)ecall)->e1; if (pe->op == TOKvar) { VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration(); - if (vd && vd->getValue() && vd->getValue()->op == TOKsymoff) - fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration(); + if (vd && vd->getValue() && vd->getValue()->op == TOKsymoff) + fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration(); else { - ecall = getVarExp(loc, istate, vd, goal); - if (exceptionOrCantInterpret(ecall)) + ecall = getVarExp(loc, istate, vd, goal); + if (exceptionOrCantInterpret(ecall)) return ecall; if (ecall->op == TOKsymoff) fd = ((SymOffExp *)ecall)->var->isFuncDeclaration(); } } - else if (pe->op == TOKsymoff) - fd = ((SymOffExp *)pe)->var->isFuncDeclaration(); + else if (pe->op == TOKsymoff) + fd = ((SymOffExp *)pe)->var->isFuncDeclaration(); else ecall = ((PtrExp*)ecall)->e1->interpret(istate); } - if (exceptionOrCantInterpret(ecall)) + if (exceptionOrCantInterpret(ecall)) return ecall; if (ecall->op == TOKindex) { ecall = e1->interpret(istate); - if (exceptionOrCantInterpret(ecall)) + if (exceptionOrCantInterpret(ecall)) return ecall; } if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration()) { ecall = e1->interpret(istate); - if (exceptionOrCantInterpret(ecall)) + if (exceptionOrCantInterpret(ecall)) return ecall; } @@ -4691,8 +4691,8 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) else if (ecall->op == TOKvar) { VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration(); - if (vd && vd->getValue()) - ecall = vd->getValue(); + if (vd && vd->getValue()) + ecall = vd->getValue(); else // Calling a function fd = ((VarExp *)e1)->var->isFuncDeclaration(); } @@ -4712,111 +4712,111 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL; if (!tf) - { // DAC: This should never happen, it's an internal compiler error. + { // DAC: This should never happen, it's an internal compiler error. //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall); - if (ecall->op == TOKidentifier) - error("cannot evaluate %s at compile time. Circular reference?", toChars()); - else - error("CTFE internal error: cannot evaluate %s at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - if (!fd) - { + if (ecall->op == TOKidentifier) + error("cannot evaluate %s at compile time. Circular reference?", toChars()); + else + error("CTFE internal error: cannot evaluate %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + if (!fd) + { error("cannot evaluate %s at compile time", toChars()); return EXP_CANT_INTERPRET; } - if (pthis) + if (pthis) { // Member function call - Expression *oldpthis; + Expression *oldpthis; if (pthis->op == TOKthis) - { - pthis = istate ? istate->localThis : NULL; - oldpthis = pthis; - } - else - { - if (pthis->op == TOKcomma) + { + pthis = istate ? istate->localThis : NULL; + oldpthis = pthis; + } + else + { + if (pthis->op == TOKcomma) pthis = pthis->interpret(istate); - if (exceptionOrCantInterpret(pthis)) - return pthis; - // Evaluate 'this' - oldpthis = pthis; - if (pthis->op != TOKvar) - pthis = pthis->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(pthis)) - return pthis; - } - if (fd->isVirtual()) - { // Make a virtual function call. - Expression *thisval = pthis; - if (pthis->op == TOKvar) - { assert(((VarExp*)thisval)->var->isVarDeclaration()); - thisval = ((VarExp*)thisval)->var->isVarDeclaration()->getValue(); - } - // Get the function from the vtable of the original class - ClassDeclaration *cd; - if (thisval && thisval->op == TOKnull) - { - error("function call through null class reference %s", pthis->toChars()); - return EXP_CANT_INTERPRET; - } - if (oldpthis->op == TOKsuper) - { assert(oldpthis->type->ty == Tclass); - cd = ((TypeClass *)oldpthis->type)->sym; - } - else - { - assert(thisval && thisval->op == TOKclassreference); - cd = ((ClassReferenceExp *)thisval)->originalClass(); - } - // We can't just use the vtable index to look it up, because - // vtables for interfaces don't get populated until the glue layer. - fd = cd->findFunc(fd->ident, (TypeFunction *)fd->type); - - assert(fd); - } - } - if (fd && fd->semanticRun >= PASSsemantic3done && fd->semantic3Errors) - { - error("CTFE failed because of previous errors in %s", fd->toChars()); - return EXP_CANT_INTERPRET; - } - // Check for built-in functions - Expression *eresult = evaluateIfBuiltin(istate, loc, fd, arguments, pthis); - if (eresult) - return eresult; - - // Inline .dup. Special case because it needs the return type. - if (!pthis && fd->ident == Id::adDup && arguments && arguments->dim == 2) - { - e = arguments->tdata()[1]; - e = e->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - if (e != EXP_CANT_INTERPRET) - { - if (e->op == TOKslice) - e= resolveSlice(e); - e = paintTypeOntoLiteral(type, copyLiteral(e)); - } - return e; - } - if (!fd->fbody) - { - error("%s cannot be interpreted at compile time," - " because it has no available source code", fd->toChars()); - return EXP_CANT_INTERPRET; - } - eresult = fd->interpret(istate, arguments, pthis); - if (eresult == EXP_CANT_INTERPRET) - { // Print a stack trace. - if (!global.gag) - showCtfeBackTrace(istate, this, fd); + if (exceptionOrCantInterpret(pthis)) + return pthis; + // Evaluate 'this' + oldpthis = pthis; + if (pthis->op != TOKvar) + pthis = pthis->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(pthis)) + return pthis; + } + if (fd->isVirtual()) + { // Make a virtual function call. + Expression *thisval = pthis; + if (pthis->op == TOKvar) + { assert(((VarExp*)thisval)->var->isVarDeclaration()); + thisval = ((VarExp*)thisval)->var->isVarDeclaration()->getValue(); + } + // Get the function from the vtable of the original class + ClassDeclaration *cd; + if (thisval && thisval->op == TOKnull) + { + error("function call through null class reference %s", pthis->toChars()); + return EXP_CANT_INTERPRET; + } + if (oldpthis->op == TOKsuper) + { assert(oldpthis->type->ty == Tclass); + cd = ((TypeClass *)oldpthis->type)->sym; + } + else + { + assert(thisval && thisval->op == TOKclassreference); + cd = ((ClassReferenceExp *)thisval)->originalClass(); + } + // We can't just use the vtable index to look it up, because + // vtables for interfaces don't get populated until the glue layer. + fd = cd->findFunc(fd->ident, (TypeFunction *)fd->type); + + assert(fd); + } } - return eresult; + if (fd && fd->semanticRun >= PASSsemantic3done && fd->semantic3Errors) + { + error("CTFE failed because of previous errors in %s", fd->toChars()); + return EXP_CANT_INTERPRET; + } + // Check for built-in functions + Expression *eresult = evaluateIfBuiltin(istate, loc, fd, arguments, pthis); + if (eresult) + return eresult; + + // Inline .dup. Special case because it needs the return type. + if (!pthis && fd->ident == Id::adDup && arguments && arguments->dim == 2) + { + e = arguments->tdata()[1]; + e = e->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + if (e != EXP_CANT_INTERPRET) + { + if (e->op == TOKslice) + e= resolveSlice(e); + e = paintTypeOntoLiteral(type, copyLiteral(e)); + } + return e; + } + if (!fd->fbody) + { + error("%s cannot be interpreted at compile time," + " because it has no available source code", fd->toChars()); + return EXP_CANT_INTERPRET; + } + eresult = fd->interpret(istate, arguments, pthis); + if (eresult == EXP_CANT_INTERPRET) + { // Print a stack trace. + if (!global.gag) + showCtfeBackTrace(istate, this, fd); + } + return eresult; } -Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) +Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("CommaExp::interpret() %s\n", toChars()); @@ -4830,94 +4830,94 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) // the variable to be created in, we need to create one now. InterState istateComma; if (!istate && firstComma->e1->op == TOKdeclaration) - { - assert(ctfeStack.stackPointer() == 0); - ctfeStack.startFrame(); + { + assert(ctfeStack.stackPointer() == 0); + ctfeStack.startFrame(); istate = &istateComma; - } - - Expression *e = EXP_CANT_INTERPRET; + } + + Expression *e = EXP_CANT_INTERPRET; // If the comma returns a temporary variable, it needs to be an lvalue // (this is particularly important for struct constructors) if (e1->op == TOKdeclaration && e2->op == TOKvar - && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var - && ((VarExp*)e2)->var->storage_class & STCctfe) // same as Expression::isTemp + && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var + && ((VarExp*)e2)->var->storage_class & STCctfe) // same as Expression::isTemp { VarExp* ve = (VarExp *)e2; VarDeclaration *v = ve->var->isVarDeclaration(); - ctfeStack.push(v); - if (!v->init && !v->getValue()) - { - v->setValue(copyLiteral(v->type->defaultInitLiteral())); - } - if (!v->getValue()) { - Expression *newval = v->init->toExpression(); + ctfeStack.push(v); + if (!v->init && !v->getValue()) + { + v->setValue(copyLiteral(v->type->defaultInitLiteral())); + } + if (!v->getValue()) { + Expression *newval = v->init->toExpression(); // Bug 4027. Copy constructors are a weird case where the // initializer is a void function (the variable is modified // through a reference parameter instead). - newval = newval->interpret(istate); - if (exceptionOrCantInterpret(newval)) - { - if (istate == &istateComma) - ctfeStack.endFrame(0); - return newval; - } + newval = newval->interpret(istate); + if (exceptionOrCantInterpret(newval)) + { + if (istate == &istateComma) + ctfeStack.endFrame(0); + return newval; + } if (newval != EXP_VOID_INTERPRET) - { - // v isn't necessarily null. - v->setValueWithoutChecking(copyLiteral(newval)); + { + // v isn't necessarily null. + v->setValueWithoutChecking(copyLiteral(newval)); } - } - if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) - e = e2; - else - e = e2->interpret(istate, goal); - } - else - { - e = e1->interpret(istate, ctfeNeedNothing); - if (!exceptionOrCantInterpret(e)) - e = e2->interpret(istate, goal); - } - // If we created a temporary stack frame, end it now. - if (istate == &istateComma) - ctfeStack.endFrame(0); + } + if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) + e = e2; + else + e = e2->interpret(istate, goal); + } + else + { + e = e1->interpret(istate, ctfeNeedNothing); + if (!exceptionOrCantInterpret(e)) + e = e2->interpret(istate, goal); + } + // If we created a temporary stack frame, end it now. + if (istate == &istateComma) + ctfeStack.endFrame(0); return e; } -Expression *CondExp::interpret(InterState *istate, CtfeGoal goal) +Expression *CondExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("CondExp::interpret() %s\n", toChars()); #endif - Expression *e; - if ( isPointer(econd->type) ) + Expression *e; + if ( isPointer(econd->type) ) { - e = econd->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e)) - return e; - if (e->op != TOKnull) - e = new IntegerExp(loc, 1, Type::tbool); - } - else - e = econd->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - if (isTrueBool(e)) - e = e1->interpret(istate, goal); + e = econd->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e)) + return e; + if (e->op != TOKnull) + e = new IntegerExp(loc, 1, Type::tbool); + } + else + e = econd->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + if (isTrueBool(e)) + e = e1->interpret(istate, goal); else if (e->isBool(FALSE)) - e = e2->interpret(istate, goal); + e = e2->interpret(istate, goal); else - { - error("%s does not evaluate to boolean result at compile time", - econd->toChars()); + { + error("%s does not evaluate to boolean result at compile time", + econd->toChars()); e = EXP_CANT_INTERPRET; } return e; } -Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) +Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e; Expression *e1; @@ -4925,201 +4925,201 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) printf("ArrayLengthExp::interpret() %s\n", toChars()); #endif e1 = this->e1->interpret(istate); - assert(e1); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKslice - || e1->op == TOKassocarrayliteral || e1->op == TOKnull) + assert(e1); + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKslice + || e1->op == TOKassocarrayliteral || e1->op == TOKnull) { - e = new IntegerExp(loc, resolveArrayLength(e1), type); + e = new IntegerExp(loc, resolveArrayLength(e1), type); } - else + else { - error("%s cannot be evaluated at compile time", toChars()); - return EXP_CANT_INTERPRET; + error("%s cannot be evaluated at compile time", toChars()); + return EXP_CANT_INTERPRET; } return e; -} - -/* Given an AA literal 'ae', and a key 'e2': - * Return ae[e2] if present, or NULL if not found. - * Return EXP_CANT_INTERPRET on error. - */ -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) -{ - /* Search the keys backwards, in case there are duplicate keys - */ - for (size_t i = ae->keys->dim; i;) - { - i--; - Expression *ekey = ae->keys->tdata()[i]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); - if (ex == EXP_CANT_INTERPRET) - { - error("cannot evaluate %s==%s at compile time", - ekey->toChars(), e2->toChars()); - return ex; - } - if (ex->isBool(TRUE)) - { - return ae->values->tdata()[i]; - } - } - return NULL; } -/* Same as for constfold.Index, except that it only works for static arrays, - * dynamic arrays, and strings. We know that e1 is an - * interpreted CTFE expression, so it cannot have side-effects. - */ -Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx) -{ //printf("ctfeIndex(e1 = %s)\n", e1->toChars()); - assert(e1->type); - if (e1->op == TOKstring) - { StringExp *es1 = (StringExp *)e1; - if (indx >= es1->len) - { - error(loc, "string index %ju is out of bounds [0 .. %zu]", indx, es1->len); - return EXP_CANT_INTERPRET; - } - else - return new IntegerExp(loc, es1->charAt(indx), type); - } - assert(e1->op == TOKarrayliteral); - ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - if (indx >= ale->elements->dim) - { - error(loc, "array index %ju is out of bounds %s[0 .. %u]", indx, e1->toChars(), ale->elements->dim); - return EXP_CANT_INTERPRET; - } - Expression *e = ale->elements->tdata()[indx]; - return paintTypeOntoLiteral(type, e); -} - -Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) -{ - Expression *e1 = NULL; +/* Given an AA literal 'ae', and a key 'e2': + * Return ae[e2] if present, or NULL if not found. + * Return EXP_CANT_INTERPRET on error. + */ +Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) +{ + /* Search the keys backwards, in case there are duplicate keys + */ + for (size_t i = ae->keys->dim; i;) + { + i--; + Expression *ekey = ae->keys->tdata()[i]; + Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); + if (ex == EXP_CANT_INTERPRET) + { + error("cannot evaluate %s==%s at compile time", + ekey->toChars(), e2->toChars()); + return ex; + } + if (ex->isBool(TRUE)) + { + return ae->values->tdata()[i]; + } + } + return NULL; +} + +/* Same as for constfold.Index, except that it only works for static arrays, + * dynamic arrays, and strings. We know that e1 is an + * interpreted CTFE expression, so it cannot have side-effects. + */ +Expression *ctfeIndex(Loc loc, Type *type, Expression *e1, uinteger_t indx) +{ //printf("ctfeIndex(e1 = %s)\n", e1->toChars()); + assert(e1->type); + if (e1->op == TOKstring) + { StringExp *es1 = (StringExp *)e1; + if (indx >= es1->len) + { + error(loc, "string index %ju is out of bounds [0 .. %zu]", indx, es1->len); + return EXP_CANT_INTERPRET; + } + else + return new IntegerExp(loc, es1->charAt(indx), type); + } + assert(e1->op == TOKarrayliteral); + ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + if (indx >= ale->elements->dim) + { + error(loc, "array index %ju is out of bounds %s[0 .. %u]", indx, e1->toChars(), ale->elements->dim); + return EXP_CANT_INTERPRET; + } + Expression *e = ale->elements->tdata()[indx]; + return paintTypeOntoLiteral(type, e); +} + +Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) +{ + Expression *e1 = NULL; Expression *e2; #if LOG printf("IndexExp::interpret() %s\n", toChars()); #endif - if (this->e1->type->toBasetype()->ty == Tpointer) - { - // Indexing a pointer. Note that there is no $ in this case. - e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; - dinteger_t indx = e2->toInteger(); - dinteger_t ofs; - Expression *agg = getAggregateFromPointer(e1, &ofs); - if (agg->op == TOKnull) - { - error("cannot index null pointer %s", this->e1->toChars()); - return EXP_CANT_INTERPRET; - } - assert(agg->op == TOKarrayliteral || agg->op == TOKstring); - dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; - if ((indx + ofs) < 0 || (indx+ofs) > len) - { - error("pointer index [%jd] exceeds allocated memory block [0..%jd]", - indx+ofs, len); - return EXP_CANT_INTERPRET; - } - return ctfeIndex(loc, type, agg, indx+ofs); - } - e1 = this->e1; - if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe)) - e1 = e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - - if (e1->op == TOKnull) + if (this->e1->type->toBasetype()->ty == Tpointer) { - if (goal == ctfeNeedLvalue && e1->type->ty == Taarray) - return paintTypeOntoLiteral(type, e1); - error("cannot index null array %s", this->e1->toChars()); - return EXP_CANT_INTERPRET; - } - /* Set the $ variable. - * Note that foreach uses indexing but doesn't need $ + // Indexing a pointer. Note that there is no $ in this case. + e1 = this->e1->interpret(istate); + if (exceptionOrCantInterpret(e1)) + return e1; + e2 = this->e2->interpret(istate); + if (exceptionOrCantInterpret(e2)) + return e2; + dinteger_t indx = e2->toInteger(); + dinteger_t ofs; + Expression *agg = getAggregateFromPointer(e1, &ofs); + if (agg->op == TOKnull) + { + error("cannot index null pointer %s", this->e1->toChars()); + return EXP_CANT_INTERPRET; + } + assert(agg->op == TOKarrayliteral || agg->op == TOKstring); + dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); + Type *pointee = ((TypePointer *)agg->type)->next; + if ((indx + ofs) < 0 || (indx+ofs) > len) + { + error("pointer index [%jd] exceeds allocated memory block [0..%jd]", + indx+ofs, len); + return EXP_CANT_INTERPRET; + } + return ctfeIndex(loc, type, agg, indx+ofs); + } + e1 = this->e1; + if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe)) + e1 = e1->interpret(istate); + if (exceptionOrCantInterpret(e1)) + return e1; + + if (e1->op == TOKnull) + { + if (goal == ctfeNeedLvalue && e1->type->ty == Taarray) + return paintTypeOntoLiteral(type, e1); + error("cannot index null array %s", this->e1->toChars()); + return EXP_CANT_INTERPRET; + } + /* Set the $ variable. + * Note that foreach uses indexing but doesn't need $ */ - if (lengthVar && (e1->op == TOKstring || e1->op == TOKarrayliteral - || e1->op == TOKslice)) - { - uinteger_t dollar = resolveArrayLength(e1); - Expression *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); - ctfeStack.push(lengthVar); - lengthVar->setValue(dollarExp); + if (lengthVar && (e1->op == TOKstring || e1->op == TOKarrayliteral + || e1->op == TOKslice)) + { + uinteger_t dollar = resolveArrayLength(e1); + Expression *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); + ctfeStack.push(lengthVar); + lengthVar->setValue(dollarExp); } e2 = this->e2->interpret(istate); - if (lengthVar) - ctfeStack.pop(lengthVar); // $ is defined only inside [] - if (exceptionOrCantInterpret(e2)) - return e2; - if (e1->op == TOKslice && e2->op == TOKint64) - { - // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx'] - uinteger_t indx = e2->toInteger(); - uinteger_t ilo = ((SliceExp *)e1)->lwr->toInteger(); - uinteger_t iup = ((SliceExp *)e1)->upr->toInteger(); - - if (indx > iup - ilo) - { - error("index %ju exceeds array length %ju", indx, iup - ilo); - return EXP_CANT_INTERPRET; - } - indx += ilo; - e1 = ((SliceExp *)e1)->e1; - e2 = new IntegerExp(e2->loc, indx, e2->type); - } - Expression *e = NULL; - if ((goal == ctfeNeedLvalue && type->ty != Taarray && type->ty != Tarray - && type->ty != Tsarray && type->ty != Tstruct && type->ty != Tclass) - || (goal == ctfeNeedLvalueRef && type->ty != Tsarray && type->ty != Tstruct) - ) - { // Pointer or reference of a scalar type - e = new IndexExp(loc, e1, e2); - e->type = type; - return e; - } - if (e1->op == TOKassocarrayliteral) - { - if (e2->op == TOKslice) - e2 = resolveSlice(e2); - e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); - if (!e) - { - error("key %s not found in associative array %s", - e2->toChars(), this->e1->toChars()); - return EXP_CANT_INTERPRET; - } - } - else - { - if (e2->op != TOKint64) - { - e1->error("CTFE internal error: non-integral index [%s]", this->e2->toChars()); - return EXP_CANT_INTERPRET; - } - e = ctfeIndex(loc, type, e1, e2->toInteger()); - } - if (exceptionOrCantInterpret(e)) - return e; - if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) - e = e->interpret(istate); - e = paintTypeOntoLiteral(type, e); - return e; + if (lengthVar) + ctfeStack.pop(lengthVar); // $ is defined only inside [] + if (exceptionOrCantInterpret(e2)) + return e2; + if (e1->op == TOKslice && e2->op == TOKint64) + { + // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx'] + uinteger_t indx = e2->toInteger(); + uinteger_t ilo = ((SliceExp *)e1)->lwr->toInteger(); + uinteger_t iup = ((SliceExp *)e1)->upr->toInteger(); + + if (indx > iup - ilo) + { + error("index %ju exceeds array length %ju", indx, iup - ilo); + return EXP_CANT_INTERPRET; + } + indx += ilo; + e1 = ((SliceExp *)e1)->e1; + e2 = new IntegerExp(e2->loc, indx, e2->type); + } + Expression *e = NULL; + if ((goal == ctfeNeedLvalue && type->ty != Taarray && type->ty != Tarray + && type->ty != Tsarray && type->ty != Tstruct && type->ty != Tclass) + || (goal == ctfeNeedLvalueRef && type->ty != Tsarray && type->ty != Tstruct) + ) + { // Pointer or reference of a scalar type + e = new IndexExp(loc, e1, e2); + e->type = type; + return e; + } + if (e1->op == TOKassocarrayliteral) + { + if (e2->op == TOKslice) + e2 = resolveSlice(e2); + e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); + if (!e) + { + error("key %s not found in associative array %s", + e2->toChars(), this->e1->toChars()); + return EXP_CANT_INTERPRET; + } + } + else + { + if (e2->op != TOKint64) + { + e1->error("CTFE internal error: non-integral index [%s]", this->e2->toChars()); + return EXP_CANT_INTERPRET; + } + e = ctfeIndex(loc, type, e1, e2->toInteger()); + } + if (exceptionOrCantInterpret(e)) + return e; + if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) + e = e->interpret(istate); + e = paintTypeOntoLiteral(type, e); + return e; } -Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) -{ +Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) +{ Expression *e1; Expression *lwr; Expression *upr; @@ -5127,186 +5127,186 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) #if LOG printf("SliceExp::interpret() %s\n", toChars()); #endif - - if (this->e1->type->toBasetype()->ty == Tpointer) - { - // Slicing a pointer. Note that there is no $ in this case. + + if (this->e1->type->toBasetype()->ty == Tpointer) + { + // Slicing a pointer. Note that there is no $ in this case. e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKint64) - { - error("cannot slice invalid pointer %s of value %s", - this->e1->toChars(), e1->toChars()); - return EXP_CANT_INTERPRET; - } - - /* Evaluate lower and upper bounds of slice - */ - lwr = this->lwr->interpret(istate); - if (exceptionOrCantInterpret(lwr)) - return lwr; - upr = this->upr->interpret(istate); - if (exceptionOrCantInterpret(upr)) - return upr; - uinteger_t ilwr; - uinteger_t iupr; - ilwr = lwr->toInteger(); - iupr = upr->toInteger(); - Expression *e; - dinteger_t ofs; - Expression *agg = getAggregateFromPointer(e1, &ofs); - if (agg->op == TOKnull) - { - if (iupr == ilwr) - { - e = new NullExp(loc); - e->type = type; - return e; - } - error("cannot slice null pointer %s", this->e1->toChars()); - return EXP_CANT_INTERPRET; - } - assert(agg->op == TOKarrayliteral || agg->op == TOKstring); - dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; - if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) - { - error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", - ilwr+ofs, iupr+ofs, len); - return EXP_CANT_INTERPRET; - } - e = new SliceExp(loc, agg, lwr, upr); - e->type = type; - return e; - } - if (goal == ctfeNeedRvalue && this->e1->op == TOKstring) - e1 = this->e1; // Will get duplicated anyway - else - e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKvar) - e1 = e1->interpret(istate); - + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKint64) + { + error("cannot slice invalid pointer %s of value %s", + this->e1->toChars(), e1->toChars()); + return EXP_CANT_INTERPRET; + } + + /* Evaluate lower and upper bounds of slice + */ + lwr = this->lwr->interpret(istate); + if (exceptionOrCantInterpret(lwr)) + return lwr; + upr = this->upr->interpret(istate); + if (exceptionOrCantInterpret(upr)) + return upr; + uinteger_t ilwr; + uinteger_t iupr; + ilwr = lwr->toInteger(); + iupr = upr->toInteger(); + Expression *e; + dinteger_t ofs; + Expression *agg = getAggregateFromPointer(e1, &ofs); + if (agg->op == TOKnull) + { + if (iupr == ilwr) + { + e = new NullExp(loc); + e->type = type; + return e; + } + error("cannot slice null pointer %s", this->e1->toChars()); + return EXP_CANT_INTERPRET; + } + assert(agg->op == TOKarrayliteral || agg->op == TOKstring); + dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); + Type *pointee = ((TypePointer *)agg->type)->next; + if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) + { + error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", + ilwr+ofs, iupr+ofs, len); + return EXP_CANT_INTERPRET; + } + e = new SliceExp(loc, agg, lwr, upr); + e->type = type; + return e; + } + if (goal == ctfeNeedRvalue && this->e1->op == TOKstring) + e1 = this->e1; // Will get duplicated anyway + else + e1 = this->e1->interpret(istate); + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKvar) + e1 = e1->interpret(istate); + if (!this->lwr) { - if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) - return e1; - return paintTypeOntoLiteral(type, e1); + if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) + return e1; + return paintTypeOntoLiteral(type, e1); } /* Set the $ variable */ - if (e1->op != TOKarrayliteral && e1->op != TOKstring && - e1->op != TOKnull && e1->op != TOKslice) - { - error("Cannot determine length of %s at compile time", e1->toChars()); - return EXP_CANT_INTERPRET; - } - uinteger_t dollar = resolveArrayLength(e1); + if (e1->op != TOKarrayliteral && e1->op != TOKstring && + e1->op != TOKnull && e1->op != TOKslice) + { + error("Cannot determine length of %s at compile time", e1->toChars()); + return EXP_CANT_INTERPRET; + } + uinteger_t dollar = resolveArrayLength(e1); if (lengthVar) - { - IntegerExp *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); - ctfeStack.push(lengthVar); - lengthVar->setValue(dollarExp); - } + { + IntegerExp *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t); + ctfeStack.push(lengthVar); + lengthVar->setValue(dollarExp); + } /* Evaluate lower and upper bounds of slice */ lwr = this->lwr->interpret(istate); - if (exceptionOrCantInterpret(lwr)) - { - if (lengthVar) - ctfeStack.pop(lengthVar);; // $ is defined only inside [L..U] - return lwr; - } + if (exceptionOrCantInterpret(lwr)) + { + if (lengthVar) + ctfeStack.pop(lengthVar);; // $ is defined only inside [L..U] + return lwr; + } upr = this->upr->interpret(istate); - if (lengthVar) - ctfeStack.pop(lengthVar); // $ is defined only inside [L..U] - if (exceptionOrCantInterpret(upr)) - return upr; + if (lengthVar) + ctfeStack.pop(lengthVar); // $ is defined only inside [L..U] + if (exceptionOrCantInterpret(upr)) + return upr; - Expression *e; - uinteger_t ilwr; - uinteger_t iupr; - ilwr = lwr->toInteger(); - iupr = upr->toInteger(); - if (e1->op == TOKnull) - { - if (ilwr== 0 && iupr == 0) - return e1; - e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); - return EXP_CANT_INTERPRET; - } - if (e1->op == TOKslice) - { - SliceExp *se = (SliceExp *)e1; - // Simplify slice of slice: - // aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr'] - uinteger_t lo1 = se->lwr->toInteger(); - uinteger_t up1 = se->upr->toInteger(); - if (ilwr > iupr || iupr > up1 - lo1) - { - error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", - ilwr, iupr, lo1, up1); - return EXP_CANT_INTERPRET; - } - ilwr += lo1; - iupr += lo1; - e = new SliceExp(loc, se->e1, - new IntegerExp(loc, ilwr, lwr->type), - new IntegerExp(loc, iupr, upr->type)); - e->type = type; + Expression *e; + uinteger_t ilwr; + uinteger_t iupr; + ilwr = lwr->toInteger(); + iupr = upr->toInteger(); + if (e1->op == TOKnull) + { + if (ilwr== 0 && iupr == 0) + return e1; + e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); + return EXP_CANT_INTERPRET; + } + if (e1->op == TOKslice) + { + SliceExp *se = (SliceExp *)e1; + // Simplify slice of slice: + // aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr'] + uinteger_t lo1 = se->lwr->toInteger(); + uinteger_t up1 = se->upr->toInteger(); + if (ilwr > iupr || iupr > up1 - lo1) + { + error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", + ilwr, iupr, lo1, up1); + return EXP_CANT_INTERPRET; + } + ilwr += lo1; + iupr += lo1; + e = new SliceExp(loc, se->e1, + new IntegerExp(loc, ilwr, lwr->type), + new IntegerExp(loc, iupr, upr->type)); + e->type = type; return e; - } - if (e1->op == TOKarrayliteral - || e1->op == TOKstring) - { - if (iupr < ilwr || ilwr < 0 || iupr > dollar) - { - error("slice [%jd..%jd] exceeds array bounds [0..%jd]", - ilwr, iupr, dollar); + } + if (e1->op == TOKarrayliteral + || e1->op == TOKstring) + { + if (iupr < ilwr || ilwr < 0 || iupr > dollar) + { + error("slice [%jd..%jd] exceeds array bounds [0..%jd]", + ilwr, iupr, dollar); return EXP_CANT_INTERPRET; - } - } - e = new SliceExp(loc, e1, lwr, upr); - e->type = type; - return e; + } + } + e = new SliceExp(loc, e1, lwr, upr); + e->type = type; + return e; } -Expression *InExp::interpret(InterState *istate, CtfeGoal goal) -{ Expression *e = EXP_CANT_INTERPRET; - -#if LOG - printf("InExp::interpret() %s\n", toChars()); -#endif - Expression *e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - Expression *e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; - if (e2->op == TOKnull) - return new NullExp(loc, type); - if (e2->op != TOKassocarrayliteral) - { - error(" %s cannot be interpreted at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - if (e1->op == TOKslice) - e1 = resolveSlice(e1); - e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); - if (exceptionOrCantInterpret(e)) - return e; - if (!e) - return new NullExp(loc, type); - e = new IndexExp(loc, e2, e1); - e->type = type; - return e; -} +Expression *InExp::interpret(InterState *istate, CtfeGoal goal) +{ Expression *e = EXP_CANT_INTERPRET; -Expression *CatExp::interpret(InterState *istate, CtfeGoal goal) +#if LOG + printf("InExp::interpret() %s\n", toChars()); +#endif + Expression *e1 = this->e1->interpret(istate); + if (exceptionOrCantInterpret(e1)) + return e1; + Expression *e2 = this->e2->interpret(istate); + if (exceptionOrCantInterpret(e2)) + return e2; + if (e2->op == TOKnull) + return new NullExp(loc, type); + if (e2->op != TOKassocarrayliteral) + { + error(" %s cannot be interpreted at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + if (e1->op == TOKslice) + e1 = resolveSlice(e1); + e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); + if (exceptionOrCantInterpret(e)) + return e; + if (!e) + return new NullExp(loc, type); + e = new IndexExp(loc, e2, e1); + e->type = type; + return e; +} + +Expression *CatExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e; Expression *e1; Expression *e2; @@ -5315,256 +5315,256 @@ Expression *CatExp::interpret(InterState *istate, CtfeGoal goal) printf("CatExp::interpret() %s\n", toChars()); #endif e1 = this->e1->interpret(istate); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op == TOKslice) + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op == TOKslice) { - e1 = resolveSlice(e1); + e1 = resolveSlice(e1); } e2 = this->e2->interpret(istate); - if (exceptionOrCantInterpret(e2)) - return e2; - if (e2->op == TOKslice) - e2 = resolveSlice(e2); - e = ctfeCat(type, e1, e2); + if (exceptionOrCantInterpret(e2)) + return e2; + if (e2->op == TOKslice) + e2 = resolveSlice(e2); + e = ctfeCat(type, e1, e2); if (e == EXP_CANT_INTERPRET) error("%s cannot be interpreted at compile time", toChars()); - // We know we still own it, because we interpreted both e1 and e2 - if (e->op == TOKarrayliteral) - ((ArrayLiteralExp *)e)->ownedByCtfe = true; - if (e->op == TOKstring) - ((StringExp *)e)->ownedByCtfe = true; + // We know we still own it, because we interpreted both e1 and e2 + if (e->op == TOKarrayliteral) + ((ArrayLiteralExp *)e)->ownedByCtfe = true; + if (e->op == TOKstring) + ((StringExp *)e)->ownedByCtfe = true; return e; -} - - -// Return true if t is a pointer (not a function pointer) -bool isPointer(Type *t) -{ - Type * tb = t->toBasetype(); - return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction; -} - -// Return true if t is an AA, or AssociativeArray!(key, value) -bool isAssocArray(Type *t) -{ - t = t->toBasetype(); - if (t->ty == Taarray) - return true; -#if DMDV2 - if (t->ty != Tstruct) - return false; - StructDeclaration *sym = ((TypeStruct *)t)->sym; - if (sym->ident == Id::AssociativeArray) - return true; -#endif - return false; } -// Given a template AA type, extract the corresponding built-in AA type -TypeAArray *toBuiltinAAType(Type *t) -{ - t = t->toBasetype(); - if (t->ty == Taarray) - return (TypeAArray *)t; -#if DMDV2 - assert(t->ty == Tstruct); - StructDeclaration *sym = ((TypeStruct *)t)->sym; - assert(sym->ident == Id::AssociativeArray); - TemplateInstance *tinst = sym->parent->isTemplateInstance(); - assert(tinst); - return new TypeAArray((Type *)(tinst->tiargs->tdata()[1]), (Type *)(tinst->tiargs->tdata()[0])); -#else - assert(0); - return NULL; -#endif -} -Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) +// Return true if t is a pointer (not a function pointer) +bool isPointer(Type *t) +{ + Type * tb = t->toBasetype(); + return tb->ty == Tpointer && tb->nextOf()->ty != Tfunction; +} + +// Return true if t is an AA, or AssociativeArray!(key, value) +bool isAssocArray(Type *t) +{ + t = t->toBasetype(); + if (t->ty == Taarray) + return true; +#if DMDV2 + if (t->ty != Tstruct) + return false; + StructDeclaration *sym = ((TypeStruct *)t)->sym; + if (sym->ident == Id::AssociativeArray) + return true; +#endif + return false; +} + +// Given a template AA type, extract the corresponding built-in AA type +TypeAArray *toBuiltinAAType(Type *t) +{ + t = t->toBasetype(); + if (t->ty == Taarray) + return (TypeAArray *)t; +#if DMDV2 + assert(t->ty == Tstruct); + StructDeclaration *sym = ((TypeStruct *)t)->sym; + assert(sym->ident == Id::AssociativeArray); + TemplateInstance *tinst = sym->parent->isTemplateInstance(); + assert(tinst); + return new TypeAArray((Type *)(tinst->tiargs->tdata()[1]), (Type *)(tinst->tiargs->tdata()[0])); +#else + assert(0); + return NULL; +#endif +} + +Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e; Expression *e1; #if LOG printf("CastExp::interpret() %s\n", toChars()); #endif - e1 = this->e1->interpret(istate, goal); - if (exceptionOrCantInterpret(e1)) - return e1; - // If the expression has been cast to void, do nothing. - if (to->ty == Tvoid && goal == ctfeNeedNothing) - return e1; - if (to->ty == Tpointer && e1->op != TOKnull) - { - Type *pointee = ((TypePointer *)type)->next; - // Implement special cases of normally-unsafe casts -#if DMDV2 - if (pointee->ty == Taarray && e1->op == TOKaddress - && isAssocArray(((AddrExp*)e1)->e1->type)) - { // cast from template AA pointer to true AA pointer is OK. - return paintTypeOntoLiteral(to, e1); - } + e1 = this->e1->interpret(istate, goal); + if (exceptionOrCantInterpret(e1)) + return e1; + // If the expression has been cast to void, do nothing. + if (to->ty == Tvoid && goal == ctfeNeedNothing) + return e1; + if (to->ty == Tpointer && e1->op != TOKnull) + { + Type *pointee = ((TypePointer *)type)->next; + // Implement special cases of normally-unsafe casts +#if DMDV2 + if (pointee->ty == Taarray && e1->op == TOKaddress + && isAssocArray(((AddrExp*)e1)->e1->type)) + { // cast from template AA pointer to true AA pointer is OK. + return paintTypeOntoLiteral(to, e1); + } #endif - if (e1->op == TOKint64) - { // Happens with Windows HANDLEs, for example. - return paintTypeOntoLiteral(to, e1); - } - bool castBackFromVoid = false; - if (e1->type->ty == Tarray || e1->type->ty == Tsarray || e1->type->ty == Tpointer) - { - // Check for unsupported type painting operations - // For slices, we need the type being sliced, - // since it may have already been type painted - Type *elemtype = e1->type->nextOf(); - if (e1->op == TOKslice) - elemtype = ((SliceExp *)e1)->e1->type->nextOf(); - // Allow casts from X* to void *, and X** to void** for any X. - // But don't allow cast from X* to void**. - // So, we strip all matching * from source and target to find X. - // Allow casts to X* from void* only if the 'void' was originally an X; - // we check this later on. - Type *ultimatePointee = pointee; - Type *ultimateSrc = elemtype; - while (ultimatePointee->ty == Tpointer && ultimateSrc->ty == Tpointer) - { - ultimatePointee = ultimatePointee->nextOf(); - ultimateSrc = ultimateSrc->nextOf(); - } - if (ultimatePointee->ty != Tvoid && ultimateSrc->ty != Tvoid - && !isSafePointerCast(elemtype, pointee)) - { - error("reinterpreting cast from %s* to %s* is not supported in CTFE", - elemtype->toChars(), pointee->toChars()); + if (e1->op == TOKint64) + { // Happens with Windows HANDLEs, for example. + return paintTypeOntoLiteral(to, e1); + } + bool castBackFromVoid = false; + if (e1->type->ty == Tarray || e1->type->ty == Tsarray || e1->type->ty == Tpointer) + { + // Check for unsupported type painting operations + // For slices, we need the type being sliced, + // since it may have already been type painted + Type *elemtype = e1->type->nextOf(); + if (e1->op == TOKslice) + elemtype = ((SliceExp *)e1)->e1->type->nextOf(); + // Allow casts from X* to void *, and X** to void** for any X. + // But don't allow cast from X* to void**. + // So, we strip all matching * from source and target to find X. + // Allow casts to X* from void* only if the 'void' was originally an X; + // we check this later on. + Type *ultimatePointee = pointee; + Type *ultimateSrc = elemtype; + while (ultimatePointee->ty == Tpointer && ultimateSrc->ty == Tpointer) + { + ultimatePointee = ultimatePointee->nextOf(); + ultimateSrc = ultimateSrc->nextOf(); + } + if (ultimatePointee->ty != Tvoid && ultimateSrc->ty != Tvoid + && !isSafePointerCast(elemtype, pointee)) + { + error("reinterpreting cast from %s* to %s* is not supported in CTFE", + elemtype->toChars(), pointee->toChars()); return EXP_CANT_INTERPRET; - } - if (ultimateSrc->ty == Tvoid) - castBackFromVoid = true; - } - - if (e1->op == TOKslice) - { - if ( ((SliceExp *)e1)->e1->op == TOKnull) - { - return paintTypeOntoLiteral(type, ((SliceExp *)e1)->e1); - } - e = new IndexExp(loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr); - e->type = type; - return e; - } - if (e1->op == TOKarrayliteral || e1->op == TOKstring) - { - e = new IndexExp(loc, e1, new IntegerExp(loc, 0, Type::tsize_t)); - e->type = type; - return e; - } - if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type != e1->type) - { // type painting operation - IndexExp *ie = (IndexExp *)e1; - e = new IndexExp(e1->loc, ie->e1, ie->e2); - if (castBackFromVoid) - { - // get the original type. For strings, it's just the type... - Type *origType = ie->e1->type->nextOf(); - // ..but for arrays of type void*, it's the type of the element - Expression *xx = NULL; - if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64) - { ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1; - uinteger_t indx = ie->e2->toInteger(); - if (indx < ale->elements->dim) - xx = ale->elements->tdata()[indx]; - } - if (xx && xx->op == TOKindex) - origType = ((IndexExp *)xx)->e1->type->nextOf(); - else if (xx && xx->op == TOKaddress) - origType= ((AddrExp *)xx)->e1->type; - else if (xx && xx->op == TOKvar) - origType = ((VarExp *)xx)->var->type; - if (!isSafePointerCast(origType, pointee)) - { - error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", - origType->toChars(), pointee->toChars()); - return EXP_CANT_INTERPRET; - } - } - e->type = type; - return e; - } - if (e1->op == TOKaddress) - { - Type *origType = ((AddrExp *)e1)->type; - if (isSafePointerCast(origType, pointee)) - { - e = new AddrExp(loc, ((AddrExp *)e1)->e1); - e->type = type; - return e; - } - } - if (e1->op == TOKvar) - { // type painting operation - Type *origType = ((VarExp *)e1)->var->type; - if (castBackFromVoid && !isSafePointerCast(origType, pointee)) - { - error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", - origType->toChars(), pointee->toChars()); - return EXP_CANT_INTERPRET; - } - e = new VarExp(loc, ((VarExp *)e1)->var); - e->type = type; - return e; - } - error("pointer cast from %s to %s is not supported at compile time", - e1->type->toChars(), to->toChars()); - return EXP_CANT_INTERPRET; - } - if (to->ty == Tarray && e1->op == TOKslice) - { - e1 = new SliceExp(e1->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr, - ((SliceExp *)e1)->upr); - e1->type = to; - return e1; - } - // Disallow array type painting, except for conversions between built-in - // types of identical size. - if ((to->ty == Tsarray || to->ty == Tarray) && - (e1->type->ty == Tsarray || e1->type->ty == Tarray) && - !isSafePointerCast(e1->type->nextOf(), to->nextOf()) ) - { - error("array cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars()); - return EXP_CANT_INTERPRET; - } - if (to->ty == Tsarray && e1->op == TOKslice) - e1 = resolveSlice(e1); - if (to->toBasetype()->ty == Tbool && e1->type->ty==Tpointer) - { - return new IntegerExp(loc, e1->op != TOKnull, to); - } - return ctfeCast(loc, type, to, e1); -} - -Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) -{ Expression *e; - Expression *e1; + } + if (ultimateSrc->ty == Tvoid) + castBackFromVoid = true; + } + + if (e1->op == TOKslice) + { + if ( ((SliceExp *)e1)->e1->op == TOKnull) + { + return paintTypeOntoLiteral(type, ((SliceExp *)e1)->e1); + } + e = new IndexExp(loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr); + e->type = type; + return e; + } + if (e1->op == TOKarrayliteral || e1->op == TOKstring) + { + e = new IndexExp(loc, e1, new IntegerExp(loc, 0, Type::tsize_t)); + e->type = type; + return e; + } + if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type != e1->type) + { // type painting operation + IndexExp *ie = (IndexExp *)e1; + e = new IndexExp(e1->loc, ie->e1, ie->e2); + if (castBackFromVoid) + { + // get the original type. For strings, it's just the type... + Type *origType = ie->e1->type->nextOf(); + // ..but for arrays of type void*, it's the type of the element + Expression *xx = NULL; + if (ie->e1->op == TOKarrayliteral && ie->e2->op == TOKint64) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)ie->e1; + uinteger_t indx = ie->e2->toInteger(); + if (indx < ale->elements->dim) + xx = ale->elements->tdata()[indx]; + } + if (xx && xx->op == TOKindex) + origType = ((IndexExp *)xx)->e1->type->nextOf(); + else if (xx && xx->op == TOKaddress) + origType= ((AddrExp *)xx)->e1->type; + else if (xx && xx->op == TOKvar) + origType = ((VarExp *)xx)->var->type; + if (!isSafePointerCast(origType, pointee)) + { + error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", + origType->toChars(), pointee->toChars()); + return EXP_CANT_INTERPRET; + } + } + e->type = type; + return e; + } + if (e1->op == TOKaddress) + { + Type *origType = ((AddrExp *)e1)->type; + if (isSafePointerCast(origType, pointee)) + { + e = new AddrExp(loc, ((AddrExp *)e1)->e1); + e->type = type; + return e; + } + } + if (e1->op == TOKvar) + { // type painting operation + Type *origType = ((VarExp *)e1)->var->type; + if (castBackFromVoid && !isSafePointerCast(origType, pointee)) + { + error("using void* to reinterpret cast from %s* to %s* is not supported in CTFE", + origType->toChars(), pointee->toChars()); + return EXP_CANT_INTERPRET; + } + e = new VarExp(loc, ((VarExp *)e1)->var); + e->type = type; + return e; + } + error("pointer cast from %s to %s is not supported at compile time", + e1->type->toChars(), to->toChars()); + return EXP_CANT_INTERPRET; + } + if (to->ty == Tarray && e1->op == TOKslice) + { + e1 = new SliceExp(e1->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr, + ((SliceExp *)e1)->upr); + e1->type = to; + return e1; + } + // Disallow array type painting, except for conversions between built-in + // types of identical size. + if ((to->ty == Tsarray || to->ty == Tarray) && + (e1->type->ty == Tsarray || e1->type->ty == Tarray) && + !isSafePointerCast(e1->type->nextOf(), to->nextOf()) ) + { + error("array cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars()); + return EXP_CANT_INTERPRET; + } + if (to->ty == Tsarray && e1->op == TOKslice) + e1 = resolveSlice(e1); + if (to->toBasetype()->ty == Tbool && e1->type->ty==Tpointer) + { + return new IntegerExp(loc, e1->op != TOKnull, to); + } + return ctfeCast(loc, type, to, e1); +} + +Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) +{ Expression *e; + Expression *e1; #if LOG printf("AssertExp::interpret() %s\n", toChars()); #endif -#if DMDV2 - e1 = this->e1->interpret(istate); -#else - // Deal with pointers (including compiler-inserted assert(&this, "null this")) - if ( isPointer(this->e1->type) ) - { - e1 = this->e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e1)) - return e1; - if (e1->op != TOKnull) - return new IntegerExp(loc, 1, Type::tbool); - } - else - e1 = this->e1->interpret(istate); -#endif - if (exceptionOrCantInterpret(e1)) - return e1; - if (isTrueBool(e1)) +#if DMDV2 + e1 = this->e1->interpret(istate); +#else + // Deal with pointers (including compiler-inserted assert(&this, "null this")) + if ( isPointer(this->e1->type) ) + { + e1 = this->e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e1)) + return e1; + if (e1->op != TOKnull) + return new IntegerExp(loc, 1, Type::tbool); + } + else + e1 = this->e1->interpret(istate); +#endif + if (exceptionOrCantInterpret(e1)) + return e1; + if (isTrueBool(e1)) { } else if (e1->isBool(FALSE)) @@ -5572,8 +5572,8 @@ Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) if (msg) { e = msg->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; + if (exceptionOrCantInterpret(e)) + return e; error("%s", e->toChars()); } else @@ -5581,17 +5581,17 @@ Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal) goto Lcant; } else - { - error("%s is not a compile-time boolean expression", e1->toChars()); + { + error("%s is not a compile-time boolean expression", e1->toChars()); goto Lcant; - } + } return e1; Lcant: return EXP_CANT_INTERPRET; } -Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) +Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e = EXP_CANT_INTERPRET; #if LOG @@ -5604,11 +5604,11 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) { AddrExp *ade = (AddrExp *)ae->e1; Expression *ex = ade->e1; ex = ex->interpret(istate); - if (exceptionOrCantInterpret(ex)) - return ex; + if (exceptionOrCantInterpret(ex)) + return ex; if (ex->op == TOKstructliteral) { StructLiteralExp *se = (StructLiteralExp *)ex; - dinteger_t offset = ae->e2->toInteger(); + dinteger_t offset = ae->e2->toInteger(); e = se->getField(type, offset); if (!e) e = EXP_CANT_INTERPRET; @@ -5626,94 +5626,94 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) } #endif else - { // It's possible we have an array bounds error. We need to make sure it - // errors with this line number, not the one where the pointer was set. - e = e1->interpret(istate, ctfeNeedLvalue); - if (exceptionOrCantInterpret(e)) - return e; - if (!(e->op == TOKvar || e->op == TOKdotvar || e->op == TOKindex - || e->op == TOKslice || e->op == TOKaddress)) - { - error("dereference of invalid pointer '%s'", e->toChars()); - return EXP_CANT_INTERPRET; - } - if (goal != ctfeNeedLvalue) - { - if (e->op == TOKindex && e->type->ty == Tpointer) - { - IndexExp *ie = (IndexExp *)e; - // Is this a real index to an array of pointers, or just a CTFE pointer? - // If the index has the same levels of indirection, it's an index - int srcLevels = 0; - int destLevels = 0; - for(Type *xx = ie->e1->type; xx->ty == Tpointer; xx = xx->nextOf()) - ++srcLevels; - for(Type *xx = e->type->nextOf(); xx->ty == Tpointer; xx = xx->nextOf()) - ++destLevels; - bool isGenuineIndex = (srcLevels == destLevels); - - if ((ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) - && ie->e2->op == TOKint64) - { - Expression *dollar = ArrayLength(Type::tsize_t, ie->e1); - dinteger_t len = dollar->toInteger(); - dinteger_t indx = ie->e2->toInteger(); - assert(indx >=0 && indx <= len); // invalid pointer - if (indx == len) - { - error("dereference of pointer %s one past end of memory block limits [0..%jd]", - toChars(), len); - return EXP_CANT_INTERPRET; - } - e = ctfeIndex(loc, type, ie->e1, indx); - if (isGenuineIndex) - { - if (e->op == TOKindex) - e = e->interpret(istate, goal); - else if (e->op == TOKaddress) - e = paintTypeOntoLiteral(type, ((AddrExp *)e)->e1); - } - return e; - } - if (ie->e1->op == TOKassocarrayliteral) - { - e = Index(type, ie->e1, ie->e2); - if (isGenuineIndex) - { - if (e->op == TOKindex) - e = e->interpret(istate, goal); - else if (e->op == TOKaddress) - e = paintTypeOntoLiteral(type, ((AddrExp *)e)->e1); - } - return e; - } - } - if (e->op == TOKstructliteral) - return e; - e = e1->interpret(istate, goal); - if (e->op == TOKaddress) - { - e = ((AddrExp*)e)->e1; - if (e->op == TOKdotvar || e->op == TOKindex) - e = e->interpret(istate, goal); - } - else if (e->op == TOKvar) - { - e = e->interpret(istate, goal); - } - if (exceptionOrCantInterpret(e)) - return e; - } - else if (e->op == TOKaddress) - e = ((AddrExp*)e)->e1; // *(&x) ==> x - if (e->op == TOKnull) - { - error("dereference of null pointer '%s'", e1->toChars()); - return EXP_CANT_INTERPRET; - } - e->type = type; - } - + { // It's possible we have an array bounds error. We need to make sure it + // errors with this line number, not the one where the pointer was set. + e = e1->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e)) + return e; + if (!(e->op == TOKvar || e->op == TOKdotvar || e->op == TOKindex + || e->op == TOKslice || e->op == TOKaddress)) + { + error("dereference of invalid pointer '%s'", e->toChars()); + return EXP_CANT_INTERPRET; + } + if (goal != ctfeNeedLvalue) + { + if (e->op == TOKindex && e->type->ty == Tpointer) + { + IndexExp *ie = (IndexExp *)e; + // Is this a real index to an array of pointers, or just a CTFE pointer? + // If the index has the same levels of indirection, it's an index + int srcLevels = 0; + int destLevels = 0; + for(Type *xx = ie->e1->type; xx->ty == Tpointer; xx = xx->nextOf()) + ++srcLevels; + for(Type *xx = e->type->nextOf(); xx->ty == Tpointer; xx = xx->nextOf()) + ++destLevels; + bool isGenuineIndex = (srcLevels == destLevels); + + if ((ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) + && ie->e2->op == TOKint64) + { + Expression *dollar = ArrayLength(Type::tsize_t, ie->e1); + dinteger_t len = dollar->toInteger(); + dinteger_t indx = ie->e2->toInteger(); + assert(indx >=0 && indx <= len); // invalid pointer + if (indx == len) + { + error("dereference of pointer %s one past end of memory block limits [0..%jd]", + toChars(), len); + return EXP_CANT_INTERPRET; + } + e = ctfeIndex(loc, type, ie->e1, indx); + if (isGenuineIndex) + { + if (e->op == TOKindex) + e = e->interpret(istate, goal); + else if (e->op == TOKaddress) + e = paintTypeOntoLiteral(type, ((AddrExp *)e)->e1); + } + return e; + } + if (ie->e1->op == TOKassocarrayliteral) + { + e = Index(type, ie->e1, ie->e2); + if (isGenuineIndex) + { + if (e->op == TOKindex) + e = e->interpret(istate, goal); + else if (e->op == TOKaddress) + e = paintTypeOntoLiteral(type, ((AddrExp *)e)->e1); + } + return e; + } + } + if (e->op == TOKstructliteral) + return e; + e = e1->interpret(istate, goal); + if (e->op == TOKaddress) + { + e = ((AddrExp*)e)->e1; + if (e->op == TOKdotvar || e->op == TOKindex) + e = e->interpret(istate, goal); + } + else if (e->op == TOKvar) + { + e = e->interpret(istate, goal); + } + if (exceptionOrCantInterpret(e)) + return e; + } + else if (e->op == TOKaddress) + e = ((AddrExp*)e)->e1; // *(&x) ==> x + if (e->op == TOKnull) + { + error("dereference of null pointer '%s'", e1->toChars()); + return EXP_CANT_INTERPRET; + } + e->type = type; + } + #if LOG if (e == EXP_CANT_INTERPRET) printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); @@ -5721,7 +5721,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) return e; } -Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) +Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e = EXP_CANT_INTERPRET; #if LOG @@ -5729,84 +5729,84 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) #endif Expression *ex = e1->interpret(istate); - if (exceptionOrCantInterpret(ex)) - return ex; + if (exceptionOrCantInterpret(ex)) + return ex; if (ex != EXP_CANT_INTERPRET) { - #if DMDV2 - // Special case for template AAs: AA.var returns the AA itself. - // ie AA.p ----> AA. This is a hack, to get around the - // corresponding hack in the AA druntime implementation. - if (isAssocArray(ex->type)) - return ex; - #endif - if (ex->op == TOKaddress) - ex = ((AddrExp *)ex)->e1; + #if DMDV2 + // Special case for template AAs: AA.var returns the AA itself. + // ie AA.p ----> AA. This is a hack, to get around the + // corresponding hack in the AA druntime implementation. + if (isAssocArray(ex->type)) + return ex; + #endif + if (ex->op == TOKaddress) + ex = ((AddrExp *)ex)->e1; VarDeclaration *v = var->isVarDeclaration(); - if (!v) - error("CTFE internal error: %s", toChars()); - if (ex->op == TOKnull && ex->type->toBasetype()->ty == Tclass) - { error("class '%s' is null and cannot be dereferenced", e1->toChars()); - return EXP_CANT_INTERPRET; - } - if (ex->op == TOKstructliteral || ex->op == TOKclassreference) - { - StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex; - // We can't use getField, because it makes a copy - int i = -1; - if (ex->op == TOKclassreference) - i = ((ClassReferenceExp *)ex)->findFieldIndexByName(v); - else - i = findFieldIndexByName(se->sd, v); - if (i == -1) - { - error("couldn't find field %s of type %s in %s", v->toChars(), type->toChars(), se->toChars()); - return EXP_CANT_INTERPRET; - } - e = se->elements->tdata()[i]; - if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) - { - // If it is an lvalue literal, return it... - if (e->op == TOKstructliteral) - return e; - if ((type->ty == Tsarray || goal == ctfeNeedLvalue) && ( - e->op == TOKarrayliteral || - e->op == TOKassocarrayliteral || e->op == TOKstring || - e->op == TOKclassreference || e->op == TOKslice)) - return e; - /* Element is an allocated pointer, which was created in - * CastExp. - */ - if (goal == ctfeNeedLvalue && e->op == TOKindex && - e->type == type && - isPointer(type) ) - return e; - // ...Otherwise, just return the (simplified) dotvar expression - e = new DotVarExp(loc, ex, v); - e->type = type; - return e; - } + if (!v) + error("CTFE internal error: %s", toChars()); + if (ex->op == TOKnull && ex->type->toBasetype()->ty == Tclass) + { error("class '%s' is null and cannot be dereferenced", e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (ex->op == TOKstructliteral || ex->op == TOKclassreference) + { + StructLiteralExp *se = ex->op == TOKclassreference ? ((ClassReferenceExp *)ex)->value : (StructLiteralExp *)ex; + // We can't use getField, because it makes a copy + int i = -1; + if (ex->op == TOKclassreference) + i = ((ClassReferenceExp *)ex)->findFieldIndexByName(v); + else + i = findFieldIndexByName(se->sd, v); + if (i == -1) + { + error("couldn't find field %s of type %s in %s", v->toChars(), type->toChars(), se->toChars()); + return EXP_CANT_INTERPRET; + } + e = se->elements->tdata()[i]; + if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef) + { + // If it is an lvalue literal, return it... + if (e->op == TOKstructliteral) + return e; + if ((type->ty == Tsarray || goal == ctfeNeedLvalue) && ( + e->op == TOKarrayliteral || + e->op == TOKassocarrayliteral || e->op == TOKstring || + e->op == TOKclassreference || e->op == TOKslice)) + return e; + /* Element is an allocated pointer, which was created in + * CastExp. + */ + if (goal == ctfeNeedLvalue && e->op == TOKindex && + e->type == type && + isPointer(type) ) + return e; + // ...Otherwise, just return the (simplified) dotvar expression + e = new DotVarExp(loc, ex, v); + e->type = type; + return e; + } if (!e) { error("couldn't find field %s in %s", v->toChars(), type->toChars()); e = EXP_CANT_INTERPRET; } - // If it is an rvalue literal, return it... - if (e->op == TOKstructliteral || e->op == TOKarrayliteral || - e->op == TOKassocarrayliteral || e->op == TOKstring) - return e; - if ( isPointer(type) ) - { - return paintTypeOntoLiteral(type, e); - } - if (e->op == TOKvar) - { // Don't typepaint twice, since that might cause an erroneous copy - e = getVarExp(loc, istate, ((VarExp *)e)->var, goal); - if (e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) - e = paintTypeOntoLiteral(type, e); + // If it is an rvalue literal, return it... + if (e->op == TOKstructliteral || e->op == TOKarrayliteral || + e->op == TOKassocarrayliteral || e->op == TOKstring) + return e; + if ( isPointer(type) ) + { + return paintTypeOntoLiteral(type, e); + } + if (e->op == TOKvar) + { // Don't typepaint twice, since that might cause an erroneous copy + e = getVarExp(loc, istate, ((VarExp *)e)->var, goal); + if (e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) + e = paintTypeOntoLiteral(type, e); return e; } - return e->interpret(istate, goal); + return e->interpret(istate, goal); } else error("%s.%s is not yet implemented at compile time", e1->toChars(), var->toChars()); @@ -5819,689 +5819,689 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) return e; } -Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal) -{ -#if LOG - printf("RemoveExp::interpret() %s\n", toChars()); -#endif - Expression *agg = e1->interpret(istate); - if (exceptionOrCantInterpret(agg)) - return agg; - Expression *index = e2->interpret(istate); - if (exceptionOrCantInterpret(index)) - return index; - if (agg->op == TOKnull) - return EXP_VOID_INTERPRET; - assert(agg->op == TOKassocarrayliteral); - AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)agg; - Expressions *keysx = aae->keys; - Expressions *valuesx = aae->values; - size_t removed = 0; - for (size_t j = 0; j < valuesx->dim; ++j) - { Expression *ekey = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); - if (exceptionOrCantInterpret(ex)) - return ex; - if (ex->isBool(TRUE)) - ++removed; - else if (removed != 0) - { keysx->tdata()[j - removed] = ekey; - valuesx->tdata()[j - removed] = valuesx->tdata()[j]; - } - } - valuesx->dim = valuesx->dim - removed; - keysx->dim = keysx->dim - removed; - return new IntegerExp(loc, removed?1:0, Type::tbool); -} - - -/******************************* Special Functions ***************************/ - -Expression *interpret_length(InterState *istate, Expression *earg) +Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal) { - //printf("interpret_length()\n"); +#if LOG + printf("RemoveExp::interpret() %s\n", toChars()); +#endif + Expression *agg = e1->interpret(istate); + if (exceptionOrCantInterpret(agg)) + return agg; + Expression *index = e2->interpret(istate); + if (exceptionOrCantInterpret(index)) + return index; + if (agg->op == TOKnull) + return EXP_VOID_INTERPRET; + assert(agg->op == TOKassocarrayliteral); + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)agg; + Expressions *keysx = aae->keys; + Expressions *valuesx = aae->values; + size_t removed = 0; + for (size_t j = 0; j < valuesx->dim; ++j) + { Expression *ekey = keysx->tdata()[j]; + Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + if (exceptionOrCantInterpret(ex)) + return ex; + if (ex->isBool(TRUE)) + ++removed; + else if (removed != 0) + { keysx->tdata()[j - removed] = ekey; + valuesx->tdata()[j - removed] = valuesx->tdata()[j]; + } + } + valuesx->dim = valuesx->dim - removed; + keysx->dim = keysx->dim - removed; + return new IntegerExp(loc, removed?1:0, Type::tbool); +} + + +/******************************* Special Functions ***************************/ + +Expression *interpret_length(InterState *istate, Expression *earg) +{ + //printf("interpret_length()\n"); earg = earg->interpret(istate); if (earg == EXP_CANT_INTERPRET) return NULL; - if (exceptionOrCantInterpret(earg)) - return earg; - dinteger_t len = 0; - if (earg->op == TOKassocarrayliteral) - len = ((AssocArrayLiteralExp *)earg)->keys->dim; - else assert(earg->op == TOKnull); - Expression *e = new IntegerExp(earg->loc, len, Type::tsize_t); + if (exceptionOrCantInterpret(earg)) + return earg; + dinteger_t len = 0; + if (earg->op == TOKassocarrayliteral) + len = ((AssocArrayLiteralExp *)earg)->keys->dim; + else assert(earg->op == TOKnull); + Expression *e = new IntegerExp(earg->loc, len, Type::tsize_t); return e; } -Expression *interpret_keys(InterState *istate, Expression *earg, Type *elemType) +Expression *interpret_keys(InterState *istate, Expression *earg, Type *elemType) { #if LOG - printf("interpret_keys()\n"); + printf("interpret_keys()\n"); #endif earg = earg->interpret(istate); if (earg == EXP_CANT_INTERPRET) return NULL; - if (exceptionOrCantInterpret(earg)) - return earg; - if (earg->op == TOKnull) - return new NullExp(earg->loc); - if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) + if (exceptionOrCantInterpret(earg)) + return earg; + if (earg->op == TOKnull) + return new NullExp(earg->loc); + if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) return NULL; - assert(earg->op == TOKassocarrayliteral); + assert(earg->op == TOKassocarrayliteral); AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; - ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->keys); - ae->ownedByCtfe = aae->ownedByCtfe; - ae->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); - return copyLiteral(ae); + ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->keys); + ae->ownedByCtfe = aae->ownedByCtfe; + ae->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); + return copyLiteral(ae); } -Expression *interpret_values(InterState *istate, Expression *earg, Type *elemType) +Expression *interpret_values(InterState *istate, Expression *earg, Type *elemType) { -#if LOG - printf("interpret_values()\n"); -#endif +#if LOG + printf("interpret_values()\n"); +#endif earg = earg->interpret(istate); if (earg == EXP_CANT_INTERPRET) return NULL; - if (exceptionOrCantInterpret(earg)) - return earg; - if (earg->op == TOKnull) - return new NullExp(earg->loc); - if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) + if (exceptionOrCantInterpret(earg)) + return earg; + if (earg->op == TOKnull) + return new NullExp(earg->loc); + if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray) return NULL; - assert(earg->op == TOKassocarrayliteral); + assert(earg->op == TOKassocarrayliteral); AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; - ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->values); - ae->ownedByCtfe = aae->ownedByCtfe; - ae->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); + ArrayLiteralExp *ae = new ArrayLiteralExp(aae->loc, aae->values); + ae->ownedByCtfe = aae->ownedByCtfe; + ae->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); //printf("result is %s\n", e->toChars()); - return copyLiteral(ae); + return copyLiteral(ae); } -// signature is int delegate(ref Value) OR int delegate(ref Key, ref Value) -Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *deleg) -{ aa = aa->interpret(istate); - if (exceptionOrCantInterpret(aa)) - return aa; - if (aa->op != TOKassocarrayliteral) - return new IntegerExp(deleg->loc, 0, Type::tsize_t); +// signature is int delegate(ref Value) OR int delegate(ref Key, ref Value) +Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *deleg) +{ aa = aa->interpret(istate); + if (exceptionOrCantInterpret(aa)) + return aa; + if (aa->op != TOKassocarrayliteral) + return new IntegerExp(deleg->loc, 0, Type::tsize_t); - FuncDeclaration *fd = NULL; - Expression *pthis = NULL; - if (deleg->op == TOKdelegate) - { - fd = ((DelegateExp *)deleg)->func; - pthis = ((DelegateExp *)deleg)->e1; - } - else if (deleg->op == TOKfunction) - fd = ((FuncExp*)deleg)->fd; + FuncDeclaration *fd = NULL; + Expression *pthis = NULL; + if (deleg->op == TOKdelegate) + { + fd = ((DelegateExp *)deleg)->func; + pthis = ((DelegateExp *)deleg)->e1; + } + else if (deleg->op == TOKfunction) + fd = ((FuncExp*)deleg)->fd; - assert(fd && fd->fbody); - assert(fd->parameters); - int numParams = fd->parameters->dim; - assert(numParams == 1 || numParams==2); - - Type *valueType = fd->parameters->tdata()[numParams-1]->type; - Type *keyType = numParams == 2 ? fd->parameters->tdata()[0]->type - : Type::tsize_t; - Expressions args; - args.setDim(numParams); - - AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)aa; - if (!ae->keys || ae->keys->dim == 0) - return new IntegerExp(deleg->loc, 0, Type::tsize_t); - Expression *eresult; - - for (size_t i = 0; i < ae->keys->dim; ++i) - { - Expression *ekey = ae->keys->tdata()[i]; - Expression *evalue = ae->values->tdata()[i]; - args.tdata()[numParams - 1] = evalue; - if (numParams == 2) args.tdata()[0] = ekey; - - eresult = fd->interpret(istate, &args, pthis); - if (exceptionOrCantInterpret(eresult)) - return eresult; - - assert(eresult->op == TOKint64); - if (((IntegerExp *)eresult)->value != 0) - return eresult; - } - return eresult; -} - -// Helper function: given a function of type A[] f(...), -// return A. -Type *returnedArrayElementType(FuncDeclaration *fd) + assert(fd && fd->fbody); + assert(fd->parameters); + int numParams = fd->parameters->dim; + assert(numParams == 1 || numParams==2); + + Type *valueType = fd->parameters->tdata()[numParams-1]->type; + Type *keyType = numParams == 2 ? fd->parameters->tdata()[0]->type + : Type::tsize_t; + Expressions args; + args.setDim(numParams); + + AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)aa; + if (!ae->keys || ae->keys->dim == 0) + return new IntegerExp(deleg->loc, 0, Type::tsize_t); + Expression *eresult; + + for (size_t i = 0; i < ae->keys->dim; ++i) + { + Expression *ekey = ae->keys->tdata()[i]; + Expression *evalue = ae->values->tdata()[i]; + args.tdata()[numParams - 1] = evalue; + if (numParams == 2) args.tdata()[0] = ekey; + + eresult = fd->interpret(istate, &args, pthis); + if (exceptionOrCantInterpret(eresult)) + return eresult; + + assert(eresult->op == TOKint64); + if (((IntegerExp *)eresult)->value != 0) + return eresult; + } + return eresult; +} + +// Helper function: given a function of type A[] f(...), +// return A. +Type *returnedArrayElementType(FuncDeclaration *fd) { - assert(fd->type->ty == Tfunction); - assert(fd->type->nextOf()->ty == Tarray); - return ((TypeFunction *)fd->type)->nextOf()->nextOf(); + assert(fd->type->ty == Tfunction); + assert(fd->type->nextOf()->ty == Tarray); + return ((TypeFunction *)fd->type)->nextOf()->nextOf(); } -/* Decoding UTF strings for foreach loops. Duplicates the functionality of - * the twelve _aApplyXXn functions in aApply.d in the runtime. - */ -Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *deleg, bool rvs) +/* Decoding UTF strings for foreach loops. Duplicates the functionality of + * the twelve _aApplyXXn functions in aApply.d in the runtime. + */ +Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *deleg, bool rvs) { #if LOG - printf("foreachApplyUtf(%s, %s)\n", str->toChars(), deleg->toChars()); + printf("foreachApplyUtf(%s, %s)\n", str->toChars(), deleg->toChars()); #endif - FuncDeclaration *fd = NULL; - Expression *pthis = NULL; - if (deleg->op == TOKdelegate) - { - fd = ((DelegateExp *)deleg)->func; - pthis = ((DelegateExp *)deleg)->e1; - } - else if (deleg->op == TOKfunction) - fd = ((FuncExp*)deleg)->fd; - - assert(fd && fd->fbody); - assert(fd->parameters); - int numParams = fd->parameters->dim; - assert(numParams == 1 || numParams==2); - Type *charType = fd->parameters->tdata()[numParams-1]->type; - Type *indexType = numParams == 2 ? fd->parameters->tdata()[0]->type - : Type::tsize_t; - uinteger_t len = resolveArrayLength(str); - if (len == 0) - return new IntegerExp(deleg->loc, 0, indexType); - - if (str->op == TOKslice) - str = resolveSlice(str); - - StringExp *se = NULL; - ArrayLiteralExp *ale = NULL; - if (str->op == TOKstring) - se = (StringExp *) str; - else if (str->op == TOKarrayliteral) - ale = (ArrayLiteralExp *)str; - else - { error("CTFE internal error: cannot foreach %s", str->toChars()); - return EXP_CANT_INTERPRET; - } - Expressions args; - args.setDim(numParams); - - Expression *eresult; - - // Buffers for encoding; also used for decoding array literals - unsigned char utf8buf[4]; - unsigned short utf16buf[2]; - - size_t start = rvs ? len : 0; - size_t end = rvs ? 0: len; - for (size_t indx = start; indx != end;) - { - // Step 1: Decode the next dchar from the string. - - const char *errmsg = NULL; // Used for reporting decoding errors - dchar_t rawvalue; // Holds the decoded dchar - size_t currentIndex = indx; // The index of the decoded character - - if (ale) - { // If it is an array literal, copy the code points into the buffer - int buflen = 1; // #code points in the buffer - size_t n = 1; // #code points in this char - size_t sz = ale->type->nextOf()->size(); - - switch(sz) - { - case 1: - if (rvs) - { // find the start of the string - --indx; - buflen = 1; - while (indx > 0 && buflen < 4) - { Expression * r = ale->elements->tdata()[indx]; - assert(r->op == TOKint64); - unsigned char x = (unsigned char)(((IntegerExp *)r)->value); - if ( (x & 0xC0) != 0x80) - break; - ++buflen; - } - } - else - buflen = (indx + 4 > len) ? len - indx : 4; - for (int i=0; i < buflen; ++i) - { - Expression * r = ale->elements->tdata()[indx + i]; - assert(r->op == TOKint64); - utf8buf[i] = (unsigned char)(((IntegerExp *)r)->value); - } - n = 0; - errmsg = utf_decodeChar(&utf8buf[0], buflen, &n, &rawvalue); - break; - case 2: - if (rvs) - { // find the start of the string - --indx; - buflen = 1; - Expression * r = ale->elements->tdata()[indx]; - assert(r->op == TOKint64); - unsigned short x = (unsigned short)(((IntegerExp *)r)->value); - if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF) - { - --indx; - ++buflen; - } - } - else - buflen = (indx + 2 > len) ? len - indx : 2; - for (int i=0; i < buflen; ++i) - { - Expression * r = ale->elements->tdata()[indx + i]; - assert(r->op == TOKint64); - utf16buf[i] = (unsigned short)(((IntegerExp *)r)->value); - } - n = 0; - errmsg = utf_decodeWchar(&utf16buf[0], buflen, &n, &rawvalue); - break; - case 4: - { - if (rvs) - --indx; - - Expression * r = ale->elements->tdata()[indx]; - assert(r->op == TOKint64); - rawvalue = ((IntegerExp *)r)->value; - n = 1; - } - break; - default: - assert(0); - } - if (!rvs) - indx += n; - } - else - { // String literals - size_t saveindx; // used for reverse iteration - - switch (se->sz) - { - case 1: - if (rvs) - { // find the start of the string - unsigned char *s = (unsigned char *)se->string; - --indx; - while (indx > 0 && ((s[indx]&0xC0)==0x80)) - --indx; - saveindx = indx; - } - errmsg = utf_decodeChar((unsigned char *)se->string, se->len, &indx, &rawvalue); - if (rvs) - indx = saveindx; - break; - case 2: - if (rvs) - { // find the start - unsigned short *s = (unsigned short *)se->string; - --indx; - if (s[indx] >= 0xDC00 && s[indx]<= 0xDFFF) - --indx; - saveindx = indx; - } - errmsg = utf_decodeWchar((unsigned short *)se->string, se->len, &indx, &rawvalue); - if (rvs) - indx = saveindx; - break; - case 4: - if (rvs) - --indx; - rawvalue = ((unsigned *)(se->string))[indx]; - if (!rvs) - ++indx; - break; - default: - assert(0); - } - } - if (errmsg) - { deleg->error("%s", errmsg); - return EXP_CANT_INTERPRET; - } - - // Step 2: encode the dchar in the target encoding - - int charlen = 1; // How many codepoints are involved? - switch(charType->size()) - { - case 1: - charlen = utf_codeLengthChar(rawvalue); - utf_encodeChar(&utf8buf[0], rawvalue); - break; - case 2: - charlen = utf_codeLengthWchar(rawvalue); - utf_encodeWchar(&utf16buf[0], rawvalue); - break; - case 4: - break; - default: - assert(0); - } - if (rvs) - currentIndex = indx; - - // Step 3: call the delegate once for each code point - - // The index only needs to be set once - if (numParams == 2) - args.tdata()[0] = new IntegerExp(deleg->loc, currentIndex, indexType); - - Expression *val = NULL; - - for (int k= 0; k < charlen; ++k) - { - dchar_t codepoint; - switch(charType->size()) - { - case 1: - codepoint = utf8buf[k]; - break; - case 2: - codepoint = utf16buf[k]; - break; - case 4: - codepoint = rawvalue; - break; - default: - assert(0); - } - val = new IntegerExp(str->loc, codepoint, charType); - - args.tdata()[numParams - 1] = val; - - eresult = fd->interpret(istate, &args, pthis); - if (exceptionOrCantInterpret(eresult)) - return eresult; - assert(eresult->op == TOKint64); - if (((IntegerExp *)eresult)->value != 0) - return eresult; - } - } - return eresult; + FuncDeclaration *fd = NULL; + Expression *pthis = NULL; + if (deleg->op == TOKdelegate) + { + fd = ((DelegateExp *)deleg)->func; + pthis = ((DelegateExp *)deleg)->e1; + } + else if (deleg->op == TOKfunction) + fd = ((FuncExp*)deleg)->fd; + + assert(fd && fd->fbody); + assert(fd->parameters); + int numParams = fd->parameters->dim; + assert(numParams == 1 || numParams==2); + Type *charType = fd->parameters->tdata()[numParams-1]->type; + Type *indexType = numParams == 2 ? fd->parameters->tdata()[0]->type + : Type::tsize_t; + uinteger_t len = resolveArrayLength(str); + if (len == 0) + return new IntegerExp(deleg->loc, 0, indexType); + + if (str->op == TOKslice) + str = resolveSlice(str); + + StringExp *se = NULL; + ArrayLiteralExp *ale = NULL; + if (str->op == TOKstring) + se = (StringExp *) str; + else if (str->op == TOKarrayliteral) + ale = (ArrayLiteralExp *)str; + else + { error("CTFE internal error: cannot foreach %s", str->toChars()); + return EXP_CANT_INTERPRET; + } + Expressions args; + args.setDim(numParams); + + Expression *eresult; + + // Buffers for encoding; also used for decoding array literals + unsigned char utf8buf[4]; + unsigned short utf16buf[2]; + + size_t start = rvs ? len : 0; + size_t end = rvs ? 0: len; + for (size_t indx = start; indx != end;) + { + // Step 1: Decode the next dchar from the string. + + const char *errmsg = NULL; // Used for reporting decoding errors + dchar_t rawvalue; // Holds the decoded dchar + size_t currentIndex = indx; // The index of the decoded character + + if (ale) + { // If it is an array literal, copy the code points into the buffer + int buflen = 1; // #code points in the buffer + size_t n = 1; // #code points in this char + size_t sz = ale->type->nextOf()->size(); + + switch(sz) + { + case 1: + if (rvs) + { // find the start of the string + --indx; + buflen = 1; + while (indx > 0 && buflen < 4) + { Expression * r = ale->elements->tdata()[indx]; + assert(r->op == TOKint64); + unsigned char x = (unsigned char)(((IntegerExp *)r)->value); + if ( (x & 0xC0) != 0x80) + break; + ++buflen; + } + } + else + buflen = (indx + 4 > len) ? len - indx : 4; + for (int i=0; i < buflen; ++i) + { + Expression * r = ale->elements->tdata()[indx + i]; + assert(r->op == TOKint64); + utf8buf[i] = (unsigned char)(((IntegerExp *)r)->value); + } + n = 0; + errmsg = utf_decodeChar(&utf8buf[0], buflen, &n, &rawvalue); + break; + case 2: + if (rvs) + { // find the start of the string + --indx; + buflen = 1; + Expression * r = ale->elements->tdata()[indx]; + assert(r->op == TOKint64); + unsigned short x = (unsigned short)(((IntegerExp *)r)->value); + if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF) + { + --indx; + ++buflen; + } + } + else + buflen = (indx + 2 > len) ? len - indx : 2; + for (int i=0; i < buflen; ++i) + { + Expression * r = ale->elements->tdata()[indx + i]; + assert(r->op == TOKint64); + utf16buf[i] = (unsigned short)(((IntegerExp *)r)->value); + } + n = 0; + errmsg = utf_decodeWchar(&utf16buf[0], buflen, &n, &rawvalue); + break; + case 4: + { + if (rvs) + --indx; + + Expression * r = ale->elements->tdata()[indx]; + assert(r->op == TOKint64); + rawvalue = ((IntegerExp *)r)->value; + n = 1; + } + break; + default: + assert(0); + } + if (!rvs) + indx += n; + } + else + { // String literals + size_t saveindx; // used for reverse iteration + + switch (se->sz) + { + case 1: + if (rvs) + { // find the start of the string + unsigned char *s = (unsigned char *)se->string; + --indx; + while (indx > 0 && ((s[indx]&0xC0)==0x80)) + --indx; + saveindx = indx; + } + errmsg = utf_decodeChar((unsigned char *)se->string, se->len, &indx, &rawvalue); + if (rvs) + indx = saveindx; + break; + case 2: + if (rvs) + { // find the start + unsigned short *s = (unsigned short *)se->string; + --indx; + if (s[indx] >= 0xDC00 && s[indx]<= 0xDFFF) + --indx; + saveindx = indx; + } + errmsg = utf_decodeWchar((unsigned short *)se->string, se->len, &indx, &rawvalue); + if (rvs) + indx = saveindx; + break; + case 4: + if (rvs) + --indx; + rawvalue = ((unsigned *)(se->string))[indx]; + if (!rvs) + ++indx; + break; + default: + assert(0); + } + } + if (errmsg) + { deleg->error("%s", errmsg); + return EXP_CANT_INTERPRET; + } + + // Step 2: encode the dchar in the target encoding + + int charlen = 1; // How many codepoints are involved? + switch(charType->size()) + { + case 1: + charlen = utf_codeLengthChar(rawvalue); + utf_encodeChar(&utf8buf[0], rawvalue); + break; + case 2: + charlen = utf_codeLengthWchar(rawvalue); + utf_encodeWchar(&utf16buf[0], rawvalue); + break; + case 4: + break; + default: + assert(0); + } + if (rvs) + currentIndex = indx; + + // Step 3: call the delegate once for each code point + + // The index only needs to be set once + if (numParams == 2) + args.tdata()[0] = new IntegerExp(deleg->loc, currentIndex, indexType); + + Expression *val = NULL; + + for (int k= 0; k < charlen; ++k) + { + dchar_t codepoint; + switch(charType->size()) + { + case 1: + codepoint = utf8buf[k]; + break; + case 2: + codepoint = utf16buf[k]; + break; + case 4: + codepoint = rawvalue; + break; + default: + assert(0); + } + val = new IntegerExp(str->loc, codepoint, charType); + + args.tdata()[numParams - 1] = val; + + eresult = fd->interpret(istate, &args, pthis); + if (exceptionOrCantInterpret(eresult)) + return eresult; + assert(eresult->op == TOKint64); + if (((IntegerExp *)eresult)->value != 0) + return eresult; + } + } + return eresult; } -/* If this is a built-in function, return the interpreted result, - * Otherwise, return NULL. - */ -Expression *evaluateIfBuiltin(InterState *istate, Loc loc, - FuncDeclaration *fd, Expressions *arguments, Expression *pthis) +/* If this is a built-in function, return the interpreted result, + * Otherwise, return NULL. + */ +Expression *evaluateIfBuiltin(InterState *istate, Loc loc, + FuncDeclaration *fd, Expressions *arguments, Expression *pthis) { - Expression *e = NULL; - int nargs = arguments ? arguments->dim : 0; -#if DMDV2 - if (pthis && isAssocArray(pthis->type)) - { - if (fd->ident == Id::length && nargs==0) - return interpret_length(istate, pthis); - else if (fd->ident == Id::keys && nargs==0) - return interpret_keys(istate, pthis, returnedArrayElementType(fd)); - else if (fd->ident == Id::values && nargs==0) - return interpret_values(istate, pthis, returnedArrayElementType(fd)); - else if (fd->ident == Id::rehash && nargs==0) - return pthis->interpret(istate, ctfeNeedLvalue); // rehash is a no-op - } - if (!pthis) - { - enum BUILTIN b = fd->isBuiltin(); - if (b) - { Expressions args; - args.setDim(nargs); - for (size_t i = 0; i < args.dim; i++) - { - Expression *earg = arguments->tdata()[i]; + Expression *e = NULL; + int nargs = arguments ? arguments->dim : 0; +#if DMDV2 + if (pthis && isAssocArray(pthis->type)) + { + if (fd->ident == Id::length && nargs==0) + return interpret_length(istate, pthis); + else if (fd->ident == Id::keys && nargs==0) + return interpret_keys(istate, pthis, returnedArrayElementType(fd)); + else if (fd->ident == Id::values && nargs==0) + return interpret_values(istate, pthis, returnedArrayElementType(fd)); + else if (fd->ident == Id::rehash && nargs==0) + return pthis->interpret(istate, ctfeNeedLvalue); // rehash is a no-op + } + if (!pthis) + { + enum BUILTIN b = fd->isBuiltin(); + if (b) + { Expressions args; + args.setDim(nargs); + for (size_t i = 0; i < args.dim; i++) + { + Expression *earg = arguments->tdata()[i]; earg = earg->interpret(istate); - if (exceptionOrCantInterpret(earg)) - return earg; - args.tdata()[i] = earg; - } - e = eval_builtin(loc, b, &args); - if (!e) - e = EXP_CANT_INTERPRET; - } - } - /* Horrid hack to retrieve the builtin AA functions after they've been - * mashed by the inliner. - */ - if (!pthis) - { - Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; - // Check for the first parameter being a templatized AA. Hack: we assume that - // template AA.var is always the AA data itself. - Expression *firstdotvar = (firstarg && firstarg->op == TOKdotvar) - ? ((DotVarExp *)firstarg)->e1 : NULL; - if (nargs==3 && isAssocArray(firstarg->type) && !strcmp(fd->ident->string, "_aaApply")) - return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); - if (nargs==3 && isAssocArray(firstarg->type) &&!strcmp(fd->ident->string, "_aaApply2")) - return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); - if (firstdotvar && isAssocArray(firstdotvar->type)) - { if (fd->ident == Id::aaLen && nargs == 1) - return interpret_length(istate, firstdotvar->interpret(istate)); - else if (fd->ident == Id::aaKeys && nargs == 2) - { - Expression *trueAA = firstdotvar->interpret(istate); - return interpret_keys(istate, trueAA, toBuiltinAAType(trueAA->type)->index); - } - else if (fd->ident == Id::aaValues && nargs == 3) - { - Expression *trueAA = firstdotvar->interpret(istate); - return interpret_values(istate, trueAA, toBuiltinAAType(trueAA->type)->nextOf()); - } - else if (fd->ident == Id::aaRehash && nargs == 2) - { - return firstdotvar->interpret(istate, ctfeNeedLvalue); - } - } - } -#endif -#if DMDV1 - if (!pthis) - { - Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; - if (firstarg && firstarg->type->toBasetype()->ty == Taarray) - { - TypeAArray *firstAAtype = (TypeAArray *)firstarg->type; - if (fd->ident == Id::aaLen && nargs == 1) - return interpret_length(istate, firstarg); - else if (fd->ident == Id::aaKeys) - return interpret_keys(istate, firstarg, firstAAtype->index); - else if (fd->ident == Id::aaValues) - return interpret_values(istate, firstarg, firstAAtype->nextOf()); - else if (nargs==2 && fd->ident == Id::aaRehash) - return firstarg->interpret(istate, ctfeNeedLvalue); //no-op - else if (nargs==3 && !strcmp(fd->ident->string, "_aaApply")) - return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); - else if (nargs==3 && !strcmp(fd->ident->string, "_aaApply2")) - return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); - } - } -#endif -#if DMDV2 - if (pthis && !fd->fbody && fd->isCtorDeclaration() && fd->parent && fd->parent->parent && fd->parent->parent->ident == Id::object) - { - if (pthis->op == TOKclassreference && fd->parent->ident == Id::Throwable) - { // At present, the constructors just copy their arguments into the struct. - // But we might need some magic if stack tracing gets added to druntime. - StructLiteralExp *se = ((ClassReferenceExp *)pthis)->value; - assert(arguments->dim <= se->elements->dim); - for (int i = 0; i < arguments->dim; ++i) - { - Expression *e = arguments->tdata()[i]->interpret(istate); - if (exceptionOrCantInterpret(e)) - return e; - se->elements->tdata()[i] = e; - } - return EXP_VOID_INTERPRET; - } - } -#endif - if (nargs == 1 && !pthis && - (fd->ident == Id::criticalenter || fd->ident == Id::criticalexit)) - { // Support synchronized{} as a no-op - return EXP_VOID_INTERPRET; - } - if (!pthis) - { - size_t idlen = strlen(fd->ident->string); - if (nargs == 2 && (idlen == 10 || idlen == 11) - && !strncmp(fd->ident->string, "_aApply", 7)) - { // Functions from aApply.d and aApplyR.d in the runtime - bool rvs = (idlen == 11); // true if foreach_reverse - char c = fd->ident->string[idlen-3]; // char width: 'c', 'w', or 'd' - char s = fd->ident->string[idlen-2]; // string width: 'c', 'w', or 'd' - char n = fd->ident->string[idlen-1]; // numParams: 1 or 2. - // There are 12 combinations - if ( (n == '1' || n == '2') && - (c == 'c' || c == 'w' || c == 'd') && - (s == 'c' || s == 'w' || s == 'd') && c != s) - { Expression *str = arguments->tdata()[0]; - str = str->interpret(istate); - if (exceptionOrCantInterpret(str)) - return str; - return foreachApplyUtf(istate, str, arguments->tdata()[1], rvs); - } - } - } + if (exceptionOrCantInterpret(earg)) + return earg; + args.tdata()[i] = earg; + } + e = eval_builtin(loc, b, &args); + if (!e) + e = EXP_CANT_INTERPRET; + } + } + /* Horrid hack to retrieve the builtin AA functions after they've been + * mashed by the inliner. + */ + if (!pthis) + { + Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; + // Check for the first parameter being a templatized AA. Hack: we assume that + // template AA.var is always the AA data itself. + Expression *firstdotvar = (firstarg && firstarg->op == TOKdotvar) + ? ((DotVarExp *)firstarg)->e1 : NULL; + if (nargs==3 && isAssocArray(firstarg->type) && !strcmp(fd->ident->string, "_aaApply")) + return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); + if (nargs==3 && isAssocArray(firstarg->type) &&!strcmp(fd->ident->string, "_aaApply2")) + return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); + if (firstdotvar && isAssocArray(firstdotvar->type)) + { if (fd->ident == Id::aaLen && nargs == 1) + return interpret_length(istate, firstdotvar->interpret(istate)); + else if (fd->ident == Id::aaKeys && nargs == 2) + { + Expression *trueAA = firstdotvar->interpret(istate); + return interpret_keys(istate, trueAA, toBuiltinAAType(trueAA->type)->index); + } + else if (fd->ident == Id::aaValues && nargs == 3) + { + Expression *trueAA = firstdotvar->interpret(istate); + return interpret_values(istate, trueAA, toBuiltinAAType(trueAA->type)->nextOf()); + } + else if (fd->ident == Id::aaRehash && nargs == 2) + { + return firstdotvar->interpret(istate, ctfeNeedLvalue); + } + } + } +#endif +#if DMDV1 + if (!pthis) + { + Expression *firstarg = nargs > 0 ? (Expression *)(arguments->data[0]) : NULL; + if (firstarg && firstarg->type->toBasetype()->ty == Taarray) + { + TypeAArray *firstAAtype = (TypeAArray *)firstarg->type; + if (fd->ident == Id::aaLen && nargs == 1) + return interpret_length(istate, firstarg); + else if (fd->ident == Id::aaKeys) + return interpret_keys(istate, firstarg, firstAAtype->index); + else if (fd->ident == Id::aaValues) + return interpret_values(istate, firstarg, firstAAtype->nextOf()); + else if (nargs==2 && fd->ident == Id::aaRehash) + return firstarg->interpret(istate, ctfeNeedLvalue); //no-op + else if (nargs==3 && !strcmp(fd->ident->string, "_aaApply")) + return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); + else if (nargs==3 && !strcmp(fd->ident->string, "_aaApply2")) + return interpret_aaApply(istate, firstarg, (Expression *)(arguments->data[2])); + } + } +#endif +#if DMDV2 + if (pthis && !fd->fbody && fd->isCtorDeclaration() && fd->parent && fd->parent->parent && fd->parent->parent->ident == Id::object) + { + if (pthis->op == TOKclassreference && fd->parent->ident == Id::Throwable) + { // At present, the constructors just copy their arguments into the struct. + // But we might need some magic if stack tracing gets added to druntime. + StructLiteralExp *se = ((ClassReferenceExp *)pthis)->value; + assert(arguments->dim <= se->elements->dim); + for (int i = 0; i < arguments->dim; ++i) + { + Expression *e = arguments->tdata()[i]->interpret(istate); + if (exceptionOrCantInterpret(e)) + return e; + se->elements->tdata()[i] = e; + } + return EXP_VOID_INTERPRET; + } + } +#endif + if (nargs == 1 && !pthis && + (fd->ident == Id::criticalenter || fd->ident == Id::criticalexit)) + { // Support synchronized{} as a no-op + return EXP_VOID_INTERPRET; + } + if (!pthis) + { + size_t idlen = strlen(fd->ident->string); + if (nargs == 2 && (idlen == 10 || idlen == 11) + && !strncmp(fd->ident->string, "_aApply", 7)) + { // Functions from aApply.d and aApplyR.d in the runtime + bool rvs = (idlen == 11); // true if foreach_reverse + char c = fd->ident->string[idlen-3]; // char width: 'c', 'w', or 'd' + char s = fd->ident->string[idlen-2]; // string width: 'c', 'w', or 'd' + char n = fd->ident->string[idlen-1]; // numParams: 1 or 2. + // There are 12 combinations + if ( (n == '1' || n == '2') && + (c == 'c' || c == 'w' || c == 'd') && + (s == 'c' || s == 'w' || s == 'd') && c != s) + { Expression *str = arguments->tdata()[0]; + str = str->interpret(istate); + if (exceptionOrCantInterpret(str)) + return str; + return foreachApplyUtf(istate, str, arguments->tdata()[1], rvs); + } + } + } return e; } -/*************************** CTFE Sanity Checks ***************************/ - -/* Setter functions for CTFE variable values. - * These functions exist to check for compiler CTFE bugs. - */ - -bool isCtfeValueValid(Expression *newval) -{ - if ( -#if DMDV2 - newval->type->ty == Tnull || -#endif - isPointer(newval->type) ) - { - if (newval->op == TOKaddress || newval->op == TOKnull || - newval->op == TOKstring) - return true; - if (newval->op == TOKindex) - { - Expression *g = ((IndexExp *)newval)->e1; - if (g->op == TOKarrayliteral || g->op == TOKstring || - g->op == TOKassocarrayliteral) - return true; - } - if (newval->op == TOKvar) - return true; - if (newval->type->nextOf()->ty == Tarray && newval->op == TOKslice) - return true; - if (newval->op == TOKint64) - return true; // Result of a cast, but cannot be dereferenced - // else it must be a reference - } - if (newval->op == TOKclassreference || (newval->op == TOKnull && newval->type->ty == Tclass)) - return true; - if (newval->op == TOKvar) - { - VarExp *ve = (VarExp *)newval; - VarDeclaration *vv = ve->var->isVarDeclaration(); - // Must not be a reference to a reference - if (!(vv && vv->getValue() && vv->getValue()->op == TOKvar)) - return true; - } - if (newval->op == TOKdotvar) - { - if (((DotVarExp *)newval)->e1->op == TOKstructliteral) - { - assert(((StructLiteralExp *)((DotVarExp *)newval)->e1)->ownedByCtfe); - return true; - } - } - if (newval->op == TOKindex) - { - IndexExp *ie = (IndexExp *)newval; - if (ie->e2->op == TOKint64) - { - if (ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) - return true; - } - if (ie->e1->op == TOKassocarrayliteral) - return true; - // BUG: Happens ONLY in ref foreach. Should tighten this. - if (ie->e2->op == TOKvar) - return true; - } - if (newval->op == TOKfunction) return true; // function/delegate literal - if (newval->op == TOKdelegate) return true; - if (newval->op == TOKsymoff) // function pointer - { - if (((SymOffExp *)newval)->var->isFuncDeclaration()) - return true; - } - if (newval->op == TOKint64 || newval->op == TOKfloat64 || - newval->op == TOKchar || newval->op == TOKcomplex80) - return true; +/*************************** CTFE Sanity Checks ***************************/ - // References - - if (newval->op == TOKstructliteral) - assert(((StructLiteralExp *)newval)->ownedByCtfe); - if (newval->op == TOKarrayliteral) - assert(((ArrayLiteralExp *)newval)->ownedByCtfe); - if (newval->op == TOKassocarrayliteral) - assert(((AssocArrayLiteralExp *)newval)->ownedByCtfe); - - if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) || - (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) || - (newval->op == TOKnull)) - { return true; - } - // Dynamic arrays passed by ref may be null. When this happens - // they may originate from an index or dotvar expression. - if (newval->type->ty == Tarray || newval->type->ty == Taarray) - if (newval->op == TOKdotvar || newval->op == TOKindex) - return true; // actually must be null - - if (newval->op == TOKslice) - { - SliceExp *se = (SliceExp *)newval; - assert(se->lwr && se->lwr != EXP_CANT_INTERPRET && se->lwr->op == TOKint64); - assert(se->upr && se->upr != EXP_CANT_INTERPRET && se->upr->op == TOKint64); - assert(se->e1->op == TOKarrayliteral || se->e1->op == TOKstring); - if (se->e1->op == TOKarrayliteral) - assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe); - return true; - } - newval->error("CTFE internal error: illegal value %s\n", newval->toChars()); - return false; -} - -bool VarDeclaration::hasValue() -{ - if (ctfeAdrOnStack == (size_t)-1) - return false; - return NULL != getValue(); -} - -Expression *VarDeclaration::getValue() -{ - return ctfeStack.getValue(this); -} - -void VarDeclaration::setValueNull() -{ - ctfeStack.setValue(this, NULL); -} - -// Don't check for validity -void VarDeclaration::setValueWithoutChecking(Expression *newval) -{ - ctfeStack.setValue(this, newval); -} - -void VarDeclaration::setValue(Expression *newval) -{ - assert(isCtfeValueValid(newval)); - ctfeStack.setValue(this, newval); -} +/* Setter functions for CTFE variable values. + * These functions exist to check for compiler CTFE bugs. + */ + +bool isCtfeValueValid(Expression *newval) +{ + if ( +#if DMDV2 + newval->type->ty == Tnull || +#endif + isPointer(newval->type) ) + { + if (newval->op == TOKaddress || newval->op == TOKnull || + newval->op == TOKstring) + return true; + if (newval->op == TOKindex) + { + Expression *g = ((IndexExp *)newval)->e1; + if (g->op == TOKarrayliteral || g->op == TOKstring || + g->op == TOKassocarrayliteral) + return true; + } + if (newval->op == TOKvar) + return true; + if (newval->type->nextOf()->ty == Tarray && newval->op == TOKslice) + return true; + if (newval->op == TOKint64) + return true; // Result of a cast, but cannot be dereferenced + // else it must be a reference + } + if (newval->op == TOKclassreference || (newval->op == TOKnull && newval->type->ty == Tclass)) + return true; + if (newval->op == TOKvar) + { + VarExp *ve = (VarExp *)newval; + VarDeclaration *vv = ve->var->isVarDeclaration(); + // Must not be a reference to a reference + if (!(vv && vv->getValue() && vv->getValue()->op == TOKvar)) + return true; + } + if (newval->op == TOKdotvar) + { + if (((DotVarExp *)newval)->e1->op == TOKstructliteral) + { + assert(((StructLiteralExp *)((DotVarExp *)newval)->e1)->ownedByCtfe); + return true; + } + } + if (newval->op == TOKindex) + { + IndexExp *ie = (IndexExp *)newval; + if (ie->e2->op == TOKint64) + { + if (ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring) + return true; + } + if (ie->e1->op == TOKassocarrayliteral) + return true; + // BUG: Happens ONLY in ref foreach. Should tighten this. + if (ie->e2->op == TOKvar) + return true; + } + if (newval->op == TOKfunction) return true; // function/delegate literal + if (newval->op == TOKdelegate) return true; + if (newval->op == TOKsymoff) // function pointer + { + if (((SymOffExp *)newval)->var->isFuncDeclaration()) + return true; + } + if (newval->op == TOKint64 || newval->op == TOKfloat64 || + newval->op == TOKchar || newval->op == TOKcomplex80) + return true; + + // References + + if (newval->op == TOKstructliteral) + assert(((StructLiteralExp *)newval)->ownedByCtfe); + if (newval->op == TOKarrayliteral) + assert(((ArrayLiteralExp *)newval)->ownedByCtfe); + if (newval->op == TOKassocarrayliteral) + assert(((AssocArrayLiteralExp *)newval)->ownedByCtfe); + + if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) || + (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) || + (newval->op == TOKnull)) + { return true; + } + // Dynamic arrays passed by ref may be null. When this happens + // they may originate from an index or dotvar expression. + if (newval->type->ty == Tarray || newval->type->ty == Taarray) + if (newval->op == TOKdotvar || newval->op == TOKindex) + return true; // actually must be null + + if (newval->op == TOKslice) + { + SliceExp *se = (SliceExp *)newval; + assert(se->lwr && se->lwr != EXP_CANT_INTERPRET && se->lwr->op == TOKint64); + assert(se->upr && se->upr != EXP_CANT_INTERPRET && se->upr->op == TOKint64); + assert(se->e1->op == TOKarrayliteral || se->e1->op == TOKstring); + if (se->e1->op == TOKarrayliteral) + assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe); + return true; + } + newval->error("CTFE internal error: illegal value %s\n", newval->toChars()); + return false; +} + +bool VarDeclaration::hasValue() +{ + if (ctfeAdrOnStack == (size_t)-1) + return false; + return NULL != getValue(); +} + +Expression *VarDeclaration::getValue() +{ + return ctfeStack.getValue(this); +} + +void VarDeclaration::setValueNull() +{ + ctfeStack.setValue(this, NULL); +} + +// Don't check for validity +void VarDeclaration::setValueWithoutChecking(Expression *newval) +{ + ctfeStack.setValue(this, newval); +} + +void VarDeclaration::setValue(Expression *newval) +{ + assert(isCtfeValueValid(newval)); + ctfeStack.setValue(this, newval); +} diff --git a/dmd/json.c b/dmd/json.c index 16f9f435..d3efacf5 100644 --- a/dmd/json.c +++ b/dmd/json.c @@ -1,462 +1,462 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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. - -// This implements the JSON capability. - -#include -#include -#include -#include -#include - -#include "rmem.h" -#include "root.h" - -#include "mars.h" -#include "dsymbol.h" -#include "macro.h" -#include "template.h" -#include "lexer.h" -#include "aggregate.h" -#include "declaration.h" -#include "enum.h" -#include "id.h" -#include "module.h" -#include "scope.h" -#include "hdrgen.h" -#include "json.h" -#include "mtype.h" -#include "attrib.h" -#include "cond.h" - -const char Pname[] = "name"; -const char Pkind[] = "kind"; -const char Pfile[] = "file"; -const char Pline[] = "line"; -const char Ptype[] = "type"; -const char Pcomment[] = "comment"; -const char Pmembers[] = "members"; -const char Pprotection[] = "protection"; -const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"}; - -void JsonRemoveComma(OutBuffer *buf); - -void json_generate(Modules *modules) -{ OutBuffer buf; - - buf.writestring("[\n"); - for (size_t i = 0; i < modules->dim; i++) - { Module *m = modules->tdata()[i]; - if (global.params.verbose) - printf("json gen %s\n", m->toChars()); - m->toJsonBuffer(&buf); - buf.writestring(",\n"); - } - JsonRemoveComma(&buf); - buf.writestring("]\n"); - - // Write buf to file - char *arg = global.params.xfilename; - if (!arg || !*arg) - { // Generate lib file name from first obj name - char *n = global.params.objfiles->tdata()[0]; - - n = FileName::name(n); - FileName *fn = FileName::forceExt(n, global.json_ext); - arg = fn->toChars(); - } - else if (arg[0] == '-' && arg[1] == 0) - { // Write to stdout; assume it succeeds - int n = fwrite(buf.data, 1, buf.offset, stdout); - assert(n == buf.offset); // keep gcc happy about return values - return; - } -// if (!FileName::absolute(arg)) -// arg = FileName::combine(dir, arg); - FileName *jsonfilename = FileName::defaultExt(arg, global.json_ext); - File *jsonfile = new File(jsonfilename); - assert(jsonfile); - jsonfile->setbuffer(buf.data, buf.offset); - jsonfile->ref = 1; - char *pt = FileName::path(jsonfile->toChars()); - if (*pt) - FileName::ensurePathExists(pt); - mem.free(pt); - jsonfile->writev(); -} - - -/********************************* - * Encode string into buf, and wrap it in double quotes. - */ -void JsonString(OutBuffer *buf, const char *s) -{ - buf->writeByte('\"'); - for (; *s; s++) - { - unsigned char c = (unsigned char) *s; - switch (c) - { - case '\n': - buf->writestring("\\n"); - break; - - case '\r': - buf->writestring("\\r"); - break; - - case '\t': - buf->writestring("\\t"); - break; - - case '\"': - buf->writestring("\\\""); - break; - - case '\\': - buf->writestring("\\\\"); - break; - - case '/': - buf->writestring("\\/"); - break; - - case '\b': - buf->writestring("\\b"); - break; - - case '\f': - buf->writestring("\\f"); - break; - - default: - if (c < 0x20) - buf->printf("\\u%04x", c); - else - // Note that UTF-8 chars pass through here just fine - buf->writeByte(c); - break; - } - } - buf->writeByte('\"'); -} - -void JsonProperty(OutBuffer *buf, const char *name, const char *value) -{ - JsonString(buf, name); - buf->writestring(" : "); - JsonString(buf, value); - buf->writestring(",\n"); -} - -void JsonProperty(OutBuffer *buf, const char *name, int value) -{ - JsonString(buf, name); - buf->writestring(" : "); - buf->printf("%d", value); - buf->writestring(",\n"); -} - -void JsonRemoveComma(OutBuffer *buf) -{ - if (buf->offset >= 2 && - buf->data[buf->offset - 2] == ',' && - buf->data[buf->offset - 1] == '\n') - buf->offset -= 2; -} - -void Dsymbol::toJsonBuffer(OutBuffer *buf) -{ -} - -void Module::toJsonBuffer(OutBuffer *buf) -{ - buf->writestring("{\n"); - - if (md) - JsonProperty(buf, Pname, md->toChars()); - - JsonProperty(buf, Pkind, kind()); - - JsonProperty(buf, Pfile, srcfile->toChars()); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - - size_t offset = buf->offset; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - s->toJsonBuffer(buf); - } - - JsonRemoveComma(buf); - buf->writestring("]\n"); - - buf->writestring("}\n"); -} - -void AttribDeclaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("AttribDeclaration::toJsonBuffer()\n"); - - Dsymbols *d = include(NULL, NULL); - - if (d) - { - size_t offset = buf->offset; - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; - //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars()); - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - s->toJsonBuffer(buf); - } - JsonRemoveComma(buf); - } -} - - -void ConditionalDeclaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("ConditionalDeclaration::toJsonBuffer()\n"); - if (condition->inc) - { - AttribDeclaration::toJsonBuffer(buf); - } -} - - -void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { } -void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { } -void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { } -void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { } -void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } -void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } -void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } -void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { } -#if DMDV2 -void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { } -#endif - -void Declaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("Declaration::toJsonBuffer()\n"); - buf->writestring("{\n"); - - JsonProperty(buf, Pname, toChars()); - JsonProperty(buf, Pkind, kind()); - - if (prot()) - JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); - - if (type) - JsonProperty(buf, Ptype, type->toChars()); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - if (loc.linnum) - JsonProperty(buf, Pline, loc.linnum); - - TypedefDeclaration *td = isTypedefDeclaration(); - if (td) - { - JsonProperty(buf, "base", td->basetype->toChars()); - } - - JsonRemoveComma(buf); - buf->writestring("}\n"); -} - -void AggregateDeclaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("AggregateDeclaration::toJsonBuffer()\n"); - buf->writestring("{\n"); - - JsonProperty(buf, Pname, toChars()); - JsonProperty(buf, Pkind, kind()); - - if (prot()) - JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - if (loc.linnum) - JsonProperty(buf, Pline, loc.linnum); - - ClassDeclaration *cd = isClassDeclaration(); - if (cd) - { - if (cd->baseClass) - { - JsonProperty(buf, "base", cd->baseClass->toChars()); - } - if (cd->interfaces_dim) - { - JsonString(buf, "interfaces"); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (size_t i = 0; i < cd->interfaces_dim; i++) - { BaseClass *b = cd->interfaces[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - JsonString(buf, b->base->toChars()); - } - JsonRemoveComma(buf); - buf->writestring("],\n"); - } - } - - if (members) - { - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - s->toJsonBuffer(buf); - } - JsonRemoveComma(buf); - buf->writestring("]\n"); - } - JsonRemoveComma(buf); - - buf->writestring("}\n"); -} - -void TemplateDeclaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("TemplateDeclaration::toJsonBuffer()\n"); - - buf->writestring("{\n"); - - JsonProperty(buf, Pname, toChars()); - JsonProperty(buf, Pkind, kind()); - - if (prot()) - JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - if (loc.linnum) - JsonProperty(buf, Pline, loc.linnum); - - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - s->toJsonBuffer(buf); - } - JsonRemoveComma(buf); - buf->writestring("]\n"); - - buf->writestring("}\n"); -} - -void EnumDeclaration::toJsonBuffer(OutBuffer *buf) -{ - //printf("EnumDeclaration::toJsonBuffer()\n"); - if (isAnonymous()) - { - if (members) - { - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = members->tdata()[i]; - s->toJsonBuffer(buf); - buf->writestring(",\n"); - } - JsonRemoveComma(buf); - } - return; - } - - buf->writestring("{\n"); - - JsonProperty(buf, Pname, toChars()); - JsonProperty(buf, Pkind, kind()); - - if (prot()) - JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - if (loc.linnum) - JsonProperty(buf, Pline, loc.linnum); - - if (memtype) - JsonProperty(buf, "base", memtype->toChars()); - - if (members) - { - JsonString(buf, Pmembers); - buf->writestring(" : [\n"); - size_t offset = buf->offset; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - if (offset != buf->offset) - { buf->writestring(",\n"); - offset = buf->offset; - } - s->toJsonBuffer(buf); - } - JsonRemoveComma(buf); - buf->writestring("]\n"); - } - JsonRemoveComma(buf); - - buf->writestring("}\n"); -} - -void EnumMember::toJsonBuffer(OutBuffer *buf) -{ - //printf("EnumMember::toJsonBuffer()\n"); - buf->writestring("{\n"); - - JsonProperty(buf, Pname, toChars()); - JsonProperty(buf, Pkind, kind()); - - if (prot()) - JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); - - if (comment) - JsonProperty(buf, Pcomment, (const char *)comment); - - if (loc.linnum) - JsonProperty(buf, Pline, loc.linnum); - - JsonRemoveComma(buf); - buf->writestring("}\n"); -} - - + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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. + +// This implements the JSON capability. + +#include +#include +#include +#include +#include + +#include "rmem.h" +#include "root.h" + +#include "mars.h" +#include "dsymbol.h" +#include "macro.h" +#include "template.h" +#include "lexer.h" +#include "aggregate.h" +#include "declaration.h" +#include "enum.h" +#include "id.h" +#include "module.h" +#include "scope.h" +#include "hdrgen.h" +#include "json.h" +#include "mtype.h" +#include "attrib.h" +#include "cond.h" + +const char Pname[] = "name"; +const char Pkind[] = "kind"; +const char Pfile[] = "file"; +const char Pline[] = "line"; +const char Ptype[] = "type"; +const char Pcomment[] = "comment"; +const char Pmembers[] = "members"; +const char Pprotection[] = "protection"; +const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"}; + +void JsonRemoveComma(OutBuffer *buf); + +void json_generate(Modules *modules) +{ OutBuffer buf; + + buf.writestring("[\n"); + for (size_t i = 0; i < modules->dim; i++) + { Module *m = modules->tdata()[i]; + if (global.params.verbose) + printf("json gen %s\n", m->toChars()); + m->toJsonBuffer(&buf); + buf.writestring(",\n"); + } + JsonRemoveComma(&buf); + buf.writestring("]\n"); + + // Write buf to file + char *arg = global.params.xfilename; + if (!arg || !*arg) + { // Generate lib file name from first obj name + char *n = global.params.objfiles->tdata()[0]; + + n = FileName::name(n); + FileName *fn = FileName::forceExt(n, global.json_ext); + arg = fn->toChars(); + } + else if (arg[0] == '-' && arg[1] == 0) + { // Write to stdout; assume it succeeds + int n = fwrite(buf.data, 1, buf.offset, stdout); + assert(n == buf.offset); // keep gcc happy about return values + return; + } +// if (!FileName::absolute(arg)) +// arg = FileName::combine(dir, arg); + FileName *jsonfilename = FileName::defaultExt(arg, global.json_ext); + File *jsonfile = new File(jsonfilename); + assert(jsonfile); + jsonfile->setbuffer(buf.data, buf.offset); + jsonfile->ref = 1; + char *pt = FileName::path(jsonfile->toChars()); + if (*pt) + FileName::ensurePathExists(pt); + mem.free(pt); + jsonfile->writev(); +} + + +/********************************* + * Encode string into buf, and wrap it in double quotes. + */ +void JsonString(OutBuffer *buf, const char *s) +{ + buf->writeByte('\"'); + for (; *s; s++) + { + unsigned char c = (unsigned char) *s; + switch (c) + { + case '\n': + buf->writestring("\\n"); + break; + + case '\r': + buf->writestring("\\r"); + break; + + case '\t': + buf->writestring("\\t"); + break; + + case '\"': + buf->writestring("\\\""); + break; + + case '\\': + buf->writestring("\\\\"); + break; + + case '/': + buf->writestring("\\/"); + break; + + case '\b': + buf->writestring("\\b"); + break; + + case '\f': + buf->writestring("\\f"); + break; + + default: + if (c < 0x20) + buf->printf("\\u%04x", c); + else + // Note that UTF-8 chars pass through here just fine + buf->writeByte(c); + break; + } + } + buf->writeByte('\"'); +} + +void JsonProperty(OutBuffer *buf, const char *name, const char *value) +{ + JsonString(buf, name); + buf->writestring(" : "); + JsonString(buf, value); + buf->writestring(",\n"); +} + +void JsonProperty(OutBuffer *buf, const char *name, int value) +{ + JsonString(buf, name); + buf->writestring(" : "); + buf->printf("%d", value); + buf->writestring(",\n"); +} + +void JsonRemoveComma(OutBuffer *buf) +{ + if (buf->offset >= 2 && + buf->data[buf->offset - 2] == ',' && + buf->data[buf->offset - 1] == '\n') + buf->offset -= 2; +} + +void Dsymbol::toJsonBuffer(OutBuffer *buf) +{ +} + +void Module::toJsonBuffer(OutBuffer *buf) +{ + buf->writestring("{\n"); + + if (md) + JsonProperty(buf, Pname, md->toChars()); + + JsonProperty(buf, Pkind, kind()); + + JsonProperty(buf, Pfile, srcfile->toChars()); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + + size_t offset = buf->offset; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = members->tdata()[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); + } + + JsonRemoveComma(buf); + buf->writestring("]\n"); + + buf->writestring("}\n"); +} + +void AttribDeclaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("AttribDeclaration::toJsonBuffer()\n"); + + Dsymbols *d = include(NULL, NULL); + + if (d) + { + size_t offset = buf->offset; + for (unsigned i = 0; i < d->dim; i++) + { Dsymbol *s = d->tdata()[i]; + //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars()); + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); + } + JsonRemoveComma(buf); + } +} + + +void ConditionalDeclaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("ConditionalDeclaration::toJsonBuffer()\n"); + if (condition->inc) + { + AttribDeclaration::toJsonBuffer(buf); + } +} + + +void InvariantDeclaration::toJsonBuffer(OutBuffer *buf) { } +void DtorDeclaration::toJsonBuffer(OutBuffer *buf) { } +void StaticCtorDeclaration::toJsonBuffer(OutBuffer *buf) { } +void StaticDtorDeclaration::toJsonBuffer(OutBuffer *buf) { } +void ClassInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } +void ModuleInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } +void TypeInfoDeclaration::toJsonBuffer(OutBuffer *buf) { } +void UnitTestDeclaration::toJsonBuffer(OutBuffer *buf) { } +#if DMDV2 +void PostBlitDeclaration::toJsonBuffer(OutBuffer *buf) { } +#endif + +void Declaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("Declaration::toJsonBuffer()\n"); + buf->writestring("{\n"); + + JsonProperty(buf, Pname, toChars()); + JsonProperty(buf, Pkind, kind()); + + if (prot()) + JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); + + if (type) + JsonProperty(buf, Ptype, type->toChars()); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + if (loc.linnum) + JsonProperty(buf, Pline, loc.linnum); + + TypedefDeclaration *td = isTypedefDeclaration(); + if (td) + { + JsonProperty(buf, "base", td->basetype->toChars()); + } + + JsonRemoveComma(buf); + buf->writestring("}\n"); +} + +void AggregateDeclaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("AggregateDeclaration::toJsonBuffer()\n"); + buf->writestring("{\n"); + + JsonProperty(buf, Pname, toChars()); + JsonProperty(buf, Pkind, kind()); + + if (prot()) + JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + if (loc.linnum) + JsonProperty(buf, Pline, loc.linnum); + + ClassDeclaration *cd = isClassDeclaration(); + if (cd) + { + if (cd->baseClass) + { + JsonProperty(buf, "base", cd->baseClass->toChars()); + } + if (cd->interfaces_dim) + { + JsonString(buf, "interfaces"); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (size_t i = 0; i < cd->interfaces_dim; i++) + { BaseClass *b = cd->interfaces[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + JsonString(buf, b->base->toChars()); + } + JsonRemoveComma(buf); + buf->writestring("],\n"); + } + } + + if (members) + { + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = members->tdata()[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); + } + JsonRemoveComma(buf); + buf->writestring("]\n"); + } + JsonRemoveComma(buf); + + buf->writestring("}\n"); +} + +void TemplateDeclaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("TemplateDeclaration::toJsonBuffer()\n"); + + buf->writestring("{\n"); + + JsonProperty(buf, Pname, toChars()); + JsonProperty(buf, Pkind, kind()); + + if (prot()) + JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + if (loc.linnum) + JsonProperty(buf, Pline, loc.linnum); + + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = members->tdata()[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); + } + JsonRemoveComma(buf); + buf->writestring("]\n"); + + buf->writestring("}\n"); +} + +void EnumDeclaration::toJsonBuffer(OutBuffer *buf) +{ + //printf("EnumDeclaration::toJsonBuffer()\n"); + if (isAnonymous()) + { + if (members) + { + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *s = members->tdata()[i]; + s->toJsonBuffer(buf); + buf->writestring(",\n"); + } + JsonRemoveComma(buf); + } + return; + } + + buf->writestring("{\n"); + + JsonProperty(buf, Pname, toChars()); + JsonProperty(buf, Pkind, kind()); + + if (prot()) + JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + if (loc.linnum) + JsonProperty(buf, Pline, loc.linnum); + + if (memtype) + JsonProperty(buf, "base", memtype->toChars()); + + if (members) + { + JsonString(buf, Pmembers); + buf->writestring(" : [\n"); + size_t offset = buf->offset; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = members->tdata()[i]; + if (offset != buf->offset) + { buf->writestring(",\n"); + offset = buf->offset; + } + s->toJsonBuffer(buf); + } + JsonRemoveComma(buf); + buf->writestring("]\n"); + } + JsonRemoveComma(buf); + + buf->writestring("}\n"); +} + +void EnumMember::toJsonBuffer(OutBuffer *buf) +{ + //printf("EnumMember::toJsonBuffer()\n"); + buf->writestring("{\n"); + + JsonProperty(buf, Pname, toChars()); + JsonProperty(buf, Pkind, kind()); + + if (prot()) + JsonProperty(buf, Pprotection, Pprotectionnames[prot()]); + + if (comment) + JsonProperty(buf, Pcomment, (const char *)comment); + + if (loc.linnum) + JsonProperty(buf, Pline, loc.linnum); + + JsonRemoveComma(buf); + buf->writestring("}\n"); +} + + diff --git a/dmd/json.h b/dmd/json.h index 1cf8bfab..2c7e2e60 100644 --- a/dmd/json.h +++ b/dmd/json.h @@ -1,24 +1,24 @@ - - -// 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. - -#ifndef DMD_JSON_H -#define DMD_JSON_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "arraytypes.h" - -void json_generate(Modules *); - -#endif /* DMD_JSON_H */ - + + +// 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. + +#ifndef DMD_JSON_H +#define DMD_JSON_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "arraytypes.h" + +void json_generate(Modules *); + +#endif /* DMD_JSON_H */ + diff --git a/dmd/lexer.c b/dmd/lexer.c index 1ba4d15b..5495b86a 100644 --- a/dmd/lexer.c +++ b/dmd/lexer.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -16,7 +16,7 @@ #include #endif -#include +#include /* Lexical Analyzer */ @@ -106,7 +106,7 @@ void Token::print() const char *Token::toChars() { const char *p; - static char buffer[3 + 3 * sizeof(float80value) + 1]; + static char buffer[3 + 3 * sizeof(float80value) + 1]; p = buffer; switch (value) @@ -123,11 +123,11 @@ const char *Token::toChars() break; case TOKint64v: - sprintf(buffer,"%jdL",(intmax_t)int64value); + sprintf(buffer,"%jdL",(intmax_t)int64value); break; case TOKuns64v: - sprintf(buffer,"%juUL",(uintmax_t)uns64value); + sprintf(buffer,"%juUL",(uintmax_t)uns64value); break; #if IN_GCC @@ -304,20 +304,20 @@ void Lexer::error(const char *format, ...) { va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(loc, format, ap); va_end(ap); } void Lexer::error(Loc loc, const char *format, ...) { - va_list ap; - va_start(ap, format); - verror(loc, format, ap); - va_end(ap); -} - -void Lexer::verror(Loc loc, const char *format, va_list ap) -{ + va_list ap; + va_start(ap, format); + verror(loc, format, ap); + va_end(ap); +} + +void Lexer::verror(Loc loc, const char *format, va_list ap) +{ if (mod && !global.gag) { char *p = loc.toChars(); @@ -333,10 +333,10 @@ void Lexer::verror(Loc loc, const char *format, va_list ap) if (global.errors >= 20) // moderate blizzard of cascading messages fatal(); } - else - { - global.gaggedErrors++; - } + else + { + global.gaggedErrors++; + } global.errors++; } @@ -736,7 +736,7 @@ void Lexer::scan(Token *t) for (const char *p = global.version + 1; 1; p++) { char c = *p; - if (isdigit((unsigned char)c)) + if (isdigit((unsigned char)c)) minor = minor * 10 + c - '0'; else if (c == '.') { major = minor; @@ -1148,12 +1148,12 @@ void Lexer::scan(Token *t) else t->value = TOKequal; // == } -#if DMDV2 - else if (*p == '>') - { p++; - t->value = TOKgoesto; // => - } -#endif +#if DMDV2 + else if (*p == '>') + { p++; + t->value = TOKgoesto; // => + } +#endif else t->value = TOKassign; // = return; @@ -2079,13 +2079,13 @@ TOK Lexer::number(Token *t) continue; } if (c == '.' && p[1] != '.') - { -#if DMDV2 - if (isalpha(p[1]) || p[1] == '_') - goto done; -#endif + { +#if DMDV2 + if (isalpha(p[1]) || p[1] == '_') + goto done; +#endif goto real; - } + } else if (c == 'i' || c == 'f' || c == 'F' || c == 'e' || c == 'E') { @@ -2234,7 +2234,7 @@ done: p += 2, r = 16; else if (p[1] == 'b' || p[1] == 'B') p += 2, r = 2; - else if (isdigit((unsigned char)p[1])) + else if (isdigit((unsigned char)p[1])) p += 1, r = 8; } @@ -2269,7 +2269,7 @@ done: } // Parse trailing 'u', 'U', 'l' or 'L' in any combination - const unsigned char *psuffix = p; + const unsigned char *psuffix = p; while (1) { unsigned char f; @@ -2296,12 +2296,12 @@ done: break; } -#if DMDV2 - if (state == STATE_octal && n >= 8 && !global.params.useDeprecated) - error("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead", - n, p - psuffix, psuffix, n, p - psuffix, psuffix); -#endif - +#if DMDV2 + if (state == STATE_octal && n >= 8 && !global.params.useDeprecated) + error("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead", + n, p - psuffix, psuffix, n, p - psuffix, psuffix); +#endif + switch (flags) { case 0: @@ -2582,10 +2582,10 @@ void Lexer::pragma() scan(&tok); if (tok.value == TOKint32v || tok.value == TOKint64v) - { linnum = tok.uns64value - 1; - if (linnum != tok.uns64value - 1) - error("line number out of range"); - } + { linnum = tok.uns64value - 1; + if (linnum != tok.uns64value - 1) + error("line number out of range"); + } else goto Lerr; @@ -3028,7 +3028,7 @@ static Keyword keywords[] = { "__thread", TOKtls }, { "__gshared", TOKgshared }, { "__traits", TOKtraits }, - { "__vector", TOKvector }, + { "__vector", TOKvector }, { "__overloadset", TOKoverloadset }, { "__FILE__", TOKfile }, { "__LINE__", TOKline }, @@ -3048,22 +3048,22 @@ int Token::isKeyword() } void Lexer::initKeywords() -{ +{ unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]); - stringtable.init(1543); - + stringtable.init(1543); + if (global.params.Dversion == 1) nkeywords -= 2; cmtable_init(); - for (unsigned u = 0; u < nkeywords; u++) - { + for (unsigned u = 0; u < nkeywords; u++) + { //printf("keyword[%d] = '%s'\n",u, keywords[u].name); - const char *s = keywords[u].name; - enum TOK v = keywords[u].value; - StringValue *sv = stringtable.insert(s, strlen(s)); + const char *s = keywords[u].name; + enum TOK v = keywords[u].value; + StringValue *sv = stringtable.insert(s, strlen(s)); sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v); //printf("tochars[%d] = '%s'\n",v, s); @@ -3160,7 +3160,7 @@ void Lexer::initKeywords() Token::tochars[TOKat] = "@"; Token::tochars[TOKpow] = "^^"; Token::tochars[TOKpowass] = "^^="; - Token::tochars[TOKgoesto] = "=>"; + Token::tochars[TOKgoesto] = "=>"; #endif // For debugging diff --git a/dmd/lexer.h b/dmd/lexer.h index ccb3a799..c844f155 100644 --- a/dmd/lexer.h +++ b/dmd/lexer.h @@ -304,7 +304,7 @@ struct Lexer TOK inreal(Token *t); void error(const char *format, ...) IS_PRINTF(2); void error(Loc loc, const char *format, ...) IS_PRINTF(3); - void verror(Loc loc, const char *format, va_list ap); + void verror(Loc loc, const char *format, va_list ap); void pragma(); unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); diff --git a/dmd/macro.c b/dmd/macro.c index e87a0e06..398ba77f 100644 --- a/dmd/macro.c +++ b/dmd/macro.c @@ -1,449 +1,449 @@ - -// 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. - -/* Simple macro text processor. - */ - -#include -#include -#include -#include -#include - -#include "rmem.h" -#include "root.h" - -#include "macro.h" - -#define isidstart(c) (isalpha(c) || (c) == '_') -#define isidchar(c) (isalnum(c) || (c) == '_') - -unsigned char *memdup(unsigned char *p, size_t len) -{ - return (unsigned char *)memcpy(mem.malloc(len), p, len); -} - -Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen) -{ - next = NULL; - -#if 1 - this->name = name; - this->namelen = namelen; - - this->text = text; - this->textlen = textlen; -#else - this->name = name; - this->namelen = namelen; - - this->text = text; - this->textlen = textlen; -#endif - inuse = 0; -} - - -Macro *Macro::search(unsigned char *name, size_t namelen) -{ Macro *table; - - //printf("Macro::search(%.*s)\n", namelen, name); - for (table = this; table; table = table->next) - { - if (table->namelen == namelen && - memcmp(table->name, name, namelen) == 0) - { - //printf("\tfound %d\n", table->textlen); - break; - } - } - return table; -} - -Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen) -{ - //printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text); - - Macro *table; - - //assert(ptable); - for (table = *ptable; table; table = table->next) - { - if (table->namelen == namelen && - memcmp(table->name, name, namelen) == 0) - { - table->text = text; - table->textlen = textlen; - return table; - } - } - table = new Macro(name, namelen, text, textlen); - table->next = *ptable; - *ptable = table; - return table; -} - -/********************************************************** - * Given buffer p[0..end], extract argument marg[0..marglen]. - * Params: - * n 0: get entire argument - * 1..9: get nth argument - * -1: get 2nd through end - */ - -unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n) -{ - /* Scan forward for matching right parenthesis. - * Nest parentheses. - * Skip over $( and $) - * Skip over "..." and '...' strings inside HTML tags. - * Skip over comments. - * Skip over previous macro insertions - * Set marglen. - */ - unsigned parens = 1; - unsigned char instring = 0; - unsigned incomment = 0; - unsigned intag = 0; - unsigned inexp = 0; - unsigned argn = 0; - - unsigned v = 0; - - Largstart: -#if 1 - // Skip first space, if any, to find the start of the macro argument - if (v < end && isspace(p[v])) - v++; -#else - // Skip past spaces to find the start of the macro argument - for (; v < end && isspace(p[v]); v++) - ; -#endif - *pmarg = p + v; - - for (; v < end; v++) - { unsigned char c = p[v]; - - switch (c) - { - case ',': - if (!inexp && !instring && !incomment && parens == 1) - { - argn++; - if (argn == 1 && n == -1) - { v++; - goto Largstart; - } - if (argn == n) - break; - if (argn + 1 == n) - { v++; - goto Largstart; - } - } - continue; - - case '(': - if (!inexp && !instring && !incomment) - parens++; - continue; - - case ')': - if (!inexp && !instring && !incomment && --parens == 0) - { - break; - } - continue; - - case '"': - case '\'': - if (!inexp && !incomment && intag) - { - if (c == instring) - instring = 0; - else if (!instring) - instring = c; - } - continue; - - case '<': - if (!inexp && !instring && !incomment) - { - if (v + 6 < end && - p[v + 1] == '!' && - p[v + 2] == '-' && - p[v + 3] == '-') - { - incomment = 1; - v += 3; - } - else if (v + 2 < end && - isalpha(p[v + 1])) - intag = 1; - } - continue; - - case '>': - if (!inexp) - intag = 0; - continue; - - case '-': - if (!inexp && - !instring && - incomment && - v + 2 < end && - p[v + 1] == '-' && - p[v + 2] == '>') - { - incomment = 0; - v += 2; - } - continue; - - case 0xFF: - if (v + 1 < end) - { - if (p[v + 1] == '{') - inexp++; - else if (p[v + 1] == '}') - inexp--; - } - continue; - - default: - continue; - } - break; - } - if (argn == 0 && n == -1) - *pmarg = p + v; - *pmarglen = p + v - *pmarg; - //printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg); - return v; -} - - -/***************************************************** - * Expand macro in place in buf. - * Only look at the text in buf from start to end. - */ - -void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend, - unsigned char *arg, unsigned arglen) -{ -#if 0 - printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg); - printf("Buf is: '%.*s'\n", *pend - start, buf->data + start); -#endif - - static int nest; - if (nest > 100) // limit recursive expansion - return; - nest++; - - unsigned end = *pend; - assert(start <= end); - assert(end <= buf->offset); - - /* First pass - replace $0 - */ - arg = memdup(arg, arglen); - for (unsigned u = start; u + 1 < end; ) - { - unsigned char *p = buf->data; // buf->data is not loop invariant - - /* Look for $0, but not $$0, and replace it with arg. - */ - if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+')) - { - if (u > start && p[u - 1] == '$') - { // Don't expand $$0, but replace it with $0 - buf->remove(u - 1, 1); - end--; - u += 1; // now u is one past the closing '1' - continue; - } - - unsigned char c = p[u + 1]; - int n = (c == '+') ? -1 : c - '0'; - - unsigned char *marg; - unsigned marglen; - extractArgN(arg, arglen, &marg, &marglen, n); - if (marglen == 0) - { // Just remove macro invocation - //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); - buf->remove(u, 2); - end -= 2; - } - else if (c == '+') - { - // Replace '$+' with 'arg' - //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); - buf->remove(u, 2); - buf->insert(u, marg, marglen); - end += marglen - 2; - - // Scan replaced text for further expansion - unsigned mend = u + marglen; - expand(buf, u, &mend, NULL, 0); - end += mend - (u + marglen); - u = mend; - } - else - { - // Replace '$1' with '\xFF{arg\xFF}' - //printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg); - buf->data[u] = 0xFF; - buf->data[u + 1] = '{'; - buf->insert(u + 2, marg, marglen); - buf->insert(u + 2 + marglen, "\xFF}", 2); - end += -2 + 2 + marglen + 2; - - // Scan replaced text for further expansion - unsigned mend = u + 2 + marglen; - expand(buf, u + 2, &mend, NULL, 0); - end += mend - (u + 2 + marglen); - u = mend; - } - //printf("u = %d, end = %d\n", u, end); - //printf("#%.*s#\n", end, &buf->data[0]); - continue; - } - - u++; - } - - /* Second pass - replace other macros - */ - for (unsigned u = start; u + 4 < end; ) - { - unsigned char *p = buf->data; // buf->data is not loop invariant - - /* A valid start of macro expansion is $(c, where c is - * an id start character, and not $$(c. - */ - if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2])) - { - //printf("\tfound macro start '%c'\n", p[u + 2]); - unsigned char *name = p + u + 2; - unsigned namelen = 0; - - unsigned char *marg; - unsigned marglen; - - unsigned v; - /* Scan forward to find end of macro name and - * beginning of macro argument (marg). - */ - for (v = u + 2; v < end; v++) - { unsigned char c = p[v]; - - if (!isidchar(c)) - { // We've gone past the end of the macro name. - namelen = v - (u + 2); - break; - } - } - - v += extractArgN(p + v, end - v, &marg, &marglen, 0); - assert(v <= end); - - if (v < end) - { // v is on the closing ')' - if (u > start && p[u - 1] == '$') - { // Don't expand $$(NAME), but replace it with $(NAME) - buf->remove(u - 1, 1); - end--; - u = v; // now u is one past the closing ')' - continue; - } - - Macro *m = search(name, namelen); - if (m) - { -#if 0 - if (m->textlen && m->text[0] == ' ') - { m->text++; - m->textlen--; - } -#endif - if (m->inuse && marglen == 0) - { // Remove macro invocation - buf->remove(u, v + 1 - u); - end -= v + 1 - u; - } - else if (m->inuse && arglen == marglen && memcmp(arg, marg, arglen) == 0) - { // Recursive expansion; just leave in place - - } - else - { - //printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text); -#if 1 - marg = memdup(marg, marglen); - // Insert replacement text - buf->spread(v + 1, 2 + m->textlen + 2); - buf->data[v + 1] = 0xFF; - buf->data[v + 2] = '{'; - memcpy(buf->data + v + 3, m->text, m->textlen); - buf->data[v + 3 + m->textlen] = 0xFF; - buf->data[v + 3 + m->textlen + 1] = '}'; - - end += 2 + m->textlen + 2; - - // Scan replaced text for further expansion - m->inuse++; - unsigned mend = v + 1 + 2+m->textlen+2; - expand(buf, v + 1, &mend, marg, marglen); - end += mend - (v + 1 + 2+m->textlen+2); - m->inuse--; - - buf->remove(u, v + 1 - u); - end -= v + 1 - u; - u += mend - (v + 1); -#else - // Insert replacement text - buf->insert(v + 1, m->text, m->textlen); - end += m->textlen; - - // Scan replaced text for further expansion - m->inuse++; - unsigned mend = v + 1 + m->textlen; - expand(buf, v + 1, &mend, marg, marglen); - end += mend - (v + 1 + m->textlen); - m->inuse--; - - buf->remove(u, v + 1 - u); - end -= v + 1 - u; - u += mend - (v + 1); -#endif - mem.free(marg); - //printf("u = %d, end = %d\n", u, end); - //printf("#%.*s#\n", end - u, &buf->data[u]); - continue; - } - } - else - { - // Replace $(NAME) with nothing - buf->remove(u, v + 1 - u); - end -= (v + 1 - u); - continue; - } - } - } - u++; - } - mem.free(arg); - *pend = end; - nest--; -} + +// 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. + +/* Simple macro text processor. + */ + +#include +#include +#include +#include +#include + +#include "rmem.h" +#include "root.h" + +#include "macro.h" + +#define isidstart(c) (isalpha(c) || (c) == '_') +#define isidchar(c) (isalnum(c) || (c) == '_') + +unsigned char *memdup(unsigned char *p, size_t len) +{ + return (unsigned char *)memcpy(mem.malloc(len), p, len); +} + +Macro::Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen) +{ + next = NULL; + +#if 1 + this->name = name; + this->namelen = namelen; + + this->text = text; + this->textlen = textlen; +#else + this->name = name; + this->namelen = namelen; + + this->text = text; + this->textlen = textlen; +#endif + inuse = 0; +} + + +Macro *Macro::search(unsigned char *name, size_t namelen) +{ Macro *table; + + //printf("Macro::search(%.*s)\n", namelen, name); + for (table = this; table; table = table->next) + { + if (table->namelen == namelen && + memcmp(table->name, name, namelen) == 0) + { + //printf("\tfound %d\n", table->textlen); + break; + } + } + return table; +} + +Macro *Macro::define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen) +{ + //printf("Macro::define('%.*s' = '%.*s')\n", namelen, name, textlen, text); + + Macro *table; + + //assert(ptable); + for (table = *ptable; table; table = table->next) + { + if (table->namelen == namelen && + memcmp(table->name, name, namelen) == 0) + { + table->text = text; + table->textlen = textlen; + return table; + } + } + table = new Macro(name, namelen, text, textlen); + table->next = *ptable; + *ptable = table; + return table; +} + +/********************************************************** + * Given buffer p[0..end], extract argument marg[0..marglen]. + * Params: + * n 0: get entire argument + * 1..9: get nth argument + * -1: get 2nd through end + */ + +unsigned extractArgN(unsigned char *p, unsigned end, unsigned char **pmarg, unsigned *pmarglen, int n) +{ + /* Scan forward for matching right parenthesis. + * Nest parentheses. + * Skip over $( and $) + * Skip over "..." and '...' strings inside HTML tags. + * Skip over comments. + * Skip over previous macro insertions + * Set marglen. + */ + unsigned parens = 1; + unsigned char instring = 0; + unsigned incomment = 0; + unsigned intag = 0; + unsigned inexp = 0; + unsigned argn = 0; + + unsigned v = 0; + + Largstart: +#if 1 + // Skip first space, if any, to find the start of the macro argument + if (v < end && isspace(p[v])) + v++; +#else + // Skip past spaces to find the start of the macro argument + for (; v < end && isspace(p[v]); v++) + ; +#endif + *pmarg = p + v; + + for (; v < end; v++) + { unsigned char c = p[v]; + + switch (c) + { + case ',': + if (!inexp && !instring && !incomment && parens == 1) + { + argn++; + if (argn == 1 && n == -1) + { v++; + goto Largstart; + } + if (argn == n) + break; + if (argn + 1 == n) + { v++; + goto Largstart; + } + } + continue; + + case '(': + if (!inexp && !instring && !incomment) + parens++; + continue; + + case ')': + if (!inexp && !instring && !incomment && --parens == 0) + { + break; + } + continue; + + case '"': + case '\'': + if (!inexp && !incomment && intag) + { + if (c == instring) + instring = 0; + else if (!instring) + instring = c; + } + continue; + + case '<': + if (!inexp && !instring && !incomment) + { + if (v + 6 < end && + p[v + 1] == '!' && + p[v + 2] == '-' && + p[v + 3] == '-') + { + incomment = 1; + v += 3; + } + else if (v + 2 < end && + isalpha(p[v + 1])) + intag = 1; + } + continue; + + case '>': + if (!inexp) + intag = 0; + continue; + + case '-': + if (!inexp && + !instring && + incomment && + v + 2 < end && + p[v + 1] == '-' && + p[v + 2] == '>') + { + incomment = 0; + v += 2; + } + continue; + + case 0xFF: + if (v + 1 < end) + { + if (p[v + 1] == '{') + inexp++; + else if (p[v + 1] == '}') + inexp--; + } + continue; + + default: + continue; + } + break; + } + if (argn == 0 && n == -1) + *pmarg = p + v; + *pmarglen = p + v - *pmarg; + //printf("extractArg%d('%.*s') = '%.*s'\n", n, end, p, *pmarglen, *pmarg); + return v; +} + + +/***************************************************** + * Expand macro in place in buf. + * Only look at the text in buf from start to end. + */ + +void Macro::expand(OutBuffer *buf, unsigned start, unsigned *pend, + unsigned char *arg, unsigned arglen) +{ +#if 0 + printf("Macro::expand(buf[%d..%d], arg = '%.*s')\n", start, *pend, arglen, arg); + printf("Buf is: '%.*s'\n", *pend - start, buf->data + start); +#endif + + static int nest; + if (nest > 100) // limit recursive expansion + return; + nest++; + + unsigned end = *pend; + assert(start <= end); + assert(end <= buf->offset); + + /* First pass - replace $0 + */ + arg = memdup(arg, arglen); + for (unsigned u = start; u + 1 < end; ) + { + unsigned char *p = buf->data; // buf->data is not loop invariant + + /* Look for $0, but not $$0, and replace it with arg. + */ + if (p[u] == '$' && (isdigit(p[u + 1]) || p[u + 1] == '+')) + { + if (u > start && p[u - 1] == '$') + { // Don't expand $$0, but replace it with $0 + buf->remove(u - 1, 1); + end--; + u += 1; // now u is one past the closing '1' + continue; + } + + unsigned char c = p[u + 1]; + int n = (c == '+') ? -1 : c - '0'; + + unsigned char *marg; + unsigned marglen; + extractArgN(arg, arglen, &marg, &marglen, n); + if (marglen == 0) + { // Just remove macro invocation + //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); + buf->remove(u, 2); + end -= 2; + } + else if (c == '+') + { + // Replace '$+' with 'arg' + //printf("Replacing '$%c' with '%.*s'\n", p[u + 1], marglen, marg); + buf->remove(u, 2); + buf->insert(u, marg, marglen); + end += marglen - 2; + + // Scan replaced text for further expansion + unsigned mend = u + marglen; + expand(buf, u, &mend, NULL, 0); + end += mend - (u + marglen); + u = mend; + } + else + { + // Replace '$1' with '\xFF{arg\xFF}' + //printf("Replacing '$%c' with '\xFF{%.*s\xFF}'\n", p[u + 1], marglen, marg); + buf->data[u] = 0xFF; + buf->data[u + 1] = '{'; + buf->insert(u + 2, marg, marglen); + buf->insert(u + 2 + marglen, "\xFF}", 2); + end += -2 + 2 + marglen + 2; + + // Scan replaced text for further expansion + unsigned mend = u + 2 + marglen; + expand(buf, u + 2, &mend, NULL, 0); + end += mend - (u + 2 + marglen); + u = mend; + } + //printf("u = %d, end = %d\n", u, end); + //printf("#%.*s#\n", end, &buf->data[0]); + continue; + } + + u++; + } + + /* Second pass - replace other macros + */ + for (unsigned u = start; u + 4 < end; ) + { + unsigned char *p = buf->data; // buf->data is not loop invariant + + /* A valid start of macro expansion is $(c, where c is + * an id start character, and not $$(c. + */ + if (p[u] == '$' && p[u + 1] == '(' && isidstart(p[u + 2])) + { + //printf("\tfound macro start '%c'\n", p[u + 2]); + unsigned char *name = p + u + 2; + unsigned namelen = 0; + + unsigned char *marg; + unsigned marglen; + + unsigned v; + /* Scan forward to find end of macro name and + * beginning of macro argument (marg). + */ + for (v = u + 2; v < end; v++) + { unsigned char c = p[v]; + + if (!isidchar(c)) + { // We've gone past the end of the macro name. + namelen = v - (u + 2); + break; + } + } + + v += extractArgN(p + v, end - v, &marg, &marglen, 0); + assert(v <= end); + + if (v < end) + { // v is on the closing ')' + if (u > start && p[u - 1] == '$') + { // Don't expand $$(NAME), but replace it with $(NAME) + buf->remove(u - 1, 1); + end--; + u = v; // now u is one past the closing ')' + continue; + } + + Macro *m = search(name, namelen); + if (m) + { +#if 0 + if (m->textlen && m->text[0] == ' ') + { m->text++; + m->textlen--; + } +#endif + if (m->inuse && marglen == 0) + { // Remove macro invocation + buf->remove(u, v + 1 - u); + end -= v + 1 - u; + } + else if (m->inuse && arglen == marglen && memcmp(arg, marg, arglen) == 0) + { // Recursive expansion; just leave in place + + } + else + { + //printf("\tmacro '%.*s'(%.*s) = '%.*s'\n", m->namelen, m->name, marglen, marg, m->textlen, m->text); +#if 1 + marg = memdup(marg, marglen); + // Insert replacement text + buf->spread(v + 1, 2 + m->textlen + 2); + buf->data[v + 1] = 0xFF; + buf->data[v + 2] = '{'; + memcpy(buf->data + v + 3, m->text, m->textlen); + buf->data[v + 3 + m->textlen] = 0xFF; + buf->data[v + 3 + m->textlen + 1] = '}'; + + end += 2 + m->textlen + 2; + + // Scan replaced text for further expansion + m->inuse++; + unsigned mend = v + 1 + 2+m->textlen+2; + expand(buf, v + 1, &mend, marg, marglen); + end += mend - (v + 1 + 2+m->textlen+2); + m->inuse--; + + buf->remove(u, v + 1 - u); + end -= v + 1 - u; + u += mend - (v + 1); +#else + // Insert replacement text + buf->insert(v + 1, m->text, m->textlen); + end += m->textlen; + + // Scan replaced text for further expansion + m->inuse++; + unsigned mend = v + 1 + m->textlen; + expand(buf, v + 1, &mend, marg, marglen); + end += mend - (v + 1 + m->textlen); + m->inuse--; + + buf->remove(u, v + 1 - u); + end -= v + 1 - u; + u += mend - (v + 1); +#endif + mem.free(marg); + //printf("u = %d, end = %d\n", u, end); + //printf("#%.*s#\n", end - u, &buf->data[u]); + continue; + } + } + else + { + // Replace $(NAME) with nothing + buf->remove(u, v + 1 - u); + end -= (v + 1 - u); + continue; + } + } + } + u++; + } + mem.free(arg); + *pend = end; + nest--; +} diff --git a/dmd/macro.h b/dmd/macro.h index 7c6d4928..7c939621 100644 --- a/dmd/macro.h +++ b/dmd/macro.h @@ -1,45 +1,45 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2011 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. - -#ifndef DMD_MACRO_H -#define DMD_MACRO_H 1 - -#include -#include -#include -#include - -#include "root.h" - - -struct Macro -{ - private: - Macro *next; // next in list - - unsigned char *name; // macro name - size_t namelen; // length of macro name - - unsigned char *text; // macro replacement text - size_t textlen; // length of replacement text - - int inuse; // macro is in use (don't expand) - - Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); - Macro *search(unsigned char *name, size_t namelen); - - public: - static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); - - void expand(OutBuffer *buf, unsigned start, unsigned *pend, - unsigned char *arg, unsigned arglen); -}; - -#endif + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 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. + +#ifndef DMD_MACRO_H +#define DMD_MACRO_H 1 + +#include +#include +#include +#include + +#include "root.h" + + +struct Macro +{ + private: + Macro *next; // next in list + + unsigned char *name; // macro name + size_t namelen; // length of macro name + + unsigned char *text; // macro replacement text + size_t textlen; // length of replacement text + + int inuse; // macro is in use (don't expand) + + Macro(unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); + Macro *search(unsigned char *name, size_t namelen); + + public: + static Macro *define(Macro **ptable, unsigned char *name, size_t namelen, unsigned char *text, size_t textlen); + + void expand(OutBuffer *buf, unsigned start, unsigned *pend, + unsigned char *arg, unsigned arglen); +}; + +#endif diff --git a/dmd/mangle.c b/dmd/mangle.c index 39549179..bd089803 100644 --- a/dmd/mangle.c +++ b/dmd/mangle.c @@ -24,7 +24,7 @@ #include "id.h" #include "module.h" -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS +#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS char *cpp_mangle(Dsymbol *s); #endif @@ -34,7 +34,7 @@ char *mangle(Declaration *sthis) char *id; Dsymbol *s; - //printf("::mangle(%s), type %s\n", sthis->toChars(), sthis->type->toChars()); + //printf("::mangle(%s), type %s\n", sthis->toChars(), sthis->type->toChars()); s = sthis; do { @@ -122,7 +122,7 @@ char *Declaration::mangle() return ident->toChars(); case LINKcpp: -#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) +#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) return cpp_mangle(this); #else // Windows C++ mangling is done by C++ back end diff --git a/dmd/mars.c b/dmd/mars.c index 1faab5e8..ebb64290 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -36,21 +36,21 @@ #include "lexer.h" #include "json.h" -#if WINDOWS_SEH -#include -long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); -#endif - - -int response_expand(int *pargc, char ***pargv); -void browse(const char *url); -void getenv_setargv(const char *envvar, int *pargc, char** *pargv); - -void obj_start(char *srcfile); -void obj_end(Library *library, File *objfile); - -void printCtfePerformanceStats(); - +#if WINDOWS_SEH +#include +long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep); +#endif + + +int response_expand(int *pargc, char ***pargv); +void browse(const char *url); +void getenv_setargv(const char *envvar, int *pargc, char** *pargv); + +void obj_start(char *srcfile); +void obj_end(Library *library, File *objfile); + +void printCtfePerformanceStats(); + Global global; Global::Global() @@ -72,9 +72,9 @@ Global::Global() obj_ext_alt = "obj"; #endif - copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen"; + copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen"; - version = "v1.073"; + version = "v1.073"; ldc_version = "LDC trunk"; llvm_version = "LLVM 3.0"; global.structalign = 8; @@ -87,24 +87,24 @@ Global::Global() // may run before this one. } -unsigned Global::startGagging() -{ - ++gag; - return gaggedErrors; -} - -bool Global::endGagging(unsigned oldGagged) -{ - bool anyErrs = (gaggedErrors != oldGagged); - --gag; - // Restore the original state of gagged errors; set total errors - // to be original errors + new ungagged errors. - errors -= (gaggedErrors - oldGagged); - gaggedErrors = oldGagged; - return anyErrs; -} - - +unsigned Global::startGagging() +{ + ++gag; + return gaggedErrors; +} + +bool Global::endGagging(unsigned oldGagged) +{ + bool anyErrs = (gaggedErrors != oldGagged); + --gag; + // Restore the original state of gagged errors; set total errors + // to be original errors + new ungagged errors. + errors -= (gaggedErrors - oldGagged); + gaggedErrors = oldGagged; + return anyErrs; +} + + char *Loc::toChars() const { OutBuffer buf; @@ -132,7 +132,7 @@ bool Loc::equals(const Loc& loc) } /************************************** - * Print error message + * Print error message */ void error(Loc loc, const char *format, ...) @@ -151,18 +151,18 @@ void warning(Loc loc, const char *format, ...) va_end( ap ); } -/************************************** - * Print supplementary message about the last error - * Used for backtraces, etc - */ -void errorSupplemental(Loc loc, const char *format, ...) -{ - va_list ap; - va_start(ap, format); - verrorSupplemental(loc, format, ap); - va_end( ap ); -} - +/************************************** + * Print supplementary message about the last error + * Used for backtraces, etc + */ +void errorSupplemental(Loc loc, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + verrorSupplemental(loc, format, ap); + va_end( ap ); +} + void verror(Loc loc, const char *format, va_list ap) { if (!global.gag) @@ -177,34 +177,34 @@ void verror(Loc loc, const char *format, va_list ap) vfprintf(stdmsg, format, ap); fprintf(stdmsg, "\n"); fflush(stdmsg); -//halt(); - } - else - { - global.gaggedErrors++; +//halt(); + } + else + { + global.gaggedErrors++; } global.errors++; } -// Doesn't increase error count, doesn't print "Error:". -void verrorSupplemental(Loc loc, const char *format, va_list ap) -{ - if (!global.gag) - { - fprintf(stdmsg, "%s: ", loc.toChars()); -#if _MSC_VER - // MS doesn't recognize %zu format - OutBuffer tmp; - tmp.vprintf(format, ap); - fprintf(stdmsg, "%s", tmp.toChars()); -#else - vfprintf(stdmsg, format, ap); -#endif - fprintf(stdmsg, "\n"); - fflush(stdmsg); - } -} - +// Doesn't increase error count, doesn't print "Error:". +void verrorSupplemental(Loc loc, const char *format, va_list ap) +{ + if (!global.gag) + { + fprintf(stdmsg, "%s: ", loc.toChars()); +#if _MSC_VER + // MS doesn't recognize %zu format + OutBuffer tmp; + tmp.vprintf(format, ap); + fprintf(stdmsg, "%s", tmp.toChars()); +#else + vfprintf(stdmsg, format, ap); +#endif + fprintf(stdmsg, "\n"); + fflush(stdmsg); + } +} + void vwarning(Loc loc, const char *format, va_list ap) { if (global.params.warnings && !global.gag) @@ -252,7 +252,7 @@ void fatal() void halt() { #ifdef DEBUG - *(volatile char*)0=0; + *(volatile char*)0=0; #endif } @@ -277,11 +277,11 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv) env = mem.strdup(env); // create our own writable copy int argc = *pargc; - Strings *argv = new Strings(); + Strings *argv = new Strings(); argv->setDim(argc); - size_t argc_left = 0; - for (size_t i = 0; i < argc; i++) { + size_t argc_left = 0; + for (size_t i = 0; i < argc; i++) { if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) { // HACK: set flag to indicate we saw '-run' here global.params.run = true; @@ -299,7 +299,7 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv) argv->push((char*)""); argc++; - size_t j = 1; // leave argv[0] alone + size_t j = 1; // leave argv[0] alone while (1) { int wildcard = 1; // do wildcard expansion @@ -378,5 +378,5 @@ Ldone: argv->data[argc++] = (void *)(*pargv)[i]; *pargc = argc; - *pargv = argv->tdata(); + *pargv = argv->tdata(); } diff --git a/dmd/mars.h b/dmd/mars.h index efe25de9..ae11e652 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -496,10 +496,10 @@ typedef uint64_t StorageClass; void warning(Loc loc, const char *format, ...) IS_PRINTF(2); void error(Loc loc, const char *format, ...) IS_PRINTF(2); -void errorSupplemental(Loc loc, const char *format, ...); +void errorSupplemental(Loc loc, const char *format, ...); void verror(Loc loc, const char *format, va_list); void vwarning(Loc loc, const char *format, va_list); -void verrorSupplemental(Loc loc, const char *format, va_list); +void verrorSupplemental(Loc loc, const char *format, va_list); #ifdef __GNUC__ __attribute__((noreturn)) #endif diff --git a/dmd/mem.h b/dmd/mem.h index 4d452e7b..85ebda62 100644 --- a/dmd/mem.h +++ b/dmd/mem.h @@ -1,51 +1,51 @@ -// Copyright (C) 2000-2001 by Chromium Communications -// All Rights Reserved - -#ifndef ROOT_MEM_H -#define ROOT_MEM_H - -#include // for size_t - -typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); - -struct GC; // thread specific allocator - -struct Mem -{ - GC *gc; // pointer to our thread specific allocator - Mem() { gc = NULL; } - - void init(); - - // Derive from Mem to get these storage allocators instead of global new/delete - void * operator new(size_t m_size); - void * operator new(size_t m_size, Mem *mem); - void * operator new(size_t m_size, GC *gc); - void operator delete(void *p); - - void * operator new[](size_t m_size); - void operator delete[](void *p); - - char *strdup(const char *s); - void *malloc(size_t size); - void *malloc_uncollectable(size_t size); - void *calloc(size_t size, size_t n); - void *realloc(void *p, size_t size); - void free(void *p); - void free_uncollectable(void *p); - void *mallocdup(void *o, size_t size); - void error(); - void check(void *p); // validate pointer - void fullcollect(); // do full garbage collection - void fullcollectNoStack(); // do full garbage collection, no scan stack - void mark(void *pointer); - void addroots(char* pStart, char* pEnd); - void removeroots(char* pStart); - void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData); - void setStackBottom(void *bottom); - GC *getThreadGC(); // get apartment allocator for this thread -}; - -extern Mem mem; - -#endif /* ROOT_MEM_H */ +// Copyright (C) 2000-2001 by Chromium Communications +// All Rights Reserved + +#ifndef ROOT_MEM_H +#define ROOT_MEM_H + +#include // for size_t + +typedef void (*FINALIZERPROC)(void* pObj, void* pClientData); + +struct GC; // thread specific allocator + +struct Mem +{ + GC *gc; // pointer to our thread specific allocator + Mem() { gc = NULL; } + + void init(); + + // Derive from Mem to get these storage allocators instead of global new/delete + void * operator new(size_t m_size); + void * operator new(size_t m_size, Mem *mem); + void * operator new(size_t m_size, GC *gc); + void operator delete(void *p); + + void * operator new[](size_t m_size); + void operator delete[](void *p); + + char *strdup(const char *s); + void *malloc(size_t size); + void *malloc_uncollectable(size_t size); + void *calloc(size_t size, size_t n); + void *realloc(void *p, size_t size); + void free(void *p); + void free_uncollectable(void *p); + void *mallocdup(void *o, size_t size); + void error(); + void check(void *p); // validate pointer + void fullcollect(); // do full garbage collection + void fullcollectNoStack(); // do full garbage collection, no scan stack + void mark(void *pointer); + void addroots(char* pStart, char* pEnd); + void removeroots(char* pStart); + void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData); + void setStackBottom(void *bottom); + GC *getThreadGC(); // get apartment allocator for this thread +}; + +extern Mem mem; + +#endif /* ROOT_MEM_H */ diff --git a/dmd/module.c b/dmd/module.c index 8bc37da4..b10357c3 100644 --- a/dmd/module.c +++ b/dmd/module.c @@ -726,12 +726,12 @@ void Module::importAll(Scope *prevsc) if (scope) return; // already done - if (isDocFile) - { - error("is a Ddoc file, cannot import it"); - return; - } - + if (isDocFile) + { + error("is a Ddoc file, cannot import it"); + return; + } + /* Note that modules get their own scope, from scratch. * This is so regardless of where in the syntax a module * gets imported, it is unaffected by context. @@ -739,14 +739,14 @@ void Module::importAll(Scope *prevsc) */ Scope *sc = Scope::createGlobal(this); // create root scope - // Add import of "object", even for the "object" module. - // If it isn't there, some compiler rewrites, like - // classinst == classinst -> .object.opEquals(classinst, classinst) - // would fail inside object.d. - if (members->dim == 0 || ((*members)[0])->ident != Id::object) + // Add import of "object", even for the "object" module. + // If it isn't there, some compiler rewrites, like + // classinst == classinst -> .object.opEquals(classinst, classinst) + // would fail inside object.d. + if (members->dim == 0 || ((*members)[0])->ident != Id::object) { - Import *im = new Import(0, NULL, Id::object, NULL, 0); - members->shift(im); + Import *im = new Import(0, NULL, Id::object, NULL, 0); + members->shift(im); } if (!symtab) diff --git a/dmd/module.h b/dmd/module.h index 4384d4eb..086e0ee8 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -51,7 +51,7 @@ struct Package : ScopeDsymbol Package(Identifier *ident); const char *kind(); - static DsymbolTable *resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg); + static DsymbolTable *resolve(Identifiers *packages, Dsymbol **pparent, Package **ppkg); Package *isPackage() { return this; } @@ -62,8 +62,8 @@ struct Module : Package { static Module *rootModule; static DsymbolTable *modules; // symbol table of all modules - static Modules amodules; // array of all modules - static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them + static Modules amodules; // array of all modules + static Dsymbols deferred; // deferred Dsymbol's needing semantic() run on them static unsigned dprogress; // progress resolving the deferred list static void init(); @@ -104,19 +104,19 @@ struct Module : Package // i.e. a module that will be taken all the // way to an object file - Dsymbols *decldefs; // top level declarations for this Module + Dsymbols *decldefs; // top level declarations for this Module - Modules aimports; // all imported modules + Modules aimports; // all imported modules ModuleInfoDeclaration *vmoduleinfo; unsigned debuglevel; // debug level - Strings *debugids; // debug identifiers - Strings *debugidsNot; // forward referenced debug identifiers + Strings *debugids; // debug identifiers + Strings *debugidsNot; // forward referenced debug identifiers unsigned versionlevel; // version level - Strings *versionids; // version identifiers - Strings *versionidsNot; // forward referenced version identifiers + Strings *versionids; // version identifiers + Strings *versionidsNot; // forward referenced version identifiers Macro *macrotable; // document comment macros struct Escape *escapetable; // document comment escapes @@ -129,7 +129,7 @@ struct Module : Package Module(char *arg, Identifier *ident, int doDocComment, int doHdrGen); ~Module(); - static Module *load(Loc loc, Identifiers *packages, Identifier *ident); + static Module *load(Loc loc, Identifiers *packages, Identifier *ident); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toJsonBuffer(OutBuffer *buf); @@ -143,13 +143,13 @@ struct Module : Package void parse(); // syntactic parse #endif void importAll(Scope *sc); - void semantic(); // semantic analysis - void semantic2(); // pass 2 semantic analysis - void semantic3(); // pass 3 semantic analysis + void semantic(); // semantic analysis + void semantic2(); // pass 2 semantic analysis + void semantic3(); // pass 3 semantic analysis void inlineScan(); // scan for functions to inline - void setHdrfile(); // set hdrfile member + void setHdrfile(); // set hdrfile member void genhdrfile(); // generate D import file - void genobjfile(int multiobj); + void genobjfile(int multiobj); // void gensymfile(); void gendocfile(); int needModuleInfo(); @@ -215,10 +215,10 @@ struct Module : Package struct ModuleDeclaration { Identifier *id; - Identifiers *packages; // array of Identifier's representing packages + Identifiers *packages; // array of Identifier's representing packages bool safe; - ModuleDeclaration(Identifiers *packages, Identifier *id); + ModuleDeclaration(Identifiers *packages, Identifier *id); char *toChars(); }; diff --git a/dmd/mtype.c b/dmd/mtype.c index 3ba7dbb8..c154419e 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -190,7 +190,7 @@ void Type::init(Ir* _sir) void Type::init() #endif { - stringtable.init(1543); + stringtable.init(1543); deco_stringtable.init(); Lexer::initKeywords(); @@ -1821,7 +1821,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) arguments->push(e); // LDC, we don't support the getInternalTypeInfo // optimization arbitrarily, not yet at least... - arguments->push(n->getTypeInfo(sc)); + arguments->push(n->getTypeInfo(sc)); e = new CallExp(e->loc, ec, arguments); e->type = next->arrayOf(); } @@ -1950,12 +1950,12 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol *pe = (Expression *)o; return; } - if (o->dyncast() == DYNCAST_TYPE) - { - *ps = NULL; - *pt = (Type *)o; - return; - } + if (o->dyncast() == DYNCAST_TYPE) + { + *ps = NULL; + *pt = (Type *)o; + return; + } /* Create a new TupleDeclaration which * is a slice [d..d+1] out of the old one. @@ -1998,7 +1998,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); return Type::terror; } - Object *o = (*sd->objects)[(size_t)d]; + Object *o = (*sd->objects)[(size_t)d]; if (o->dyncast() != DYNCAST_TYPE) { error(loc, "%s is not a type", toChars()); return Type::terror; @@ -3160,7 +3160,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) Scope *argsc = sc->push(); argsc->stc = 0; // don't inherit storage class argsc->protection = PROTpublic; - argsc->func = NULL; + argsc->func = NULL; size_t dim = Parameter::dim(tf->parameters); for (size_t i = 0; i < dim; i++) @@ -4751,7 +4751,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) if (!sym->members) { error(e->loc, "struct %s is forward referenced", sym->toChars()); - return new ErrorExp(); + return new ErrorExp(); } /* If e.tupleof @@ -4762,11 +4762,11 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) * (e.field0, e.field1, e.field2, ...) */ e = e->semantic(sc); // do this before turning on noaccesscheck - e->type->size(); // do semantic of type + e->type->size(); // do semantic of type Expressions *exps = new Expressions; exps->reserve(sym->fields.dim); for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields[i]; + { VarDeclaration *v = sym->fields[i]; Expression *fe = new DotVarExp(e->loc, e, v); exps->push(fe); } @@ -4828,8 +4828,8 @@ L1: TemplateMixin *tm = s->isTemplateMixin(); if (tm) - { - Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); + { + Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); de->type = e->type; return de; } @@ -4858,7 +4858,7 @@ L1: return de; } - if (s->isImport() || s->isModule() || s->isPackage()) + if (s->isImport() || s->isModule() || s->isPackage()) { e = new DsymbolExp(e->loc, s); e = e->semantic(sc); @@ -4955,7 +4955,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) structelems->setDim(sym->fields.dim); for (size_t j = 0; j < structelems->dim; j++) { - VarDeclaration *vd = sym->fields[j]; + VarDeclaration *vd = sym->fields[j]; Expression *e; if (vd->init) { if (vd->init->isVoidInitializer()) @@ -4965,7 +4965,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) } else e = vd->type->defaultInitLiteral(); - structelems->tdata()[j] = e; + structelems->tdata()[j] = e; } StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); // Why doesn't the StructLiteralExp constructor do this, when @@ -5026,7 +5026,7 @@ Type *TypeClass::semantic(Loc loc, Scope *sc) //printf("TypeClass::semantic(%s)\n", sym->toChars()); if (deco) return this; - //printf("\t%s\n", merge()->deco); + //printf("\t%s\n", merge()->deco); return merge(); } @@ -5090,11 +5090,11 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) /* Create a TupleExp */ e = e->semantic(sc); // do this before turning on noaccesscheck - e->type->size(); // do semantic of type + e->type->size(); // do semantic of type Expressions *exps = new Expressions; exps->reserve(sym->fields.dim); for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields[i]; + { VarDeclaration *v = sym->fields[i]; // Don't include hidden 'this' pointer if (v->isThisDeclaration()) continue; @@ -5114,16 +5114,16 @@ L1: if (!s) { // See if it's a base class - if (Dsymbol *cbase = sym->searchBase(e->loc, ident)) + if (Dsymbol *cbase = sym->searchBase(e->loc, ident)) { - e = new DotTypeExp(0, e, cbase); - return e; + e = new DotTypeExp(0, e, cbase); + return e; } if (ident == Id::classinfo) { assert(ClassDeclaration::classinfo); - Type *t = ClassDeclaration::classinfo->type; + Type *t = ClassDeclaration::classinfo->type; if (e->op == TOKtype || e->op == TOKdottype) { /* For type.classinfo, we know the classinfo @@ -5272,8 +5272,8 @@ L1: TemplateMixin *tm = s->isTemplateMixin(); if (tm) - { - Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); + { + Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm)); de->type = e->type; return de; } @@ -5302,20 +5302,20 @@ L1: return de; } -#if 0 // shouldn't this be here? - if (s->isImport() || s->isModule() || s->isPackage()) - { - e = new DsymbolExp(e->loc, s, 0); - e = e->semantic(sc); - return e; - } -#endif - - Declaration *d = s->isDeclaration(); +#if 0 // shouldn't this be here? + if (s->isImport() || s->isModule() || s->isPackage()) + { + e = new DsymbolExp(e->loc, s, 0); + e = e->semantic(sc); + return e; + } +#endif + + Declaration *d = s->isDeclaration(); if (!d) { e->error("%s.%s is not a declaration", e->toChars(), ident->toChars()); - return new ErrorExp(); + return new ErrorExp(); } if (e->op == TOKtype) @@ -5344,7 +5344,7 @@ L1: { e = new ThisExp(e->loc); e = new DotTypeExp(e->loc, e, cd); - DotVarExp *de = new DotVarExp(e->loc, e, d); + DotVarExp *de = new DotVarExp(e->loc, e, d); e = de->semantic(sc); return e; } @@ -5354,10 +5354,10 @@ L1: } } - /* Rewrite as: - * this.d - */ - DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d); + /* Rewrite as: + * this.d + */ + DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d); e = de->semantic(sc); return e; } @@ -5383,7 +5383,7 @@ L1: if (d->parent && d->toParent()->isModule()) { // (e, d) - VarExp *ve = new VarExp(e->loc, d); + VarExp *ve = new VarExp(e->loc, d); e = new CommaExp(e->loc, e, ve); e->type = d->type; return e; @@ -5423,7 +5423,7 @@ MATCH TypeClass::implicitConvTo(Type *to) ClassDeclaration *cdto = to->isClassHandle(); if (cdto && cdto->isBaseOf(sym, NULL)) - { //printf("'to' is base\n"); + { //printf("'to' is base\n"); return MATCHconvert; } @@ -5755,18 +5755,18 @@ Parameters *Parameter::arraySyntaxCopy(Parameters *args) a = new Parameters(); a->setDim(args->dim); for (size_t i = 0; i < a->dim; i++) - { Parameter *arg = (*args)[i]; + { Parameter *arg = (*args)[i]; arg = arg->syntaxCopy(); - (*a)[i] = arg; + (*a)[i] = arg; } } return a; } char *Parameter::argsTypesToChars(Parameters *args, int varargs) -{ - OutBuffer *buf = new OutBuffer(); +{ + OutBuffer *buf = new OutBuffer(); buf->writeByte('('); if (args) @@ -5776,7 +5776,7 @@ char *Parameter::argsTypesToChars(Parameters *args, int varargs) for (size_t i = 0; i < args->dim; i++) { if (i) buf->writeByte(','); - Parameter *arg = args->tdata()[i]; + Parameter *arg = args->tdata()[i]; argbuf.reset(); arg->type->toCBuffer2(&argbuf, &hgs, 0); buf->write(&argbuf); @@ -5843,7 +5843,7 @@ void Parameter::argsToDecoBuffer(OutBuffer *buf, Parameters *arguments, bool man { //printf("Parameter::argsToDecoBuffer()\n"); // Write argument types - foreach(arguments, &argsToDecoBufferDg, buf); + foreach(arguments, &argsToDecoBufferDg, buf); } /**************************************** @@ -5861,7 +5861,7 @@ static int isTPLDg(void *ctx, size_t n, Parameter *arg, int) int Parameter::isTPL(Parameters *arguments) { //printf("Parameter::isTPL()\n"); - return foreach(arguments, &isTPLDg, NULL); + return foreach(arguments, &isTPLDg, NULL); } /**************************************************** @@ -5910,7 +5910,7 @@ void Parameter::toDecoBuffer(OutBuffer *buf, bool mangle) break; default: #ifdef DEBUG - printf("storageClass = x%llx\n", storageClass & (STCin | STCout | STCref | STClazy)); + printf("storageClass = x%llx\n", storageClass & (STCin | STCout | STCref | STClazy)); halt(); #endif assert(0); @@ -5931,7 +5931,7 @@ static int dimDg(void *ctx, size_t n, Parameter *, int) size_t Parameter::dim(Parameters *args) { size_t n = 0; - foreach(args, &dimDg, &n); + foreach(args, &dimDg, &n); return n; } @@ -5976,9 +5976,9 @@ Parameter *Parameter::getNth(Parameters *args, size_t nth, size_t *pn) int Parameter::foreach(Parameters *args, Parameter::ForeachDg dg, void *ctx, size_t *pn, int flags) { - assert(dg); - if (!args) - return 0; + assert(dg); + if (!args) + return 0; size_t n = pn ? *pn : 0; // take over index int result = 0; diff --git a/dmd/mtype.h b/dmd/mtype.h index 818fc15e..44aac0f1 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -170,7 +170,7 @@ struct Type : Object #define tboolean tbool // result of boolean expression #define tindex tsize_t // array/ptr index static Type *tvoidptr; // void* - static Type *tstring; // immutable(char)[] + static Type *tstring; // immutable(char)[] #define terror basic[Terror] // for error recovery #define tsize_t basic[Tsize_t] // matches size_t alias @@ -223,7 +223,7 @@ struct Type : Object virtual d_uns64 size(Loc loc); virtual unsigned alignsize(); virtual Type *semantic(Loc loc, Scope *sc); - Type *trySemantic(Loc loc, Scope *sc); + Type *trySemantic(Loc loc, Scope *sc); // append the mangleof or a string uniquely identifying this type to buf virtual void toDecoBuffer(OutBuffer *buf, bool mangle); Type *merge(); @@ -510,7 +510,7 @@ struct TypeFunction : Type Type *semantic(Loc loc, Scope *sc); void toDecoBuffer(OutBuffer *buf, bool mangle); void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); - void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td); + void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); TypeInfoDeclaration *getTypeInfoDeclaration(); @@ -531,8 +531,8 @@ struct TypeFunction : Type FuncDeclaration* funcdecl; #endif - - Expression *defaultInit(Loc loc); + + Expression *defaultInit(Loc loc); }; struct TypeDelegate : Type @@ -558,7 +558,7 @@ struct TypeDelegate : Type struct TypeQualified : Type { Loc loc; - Identifiers idents; // array of Identifier's representing ident.ident.ident etc. + Identifiers idents; // array of Identifier's representing ident.ident.ident etc. TypeQualified(TY ty, Loc loc); void syntaxCopyHelper(TypeQualified *t); @@ -820,9 +820,9 @@ struct Parameter : Object static int isTPL(Parameters *arguments); static size_t dim(Parameters *arguments); static Parameter *getNth(Parameters *arguments, size_t nth, size_t *pn = NULL); - - typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param, int flags); - static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL, int flags = 0); + + typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param, int flags); + static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL, int flags = 0); }; extern int PTRSIZE; diff --git a/dmd/opover.c b/dmd/opover.c index cad40d3a..026543eb 100644 --- a/dmd/opover.c +++ b/dmd/opover.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com diff --git a/dmd/optimize.c b/dmd/optimize.c index 17ecf074..5bfc0d0c 100644 --- a/dmd/optimize.c +++ b/dmd/optimize.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -40,7 +40,7 @@ static real_t zero; // work around DMC bug for now * return that initializer. */ -Expression *fromConstInitializer(int result, Expression *e1) +Expression *fromConstInitializer(int result, Expression *e1) { //printf("fromConstInitializer(%s)\n", e1->toChars()); if (e1->op == TOKvar) @@ -48,13 +48,13 @@ Expression *fromConstInitializer(int result, Expression *e1) VarDeclaration *v = ve->var->isVarDeclaration(); if (v && !v->originalType && v->scope) // semantic() not yet run v->semantic (v->scope); - if (!v || !v->type) - return e1; - Type * tb = v->type->toBasetype(); - if (v->isConst() && v->init - && (result & WANTinterpret || (tb->isscalar() || - ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct)))) - ) + if (!v || !v->type) + return e1; + Type * tb = v->type->toBasetype(); + if (v->isConst() && v->init + && (result & WANTinterpret || (tb->isscalar() || + ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct)))) + ) { Expression *ei = v->init->toExpression(); if (ei && ei->type) e1 = ei; @@ -72,7 +72,7 @@ Expression *Expression::optimize(int result) Expression *VarExp::optimize(int result) { - return fromConstInitializer(result, this); + return fromConstInitializer(result, this); return this; } @@ -122,11 +122,11 @@ Expression *StructLiteralExp::optimize(int result) if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (*elements)[i]; + { Expression *e = (*elements)[i]; if (!e) continue; e = e->optimize(WANTvalue | (result & WANTinterpret)); - (*elements)[i] = e; + (*elements)[i] = e; } } return this; @@ -329,20 +329,20 @@ Expression *NewExp::optimize(int result) if (newargs) { for (size_t i = 0; i < newargs->dim; i++) - { Expression *e = newargs->tdata()[i]; + { Expression *e = newargs->tdata()[i]; e = e->optimize(WANTvalue); - newargs->tdata()[i] = e; + newargs->tdata()[i] = e; } } if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = arguments->tdata()[i]; e = e->optimize(WANTvalue); - arguments->tdata()[i] = e; + arguments->tdata()[i] = e; } } return this; @@ -357,10 +357,10 @@ Expression *CallExp::optimize(int result) if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = arguments->tdata()[i]; e = e->optimize(WANTvalue); - arguments->tdata()[i] = e; + arguments->tdata()[i] = e; } } @@ -391,7 +391,7 @@ Expression *CastExp::optimize(int result) e1 = e1->optimize(result); if (result & WANTinterpret) - e1 = fromConstInitializer(result, e1); + e1 = fromConstInitializer(result, e1); if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && @@ -466,8 +466,8 @@ Expression *BinExp::optimize(int result) { dinteger_t i2 = e2->toInteger(); d_uns64 sz = e1->type->size() * 8; - if (i2 < 0 || i2 >= sz) - { error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1); + if (i2 < 0 || i2 >= sz) + { error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1); e2 = new IntegerExp(0); } } @@ -561,8 +561,8 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E { dinteger_t i2 = e->e2->toInteger(); d_uns64 sz = e->e1->type->size() * 8; - if (i2 < 0 || i2 >= sz) - { e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1); + if (i2 < 0 || i2 >= sz) + { e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1); e->e2 = new IntegerExp(0); } if (e->e1->isConst() == 1) @@ -644,7 +644,7 @@ Expression *CommaExp::optimize(int result) e1 = e1->optimize(result & WANTinterpret); e2 = e2->optimize(result); - if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->hasSideEffect()) + if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->hasSideEffect()) { e = e2; if (e) @@ -660,7 +660,7 @@ Expression *ArrayLengthExp::optimize(int result) { Expression *e; //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); - e1 = e1->optimize(WANTvalue | WANTexpand | (result & WANTinterpret)); + e1 = e1->optimize(WANTvalue | WANTexpand | (result & WANTinterpret)); e = this; if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) { @@ -677,8 +677,8 @@ Expression *EqualExp::optimize(int result) e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; - Expression *e1 = fromConstInitializer(result, this->e1); - Expression *e2 = fromConstInitializer(result, this->e2); + Expression *e1 = fromConstInitializer(result, this->e1); + Expression *e2 = fromConstInitializer(result, this->e2); e = Equal(op, type, e1, e2); if (e == EXP_CANT_INTERPRET) @@ -703,40 +703,40 @@ Expression *IdentityExp::optimize(int result) return e; } - -/* It is possible for constant folding to change an array expression of - * unknown length, into one where the length is known. - * If the expression 'arr' is a literal, set lengthVar to be its length. - */ -void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr) -{ - if (!lengthVar) - return; - if (lengthVar->init && !lengthVar->init->isVoidInitializer()) - return; // we have previously calculated the length - size_t len; - if (arr->op == TOKstring) - len = ((StringExp *)arr)->len; - else if (arr->op == TOKarrayliteral) - len = ((ArrayLiteralExp *)arr)->elements->dim; - else - return; // we don't know the length yet - - Expression *dollar = new IntegerExp(0, len, Type::tsize_t); - lengthVar->init = new ExpInitializer(0, dollar); - lengthVar->storage_class |= STCstatic | STCconst; -} - - + +/* It is possible for constant folding to change an array expression of + * unknown length, into one where the length is known. + * If the expression 'arr' is a literal, set lengthVar to be its length. + */ +void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr) +{ + if (!lengthVar) + return; + if (lengthVar->init && !lengthVar->init->isVoidInitializer()) + return; // we have previously calculated the length + size_t len; + if (arr->op == TOKstring) + len = ((StringExp *)arr)->len; + else if (arr->op == TOKarrayliteral) + len = ((ArrayLiteralExp *)arr)->elements->dim; + else + return; // we don't know the length yet + + Expression *dollar = new IntegerExp(0, len, Type::tsize_t); + lengthVar->init = new ExpInitializer(0, dollar); + lengthVar->storage_class |= STCstatic | STCconst; +} + + Expression *IndexExp::optimize(int result) { Expression *e; //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); if (result & WANTinterpret) - e1 = fromConstInitializer(result, e1); - // We might know $ now - setLengthVarIfKnown(lengthVar, e1); + e1 = fromConstInitializer(result, e1); + // We might know $ now + setLengthVarIfKnown(lengthVar, e1); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = Index(type, e1, e2); if (e == EXP_CANT_INTERPRET) @@ -744,7 +744,7 @@ Expression *IndexExp::optimize(int result) return e; } - + Expression *SliceExp::optimize(int result) { Expression *e; @@ -761,15 +761,15 @@ Expression *SliceExp::optimize(int result) return e; } if (result & WANTinterpret) - e1 = fromConstInitializer(result, e1); - // We might know $ now - setLengthVarIfKnown(lengthVar, e1); + e1 = fromConstInitializer(result, e1); + // We might know $ now + setLengthVarIfKnown(lengthVar, e1); lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); upr = upr->optimize(WANTvalue | (result & WANTinterpret)); e = Slice(type, e1, lwr, upr); if (e == EXP_CANT_INTERPRET) e = this; - //printf("-SliceExp::optimize() %s\n", e->toChars()); + //printf("-SliceExp::optimize() %s\n", e->toChars()); return e; } @@ -781,12 +781,12 @@ Expression *AndAndExp::optimize(int result) e = this; if (e1->isBool(FALSE)) { - if (type->toBasetype()->ty == Tvoid) - e = e2; - else - { e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); - e->type = type; - } + if (type->toBasetype()->ty == Tvoid) + e = e2; + else + { e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); + e->type = type; + } e = e->optimize(result); } else @@ -803,11 +803,11 @@ Expression *AndAndExp::optimize(int result) e = new IntegerExp(loc, n1 && n2, type); } else if (e1->isBool(TRUE)) - { - if (type->toBasetype()->ty == Tvoid) - e = e2; - else e = new BoolExp(loc, e2, type); - } + { + if (type->toBasetype()->ty == Tvoid) + e = e2; + else e = new BoolExp(loc, e2, type); + } } } return e; @@ -838,12 +838,12 @@ Expression *OrOrExp::optimize(int result) e = new IntegerExp(loc, n1 || n2, type); } else if (e1->isBool(FALSE)) - { - if (type->toBasetype()->ty == Tvoid) - e = e2; - else - e = new BoolExp(loc, e2, type); - } + { + if (type->toBasetype()->ty == Tvoid) + e = e2; + else + e = new BoolExp(loc, e2, type); + } } } return e; diff --git a/dmd/parse.c b/dmd/parse.c index 3a0d73dd..4065caee 100644 --- a/dmd/parse.c +++ b/dmd/parse.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -68,9 +68,9 @@ Parser::Parser(Module *module, unsigned char *base, unsigned length, int doDocCo //nextToken(); // start up the scanner } -Dsymbols *Parser::parseModule() +Dsymbols *Parser::parseModule() { - Dsymbols *decldefs; + Dsymbols *decldefs; // ModuleDeclation leads off if (token.value == TOKmodule) @@ -103,14 +103,14 @@ Dsymbols *Parser::parseModule() } else { - Identifiers *a = NULL; + Identifiers *a = NULL; Identifier *id; id = token.ident; while (nextToken() == TOKdot) { if (!a) - a = new Identifiers(); + a = new Identifiers(); a->push(id); nextToken(); if (token.value != TOKidentifier) @@ -138,21 +138,21 @@ Lerr: while (token.value != TOKsemicolon && token.value != TOKeof) nextToken(); nextToken(); - return new Dsymbols(); + return new Dsymbols(); } -Dsymbols *Parser::parseDeclDefs(int once) +Dsymbols *Parser::parseDeclDefs(int once) { Dsymbol *s; - Dsymbols *decldefs; - Dsymbols *a; - Dsymbols *aelse; + Dsymbols *decldefs; + Dsymbols *a; + Dsymbols *aelse; enum PROT prot; StorageClass stc; Condition *condition; unsigned char *comment; //printf("Parser::parseDeclDefs()\n"); - decldefs = new Dsymbols(); + decldefs = new Dsymbols(); do { comment = token.blockComment; @@ -396,10 +396,10 @@ Dsymbols *Parser::parseDeclDefs(int once) if (token.value == TOKlparen) { nextToken(); - if (token.value == TOKint32v && token.uns64value > 0) + if (token.value == TOKint32v && token.uns64value > 0) n = (unsigned)token.uns64value; else - { error("positive integer expected, not %s", token.toChars()); + { error("positive integer expected, not %s", token.toChars()); n = 1; } nextToken(); @@ -445,7 +445,7 @@ Dsymbols *Parser::parseDeclDefs(int once) nextToken(); if (token.value == TOKidentifier) s = new DebugSymbol(loc, token.ident); - else if (token.value == TOKint32v || token.value == TOKint64v) + else if (token.value == TOKint32v || token.value == TOKint64v) s = new DebugSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); @@ -466,7 +466,7 @@ Dsymbols *Parser::parseDeclDefs(int once) nextToken(); if (token.value == TOKidentifier) s = new VersionSymbol(loc, token.ident); - else if (token.value == TOKint32v || token.value == TOKint64v) + else if (token.value == TOKint32v || token.value == TOKint64v) s = new VersionSymbol(loc, (unsigned)token.uns64value); else { error("identifier or integer expected, not %s", token.toChars()); @@ -528,43 +528,43 @@ void Parser::composeStorageClass(StorageClass stc) } #endif -/*********************************************** - * Parse storage class, lexer is on '@' - */ - -#if DMDV2 -StorageClass Parser::parseAttribute() -{ - nextToken(); - StorageClass stc = 0; - if (token.value != TOKidentifier) - { - error("identifier expected after @, not %s", token.toChars()); - } - else if (token.ident == Id::property) - stc = STCproperty; - else if (token.ident == Id::safe) - stc = STCsafe; - else if (token.ident == Id::trusted) - stc = STCtrusted; - else if (token.ident == Id::system) - stc = STCsystem; - else if (token.ident == Id::disable) - stc = STCdisable; - else - error("valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @%s", token.toChars()); - return stc; -} -#endif - - +/*********************************************** + * Parse storage class, lexer is on '@' + */ + +#if DMDV2 +StorageClass Parser::parseAttribute() +{ + nextToken(); + StorageClass stc = 0; + if (token.value != TOKidentifier) + { + error("identifier expected after @, not %s", token.toChars()); + } + else if (token.ident == Id::property) + stc = STCproperty; + else if (token.ident == Id::safe) + stc = STCsafe; + else if (token.ident == Id::trusted) + stc = STCtrusted; + else if (token.ident == Id::system) + stc = STCsystem; + else if (token.ident == Id::disable) + stc = STCdisable; + else + error("valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @%s", token.toChars()); + return stc; +} +#endif + + /******************************************** * Parse declarations after an align, protection, or extern decl. */ -Dsymbols *Parser::parseBlock() +Dsymbols *Parser::parseBlock() { - Dsymbols *a = NULL; + Dsymbols *a = NULL; //printf("parseBlock()\n"); switch (token.value) @@ -721,7 +721,7 @@ Condition *Parser::parseDebugCondition() if (token.value == TOKidentifier) id = token.ident; - else if (token.value == TOKint32v || token.value == TOKint64v) + else if (token.value == TOKint32v || token.value == TOKint64v) level = (unsigned)token.uns64value; else error("identifier or integer expected, not %s", token.toChars()); @@ -750,7 +750,7 @@ Condition *Parser::parseVersionCondition() nextToken(); if (token.value == TOKidentifier) id = token.ident; - else if (token.value == TOKint32v || token.value == TOKint64v) + else if (token.value == TOKint32v || token.value == TOKint64v) level = (unsigned)token.uns64value; #if DMDV2 /* Allow: @@ -1137,7 +1137,7 @@ EnumDeclaration *Parser::parseEnum() else if (token.value == TOKlcurly) { //printf("enum definition\n"); - e->members = new Dsymbols(); + e->members = new Dsymbols(); nextToken(); unsigned char *comment = token.blockComment; while (token.value != TOKrcurly) @@ -1264,7 +1264,7 @@ Dsymbol *Parser::parseAggregate() { //printf("aggregate definition\n"); nextToken(); - Dsymbols *decl = parseDeclDefs(0); + Dsymbols *decl = parseDeclDefs(0); if (token.value != TOKrcurly) error("} expected following member declarations in aggregate"); nextToken(); @@ -1286,7 +1286,7 @@ Dsymbol *Parser::parseAggregate() if (tpl) { // Wrap a template around the aggregate declaration - Dsymbols *decldefs = new Dsymbols(); + Dsymbols *decldefs = new Dsymbols(); decldefs->push(a); TemplateDeclaration *tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs); @@ -1305,44 +1305,44 @@ BaseClasses *Parser::parseBaseClasses() for (; 1; nextToken()) { - bool prot = false; - enum PROT protection = PROTpublic; + bool prot = false; + enum PROT protection = PROTpublic; switch (token.value) { case TOKprivate: - prot = true; + prot = true; protection = PROTprivate; - nextToken(); - break; + nextToken(); + break; case TOKpackage: - prot = true; + prot = true; protection = PROTpackage; - nextToken(); - break; + nextToken(); + break; case TOKprotected: - prot = true; + prot = true; protection = PROTprotected; - nextToken(); - break; + nextToken(); + break; case TOKpublic: - prot = true; + prot = true; protection = PROTpublic; - nextToken(); - break; - } - //if (prot && !global.params.useDeprecated) - //error("use of base class protection is deprecated"); - if (token.value == TOKidentifier) - { - BaseClass *b = new BaseClass(parseBasicType(), protection); - baseclasses->push(b); - if (token.value != TOKcomma) - break; - } - else - { - error("base classes expected instead of %s", token.toChars()); - return NULL; + nextToken(); + break; + } + //if (prot && !global.params.useDeprecated) + //error("use of base class protection is deprecated"); + if (token.value == TOKidentifier) + { + BaseClass *b = new BaseClass(parseBasicType(), protection); + baseclasses->push(b); + if (token.value != TOKcomma) + break; + } + else + { + error("base classes expected instead of %s", token.toChars()); + return NULL; } } return baseclasses; @@ -1378,7 +1378,7 @@ TemplateDeclaration *Parser::parseTemplateDeclaration() TemplateDeclaration *tempdecl; Identifier *id; TemplateParameters *tpl; - Dsymbols *decldefs; + Dsymbols *decldefs; Loc loc = this->loc; nextToken(); @@ -1575,7 +1575,7 @@ Dsymbol *Parser::parseMixin() Identifier *id; Type *tqual; Objects *tiargs; - Identifiers *idents; + Identifiers *idents; //printf("parseMixin()\n"); nextToken(); @@ -1606,7 +1606,7 @@ Dsymbol *Parser::parseMixin() nextToken(); } - idents = new Identifiers(); + idents = new Identifiers(); while (1) { tiargs = NULL; @@ -1699,7 +1699,7 @@ Import *Parser::parseImport(Array *decldefs, int isstatic) { Import *s; Identifier *id; Identifier *aliasid = NULL; - Identifiers *a; + Identifiers *a; Loc loc; //printf("Parser::parseImport()\n"); @@ -1724,7 +1724,7 @@ Import *Parser::parseImport(Array *decldefs, int isstatic) while (token.value == TOKdot) { if (!a) - a = new Identifiers(); + a = new Identifiers(); a->push(id); nextToken(); if (token.value != TOKidentifier) @@ -2183,7 +2183,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters * * Return array of Declaration *'s. */ -Dsymbols *Parser::parseDeclarations() +Dsymbols *Parser::parseDeclarations() { StorageClass storage_class; StorageClass stc; @@ -2191,7 +2191,7 @@ Dsymbols *Parser::parseDeclarations() Type *t; Type *tfirst; Identifier *ident; - Dsymbols *a; + Dsymbols *a; enum TOK tok = TOKreserved; unsigned char *comment = token.blockComment; enum LINK link = linkage; @@ -2253,7 +2253,7 @@ Dsymbols *Parser::parseDeclarations() break; } - a = new Dsymbols(); + a = new Dsymbols(); /* Look for auto initializers: * storage_class identifier = initializer; @@ -2340,7 +2340,7 @@ Dsymbols *Parser::parseDeclarations() a->push(v); else { - Dsymbols *ax = new Dsymbols(); + Dsymbols *ax = new Dsymbols(); ax->push(v); Dsymbol *s = new LinkDeclaration(link, ax); a->push(s); @@ -2374,14 +2374,14 @@ Dsymbols *Parser::parseDeclarations() } else { - Dsymbols *ax = new Dsymbols(); + Dsymbols *ax = new Dsymbols(); ax->push(f); s = new LinkDeclaration(link, ax); } if (tpl) // it's a function template { // Wrap a template around the aggregate declaration - Dsymbols *decldefs = new Dsymbols(); + Dsymbols *decldefs = new Dsymbols(); decldefs->push(s); TemplateDeclaration *tempdecl = new TemplateDeclaration(loc, s->ident, tpl, NULL, decldefs); @@ -2405,7 +2405,7 @@ Dsymbols *Parser::parseDeclarations() a->push(v); else { - Dsymbols *ax = new Dsymbols(); + Dsymbols *ax = new Dsymbols(); ax->push(v); Dsymbol *s = new LinkDeclaration(link, ax); a->push(s); @@ -2625,7 +2625,7 @@ Initializer *Parser::parseInitializer() is = new StructInitializer(loc); nextToken(); - comma = 2; + comma = 2; while (1) { switch (token.value) @@ -2649,8 +2649,8 @@ Initializer *Parser::parseInitializer() continue; case TOKcomma: - if (comma == 2) - error("expression expected, not ','"); + if (comma == 2) + error("expression expected, not ','"); nextToken(); comma = 2; continue; @@ -2664,8 +2664,8 @@ Initializer *Parser::parseInitializer() break; default: - if (comma == 1) - error("comma expected separating field initializers"); + if (comma == 1) + error("comma expected separating field initializers"); value = parseInitializer(); is->addInit(NULL, value); comma = 1; @@ -2714,7 +2714,7 @@ Initializer *Parser::parseInitializer() ia = new ArrayInitializer(loc); nextToken(); - comma = 2; + comma = 2; while (1) { switch (token.value) @@ -2751,8 +2751,8 @@ Initializer *Parser::parseInitializer() continue; case TOKcomma: - if (comma == 2) - error("expression expected, not ','"); + if (comma == 2) + error("expression expected, not ','"); nextToken(); comma = 2; continue; @@ -2955,10 +2955,10 @@ Statement *Parser::parseStatement(int flags) { Statements *as = new Statements(); as->reserve(a->dim); - for (size_t i = 0; i < a->dim; i++) + for (size_t i = 0; i < a->dim; i++) { Dsymbol *d = (Dsymbol *)a->data[i]; - s = new ExpStatement(loc, d); + s = new ExpStatement(loc, d); as->push(s); } s = new CompoundDeclarationStatement(loc, as); @@ -2966,7 +2966,7 @@ Statement *Parser::parseStatement(int flags) else if (a->dim == 1) { Dsymbol *d = (Dsymbol *)a->data[0]; - s = new ExpStatement(loc, d); + s = new ExpStatement(loc, d); } else assert(0); @@ -2982,7 +2982,7 @@ Statement *Parser::parseStatement(int flags) { Dsymbol *d; d = parseAggregate(); - s = new ExpStatement(loc, d); + s = new ExpStatement(loc, d); break; } @@ -2990,7 +2990,7 @@ Statement *Parser::parseStatement(int flags) { Dsymbol *d; d = parseEnum(); - s = new ExpStatement(loc, d); + s = new ExpStatement(loc, d); break; } @@ -2999,20 +2999,20 @@ Statement *Parser::parseStatement(int flags) if (t->value == TOKlparen) { // mixin(string) Expression *e = parseAssignExp(); - check(TOKsemicolon); - if (e->op == TOKmixin) - { - CompileExp *cpe = (CompileExp *)e; - s = new CompileStatement(loc, cpe->e1); - } - else - { - s = new ExpStatement(loc, e); - } + check(TOKsemicolon); + if (e->op == TOKmixin) + { + CompileExp *cpe = (CompileExp *)e; + s = new CompileStatement(loc, cpe->e1); + } + else + { + s = new ExpStatement(loc, e); + } break; } Dsymbol *d = parseMixin(); - s = new ExpStatement(loc, d); + s = new ExpStatement(loc, d); break; } @@ -3049,7 +3049,7 @@ Statement *Parser::parseStatement(int flags) if (!(flags & PSsemi)) error("use '{ }' for an empty statement, not a ';'"); nextToken(); - s = new ExpStatement(loc, (Expression *)NULL); + s = new ExpStatement(loc, (Expression *)NULL); break; case TOKdo: @@ -3367,7 +3367,7 @@ Statement *Parser::parseStatement(int flags) s = new ScopeStatement(loc, s); // Keep cases in order by building the case statements backwards - for (size_t i = cases.dim; i; i--) + for (size_t i = cases.dim; i; i--) { exp = (Expression *)cases.data[i - 1]; s = new CaseStatement(loc, exp, s); @@ -3506,7 +3506,7 @@ Statement *Parser::parseStatement(int flags) case TOKtry: { Statement *body; - Catches *catches = NULL; + Catches *catches = NULL; Statement *finalbody = NULL; nextToken(); @@ -3536,7 +3536,7 @@ Statement *Parser::parseStatement(int flags) handler = parseStatement(0); c = new Catch(loc, t, id, handler); if (!catches) - catches = new Catches(); + catches = new Catches(); catches->push(c); } @@ -3975,12 +3975,12 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) case TOKrbracket: case TOKassign: case TOKcomma: - case TOKdotdotdot: + case TOKdotdotdot: case TOKsemicolon: case TOKlcurly: case TOKin: - case TOKout: - case TOKbody: + case TOKout: + case TOKbody: // The !parens is to disallow unnecessary parentheses if (!parens && (endtok == TOKreserved || endtok == t->value)) { *pt = t; @@ -4726,7 +4726,7 @@ Expression *Parser::parsePostExp(Expression *e) nextToken(); if (token.value == TOKrbracket) { // array[] - inBrackets--; + inBrackets--; e = new SliceExp(loc, e, NULL, NULL); nextToken(); } @@ -4747,8 +4747,8 @@ Expression *Parser::parsePostExp(Expression *e) { nextToken(); while (1) - { - Expression *arg = parseAssignExp(); + { + Expression *arg = parseAssignExp(); arguments->push(arg); if (token.value == TOKrbracket) break; @@ -5384,7 +5384,7 @@ Expressions *Parser::parseArguments() nextToken(); if (token.value != endtok) { - while (token.value != TOKeof) + while (token.value != TOKeof) { arg = parseAssignExp(); arguments->push(arg); @@ -5436,7 +5436,7 @@ Expression *Parser::parseNewExp(Expression *thisexp) else { nextToken(); - Dsymbols *decl = parseDeclDefs(0); + Dsymbols *decl = parseDeclDefs(0); if (token.value != TOKrcurly) error("class member expected"); nextToken(); @@ -5522,7 +5522,7 @@ enum PREC precedence[TOKMAX]; void initPrecedence() { - for (size_t i = 0; i < TOKMAX; i++) + for (size_t i = 0; i < TOKMAX; i++) precedence[i] = PREC_zero; precedence[TOKtype] = PREC_expr; @@ -5675,7 +5675,7 @@ void initPrecedence() precedence[TOKcomma] = PREC_expr; precedence[TOKdeclaration] = PREC_expr; - + #if IN_LLVM // Need to set precedence for TOKgep as well, as expToCBuffer expects it. precedence[TOKgep] = PREC_primary; diff --git a/dmd/parse.h b/dmd/parse.h index 8f179b9c..4e212e40 100644 --- a/dmd/parse.h +++ b/dmd/parse.h @@ -66,10 +66,10 @@ struct Parser : Lexer Parser(Module *module, unsigned char *base, unsigned length, int doDocComment); - Dsymbols *parseModule(); - Dsymbols *parseDeclDefs(int once); + Dsymbols *parseModule(); + Dsymbols *parseDeclDefs(int once); Array *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment); - Dsymbols *parseBlock(); + Dsymbols *parseBlock(); void composeStorageClass(StorageClass stc); Expression *parseConstraint(); TemplateDeclaration *parseTemplateDeclaration(); @@ -102,7 +102,7 @@ struct Parser : Lexer Type *parseBasicType(); Type *parseBasicType2(Type *t); Type *parseDeclarator(Type *t, Identifier **pident, TemplateParameters **tpl = NULL); - Dsymbols *parseDeclarations(); + Dsymbols *parseDeclarations(); void parseContracts(FuncDeclaration *f); Statement *parseStatement(int flags); Initializer *parseInitializer(); diff --git a/dmd/speller.c b/dmd/speller.c index 4cfd5273..d6437379 100644 --- a/dmd/speller.c +++ b/dmd/speller.c @@ -111,7 +111,7 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, /* Deletions */ memcpy(buf, seed + 1, seedlen); - for (size_t i = 0; i < seedlen; i++) + for (size_t i = 0; i < seedlen; i++) { //printf("del buf = '%s'\n", buf); void *p; @@ -129,7 +129,7 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, if (!flag) { memcpy(buf, seed, seedlen + 1); - for (size_t i = 0; i + 1 < seedlen; i++) + for (size_t i = 0; i + 1 < seedlen; i++) { // swap [i] and [i + 1] buf[i] = seed[i + 1]; @@ -148,7 +148,7 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, { /* Substitutions */ memcpy(buf, seed, seedlen + 1); - for (size_t i = 0; i < seedlen; i++) + for (size_t i = 0; i < seedlen; i++) { for (const char *s = charset; *s; s++) { @@ -168,7 +168,7 @@ void *spellerX(const char *seed, size_t seedlen, fp_speller_t fp, void *fparg, /* Insertions */ memcpy(buf + 1, seed, seedlen + 1); - for (size_t i = 0; i <= seedlen; i++) // yes, do seedlen+1 iterations + for (size_t i = 0; i <= seedlen; i++) // yes, do seedlen+1 iterations { for (const char *s = charset; *s; s++) { diff --git a/dmd/statement.c b/dmd/statement.c index 7e637e98..bd70df1a 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -38,27 +38,27 @@ /*********************************** * Return size of OS critical section. */ -#if IN_LLVM -// sizes based on those from tollvm.cpp:DtoMutexType() +#if IN_LLVM +// sizes based on those from tollvm.cpp:DtoMutexType() int os_critsecsize() { -#if defined(_MSC_VER) - // TODO Check size - return 68; -#else - if (global.params.os == OSWindows) - return 68; - else if (global.params.os == OSFreeBSD) - return sizeof(size_t); - else +#if defined(_MSC_VER) + // TODO Check size + return 68; +#else + if (global.params.os == OSWindows) + return 68; + else if (global.params.os == OSFreeBSD) + return sizeof(size_t); + else return sizeof(pthread_mutex_t); -#endif +#endif } -#elif IN_DMD - -extern int os_critsecsize32(); -extern int os_critsecsize64(); - +#elif IN_DMD + +extern int os_critsecsize32(); +extern int os_critsecsize64(); + #endif /******************************** Statement ***************************/ @@ -165,7 +165,7 @@ int Statement::usesEH() /* Only valid after semantic analysis */ -int Statement::blockExit(bool mustNotThrow) +int Statement::blockExit(bool mustNotThrow) { printf("Statement::blockExit(%p)\n", this); printf("%s\n", toChars()); @@ -243,12 +243,12 @@ ExpStatement::ExpStatement(Loc loc, Expression *exp) this->exp = exp; } -ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration) - : Statement(loc) -{ - this->exp = new DeclarationExp(loc, declaration); -} - +ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration) + : Statement(loc) +{ + this->exp = new DeclarationExp(loc, declaration); +} + Statement *ExpStatement::syntaxCopy() { Expression *e = exp ? exp->syntaxCopy() : NULL; @@ -259,19 +259,19 @@ Statement *ExpStatement::syntaxCopy() void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (exp) - { exp->toCBuffer(buf, hgs); - if (exp->op != TOKdeclaration) - { buf->writeByte(';'); - if (!hgs->FLinit.init) - buf->writenl(); - } - } - else - { + { exp->toCBuffer(buf, hgs); + if (exp->op != TOKdeclaration) + { buf->writeByte(';'); + if (!hgs->FLinit.init) + buf->writenl(); + } + } + else + { buf->writeByte(';'); if (!hgs->FLinit.init) buf->writenl(); - } + } } Statement *ExpStatement::semantic(Scope *sc) @@ -287,7 +287,7 @@ Statement *ExpStatement::semantic(Scope *sc) return this; } -int ExpStatement::blockExit(bool mustNotThrow) +int ExpStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; if (exp) @@ -311,52 +311,52 @@ int ExpStatement::isEmpty() return exp == NULL; } -void ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) -{ - //printf("ExpStatement::scopeCode()\n"); - //print(); - - *sentry = NULL; - *sexception = NULL; - *sfinally = NULL; - - if (exp) - { - if (exp->op == TOKdeclaration) - { - DeclarationExp *de = (DeclarationExp *)(exp); - VarDeclaration *v = de->declaration->isVarDeclaration(); - if (v) - { - Expression *e = v->callScopeDtor(sc); - if (e) - { - //printf("dtor is: "); e->print(); -#if 0 - if (v->type->toBasetype()->ty == Tstruct) - { /* Need a 'gate' to turn on/off destruction, - * in case v gets moved elsewhere. - */ - Identifier *id = Lexer::uniqueId("__runDtor"); - ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); - VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); - *sentry = new ExpStatement(loc, rd); - v->rundtor = rd; - - /* Rewrite e as: - * rundtor && e - */ - Expression *ve = new VarExp(loc, v->rundtor); - e = new AndAndExp(loc, ve, e); - e->type = Type::tbool; - } -#endif - *sfinally = new ExpStatement(loc, e); - } - } - } - } -} +void ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) +{ + //printf("ExpStatement::scopeCode()\n"); + //print(); + + *sentry = NULL; + *sexception = NULL; + *sfinally = NULL; + + if (exp) + { + if (exp->op == TOKdeclaration) + { + DeclarationExp *de = (DeclarationExp *)(exp); + VarDeclaration *v = de->declaration->isVarDeclaration(); + if (v) + { + Expression *e = v->callScopeDtor(sc); + if (e) + { + //printf("dtor is: "); e->print(); +#if 0 + if (v->type->toBasetype()->ty == Tstruct) + { /* Need a 'gate' to turn on/off destruction, + * in case v gets moved elsewhere. + */ + Identifier *id = Lexer::uniqueId("__runDtor"); + ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1)); + VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie); + *sentry = new ExpStatement(loc, rd); + v->rundtor = rd; + + /* Rewrite e as: + * rundtor && e + */ + Expression *ve = new VarExp(loc, v->rundtor); + e = new AndAndExp(loc, ve, e); + e->type = Type::tbool; + } +#endif + *sfinally = new ExpStatement(loc, e); + } + } + } + } +} /******************************** CompileStatement ***************************/ @@ -388,10 +388,10 @@ Statements *CompileStatement::flatten(Scope *sc) exp = exp->semantic(sc); exp = resolveProperties(sc, exp); exp = exp->optimize(WANTvalue | WANTinterpret); - if (exp->op == TOKerror) - return NULL; - StringExp *se = exp->toString(); - if (!se) + if (exp->op == TOKerror) + return NULL; + StringExp *se = exp->toString(); + if (!se) { error("argument to mixin must be a string, not (%s)", exp->toChars()); return NULL; } @@ -450,7 +450,7 @@ Statement *CompoundStatement::syntaxCopy() Statements *a = new Statements(); a->setDim(statements->dim); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) s = s->syntaxCopy(); a->data[i] = s; @@ -467,7 +467,7 @@ Statement *CompoundStatement::semantic(Scope *sc) for (size_t i = 0; i < statements->dim; ) { - s = (*statements)[i]; + s = (*statements)[i]; if (s) { Statements *a = s->flatten(sc); @@ -478,7 +478,7 @@ Statement *CompoundStatement::semantic(Scope *sc) continue; } s = s->semantic(sc); - (*statements)[i] = s; + (*statements)[i] = s; if (s) { Statement *sentry; @@ -492,8 +492,8 @@ Statement *CompoundStatement::semantic(Scope *sc) statements->data[i] = sentry; } if (sexception) - sexception = sexception->semantic(sc); - if (sexception) + sexception = sexception->semantic(sc); + if (sexception) { if (i + 1 == statements->dim && !sfinally) { @@ -509,22 +509,22 @@ Statement *CompoundStatement::semantic(Scope *sc) * { sexception; throw __o; } */ Statements *a = new Statements(); - for (size_t j = i + 1; j < statements->dim; j++) + for (size_t j = i + 1; j < statements->dim; j++) { - a->push((*statements)[j]); + a->push((*statements)[j]); } - Statement *body = new CompoundStatement(0, a); + Statement *body = new CompoundStatement(0, a); body = new ScopeStatement(0, body); Identifier *id = Lexer::uniqueId("__o"); - Statement *handler = sexception; - if (sexception->blockExit(FALSE) & BEfallthru) - { handler = new ThrowStatement(0, new IdentifierExp(0, id)); - handler = new CompoundStatement(0, sexception, handler); - } + Statement *handler = sexception; + if (sexception->blockExit(FALSE) & BEfallthru) + { handler = new ThrowStatement(0, new IdentifierExp(0, id)); + handler = new CompoundStatement(0, sexception, handler); + } - Catches *catches = new Catches(); + Catches *catches = new Catches(); Catch *ctch = new Catch(0, NULL, id, handler); catches->push(ctch); s = new TryCatchStatement(0, body, catches); @@ -551,11 +551,11 @@ Statement *CompoundStatement::semantic(Scope *sc) * s; try { s1; s2; } finally { sfinally; } */ Statements *a = new Statements(); - for (size_t j = i + 1; j < statements->dim; j++) + for (size_t j = i + 1; j < statements->dim; j++) { - a->push((*statements)[j]); + a->push((*statements)[j]); } - Statement *body = new CompoundStatement(0, a); + Statement *body = new CompoundStatement(0, a); s = new TryFinallyStatement(0, body, sfinally); s = s->semantic(sc); statements->setDim(i + 1); @@ -569,7 +569,7 @@ Statement *CompoundStatement::semantic(Scope *sc) } if (statements->dim == 1 && !isAsmBlockStatement()) { - return (*statements)[0]; + return (*statements)[0]; } return this; } @@ -583,8 +583,8 @@ ReturnStatement *CompoundStatement::isReturnStatement() { ReturnStatement *rs = NULL; - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; if (s) { rs = s->isReturnStatement(); @@ -597,8 +597,8 @@ ReturnStatement *CompoundStatement::isReturnStatement() void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; if (s) s->toCBuffer(buf, hgs); } @@ -606,33 +606,33 @@ void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) int CompoundStatement::usesEH() { - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; if (s && s->usesEH()) return TRUE; } return FALSE; } -int CompoundStatement::blockExit(bool mustNotThrow) +int CompoundStatement::blockExit(bool mustNotThrow) { //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); int result = BEfallthru; for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { //printf("result = x%x\n", result); //printf("%s\n", s->toChars()); if (!(result & BEfallthru) && !s->comeFrom()) { - if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty()) + if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty()) s->warning("statement is not reachable"); } else { result &= ~BEfallthru; - result |= s->blockExit(mustNotThrow); + result |= s->blockExit(mustNotThrow); } } } @@ -643,8 +643,8 @@ int CompoundStatement::comeFrom() { int comefrom = FALSE; //printf("CompoundStatement::comeFrom()\n"); - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; if (!s) continue; @@ -656,8 +656,8 @@ int CompoundStatement::comeFrom() int CompoundStatement::isEmpty() { - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; if (s && !s->isEmpty()) return FALSE; } @@ -678,7 +678,7 @@ Statement *CompoundDeclarationStatement::syntaxCopy() Statements *a = new Statements(); a->setDim(statements->dim); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) s = s->syntaxCopy(); a->data[i] = s; @@ -690,13 +690,13 @@ Statement *CompoundDeclarationStatement::syntaxCopy() void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { int nwritten = 0; - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - ExpStatement *ds; - if (s && - (ds = s->isExpStatement()) != NULL && - ds->exp->op == TOKdeclaration) - { + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; + ExpStatement *ds; + if (s && + (ds = s->isExpStatement()) != NULL && + ds->exp->op == TOKdeclaration) + { DeclarationExp *de = (DeclarationExp *)ds->exp; assert(de->op == TOKdeclaration); Declaration *d = de->declaration->isDeclaration(); @@ -756,7 +756,7 @@ Statement *UnrolledLoopStatement::syntaxCopy() Statements *a = new Statements(); a->setDim(statements->dim); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) s = s->syntaxCopy(); a->data[i] = s; @@ -777,7 +777,7 @@ Statement *UnrolledLoopStatement::semantic(Scope *sc) for (size_t i = 0; i < statements->dim; i++) { - Statement *s = (*statements)[i]; + Statement *s = (*statements)[i]; if (s) { //printf("[%d]: %s\n", i, s->toChars()); @@ -799,7 +799,7 @@ void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 0; i < statements->dim; i++) { Statement *s; - s = (*statements)[i]; + s = (*statements)[i]; if (s) s->toCBuffer(buf, hgs); } @@ -821,21 +821,21 @@ int UnrolledLoopStatement::hasContinue() int UnrolledLoopStatement::usesEH() { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s && s->usesEH()) return TRUE; } return FALSE; } -int UnrolledLoopStatement::blockExit(bool mustNotThrow) +int UnrolledLoopStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (s) { - int r = s->blockExit(mustNotThrow); + int r = s->blockExit(mustNotThrow); result |= r & ~(BEbreak | BEcontinue); } } @@ -848,7 +848,7 @@ int UnrolledLoopStatement::comeFrom() //printf("UnrolledLoopStatement::comeFrom()\n"); for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; + { Statement *s = (*statements)[i]; if (!s) continue; @@ -931,10 +931,10 @@ int ScopeStatement::usesEH() return statement ? statement->usesEH() : FALSE; } -int ScopeStatement::blockExit(bool mustNotThrow) +int ScopeStatement::blockExit(bool mustNotThrow) { //printf("ScopeStatement::blockExit(%p)\n", statement); - return statement ? statement->blockExit(mustNotThrow) : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } @@ -1004,7 +1004,7 @@ int WhileStatement::usesEH() return body ? body->usesEH() : 0; } -int WhileStatement::blockExit(bool mustNotThrow) +int WhileStatement::blockExit(bool mustNotThrow) { assert(0); //printf("WhileStatement::blockExit(%p)\n", this); @@ -1015,7 +1015,7 @@ int WhileStatement::blockExit(bool mustNotThrow) if (condition->isBool(TRUE)) { if (body) - { result |= body->blockExit(mustNotThrow); + { result |= body->blockExit(mustNotThrow); if (result & BEbreak) result |= BEfallthru; } @@ -1027,7 +1027,7 @@ int WhileStatement::blockExit(bool mustNotThrow) else { if (body) - result |= body->blockExit(mustNotThrow); + result |= body->blockExit(mustNotThrow); result |= BEfallthru; } result &= ~(BEbreak | BEcontinue); @@ -1099,11 +1099,11 @@ int DoStatement::usesEH() return body ? body->usesEH() : 0; } -int DoStatement::blockExit(bool mustNotThrow) +int DoStatement::blockExit(bool mustNotThrow) { int result; if (body) - { result = body->blockExit(mustNotThrow); + { result = body->blockExit(mustNotThrow); if (result == BEbreak) return BEfallthru; if (result & BEcontinue) @@ -1229,11 +1229,11 @@ int ForStatement::usesEH() return (init && init->usesEH()) || body->usesEH(); } -int ForStatement::blockExit(bool mustNotThrow) +int ForStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; if (init) - { result = init->blockExit(mustNotThrow); + { result = init->blockExit(mustNotThrow); if (!(result & BEfallthru)) return result; } @@ -1248,7 +1248,7 @@ int ForStatement::blockExit(bool mustNotThrow) else result &= ~BEfallthru; // the body must do the exiting if (body) - { int r = body->blockExit(mustNotThrow); + { int r = body->blockExit(mustNotThrow); if (r & (BEbreak | BEgoto)) result |= BEfallthru; result |= r & ~(BEfallthru | BEbreak | BEcontinue); @@ -1352,8 +1352,8 @@ Statement *ForeachStatement::semantic(Scope *sc) error("invalid foreach aggregate %s", aggr->toChars()); return this; } - if (aggr->type->toBasetype()->ty == Terror) - return NULL; + if (aggr->type->toBasetype()->ty == Terror) + return NULL; inferApplyArgTypes(op, arguments, aggr, sc->module); @@ -1396,17 +1396,17 @@ Statement *ForeachStatement::semantic(Scope *sc) Expression *e; Type *t; if (te) - e = (*te->exps)[k]; + e = (*te->exps)[k]; else t = Parameter::getNth(tuple->arguments, k)->type; - Parameter *arg = (*arguments)[0]; + Parameter *arg = (*arguments)[0]; Statements *st = new Statements(); if (dim == 2) { // Declare key if (arg->storageClass & (STCout | STCref | STClazy)) error("no storage class for key %s", arg->ident->toChars()); - arg->type = arg->type->semantic(loc, sc); + arg->type = arg->type->semantic(loc, sc); TY keyty = arg->type->ty; if (keyty != Tint32 && keyty != Tuns32) { @@ -1423,7 +1423,7 @@ Statement *ForeachStatement::semantic(Scope *sc) var->storage_class |= STCconst; DeclarationExp *de = new DeclarationExp(loc, var); st->push(new ExpStatement(loc, de)); - arg = (*arguments)[1]; // value + arg = (*arguments)[1]; // value } // Declare value if (arg->storageClass & (STCout | STCref | STClazy)) @@ -1431,22 +1431,22 @@ Statement *ForeachStatement::semantic(Scope *sc) Dsymbol *var; if (te) { Type *tb = e->type->toBasetype(); - Dsymbol *s = NULL; + Dsymbol *s = NULL; if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar) - s = ((VarExp *)e)->var; - else if (e->op == TOKtemplate) - s =((TemplateExp *)e)->td; - else if (e->op == TOKimport) - s =((ScopeExp *)e)->sds; - - if (s) - var = new AliasDeclaration(loc, arg->ident, s); + s = ((VarExp *)e)->var; + else if (e->op == TOKtemplate) + s =((TemplateExp *)e)->td; + else if (e->op == TOKimport) + s =((ScopeExp *)e)->sds; + + if (s) + var = new AliasDeclaration(loc, arg->ident, s); else { arg->type = e->type; Initializer *ie = new ExpInitializer(0, e); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); - if (e->isConst() || e->op == TOKstring) + if (e->isConst() || e->op == TOKstring) v->storage_class |= STCconst; var = v; } @@ -1502,7 +1502,7 @@ Statement *ForeachStatement::semantic(Scope *sc) { Parameter *arg; int i = (dim == 1) ? 0 : 1; // index of value - arg = (*arguments)[i]; + arg = (*arguments)[i]; arg->type = arg->type->semantic(loc, sc); tnv = arg->type->toBasetype(); if (tnv->ty != tn->ty && @@ -1511,7 +1511,7 @@ Statement *ForeachStatement::semantic(Scope *sc) if (arg->storageClass & STCref) error("foreach: value of UTF conversion cannot be ref"); if (dim == 2) - { arg = (*arguments)[0]; + { arg = (*arguments)[0]; if (arg->storageClass & STCref) error("foreach: key cannot be ref"); } @@ -1521,7 +1521,7 @@ Statement *ForeachStatement::semantic(Scope *sc) for (size_t i = 0; i < dim; i++) { // Declare args - Parameter *arg = (*arguments)[i]; + Parameter *arg = (*arguments)[i]; Type *argtype = arg->type->semantic(loc, sc); VarDeclaration *var; @@ -1558,8 +1558,8 @@ Statement *ForeachStatement::semantic(Scope *sc) if (!key) { - Identifier *idkey = Lexer::uniqueId("__key"); - key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL); + Identifier *idkey = Lexer::uniqueId("__key"); + key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL); } if (op == TOKforeach_reverse) key->init = new ExpInitializer(loc, tmp_length); @@ -1567,8 +1567,8 @@ Statement *ForeachStatement::semantic(Scope *sc) key->init = new ExpInitializer(loc, new IntegerExp(0)); Statements *cs = new Statements(); - cs->push(new ExpStatement(loc, tmp)); - cs->push(new ExpStatement(loc, key)); + cs->push(new ExpStatement(loc, tmp)); + cs->push(new ExpStatement(loc, key)); Statement *forinit = new CompoundDeclarationStatement(loc, cs); Expression *cond; @@ -1586,7 +1586,7 @@ Statement *ForeachStatement::semantic(Scope *sc) // T value = tmp[key]; value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); - Statement *ds = new ExpStatement(loc, value); + Statement *ds = new ExpStatement(loc, value); body = new CompoundStatement(loc, ds, body); @@ -1681,7 +1681,7 @@ Statement *ForeachStatement::semantic(Scope *sc) VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit)); // r->semantic(sc); //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars()); - Statement *init = new ExpStatement(loc, r); + Statement *init = new ExpStatement(loc, r); //printf("init: %s\n", init->toChars()); // !__r.empty @@ -1699,7 +1699,7 @@ Statement *ForeachStatement::semantic(Scope *sc) e = new VarExp(loc, r); Expression *einit = new DotIdExp(loc, e, idhead); // einit = einit->semantic(sc); - Parameter *arg = (*arguments)[0]; + Parameter *arg = (*arguments)[0]; VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit)); ve->storage_class |= STCforeach; ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); @@ -1707,7 +1707,7 @@ Statement *ForeachStatement::semantic(Scope *sc) DeclarationExp *de = new DeclarationExp(loc, ve); Statement *body = new CompoundStatement(loc, - new ExpStatement(loc, de), this->body); + new ExpStatement(loc, de), this->body); s = new ForStatement(loc, init, condition, increment, body); #if 0 @@ -1749,8 +1749,8 @@ Statement *ForeachStatement::semantic(Scope *sc) */ Parameters *args = new Parameters(); for (size_t i = 0; i < dim; i++) - { Parameter *arg = (*arguments)[i]; - StorageClass stc = STCref; + { Parameter *arg = (*arguments)[i]; + StorageClass stc = STCref; Identifier *id; arg->type = arg->type->semantic(loc, sc); @@ -1763,15 +1763,15 @@ Statement *ForeachStatement::semantic(Scope *sc) id = Lexer::uniqueId("__applyArg", i); Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); - s = new ExpStatement(0, v); + s = new ExpStatement(0, v); body = new CompoundStatement(loc, s, body); } a = new Parameter(STCref, arg->type, id, NULL); args->push(a); } Type *t = new TypeFunction(args, Type::tint32, 0, LINKd); - cases = new Statements(); - gotos = new CompoundStatements(); + cases = new Statements(); + gotos = new CompoundStatements(); FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); fld->fbody = body; Expression *flde = new FuncExp(loc, fld); @@ -1779,28 +1779,28 @@ Statement *ForeachStatement::semantic(Scope *sc) // Resolve any forward referenced goto's for (size_t i = 0; i < gotos->dim; i++) - { CompoundStatement *cs = (*gotos)[i]; - GotoStatement *gs = (GotoStatement *)(*cs->statements)[0]; + { CompoundStatement *cs = (*gotos)[i]; + GotoStatement *gs = (GotoStatement *)(*cs->statements)[0]; if (!gs->label->statement) { // 'Promote' it to this scope, and replace with a return cases->push(gs); s = new ReturnStatement(0, new IntegerExp(cases->dim + 1)); - (*cs->statements)[0] = s; + (*cs->statements)[0] = s; } } - if (taa) + if (taa) { // Check types - Parameter *arg = (*arguments)[0]; + Parameter *arg = (*arguments)[0]; if (dim == 2) { if (arg->storageClass & STCref) error("foreach: index cannot be ref"); if (!arg->type->equals(taa->index)) error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); - arg = (*arguments)[1]; + arg = (*arguments)[1]; } if (!arg->type->equals(taa->nextOf())) error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); @@ -1846,10 +1846,10 @@ Statement *ForeachStatement::semantic(Scope *sc) Expressions *exps = new Expressions(); exps->push(aggr); size_t keysize = taa->key->size(); - if (global.params.is64bit) - keysize = (keysize + 15) & ~15; - else - keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); + if (global.params.is64bit) + keysize = (keysize + 15) & ~15; + else + keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); exps->push(new IntegerExp(0, keysize, Type::tsize_t)); // LDC paint delegate argument to the type runtime expects @@ -1978,9 +1978,9 @@ Statement *ForeachStatement::semantic(Scope *sc) a->push(s); // cases 2... - for (size_t i = 0; i < cases->dim; i++) + for (size_t i = 0; i < cases->dim; i++) { - s = (*cases)[i]; + s = (*cases)[i]; s = new CaseStatement(0, new IntegerExp(i + 2), s); a->push(s); } @@ -1991,9 +1991,9 @@ Statement *ForeachStatement::semantic(Scope *sc) } break; } - case Terror: - s = NULL; - break; + case Terror: + s = NULL; + break; default: error("foreach: %s is not an aggregate type", aggr->type->toChars()); @@ -2020,7 +2020,7 @@ int ForeachStatement::usesEH() return body->usesEH(); } -int ForeachStatement::blockExit(bool mustNotThrow) +int ForeachStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; if (aggr->canThrow()) @@ -2028,7 +2028,7 @@ int ForeachStatement::blockExit(bool mustNotThrow) if (body) { - result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); + result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); } return result; } @@ -2045,9 +2045,9 @@ void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(Token::toChars(op)); buf->writestring(" ("); - for (size_t i = 0; i < arguments->dim; i++) + for (size_t i = 0; i < arguments->dim; i++) { - Parameter *a = (*arguments)[i]; + Parameter *a = (*arguments)[i]; if (i) buf->writestring(", "); if (a->storageClass & STCref) @@ -2158,13 +2158,13 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) // Keep order of evaluation as lwr, then upr if (op == TOKforeach) { - cs->push(new ExpStatement(loc, key)); - cs->push(new ExpStatement(loc, tmp)); + cs->push(new ExpStatement(loc, key)); + cs->push(new ExpStatement(loc, tmp)); } else { - cs->push(new ExpStatement(loc, tmp)); - cs->push(new ExpStatement(loc, key)); + cs->push(new ExpStatement(loc, tmp)); + cs->push(new ExpStatement(loc, key)); } Statement *forinit = new CompoundDeclarationStatement(loc, cs); @@ -2229,7 +2229,7 @@ int ForeachRangeStatement::usesEH() return body->usesEH(); } -int ForeachRangeStatement::blockExit(bool mustNotThrow) +int ForeachRangeStatement::blockExit(bool mustNotThrow) { assert(0); int result = BEfallthru; @@ -2241,7 +2241,7 @@ int ForeachRangeStatement::blockExit(bool mustNotThrow) if (body) { - result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); + result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue); } return result; } @@ -2366,7 +2366,7 @@ int IfStatement::usesEH() return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } -int IfStatement::blockExit(bool mustNotThrow) +int IfStatement::blockExit(bool mustNotThrow) { //printf("IfStatement::blockExit(%p)\n", this); @@ -2376,25 +2376,25 @@ int IfStatement::blockExit(bool mustNotThrow) if (condition->isBool(TRUE)) { if (ifbody) - result |= ifbody->blockExit(mustNotThrow); + result |= ifbody->blockExit(mustNotThrow); else result |= BEfallthru; } else if (condition->isBool(FALSE)) { if (elsebody) - result |= elsebody->blockExit(mustNotThrow); + result |= elsebody->blockExit(mustNotThrow); else result |= BEfallthru; } else { if (ifbody) - result |= ifbody->blockExit(mustNotThrow); + result |= ifbody->blockExit(mustNotThrow); else result |= BEfallthru; if (elsebody) - result |= elsebody->blockExit(mustNotThrow); + result |= elsebody->blockExit(mustNotThrow); else result |= BEfallthru; } @@ -2486,11 +2486,11 @@ int ConditionalStatement::usesEH() return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } -int ConditionalStatement::blockExit(bool mustNotThrow) +int ConditionalStatement::blockExit(bool mustNotThrow) { - int result = ifbody->blockExit(mustNotThrow); + int result = ifbody->blockExit(mustNotThrow); if (elsebody) - result |= elsebody->blockExit(mustNotThrow); + result |= elsebody->blockExit(mustNotThrow); return result; } @@ -2548,12 +2548,12 @@ Statement *PragmaStatement::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { - Expression *e = (*args)[i]; + Expression *e = (*args)[i]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - StringExp *se = e->toString(); - if (se) + StringExp *se = e->toString(); + if (se) { fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); } @@ -2574,13 +2574,13 @@ Statement *PragmaStatement::semantic(Scope *sc) error("string expected for library name"); else { - Expression *e = (*args)[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - (*args)[0] = e; - StringExp *se = e->toString(); - if (!se) + (*args)[0] = e; + StringExp *se = e->toString(); + if (!se) error("string expected for library name, not '%s'", e->toChars()); else if (global.params.verbose) { @@ -2606,10 +2606,10 @@ Statement *PragmaStatement::semantic(Scope *sc) error("function name expected for start address"); else { - Expression *e = (*args)[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - (*args)[0] = e; + (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) error("function name expected for start address, not '%s'", e->toChars()); @@ -2636,14 +2636,14 @@ int PragmaStatement::usesEH() return body && body->usesEH(); } -int PragmaStatement::blockExit(bool mustNotThrow) +int PragmaStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; #if 0 // currently, no code is generated for Pragma's, so it's just fallthru if (arrayExpressionCanThrow(args)) result |= BEthrow; if (body) - result |= body->blockExit(mustNotThrow); + result |= body->blockExit(mustNotThrow); #endif return result; } @@ -2698,7 +2698,7 @@ Statement *StaticAssertStatement::semantic(Scope *sc) return NULL; } -int StaticAssertStatement::blockExit(bool mustNotThrow) +int StaticAssertStatement::blockExit(bool mustNotThrow) { return BEfallthru; } @@ -2758,15 +2758,15 @@ Statement *SwitchStatement::semantic(Scope *sc) sc->sbreak = this; sc->sw = this; - cases = new CaseStatements(); + cases = new CaseStatements(); sc->noctor++; // BUG: should use Scope::mergeCallSuper() for each case instead body = body->semantic(sc); sc->noctor--; // Resolve any goto case's with exp - for (size_t i = 0; i < gotoCases.dim; i++) + for (size_t i = 0; i < gotoCases.dim; i++) { - GotoCaseStatement *gcs = gotoCases[i]; + GotoCaseStatement *gcs = gotoCases[i]; if (!gcs->exp) { @@ -2778,9 +2778,9 @@ Statement *SwitchStatement::semantic(Scope *sc) { if (!scx->sw) continue; - for (size_t j = 0; j < scx->sw->cases->dim; j++) + for (size_t j = 0; j < scx->sw->cases->dim; j++) { - CaseStatement *cs = (*scx->sw->cases)[j]; + CaseStatement *cs = (*scx->sw->cases)[j]; if (cs->exp->equals(gcs->exp)) { @@ -2840,11 +2840,11 @@ Statement *SwitchStatement::semantic(Scope *sc) size_t dim = ed->members->dim; for (size_t i = 0; i < dim; i++) { - EnumMember *em = (*ed->members)[i]->isEnumMember(); + EnumMember *em = (*ed->members)[i]->isEnumMember(); if (em) { for (size_t j = 0; j < cases->dim; j++) - { CaseStatement *cs = (*cases)[j]; + { CaseStatement *cs = (*cases)[j]; if (cs->exp->equals(em->value)) goto L1; } @@ -2871,13 +2871,13 @@ int SwitchStatement::usesEH() return body ? body->usesEH() : 0; } -int SwitchStatement::blockExit(bool mustNotThrow) +int SwitchStatement::blockExit(bool mustNotThrow) { int result = BEnone; if (condition->canThrow()) result |= BEthrow; if (body) - { result |= body->blockExit(mustNotThrow); + { result |= body->blockExit(mustNotThrow); if (result & BEbreak) { result |= BEfallthru; result &= ~BEbreak; @@ -2949,15 +2949,15 @@ Statement *CaseStatement::semantic(Scope *sc) exp = exp->implicitCastTo(sc, sw->condition->type); exp = exp->optimize(WANTvalue | WANTinterpret); - if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror) + if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror) { error("case must be a string or an integral constant, not %s", exp->toChars()); exp = new IntegerExp(0); } - for (size_t i = 0; i < sw->cases->dim; i++) + for (size_t i = 0; i < sw->cases->dim; i++) { - CaseStatement *cs = (*sw->cases)[i]; + CaseStatement *cs = (*sw->cases)[i]; //printf("comparing '%s' with '%s'\n", exp->toChars(), cs->exp->toChars()); if (cs->exp->equals(exp)) @@ -2971,7 +2971,7 @@ Statement *CaseStatement::semantic(Scope *sc) // Resolve any goto case's with no exp to this case statement for (size_t i = 0; i < sw->gotoCases.dim; i++) { - GotoCaseStatement *gcs = sw->gotoCases[i]; + GotoCaseStatement *gcs = sw->gotoCases[i]; if (!gcs->exp) { @@ -2999,9 +2999,9 @@ int CaseStatement::usesEH() return statement->usesEH(); } -int CaseStatement::blockExit(bool mustNotThrow) +int CaseStatement::blockExit(bool mustNotThrow) { - return statement->blockExit(mustNotThrow); + return statement->blockExit(mustNotThrow); } @@ -3053,11 +3053,11 @@ Statement *CaseRangeStatement::semantic(Scope *sc) last = last->semantic(sc); last = last->implicitCastTo(sc, sw->condition->type); last = last->optimize(WANTvalue | WANTinterpret); - - if (first->op == TOKerror || last->op == TOKerror) - return statement ? statement->semantic(sc) : NULL; - - dinteger_t fval = first->toInteger(); + + if (first->op == TOKerror || last->op == TOKerror) + return statement ? statement->semantic(sc) : NULL; + + dinteger_t fval = first->toInteger(); dinteger_t lval = last->toInteger(); if (lval - fval > 256) @@ -3152,9 +3152,9 @@ int DefaultStatement::usesEH() return statement->usesEH(); } -int DefaultStatement::blockExit(bool mustNotThrow) +int DefaultStatement::blockExit(bool mustNotThrow) { - return statement->blockExit(mustNotThrow); + return statement->blockExit(mustNotThrow); } @@ -3191,7 +3191,7 @@ Statement *GotoDefaultStatement::semantic(Scope *sc) return this; } -int GotoDefaultStatement::blockExit(bool mustNotThrow) +int GotoDefaultStatement::blockExit(bool mustNotThrow) { return BEgoto; } @@ -3239,7 +3239,7 @@ Statement *GotoCaseStatement::semantic(Scope *sc) return this; } -int GotoCaseStatement::blockExit(bool mustNotThrow) +int GotoCaseStatement::blockExit(bool mustNotThrow) { return BEgoto; } @@ -3263,7 +3263,7 @@ SwitchErrorStatement::SwitchErrorStatement(Loc loc) { } -int SwitchErrorStatement::blockExit(bool mustNotThrow) +int SwitchErrorStatement::blockExit(bool mustNotThrow) { return BEthrow; } @@ -3299,10 +3299,10 @@ Statement *ReturnStatement::semantic(Scope *sc) FuncDeclaration *fd = sc->parent->isFuncDeclaration(); Scope *scx = sc; int implicit0 = 0; - Expression *eorg = NULL; + Expression *eorg = NULL; - if (fd->fes) - fd = fd->fes->func; // fd is now function enclosing foreach + if (fd->fes) + fd = fd->fes->func; // fd is now function enclosing foreach Type *tret = fd->type->nextOf(); if (fd->tintro) @@ -3365,14 +3365,14 @@ Statement *ReturnStatement::semantic(Scope *sc) else fd->nrvo_can = 0; - if (fd->inferRetType) + if (fd->inferRetType) { - Type *tfret = fd->type->nextOf(); - if (tfret) + Type *tfret = fd->type->nextOf(); + if (tfret) { - if (tfret != Type::terror && !exp->type->equals(tfret)) + if (tfret != Type::terror && !exp->type->equals(tfret)) error("mismatched function return type inference of %s and %s", - exp->type->toChars(), tfret->toChars()); + exp->type->toChars(), tfret->toChars()); } else { @@ -3383,17 +3383,17 @@ Statement *ReturnStatement::semantic(Scope *sc) tbret = tret->toBasetype(); } } - if (fd->returnLabel) - eorg = exp; + if (fd->returnLabel) + eorg = exp; } else if (tbret->ty != Tvoid) { - if (fd->tintro) - exp = exp->implicitCastTo(sc, fd->type->nextOf()); - - // eorg isn't casted to tret (== fd->tintro->nextOf()) - if (fd->returnLabel) - eorg = exp->copy(); + if (fd->tintro) + exp = exp->implicitCastTo(sc, fd->type->nextOf()); + + // eorg isn't casted to tret (== fd->tintro->nextOf()) + if (fd->returnLabel) + eorg = exp->copy(); exp = exp->implicitCastTo(sc, tret); } } @@ -3408,7 +3408,7 @@ Statement *ReturnStatement::semantic(Scope *sc) else { fd->type->next = Type::tvoid; - //fd->type = fd->type->semantic(loc, sc); + //fd->type = fd->type->semantic(loc, sc); if (!fd->tintro) { tret = Type::tvoid; tbret = tret; @@ -3479,8 +3479,8 @@ Statement *ReturnStatement::semantic(Scope *sc) assert(fd->vresult); VarExp *v = new VarExp(0, fd->vresult); - assert(eorg); - exp = new AssignExp(loc, v, eorg); + assert(eorg); + exp = new AssignExp(loc, v, eorg); exp->op = TOKconstruct; exp = exp->semantic(sc); } @@ -3534,7 +3534,7 @@ Statement *ReturnStatement::semantic(Scope *sc) return this; } -int ReturnStatement::blockExit(bool mustNotThrow) +int ReturnStatement::blockExit(bool mustNotThrow) { int result = BEreturn; if (exp && exp->canThrow()) @@ -3629,7 +3629,7 @@ Statement *BreakStatement::semantic(Scope *sc) return this; } -int BreakStatement::blockExit(bool mustNotThrow) +int BreakStatement::blockExit(bool mustNotThrow) { //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); return ident ? BEgoto : BEbreak; @@ -3732,7 +3732,7 @@ Statement *ContinueStatement::semantic(Scope *sc) return this; } -int ContinueStatement::blockExit(bool mustNotThrow) +int ContinueStatement::blockExit(bool mustNotThrow) { return ident ? BEgoto : BEcontinue; } @@ -3808,7 +3808,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie); Statements *cs = new Statements(); - cs->push(new ExpStatement(loc, tmp)); + cs->push(new ExpStatement(loc, tmp)); Parameters* enterargs = new Parameters; enterargs->push(new Parameter(STCin, ClassDeclaration::object->type, NULL, NULL)); @@ -3836,16 +3836,16 @@ Statement *SynchronizedStatement::semantic(Scope *sc) * try { body } finally { _d_criticalexit(critsec.ptr); } */ Identifier *id = Lexer::uniqueId("__critsec"); -#if IN_DMD - Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32()))); -#elif IN_LLVM +#if IN_DMD + Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32()))); +#elif IN_LLVM Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); -#endif +#endif VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); tmp->storage_class |= STCgshared | STCstatic; Statements *cs = new Statements(); - cs->push(new ExpStatement(loc, tmp)); + cs->push(new ExpStatement(loc, tmp)); Parameters* enterargs = new Parameters; enterargs->push(new Parameter(STCin, Type::tvoidptr, NULL, NULL)); @@ -3887,9 +3887,9 @@ int SynchronizedStatement::usesEH() return TRUE; } -int SynchronizedStatement::blockExit(bool mustNotThrow) +int SynchronizedStatement::blockExit(bool mustNotThrow) { - return body ? body->blockExit(mustNotThrow) : BEfallthru; + return body ? body->blockExit(mustNotThrow) : BEfallthru; } @@ -3931,8 +3931,8 @@ Statement *WithStatement::semantic(Scope *sc) //printf("WithStatement::semantic()\n"); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - if (exp->op == TOKerror) - return NULL; + if (exp->op == TOKerror) + return NULL; if (exp->op == TOKimport) { ScopeExp *es = (ScopeExp *)exp; @@ -4002,13 +4002,13 @@ int WithStatement::usesEH() return body ? body->usesEH() : 0; } -int WithStatement::blockExit(bool mustNotThrow) +int WithStatement::blockExit(bool mustNotThrow) { int result = BEnone; if (exp->canThrow()) result = BEthrow; if (body) - result |= body->blockExit(mustNotThrow); + result |= body->blockExit(mustNotThrow); else result |= BEfallthru; return result; @@ -4017,7 +4017,7 @@ int WithStatement::blockExit(bool mustNotThrow) /******************************** TryCatchStatement ***************************/ -TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) +TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) : Statement(loc) { this->body = body; @@ -4026,14 +4026,14 @@ TryCatchStatement::TryCatchStatement(Loc loc, Statement *body, Catches *catches) Statement *TryCatchStatement::syntaxCopy() { - Catches *a = new Catches(); + Catches *a = new Catches(); a->setDim(catches->dim); - for (size_t i = 0; i < a->dim; i++) + for (size_t i = 0; i < a->dim; i++) { Catch *c; - c = (*catches)[i]; + c = (*catches)[i]; c = c->syntaxCopy(); - (*a)[i] = c; + (*a)[i] = c; } TryCatchStatement *s = new TryCatchStatement(loc, body->syntaxCopy(), a); return s; @@ -4046,12 +4046,12 @@ Statement *TryCatchStatement::semantic(Scope *sc) /* Even if body is NULL, still do semantic analysis on catches */ for (size_t i = 0; i < catches->dim; i++) - { Catch *c = (*catches)[i]; + { Catch *c = (*catches)[i]; c->semantic(sc); // Determine if current catch 'hides' any previous catches for (size_t j = 0; j < i; j++) - { Catch *cj = (*catches)[j]; + { Catch *cj = (*catches)[j]; char *si = c->loc.toChars(); char *sj = cj->loc.toChars(); @@ -4077,36 +4077,36 @@ int TryCatchStatement::usesEH() return TRUE; } -int TryCatchStatement::blockExit(bool mustNotThrow) +int TryCatchStatement::blockExit(bool mustNotThrow) { assert(body); - int result = body->blockExit(false); + int result = body->blockExit(false); - int catchresult = 0; + int catchresult = 0; for (size_t i = 0; i < catches->dim; i++) { - Catch *c =(* catches)[i]; - if (c->type == Type::terror) - continue; - - catchresult |= c->blockExit(mustNotThrow); - - /* If we're catching Object, then there is no throwing - */ - Identifier *id = c->type->toBasetype()->isClassHandle()->ident; - if (id == Id::Object) - { - result &= ~BEthrow; + Catch *c =(* catches)[i]; + if (c->type == Type::terror) + continue; + + catchresult |= c->blockExit(mustNotThrow); + + /* If we're catching Object, then there is no throwing + */ + Identifier *id = c->type->toBasetype()->isClassHandle()->ident; + if (id == Id::Object) + { + result &= ~BEthrow; } - } - if (mustNotThrow && (result & BEthrow)) - { - body->blockExit(mustNotThrow); // now explain why this is nothrow - } - return result | catchresult; + } + if (mustNotThrow && (result & BEthrow)) + { + body->blockExit(mustNotThrow); // now explain why this is nothrow + } + return result | catchresult; } - + void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("try"); @@ -4115,7 +4115,7 @@ void TryCatchStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) body->toCBuffer(buf, hgs); for (size_t i = 0; i < catches->dim; i++) { - Catch *c = (*catches)[i]; + Catch *c = (*catches)[i]; c->toCBuffer(buf, hgs); } } @@ -4184,9 +4184,9 @@ void Catch::semantic(Scope *sc) sc->pop(); } -int Catch::blockExit(bool mustNotThrow) +int Catch::blockExit(bool mustNotThrow) { - return handler ? handler->blockExit(mustNotThrow) : BEfallthru; + return handler ? handler->blockExit(mustNotThrow) : BEfallthru; } void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -4225,7 +4225,7 @@ Statement *TryFinallyStatement::syntaxCopy() Statement *TryFinallyStatement::semantic(Scope *sc) { //printf("TryFinallyStatement::semantic()\n"); - // This code is different in LDC because LDC needs to know the + // This code is different in LDC because LDC needs to know the // enclosingScopeExit for its labels Statement* oldScopeExit = sc->enclosingScopeExit; sc->enclosingScopeExit = this; @@ -4265,10 +4265,10 @@ int TryFinallyStatement::usesEH() return TRUE; } -int TryFinallyStatement::blockExit(bool mustNotThrow) +int TryFinallyStatement::blockExit(bool mustNotThrow) { if (body) - return body->blockExit(mustNotThrow); + return body->blockExit(mustNotThrow); return BEfallthru; } @@ -4295,7 +4295,7 @@ Statement *OnScopeStatement::semantic(Scope *sc) return this; } -int OnScopeStatement::blockExit(bool mustNotThrow) +int OnScopeStatement::blockExit(bool mustNotThrow) { // At this point, this statement is just an empty placeholder return BEfallthru; } @@ -4340,7 +4340,7 @@ void OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexc ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0)); VarDeclaration *v = new VarDeclaration(loc, Type::tint32, id, ie); - *sentry = new ExpStatement(loc, v); + *sentry = new ExpStatement(loc, v); Expression *e = new IntegerExp(1); e = new AssignExp(0, new VarExp(0, v), e); @@ -4383,14 +4383,14 @@ Statement *ThrowStatement::semantic(Scope *sc) error("Throw statements cannot be in contracts"); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - if (exp->op == TOKerror) - return this; + if (exp->op == TOKerror) + return this; if (!exp->type->toBasetype()->isClassHandle()) error("can only throw class objects, not type %s", exp->type->toChars()); return this; } -int ThrowStatement::blockExit(bool mustNotThrow) +int ThrowStatement::blockExit(bool mustNotThrow) { return BEthrow; // obviously } @@ -4437,20 +4437,20 @@ Statements *VolatileStatement::flatten(Scope *sc) a = statement ? statement->flatten(sc) : NULL; if (a) - { for (size_t i = 0; i < a->dim; i++) - { Statement *s = (*a)[i]; + { for (size_t i = 0; i < a->dim; i++) + { Statement *s = (*a)[i]; s = new VolatileStatement(loc, s); - (*a)[i] = s; + (*a)[i] = s; } } return a; } -int VolatileStatement::blockExit(bool mustNotThrow) +int VolatileStatement::blockExit(bool mustNotThrow) { - return statement ? statement->blockExit(mustNotThrow) : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } @@ -4501,7 +4501,7 @@ Statement *GotoStatement::semantic(Scope *sc) * list. */ Statements *a = new Statements(); - CompoundStatement *s; + CompoundStatement *s; a->push(this); s = new CompoundStatement(loc, a); @@ -4513,7 +4513,7 @@ Statement *GotoStatement::semantic(Scope *sc) return this; } -int GotoStatement::blockExit(bool mustNotThrow) +int GotoStatement::blockExit(bool mustNotThrow) { //printf("GotoStatement::blockExit(%p)\n", this); return BEgoto; @@ -4587,12 +4587,12 @@ Statements *LabelStatement::flatten(Scope *sc) { if (!a->dim) { - a->push(new ExpStatement(loc, (Expression *)NULL)); + a->push(new ExpStatement(loc, (Expression *)NULL)); } - Statement *s = (*a)[0]; + Statement *s = (*a)[0]; s = new LabelStatement(loc, ident, s); - (*a)[0] = s; + (*a)[0] = s; } } @@ -4605,10 +4605,10 @@ int LabelStatement::usesEH() return statement ? statement->usesEH() : FALSE; } -int LabelStatement::blockExit(bool mustNotThrow) +int LabelStatement::blockExit(bool mustNotThrow) { //printf("LabelStatement::blockExit(%p)\n", this); - return statement ? statement->blockExit(mustNotThrow) : BEfallthru; + return statement ? statement->blockExit(mustNotThrow) : BEfallthru; } diff --git a/dmd/statement.h b/dmd/statement.h index 6ffb84f4..27406c1b 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -27,7 +27,7 @@ struct Expression; struct LabelDsymbol; struct Identifier; struct IfStatement; -struct ExpStatement; +struct ExpStatement; struct DefaultStatement; struct VarDeclaration; struct Condition; @@ -46,9 +46,9 @@ struct GotoStatement; struct ScopeStatement; struct TryCatchStatement; struct TryFinallyStatement; -struct CaseStatement; -struct DefaultStatement; -struct LabelStatement; +struct CaseStatement; +struct DefaultStatement; +struct LabelStatement; struct HdrGenState; struct InterState; struct CaseStatement; @@ -123,7 +123,7 @@ struct Statement : Object virtual int hasBreak(); virtual int hasContinue(); virtual int usesEH(); - virtual int blockExit(bool mustNotThrow); + virtual int blockExit(bool mustNotThrow); virtual int comeFrom(); virtual int isEmpty(); virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); @@ -132,19 +132,19 @@ struct Statement : Object virtual int inlineCost(InlineCostState *ics); virtual Expression *doInline(InlineDoState *ids); - virtual Statement *doInlineStatement(InlineDoState *ids); + virtual Statement *doInlineStatement(InlineDoState *ids); virtual Statement *inlineScan(InlineScanState *iss); // Back end virtual void toIR(IRState *irs); // Avoid dynamic_cast - virtual ExpStatement *isExpStatement() { return NULL; } + virtual ExpStatement *isExpStatement() { return NULL; } virtual CompoundStatement *isCompoundStatement() { return NULL; } virtual ReturnStatement *isReturnStatement() { return NULL; } virtual IfStatement *isIfStatement() { return NULL; } virtual CaseStatement* isCaseStatement() { return NULL; } - virtual DefaultStatement *isDefaultStatement() { return NULL; } + virtual DefaultStatement *isDefaultStatement() { return NULL; } virtual LabelStatement* isLabelStatement() { return NULL; } #if IN_LLVM @@ -166,18 +166,18 @@ struct ExpStatement : Statement Expression *exp; ExpStatement(Loc loc, Expression *exp); - ExpStatement(Loc loc, Dsymbol *s); + ExpStatement(Loc loc, Dsymbol *s); Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int isEmpty(); - void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); + void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); @@ -185,8 +185,8 @@ struct ExpStatement : Statement #if IN_LLVM void toNakedIR(IRState *irs); #endif - - ExpStatement *isExpStatement() { return this; } + + ExpStatement *isExpStatement() { return this; } }; struct CompileStatement : Statement @@ -211,7 +211,7 @@ struct CompoundStatement : Statement void toCBuffer(OutBuffer *buf, HdrGenState *hgs); virtual Statement *semantic(Scope *sc); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); int isEmpty(); virtual Statements *flatten(Scope *sc); @@ -220,7 +220,7 @@ struct CompoundStatement : Statement int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); virtual void toIR(IRState *irs); @@ -252,14 +252,14 @@ struct UnrolledLoopStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); @@ -277,14 +277,14 @@ struct ScopeStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); int isEmpty(); Expression *interpret(InterState *istate); - int inlineCost(InlineCostState *ics); - Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); @@ -301,7 +301,7 @@ struct WhileStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -322,7 +322,7 @@ struct DoStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -346,14 +346,14 @@ struct ForStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int inlineCost(InlineCostState *ics); + int inlineCost(InlineCostState *ics); Statement *inlineScan(InlineScanState *iss); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); void toIR(IRState *irs); }; @@ -370,8 +370,8 @@ struct ForeachStatement : Statement FuncDeclaration *func; // function we're lexically in - Statements *cases; // put breaks, continues, gotos and returns here - CompoundStatements *gotos; // forward referenced goto's go here + Statements *cases; // put breaks, continues, gotos and returns here + CompoundStatements *gotos; // forward referenced goto's go here ForeachStatement(Loc loc, enum TOK op, Parameters *arguments, Expression *aggr, Statement *body); Statement *syntaxCopy(); @@ -380,7 +380,7 @@ struct ForeachStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -408,7 +408,7 @@ struct ForeachRangeStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -434,12 +434,12 @@ struct IfStatement : Statement Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); IfStatement *isIfStatement() { return this; } int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); @@ -456,7 +456,7 @@ struct ConditionalStatement : Statement Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -471,7 +471,7 @@ struct PragmaStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -483,7 +483,7 @@ struct StaticAssertStatement : Statement StaticAssertStatement(StaticAssert *sa); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -495,8 +495,8 @@ struct SwitchStatement : Statement DefaultStatement *sdefault; - GotoCaseStatements gotoCases; // array of unresolved GotoCaseStatement's - CaseStatements *cases; // array of CaseStatement's + GotoCaseStatements gotoCases; // array of unresolved GotoCaseStatement's + CaseStatements *cases; // array of CaseStatement's int hasNoDefault; // !=0 if no default statement // LDC @@ -507,7 +507,7 @@ struct SwitchStatement : Statement Statement *semantic(Scope *sc); int hasBreak(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -532,11 +532,11 @@ struct CaseStatement : Statement Statement *semantic(Scope *sc); int compare(Object *obj); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - CaseStatement *isCaseStatement() { return this; } + CaseStatement *isCaseStatement() { return this; } Statement *inlineScan(InlineScanState *iss); @@ -578,11 +578,11 @@ struct DefaultStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - DefaultStatement *isDefaultStatement() { return this; } + DefaultStatement *isDefaultStatement() { return this; } Statement *inlineScan(InlineScanState *iss); @@ -600,7 +600,7 @@ struct GotoDefaultStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -616,7 +616,7 @@ struct GotoCaseStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -625,7 +625,7 @@ struct GotoCaseStatement : Statement struct SwitchErrorStatement : Statement { SwitchErrorStatement(Loc loc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -639,12 +639,12 @@ struct ReturnStatement : Statement Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); - Statement *doInlineStatement(InlineDoState *ids); + Statement *doInlineStatement(InlineDoState *ids); Statement *inlineScan(InlineScanState *iss); void toIR(IRState *irs); @@ -660,7 +660,7 @@ struct BreakStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -677,7 +677,7 @@ struct ContinueStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toIR(IRState *irs); @@ -697,7 +697,7 @@ struct SynchronizedStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -720,7 +720,7 @@ struct WithStatement : Statement Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -731,14 +731,14 @@ struct WithStatement : Statement struct TryCatchStatement : Statement { Statement *body; - Catches *catches; + Catches *catches; - TryCatchStatement(Loc loc, Statement *body, Catches *catches); + TryCatchStatement(Loc loc, Statement *body, Catches *catches); Statement *syntaxCopy(); Statement *semantic(Scope *sc); int hasBreak(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -759,7 +759,7 @@ struct Catch : Object Catch(Loc loc, Type *t, Identifier *id, Statement *handler); Catch *syntaxCopy(); void semantic(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -775,7 +775,7 @@ struct TryFinallyStatement : Statement int hasBreak(); int hasContinue(); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -790,7 +790,7 @@ struct OnScopeStatement : Statement OnScopeStatement(Loc loc, TOK tok, Statement *statement); Statement *syntaxCopy(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); int usesEH(); @@ -808,7 +808,7 @@ struct ThrowStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); Statement *inlineScan(InlineScanState *iss); @@ -824,7 +824,7 @@ struct VolatileStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -842,7 +842,7 @@ struct GotoStatement : Statement GotoStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); void toIR(IRState *irs); @@ -858,20 +858,20 @@ struct LabelStatement : Statement Statement* enclosingScopeExit; block *lblock; // back end - Blocks *fwdrefs; // forward references to this LabelStatement + Blocks *fwdrefs; // forward references to this LabelStatement LabelStatement(Loc loc, Identifier *ident, Statement *statement); Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int usesEH(); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); - LabelStatement *isLabelStatement() { return this; } + LabelStatement *isLabelStatement() { return this; } void toIR(IRState *irs); @@ -893,14 +893,14 @@ struct AsmStatement : Statement Token *tokens; code *asmcode; unsigned asmalign; // alignment of this statement - unsigned regs; // mask of registers modified (must match regm_t in back end) - unsigned char refparam; // !=0 if function parameter is referenced - unsigned char naked; // !=0 if function is to be naked + unsigned regs; // mask of registers modified (must match regm_t in back end) + unsigned char refparam; // !=0 if function parameter is referenced + unsigned char naked; // !=0 if function is to be naked AsmStatement(Loc loc, Token *tokens); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - int blockExit(bool mustNotThrow); + int blockExit(bool mustNotThrow); int comeFrom(); Expression *interpret(InterState *istate); diff --git a/dmd/staticassert.c b/dmd/staticassert.c index 07adb737..6c358ebc 100644 --- a/dmd/staticassert.c +++ b/dmd/staticassert.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -53,16 +53,16 @@ void StaticAssert::semantic(Scope *sc) void StaticAssert::semantic2(Scope *sc) { //printf("StaticAssert::semantic2() %s\n", toChars()); - Expression *e = exp->semantic(sc); - if (e->type == Type::terror) + Expression *e = exp->semantic(sc); + if (e->type == Type::terror) return; - unsigned olderrs = global.errors; + unsigned olderrs = global.errors; e = e->optimize(WANTvalue | WANTinterpret); - if (global.errors != olderrs) - { - errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars()); - } - else if (e->isBool(FALSE)) + if (global.errors != olderrs) + { + errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars()); + } + else if (e->isBool(FALSE)) { if (msg) { HdrGenState hgs; diff --git a/dmd/staticassert.h b/dmd/staticassert.h index 91c37f04..2f7e0906 100644 --- a/dmd/staticassert.h +++ b/dmd/staticassert.h @@ -1,41 +1,41 @@ - -// 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. - -#ifndef DMD_STATICASSERT_H -#define DMD_STATICASSERT_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct Expression; -struct HdrGenState; - -struct StaticAssert : Dsymbol -{ - Expression *exp; - Expression *msg; - - StaticAssert(Loc loc, Expression *exp, Expression *msg); - - Dsymbol *syntaxCopy(Dsymbol *s); - int addMember(Scope *sc, ScopeDsymbol *sd, int memnum); - void semantic(Scope *sc); - void semantic2(Scope *sc); - void inlineScan(); - int oneMember(Dsymbol **ps); - void toObjFile(int multiobj); - const char *kind(); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); -}; - -#endif + +// 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. + +#ifndef DMD_STATICASSERT_H +#define DMD_STATICASSERT_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "dsymbol.h" + +struct Expression; +struct HdrGenState; + +struct StaticAssert : Dsymbol +{ + Expression *exp; + Expression *msg; + + StaticAssert(Loc loc, Expression *exp, Expression *msg); + + Dsymbol *syntaxCopy(Dsymbol *s); + int addMember(Scope *sc, ScopeDsymbol *sd, int memnum); + void semantic(Scope *sc); + void semantic2(Scope *sc); + void inlineScan(); + int oneMember(Dsymbol **ps); + void toObjFile(int multiobj); + const char *kind(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +#endif diff --git a/dmd/struct.c b/dmd/struct.c index b542b180..b320fdb8 100644 --- a/dmd/struct.c +++ b/dmd/struct.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -51,10 +51,10 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) ctor = NULL; defaultCtor = NULL; - aliasthis = NULL; - noDefaultCtor = FALSE; + aliasthis = NULL; + noDefaultCtor = FALSE; #endif - dtor = NULL; + dtor = NULL; #if IN_LLVM availableExternally = true; // assume this unless proven otherwise @@ -78,7 +78,7 @@ void AggregateDeclaration::semantic2(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; s->semantic2(sc); } sc->pop(); @@ -86,7 +86,7 @@ void AggregateDeclaration::semantic2(Scope *sc) } void AggregateDeclaration::semantic3(Scope *sc) -{ +{ // LDC if (!global.params.useAvailableExternally) availableExternally = false; @@ -95,9 +95,9 @@ void AggregateDeclaration::semantic3(Scope *sc) if (members) { sc = sc->push(this); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; s->semantic3(sc); } sc->pop(); @@ -105,13 +105,13 @@ void AggregateDeclaration::semantic3(Scope *sc) } void AggregateDeclaration::inlineScan() -{ +{ //printf("AggregateDeclaration::inlineScan(%s)\n", toChars()); if (members) { - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; //printf("inline scan aggregate symbol '%s'\n", s->toChars()); s->inlineScan(); } @@ -142,11 +142,11 @@ int AggregateDeclaration::isDeprecated() return isdeprecated; } -int AggregateDeclaration::isExport() -{ - return protection == PROTexport; -} - +int AggregateDeclaration::isExport() +{ + return protection == PROTexport; +} + /**************************** * Do byte or word alignment as necessary. * Align sizes of 0, as we may not know array sizes yet. @@ -161,7 +161,7 @@ void AggregateDeclaration::alignmember( if (salign > 1) { assert(size != 3); - unsigned sa = size; + unsigned sa = size; if (sa == 0 || salign < sa) sa = salign; *poffset = (*poffset + sa - 1) & ~(sa - 1); @@ -222,10 +222,10 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) if (!isUnionDeclaration()) sc->offset = ofs; #endif - if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) - /* Not sure how to handle this */ - ; - else if (sc->structalign < memalignsize) + if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) + /* Not sure how to handle this */ + ; + else if (sc->structalign < memalignsize) memalignsize = sc->structalign; if (alignsize < memalignsize) alignsize = memalignsize; @@ -236,57 +236,57 @@ void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) fields.push(v); } -/**************************************** - * If field[indx] is not part of a union, return indx. - * Otherwise, return the lowest field index of the union. - */ -int AggregateDeclaration::firstFieldInUnion(int indx) -{ - if (isUnionDeclaration()) - return 0; - VarDeclaration * vd = fields.tdata()[indx]; - int firstNonZero = indx; // first index in the union with non-zero size - for (; ;) - { - if (indx == 0) - return firstNonZero; - VarDeclaration * v = fields.tdata()[indx - 1]; - if (v->offset != vd->offset) - return firstNonZero; - --indx; - /* If it is a zero-length field, it's ambiguous: we don't know if it is - * in the union unless we find an earlier non-zero sized field with the - * same offset. - */ - if (v->size(loc) != 0) - firstNonZero = indx; - } -} - -/**************************************** - * Count the number of fields starting at firstIndex which are part of the - * same union as field[firstIndex]. If not a union, return 1. - */ -int AggregateDeclaration::numFieldsInUnion(int firstIndex) -{ - VarDeclaration * vd = fields.tdata()[firstIndex]; - /* If it is a zero-length field, AND we can't find an earlier non-zero - * sized field with the same offset, we assume it's not part of a union. - */ - if (vd->size(loc) == 0 && !isUnionDeclaration() && - firstFieldInUnion(firstIndex) == firstIndex) - return 1; - int count = 1; - for (size_t i = firstIndex+1; i < fields.dim; ++i) - { - VarDeclaration * v = fields.tdata()[i]; - // If offsets are different, they are not in the same union - if (v->offset != vd->offset) - break; - ++count; - } - return count; -} +/**************************************** + * If field[indx] is not part of a union, return indx. + * Otherwise, return the lowest field index of the union. + */ +int AggregateDeclaration::firstFieldInUnion(int indx) +{ + if (isUnionDeclaration()) + return 0; + VarDeclaration * vd = fields.tdata()[indx]; + int firstNonZero = indx; // first index in the union with non-zero size + for (; ;) + { + if (indx == 0) + return firstNonZero; + VarDeclaration * v = fields.tdata()[indx - 1]; + if (v->offset != vd->offset) + return firstNonZero; + --indx; + /* If it is a zero-length field, it's ambiguous: we don't know if it is + * in the union unless we find an earlier non-zero sized field with the + * same offset. + */ + if (v->size(loc) != 0) + firstNonZero = indx; + } +} + +/**************************************** + * Count the number of fields starting at firstIndex which are part of the + * same union as field[firstIndex]. If not a union, return 1. + */ +int AggregateDeclaration::numFieldsInUnion(int firstIndex) +{ + VarDeclaration * vd = fields.tdata()[firstIndex]; + /* If it is a zero-length field, AND we can't find an earlier non-zero + * sized field with the same offset, we assume it's not part of a union. + */ + if (vd->size(loc) == 0 && !isUnionDeclaration() && + firstFieldInUnion(firstIndex) == firstIndex) + return 1; + int count = 1; + for (size_t i = firstIndex+1; i < fields.dim; ++i) + { + VarDeclaration * v = fields.tdata()[i]; + // If offsets are different, they are not in the same union + if (v->offset != vd->offset) + break; + ++count; + } + return count; +} /********************************* StructDeclaration ****************************/ @@ -317,7 +317,7 @@ Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s) } void StructDeclaration::semantic(Scope *sc) -{ +{ Scope *sc2; //printf("+StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); @@ -370,9 +370,9 @@ void StructDeclaration::semantic(Scope *sc) if (sizeok == 0) // if not already done the addMember step { - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); s->addMember(sc, this, 1); } @@ -387,13 +387,13 @@ void StructDeclaration::semantic(Scope *sc) sc2->protection = PROTpublic; sc2->explicitProtection = 0; - size_t members_dim = members->dim; + size_t members_dim = members->dim; /* Set scope so if there are forward references, we still might be able to * resolve individual members like enums. */ - for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = members->tdata()[i]; + for (size_t i = 0; i < members_dim; i++) + { Dsymbol *s = members->tdata()[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ @@ -404,9 +404,9 @@ void StructDeclaration::semantic(Scope *sc) } } - for (size_t i = 0; i < members_dim; i++) + for (size_t i = 0; i < members_dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; s->semantic(sc2); #if 0 if (sizeok == 2) @@ -416,10 +416,10 @@ void StructDeclaration::semantic(Scope *sc) #endif } -#if DMDV1 - /* This doesn't work for DMDV2 because (ref S) and (S) parameter - * lists will overload the same. - */ +#if DMDV1 + /* This doesn't work for DMDV2 because (ref S) and (S) parameter + * lists will overload the same. + */ /* The TypeInfo_Struct is expecting an opEquals and opCmp with * a parameter that is a pointer to the struct. But if there * isn't one, but is an opEquals or opCmp with a value, write @@ -477,7 +477,7 @@ void StructDeclaration::semantic(Scope *sc) id = Id::cmp; } -#endif +#endif #if DMDV2 dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); @@ -523,7 +523,7 @@ void StructDeclaration::semantic(Scope *sc) // Determine if struct is all zeros or not zeroInit = 1; - for (size_t i = 0; i < fields.dim; i++) + for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = (Dsymbol *)fields.data[i]; VarDeclaration *vd = s->isVarDeclaration(); @@ -566,7 +566,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) { //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); - if (scope && !symtab) + if (scope && !symtab) semantic(scope); if (!members || !symtab) @@ -579,7 +579,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) } void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ +{ buf->printf("%s ", kind()); if (!isAnonymous()) buf->writestring(toChars()); @@ -592,9 +592,9 @@ void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); diff --git a/dmd/template.c b/dmd/template.c index 9d9c6a78..a692a0b3 100644 --- a/dmd/template.c +++ b/dmd/template.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -16,7 +16,7 @@ #if !IN_LLVM #endif #include "root.h" -#include "aav.h" +#include "aav.h" #include "rmem.h" #include "stringtable.h" #include "mars.h" @@ -159,35 +159,35 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) Expression *e2 = isExpression(o2); Dsymbol *s1 = isDsymbol(o1); Dsymbol *s2 = isDsymbol(o2); - Tuple *u1 = isTuple(o1); - Tuple *u2 = isTuple(o2); + Tuple *u1 = isTuple(o1); + Tuple *u2 = isTuple(o2); - //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, u1 %p u2 %p\n", t1,t2,e1,e2,s1,s2,u1,u2); + //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, u1 %p u2 %p\n", t1,t2,e1,e2,s1,s2,u1,u2); /* A proper implementation of the various equals() overrides * should make it possible to just do o1->equals(o2), but * we'll do that another day. */ - if (s1) - { - VarDeclaration *v1 = s1->isVarDeclaration(); - if (v1 && v1->storage_class & STCmanifest) - { ExpInitializer *ei1 = v1->init->isExpInitializer(); - if (ei1) - e1 = ei1->exp, s1 = NULL; - } - } - if (s2) - { - VarDeclaration *v2 = s2->isVarDeclaration(); - if (v2 && v2->storage_class & STCmanifest) - { ExpInitializer *ei2 = v2->init->isExpInitializer(); - if (ei2) - e2 = ei2->exp, s2 = NULL; - } - } - + if (s1) + { + VarDeclaration *v1 = s1->isVarDeclaration(); + if (v1 && v1->storage_class & STCmanifest) + { ExpInitializer *ei1 = v1->init->isExpInitializer(); + if (ei1) + e1 = ei1->exp, s1 = NULL; + } + } + if (s2) + { + VarDeclaration *v2 = s2->isVarDeclaration(); + if (v2 && v2->storage_class & STCmanifest) + { ExpInitializer *ei2 = v2->init->isExpInitializer(); + if (ei2) + e2 = ei2->exp, s2 = NULL; + } + } + if (t1) { /* if t1 is an instance of ti, then give error @@ -233,26 +233,26 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) } else if (s1) { - if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) + if (!s2 || !s1->equals(s2) || s1->parent != s2->parent) goto Lnomatch; } - else if (u1) + else if (u1) { - if (!u2) + if (!u2) goto Lnomatch; - if (u1->objects.dim != u2->objects.dim) + if (u1->objects.dim != u2->objects.dim) goto Lnomatch; - for (size_t i = 0; i < u1->objects.dim; i++) + for (size_t i = 0; i < u1->objects.dim; i++) { - if (!match(u1->objects.tdata()[i], - u2->objects.tdata()[i], + if (!match(u1->objects.tdata()[i], + u2->objects.tdata()[i], tempdecl, sc)) goto Lnomatch; } } //printf("match\n"); return 1; // match - + Lnomatch: //printf("nomatch\n"); return 0; // nomatch; @@ -281,8 +281,8 @@ int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl, } /**************************************** - * This makes a 'pretty' version of the template arguments. - * It's analogous to genIdent() which makes a mangled version. + * This makes a 'pretty' version of the template arguments. + * It's analogous to genIdent() which makes a mangled version. */ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) @@ -292,21 +292,21 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) Expression *e = isExpression(oarg); Dsymbol *s = isDsymbol(oarg); Tuple *v = isTuple(oarg); - /* The logic of this should match what genIdent() does. The _dynamic_cast() - * function relies on all the pretty strings to be unique for different classes - * (see Bugzilla 7375). - * Perhaps it would be better to demangle what genIdent() does. - */ + /* The logic of this should match what genIdent() does. The _dynamic_cast() + * function relies on all the pretty strings to be unique for different classes + * (see Bugzilla 7375). + * Perhaps it would be better to demangle what genIdent() does. + */ if (t) { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty); t->toCBuffer(buf, NULL, hgs); } else if (e) - { - if (e->op == TOKvar) - e = e->optimize(WANTvalue); // added to fix Bugzilla 7375 + { + if (e->op == TOKvar) + e = e->optimize(WANTvalue); // added to fix Bugzilla 7375 e->toCBuffer(buf, hgs); - } + } else if (s) { char *p = s->ident ? s->ident->toChars() : s->toChars(); @@ -319,7 +319,7 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) { if (i) buf->writeByte(','); - Object *o = (*args)[i]; + Object *o = (*args)[i]; ObjectToCBuffer(buf, hgs, o); } } @@ -355,7 +355,7 @@ Object *objectSyntaxCopy(Object *o) /* ======================== TemplateDeclaration ============================= */ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, - TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs) + TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs) : ScopeDsymbol(id) { #if LOG @@ -363,7 +363,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, #endif #if 0 if (parameters) - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; //printf("\tparameter[%d] = %p\n", i, tp); TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); @@ -383,20 +383,20 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, this->overroot = NULL; this->semanticRun = 0; this->onemember = NULL; - - // Compute in advance for Ddoc's use - if (members) - { - Dsymbol *s; - if (Dsymbol::oneMembers(members, &s)) - { - if (s && s->ident && s->ident->equals(ident)) - { - onemember = s; - s->parent = this; - } - } - } + + // Compute in advance for Ddoc's use + if (members) + { + Dsymbol *s; + if (Dsymbol::oneMembers(members, &s)) + { + if (s && s->ident && s->ident->equals(ident)) + { + onemember = s; + s->parent = this; + } + } + } } Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) @@ -410,7 +410,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) { p = new TemplateParameters(); p->setDim(parameters->dim); - for (size_t i = 0; i < p->dim; i++) + for (size_t i = 0; i < p->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; p->data[i] = (void *)tp->syntaxCopy(); } @@ -418,7 +418,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) Expression *e = NULL; if (constraint) e = constraint->syntaxCopy(); - Dsymbols *d = Dsymbol::arraySyntaxCopy(members); + Dsymbols *d = Dsymbol::arraySyntaxCopy(members); td = new TemplateDeclaration(loc, ident, p, e, d); #if IN_LLVM @@ -491,21 +491,21 @@ void TemplateDeclaration::semantic(Scope *sc) { origParameters = new TemplateParameters(); origParameters->setDim(parameters->dim); - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; origParameters->data[i] = (void *)tp->syntaxCopy(); } } - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; tp->declareParameter(paramscope); } - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; @@ -516,8 +516,8 @@ void TemplateDeclaration::semantic(Scope *sc) paramscope->pop(); - // Compute again - onemember = NULL; + // Compute again + onemember = NULL; if (members) { Dsymbol *s; @@ -571,7 +571,7 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s) if (f->parameters->dim != f2->parameters->dim) goto Lcontinue; - for (size_t i = 0; i < f->parameters->dim; i++) + for (size_t i = 0; i < f->parameters->dim; i++) { TemplateParameter *p1 = (TemplateParameter *)f->parameters->data[i]; TemplateParameter *p2 = (TemplateParameter *)f2->parameters->data[i]; @@ -612,7 +612,7 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s) MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, Objects *dedtypes, int flag) { MATCH m; - size_t dedtypes_dim = dedtypes->dim; + size_t dedtypes_dim = dedtypes->dim; #define LOGM 0 #if LOGM @@ -628,7 +628,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, #endif dedtypes->zero(); - size_t parameters_dim = parameters->dim; + size_t parameters_dim = parameters->dim; int variadic = isVariadic() != NULL; // If more arguments than parameters, no match @@ -652,7 +652,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, // Attempt type deduction m = MATCHexact; - for (size_t i = 0; i < dedtypes_dim; i++) + for (size_t i = 0; i < dedtypes_dim; i++) { MATCH m2; TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; Declaration *sparam; @@ -695,7 +695,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, /* Any parameter left without a type gets the type of * its corresponding arg */ - for (size_t i = 0; i < dedtypes_dim; i++) + for (size_t i = 0; i < dedtypes_dim; i++) { if (!dedtypes->data[i]) { assert(i < ti->tiargs->dim); @@ -730,7 +730,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, printf("instance %s\n", ti->toChars()); if (m) { - for (size_t i = 0; i < dedtypes_dim; i++) + for (size_t i = 0; i < dedtypes_dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; Object *oarg; @@ -796,7 +796,7 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2) // generated from the parameters to this template declaration ti.tiargs = new Objects(); ti.tiargs->setDim(parameters->dim); - for (size_t i = 0; i < ti.tiargs->dim; i++) + for (size_t i = 0; i < ti.tiargs->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; @@ -864,7 +864,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, #if 0 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); - for (size_t i = 0; i < fargs->dim; i++) + for (size_t i = 0; i < fargs->dim; i++) { Expression *e = (Expression *)fargs->data[i]; printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars()); } @@ -889,7 +889,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, TemplateTupleParameter *tp = isVariadic(); #if 0 - for (size_t i = 0; i < dedargs->dim; i++) + for (size_t i = 0; i < dedargs->dim; i++) { printf("\tdedarg[%d] = ", i); Object *oarg = (Object *)dedargs->data[i]; @@ -940,7 +940,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, } } #if 0 - for (size_t i = 0; i < dedargs->dim; i++) + for (size_t i = 0; i < dedargs->dim; i++) { printf("\tdedarg[%d] = ", i); Object *oarg = (Object *)dedargs->data[i]; @@ -998,7 +998,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi, tuple_dim = nfargs - (nfparams - 1); t->objects.setDim(tuple_dim); - for (size_t i = 0; i < tuple_dim; i++) + for (size_t i = 0; i < tuple_dim; i++) { Expression *farg = (Expression *)fargs->data[fptupindex + i]; t->objects.data[i] = (void *)farg->type; } @@ -1085,7 +1085,7 @@ L2: * arg [fptupindex..fptupindex+tuple_dim] == param[fptupindex] * arg[fputupindex+dim.. ] == param[fptupindex+1.. ] */ - size_t i = parami; + size_t i = parami; if (fptupindex >= 0 && parami > fptupindex) i += tuple_dim - 1; @@ -1219,7 +1219,7 @@ Lmatch: /* Fill in any missing arguments with their defaults. */ - for (size_t i = nargsi; i < dedargs->dim; i++) + for (size_t i = nargsi; i < dedargs->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; //printf("tp[%d] = %s\n", i, tp->ident->toChars()); @@ -1282,7 +1282,7 @@ Lmatch: #endif #if 0 - for (size_t i = 0; i < dedargs->dim; i++) + for (size_t i = 0; i < dedargs->dim; i++) { Type *t = (Type *)dedargs->data[i]; printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars()); } @@ -1421,13 +1421,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars()); printf(" targsi:\n"); if (targsi) - { for (size_t i = 0; i < targsi->dim; i++) + { for (size_t i = 0; i < targsi->dim; i++) { Object *arg = (Object *)targsi->data[i]; printf("\t%s\n", arg->toChars()); } } printf(" fargs:\n"); - for (size_t i = 0; i < fargs->dim; i++) + for (size_t i = 0; i < fargs->dim; i++) { Expression *arg = (Expression *)fargs->data[i]; printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); //printf("\tty = %d\n", arg->type->ty); @@ -1526,7 +1526,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, OutBuffer bufa; Objects *args = targsi; if (args) - { for (size_t i = 0; i < args->dim; i++) + { for (size_t i = 0; i < args->dim; i++) { if (i) bufa.writeByte(','); @@ -1543,25 +1543,25 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, return NULL; } -bool TemplateDeclaration::hasStaticCtorOrDtor() -{ - return FALSE; // don't scan uninstantiated templates -} - +bool TemplateDeclaration::hasStaticCtorOrDtor() +{ + return FALSE; // don't scan uninstantiated templates +} + void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { -#if 0 // Should handle template functions for doc generation +#if 0 // Should handle template functions for doc generation if (onemember && onemember->isFuncDeclaration()) buf->writestring("foo "); #endif - if (hgs->ddoc) + if (hgs->ddoc) buf->writestring(kind()); - else - buf->writestring("template"); + else + buf->writestring("template"); buf->writeByte(' '); buf->writestring(ident->toChars()); buf->writeByte('('); - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; if (hgs->ddoc) @@ -1585,7 +1585,7 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writebyte('{'); buf->writenl(); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->toCBuffer(buf, hgs); @@ -1604,7 +1604,7 @@ char *TemplateDeclaration::toChars() memset(&hgs, 0, sizeof(hgs)); buf.writestring(ident->toChars()); buf.writeByte('('); - for (size_t i = 0; i < parameters->dim; i++) + for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; if (i) @@ -1733,19 +1733,19 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, else goto Lnomatch; } - else if (tparam->ty == Ttypeof) - { - /* Need a loc to go with the semantic routine. - */ - Loc loc; - if (parameters->dim) - { - TemplateParameter *tp = parameters->tdata()[0]; - loc = tp->loc; - } - - tparam = tparam->semantic(loc, sc); - } + else if (tparam->ty == Ttypeof) + { + /* Need a loc to go with the semantic routine. + */ + Loc loc; + if (parameters->dim) + { + TemplateParameter *tp = parameters->tdata()[0]; + loc = tp->loc; + } + + tparam = tparam->semantic(loc, sc); + } if (ty != tparam->ty) { @@ -1753,17 +1753,17 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, // Can't instantiate AssociativeArray!() without a scope if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc) ((TypeAArray*)tparam)->sc = sc; - - MATCH m = implicitConvTo(tparam); - if (m == MATCHnomatch) - { - Type *at = aliasthisOf(); - if (at) - m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch); - } - return m; -#else - return implicitConvTo(tparam); + + MATCH m = implicitConvTo(tparam); + if (m == MATCHnomatch) + { + Type *at = aliasthisOf(); + if (at) + m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch); + } + return m; +#else + return implicitConvTo(tparam); #endif } @@ -1784,14 +1784,14 @@ Lconst: #if DMDV2 MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, - Objects *dedtypes, unsigned *wildmatch) + Objects *dedtypes, unsigned *wildmatch) { #if 0 printf("TypeDArray::deduceType()\n"); printf("\tthis = %d, ", ty); print(); printf("\ttparam = %d, ", tparam->ty); tparam->print(); #endif - return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); + return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); } #endif @@ -1807,23 +1807,23 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame // Extra check that array dimensions must match if (tparam) { - if (tparam->ty == Tarray) - { MATCH m; - - m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); - if (m == MATCHexact) - m = MATCHconvert; - return m; - } - - Identifier *id = NULL; + if (tparam->ty == Tarray) + { MATCH m; + + m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); + if (m == MATCHexact) + m = MATCHconvert; + return m; + } + + Identifier *id = NULL; if (tparam->ty == Tsarray) { TypeSArray *tp = (TypeSArray *)tparam; if (tp->dim->op == TOKvar && ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter) { - id = ((VarExp *)tp->dim)->var->ident; + id = ((VarExp *)tp->dim)->var->ident; } else if (dim->toInteger() != tp->dim->toInteger()) return MATCHnomatch; @@ -1831,35 +1831,35 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame else if (tparam->ty == Taarray) { TypeAArray *tp = (TypeAArray *)tparam; - if (tp->index->ty == Tident && - ((TypeIdentifier *)tp->index)->idents.dim == 0) + if (tp->index->ty == Tident && + ((TypeIdentifier *)tp->index)->idents.dim == 0) { - id = ((TypeIdentifier *)tp->index)->ident; - } - } - if (id) - { - // This code matches code in TypeInstance::deduceType() - int i = templateIdentifierLookup(id, parameters); - if (i == -1) + id = ((TypeIdentifier *)tp->index)->ident; + } + } + if (id) + { + // This code matches code in TypeInstance::deduceType() + int i = templateIdentifierLookup(id, parameters); + if (i == -1) goto Lnomatch; - TemplateParameter *tprm = parameters->tdata()[i]; - TemplateValueParameter *tvp = tprm->isTemplateValueParameter(); - if (!tvp) - goto Lnomatch; - Expression *e = (Expression *)dedtypes->tdata()[i]; - if (e) + TemplateParameter *tprm = parameters->tdata()[i]; + TemplateValueParameter *tvp = tprm->isTemplateValueParameter(); + if (!tvp) + goto Lnomatch; + Expression *e = (Expression *)dedtypes->tdata()[i]; + if (e) { - if (!dim->equals(e)) + if (!dim->equals(e)) goto Lnomatch; } else - { - Type *vt = tvp->valType->semantic(0, sc); - MATCH m = (MATCH)dim->implicitConvTo(vt); - if (!m) - goto Lnomatch; - dedtypes->tdata()[i] = dim; + { + Type *vt = tvp->valType->semantic(0, sc); + MATCH m = (MATCH)dim->implicitConvTo(vt); + if (!m) + goto Lnomatch; + dedtypes->tdata()[i] = dim; } return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); } @@ -1938,7 +1938,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para /* The types of the function arguments [nfparams - 1 .. nfargs] * now form the tuple argument. */ - size_t tuple_dim = nfargs - (nfparams - 1); + size_t tuple_dim = nfargs - (nfparams - 1); /* See if existing tuple, and whether it matches or not */ @@ -1991,7 +1991,7 @@ MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *pa { TypeIdentifier *tp = (TypeIdentifier *)tparam; - for (size_t i = 0; i < idents.dim; i++) + for (size_t i = 0; i < idents.dim; i++) { Identifier *id1 = (Identifier *)idents.data[i]; Identifier *id2 = (Identifier *)tp->idents.data[i]; @@ -2067,7 +2067,7 @@ MATCH TypeInstance::deduceType(Scope *sc, L2: - for (size_t i = 0; 1; i++) + for (size_t i = 0; 1; i++) { //printf("\ttest: tempinst->tiargs[%d]\n", i); Object *o1; @@ -2128,7 +2128,7 @@ MATCH TypeInstance::deduceType(Scope *sc, /* Create tuple from remaining args */ Tuple *vt = new Tuple(); - size_t vtdim = tempinst->tiargs->dim - i; + size_t vtdim = tempinst->tiargs->dim - i; vt->objects.setDim(vtdim); for (size_t k = 0; k < vtdim; k++) vt->objects.data[k] = (void *)tempinst->tiargs->data[i + k]; @@ -2585,7 +2585,7 @@ Lnomatch: */ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs, - size_t i, TemplateParameters *parameters, Objects *dedtypes, + size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags) { //printf("TemplateTypeParameter::matchArg()\n"); @@ -2829,8 +2829,8 @@ Lnomatch: } MATCH TemplateAliasParameter::matchArg(Scope *sc, - Objects *tiargs, size_t i, TemplateParameters *parameters, - Objects *dedtypes, + Objects *tiargs, size_t i, TemplateParameters *parameters, + Objects *dedtypes, Declaration **psparam, int flags) { Dsymbol *sa; @@ -2946,7 +2946,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc) // value-parameter -AA *TemplateValueParameter::edummies = NULL; +AA *TemplateValueParameter::edummies = NULL; TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue) @@ -3045,7 +3045,7 @@ Lnomatch: MATCH TemplateValueParameter::matchArg(Scope *sc, - Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, + Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags) { //printf("TemplateValueParameter::matchArg()\n"); @@ -3057,14 +3057,14 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Object *oarg; if (i < tiargs->dim) - oarg = tiargs->tdata()[i]; + oarg = tiargs->tdata()[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes->dim); // It might have already been deduced - oarg = dedtypes->tdata()[i]; + oarg = dedtypes->tdata()[i]; if (!oarg) goto Lnomatch; } @@ -3078,7 +3078,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, if (specValue) { - if (!ei || _aaGetRvalue(edummies, ei->type) == ei) + if (!ei || _aaGetRvalue(edummies, ei->type) == ei) goto Lnomatch; Expression *e = specValue; @@ -3163,10 +3163,10 @@ void *TemplateValueParameter::dummyArg() if (!e) { // Create a dummy value - Expression **pe = (Expression **)_aaGet(&edummies, valType); - if (!*pe) - *pe = valType->defaultInit(); - e = *pe; + Expression **pe = (Expression **)_aaGet(&edummies, valType); + if (!*pe) + *pe = valType->defaultInit(); + e = *pe; } return (void *)e; } @@ -3186,7 +3186,7 @@ Object *TemplateValueParameter::defaultArg(Loc loc, Scope *sc) e = e->syntaxCopy(); e = e->semantic(sc); #if DMDV2 - e = e->resolveLoc(loc, sc); + e = e->resolveLoc(loc, sc); #endif } return e; @@ -3238,7 +3238,7 @@ int TemplateTupleParameter::overloadMatch(TemplateParameter *tp) } MATCH TemplateTupleParameter::matchArg(Scope *sc, - Objects *tiargs, size_t i, TemplateParameters *parameters, + Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags) { @@ -3279,7 +3279,7 @@ void TemplateTupleParameter::print(Object *oarg, Object *oded) assert(v); //printf("|%d| ", v->objects.dim); - for (size_t i = 0; i < v->objects.dim; i++) + for (size_t i = 0; i < v->objects.dim; i++) { if (i) printf(", "); @@ -3351,7 +3351,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->havetempdecl = 0; this->isnested = NULL; this->errors = 0; - this->speculative = 0; + this->speculative = 0; #if IN_LLVM // LDC @@ -3386,7 +3386,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->havetempdecl = 1; this->isnested = NULL; this->errors = 0; - this->speculative = 0; + this->speculative = 0; #if IN_LLVM // LDC @@ -3505,11 +3505,11 @@ void TemplateInstance::semantic(Scope *sc) * (if we havetempdecl, then tiargs is already evaluated) */ semanticTiargs(sc); - if (arrayObjectIsError(tiargs)) - { inst = this; - //printf("error return %p, %d\n", tempdecl, global.errors); - return; // error recovery - } + if (arrayObjectIsError(tiargs)) + { inst = this; + //printf("error return %p, %d\n", tempdecl, global.errors); + return; // error recovery + } tempdecl = findTemplateDeclaration(sc); if (tempdecl) @@ -3557,27 +3557,27 @@ void TemplateInstance::semantic(Scope *sc) // It's a match inst = ti; parent = ti->parent; - - // If both this and the previous instantiation were speculative, - // use the number of errors that happened last time. - if (inst->speculative && global.gag) - { - global.errors += inst->errors; - global.gaggedErrors += inst->errors; - } - - // If the first instantiation was speculative, but this is not: - if (inst->speculative && !global.gag) - { - // If the first instantiation had failed, re-run semantic, - // so that error messages are shown. - if (inst->errors) - goto L1; - // It had succeeded, mark it is a non-speculative instantiation, - // and reuse it. - inst->speculative = 0; - } - + + // If both this and the previous instantiation were speculative, + // use the number of errors that happened last time. + if (inst->speculative && global.gag) + { + global.errors += inst->errors; + global.gaggedErrors += inst->errors; + } + + // If the first instantiation was speculative, but this is not: + if (inst->speculative && !global.gag) + { + // If the first instantiation had failed, re-run semantic, + // so that error messages are shown. + if (inst->errors) + goto L1; + // It had succeeded, mark it is a non-speculative instantiation, + // and reuse it. + inst->speculative = 0; + } + #if LOG printf("\tit's a match with instance %p\n", inst); #endif @@ -3590,15 +3590,15 @@ void TemplateInstance::semantic(Scope *sc) /* So, we need to implement 'this' instance. */ #if LOG - printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars()); - printf("\ttempdecl %s\n", tempdecl->toChars()); + printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars()); + printf("\ttempdecl %s\n", tempdecl->toChars()); #endif unsigned errorsave = global.errors; inst = this; - // Mark as speculative if we are instantiated from inside is(typeof()) - if (global.gag && sc->intypeof) - speculative = 1; - + // Mark as speculative if we are instantiated from inside is(typeof()) + if (global.gag && sc->intypeof) + speculative = 1; + int tempdecl_instance_idx = tempdecl->instances.dim; tempdecl->instances.push(this); parent = tempdecl->parent; @@ -3613,16 +3613,16 @@ void TemplateInstance::semantic(Scope *sc) //printf("parent = '%s'\n", parent->kind()); // Add 'this' to the enclosing scope's members[] so the semantic routines - // will get called on the instance members. Store the place we added it to - // in target_symbol_list(_idx) so we can remove it later if we encounter - // an error. + // will get called on the instance members. Store the place we added it to + // in target_symbol_list(_idx) so we can remove it later if we encounter + // an error. #if 1 int dosemantic3 = 0; - Dsymbols *target_symbol_list = NULL; - int target_symbol_list_idx; - - if (!sc->parameterSpecialization) - { Dsymbols *a; + Dsymbols *target_symbol_list = NULL; + int target_symbol_list_idx; + + if (!sc->parameterSpecialization) + { Dsymbols *a; Scope *scx = sc; #if 0 @@ -3653,20 +3653,20 @@ void TemplateInstance::semantic(Scope *sc) //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; if (m->semanticRun >= 3) - { + { dosemantic3 = 1; } - } - for (size_t i = 0; 1; i++) + } + for (size_t i = 0; 1; i++) { if (i == a->dim) { - target_symbol_list = a; - target_symbol_list_idx = i; + target_symbol_list = a; + target_symbol_list_idx = i; a->push(this); break; } - if (this == a->tdata()[i]) // if already in Array + if (this == a->tdata()[i]) // if already in Array break; } } @@ -3700,9 +3700,9 @@ void TemplateInstance::semantic(Scope *sc) // parent = scope->scopesym; symtab = new DsymbolTable(); int memnum = 0; - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; #if LOG printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum); #endif @@ -3765,9 +3765,9 @@ void TemplateInstance::semantic(Scope *sc) error("recursive expansion"); fatal(); } - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = members->tdata()[i]; //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); // if (isnested) @@ -3793,7 +3793,7 @@ void TemplateInstance::semantic(Scope *sc) * or semantic3() yet. */ for (size_t i = 0; i < Module::deferred.dim; i++) - { Dsymbol *sd = Module::deferred.tdata()[i]; + { Dsymbol *sd = Module::deferred.tdata()[i]; if (sd->parent == this) goto Laftersemantic; @@ -3853,19 +3853,19 @@ void TemplateInstance::semantic(Scope *sc) } errors = 1; if (global.gag) - { - // Errors are gagged, so remove the template instance from the - // instance/symbol lists we added it to and reset our state to - // finish clean and so we can try to instantiate it again later - // (see bugzilla 4302 and 6602). + { + // Errors are gagged, so remove the template instance from the + // instance/symbol lists we added it to and reset our state to + // finish clean and so we can try to instantiate it again later + // (see bugzilla 4302 and 6602). tempdecl->instances.remove(tempdecl_instance_idx); - if (target_symbol_list) - { - // Because we added 'this' in the last position above, we - // should be able to remove it without messing other indices up. - assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); - target_symbol_list->remove(target_symbol_list_idx); - } + if (target_symbol_list) + { + // Because we added 'this' in the last position above, we + // should be able to remove it without messing other indices up. + assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); + target_symbol_list->remove(target_symbol_list_idx); + } semanticRun = 0; inst = NULL; } @@ -3917,9 +3917,9 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f tiargs->data[j] = ea; } else if (sa) - { - Ldsym: - tiargs->tdata()[j] = sa; + { + Ldsym: + tiargs->tdata()[j] = sa; TupleDeclaration *d = sa->toAlias()->isTupleDeclaration(); if (d) { @@ -3940,14 +3940,14 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f if (dim) { tiargs->reserve(dim); for (size_t i = 0; i < dim; i++) - { Parameter *arg = tt->arguments->tdata()[i]; + { Parameter *arg = tt->arguments->tdata()[i]; tiargs->insert(j + i, arg->type); } } j--; } else - tiargs->tdata()[j] = ta; + tiargs->tdata()[j] = ta; } else { @@ -3959,7 +3959,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { if (!ea) { assert(global.errors); - ea = new ErrorExp(); + ea = new ErrorExp(); } assert(ea); ea = ea->semantic(sc); @@ -3969,10 +3969,10 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { ta = ea->type; goto Ltype; } - if (ea->op == TOKimport) - { sa = ((ScopeExp *)ea)->sds; - goto Ldsym; - } + if (ea->op == TOKimport) + { sa = ((ScopeExp *)ea)->sds; + goto Ldsym; + } if (ea->op == TOKtuple) { // Expand tuple TupleExp *te = (TupleExp *)ea; @@ -3981,7 +3981,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f if (dim) { tiargs->reserve(dim); for (size_t i = 0; i < dim; i++) - tiargs->insert(j + i, (*te->exps)[i]); + tiargs->insert(j + i, (*te->exps)[i]); } j--; } @@ -4262,12 +4262,12 @@ int TemplateInstance::hasNestedArgs(Objects *args) * symbol that is on the stack. */ for (size_t i = 0; i < args->dim; i++) - { Object *o = (*args)[i]; + { Object *o = (*args)[i]; Expression *ea = isExpression(o); - Type *ta = isType(o); + Type *ta = isType(o); Dsymbol *sa = isDsymbol(o); Tuple *va = isTuple(o); - //printf("o %p ea %p ta %p sa %p va %p\n", o, ea, ta, sa, va); + //printf("o %p ea %p ta %p sa %p va %p\n", o, ea, ta, sa, va); if (ea) { if (ea->op == TOKvar) @@ -4281,36 +4281,36 @@ int TemplateInstance::hasNestedArgs(Objects *args) goto Lsa; } } - else if (ta) - { - if (ta->ty == Tstruct || ta->ty == Tclass) - { sa = ta->toDsymbol(NULL); - TemplateInstance *ti = sa->parent->isTemplateInstance(); - if (ti && ti->isnested) - { sa = ti; - goto Lsa; - } - } - } + else if (ta) + { + if (ta->ty == Tstruct || ta->ty == Tclass) + { sa = ta->toDsymbol(NULL); + TemplateInstance *ti = sa->parent->isTemplateInstance(); + if (ti && ti->isnested) + { sa = ti; + goto Lsa; + } + } + } else if (sa) { Lsa: - //printf("sa = %s %s\n", sa->kind(), sa->toChars()); + //printf("sa = %s %s\n", sa->kind(), sa->toChars()); Declaration *d = sa->isDeclaration(); - TemplateInstance *ad = sa->isTemplateInstance(); - if ( - (ad && ad->isnested) || - (d && !d->isDataseg() && + TemplateInstance *ad = sa->isTemplateInstance(); + if ( + (ad && ad->isnested) || + (d && !d->isDataseg() && #if DMDV2 !(d->storage_class & STCmanifest) && #endif (!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) && - !isTemplateMixin() - )) + !isTemplateMixin() + )) { // if module level template if (tempdecl->toParent()->isModule()) - { Dsymbol *dparent = sa->toParent(); + { Dsymbol *dparent = sa->toParent(); if (!isnested) isnested = dparent; else if (isnested != dparent) @@ -4331,14 +4331,14 @@ int TemplateInstance::hasNestedArgs(Objects *args) } } error("%s is nested in both %s and %s", - toChars(), isnested->toPrettyChars(), dparent->toPrettyChars()); + toChars(), isnested->toPrettyChars(), dparent->toPrettyChars()); } L1: //printf("\tnested inside %s\n", isnested->toChars()); nested |= 1; } else - error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars()); + error("cannot use local '%s' as parameter to non-global template %s", sa->toChars(), tempdecl->toChars()); } } else if (va) @@ -4362,7 +4362,7 @@ Identifier *TemplateInstance::genIdent() char *id = tempdecl->ident->toChars(); buf.printf("__T%zu%s", strlen(id), id); Objects *args = tiargs; - for (size_t i = 0; i < args->dim; i++) + for (size_t i = 0; i < args->dim; i++) { Object *o = (Object *)args->data[i]; Type *ta = isType(o); Expression *ea = isExpression(o); @@ -4383,7 +4383,7 @@ Identifier *TemplateInstance::genIdent() } } else if (ea) - { + { ea = ea->optimize(WANTvalue | WANTinterpret); if (ea->op == TOKvar) { @@ -4391,12 +4391,12 @@ Identifier *TemplateInstance::genIdent() ea = NULL; goto Lsa; } - if (ea->op == TOKthis) - { - sa = ((ThisExp *)ea)->var; - ea = NULL; - goto Lsa; - } + if (ea->op == TOKthis) + { + sa = ((ThisExp *)ea)->var; + ea = NULL; + goto Lsa; + } if (ea->op == TOKfunction) { sa = ((FuncExp *)ea)->fd; @@ -4408,8 +4408,8 @@ Identifier *TemplateInstance::genIdent() { ea->error("tuple is not a valid template value argument"); continue; } - if (ea->op == TOKerror) - continue; + if (ea->op == TOKerror) + continue; #if 1 /* Use deco that matches what it would be for a function parameter */ @@ -4470,7 +4470,7 @@ Identifier *TemplateInstance::genIdent() void TemplateInstance::declareParameters(Scope *sc) { //printf("TemplateInstance::declareParameters()\n"); - for (size_t i = 0; i < tdtypes.dim; i++) + for (size_t i = 0; i < tdtypes.dim; i++) { TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; //Object *o = (Object *)tiargs->data[i]; @@ -4509,12 +4509,12 @@ int TemplateInstance::needsTypeInference(Scope *sc) return FALSE; } -#if DMDV2 - for (size_t i = 0; i < td->parameters->dim; i++) - if (td->parameters->tdata()[i]->isTemplateThisParameter()) - return TRUE; -#endif - +#if DMDV2 + for (size_t i = 0; i < td->parameters->dim; i++) + if (td->parameters->tdata()[i]->isTemplateThisParameter()) + return TRUE; +#endif + /* Determine if the instance arguments, tiargs, are all that is necessary * to instantiate the template. */ @@ -4522,7 +4522,7 @@ int TemplateInstance::needsTypeInference(Scope *sc) //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); TypeFunction *fdtype = (TypeFunction *)fd->type; if (Parameter::dim(fdtype->parameters) && - ((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim)) + ((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim)) return TRUE; } //printf("false\n"); @@ -4576,26 +4576,26 @@ void TemplateInstance::semantic3(Scope *sc) sc = sc->push(argsym); sc = sc->push(this); sc->tinst = this; - int oldgag = global.gag; - int olderrors = global.errors; - /* If this is a speculative instantiation, gag errors. - * Future optimisation: If the results are actually needed, errors - * would already be gagged, so we don't really need to run semantic - * on the members. - */ - if (speculative && !oldgag) - olderrors = global.startGagging(); - for (size_t i = 0; i < members->dim; i++) + int oldgag = global.gag; + int olderrors = global.errors; + /* If this is a speculative instantiation, gag errors. + * Future optimisation: If the results are actually needed, errors + * would already be gagged, so we don't really need to run semantic + * on the members. + */ + if (speculative && !oldgag) + olderrors = global.startGagging(); + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->semantic3(sc); - if (speculative && global.errors != olderrors) - break; - } - if (speculative && !oldgag) - { // If errors occurred, this instantiation failed - errors += global.errors - olderrors; - global.endGagging(olderrors); + if (speculative && global.errors != olderrors) + break; + } + if (speculative && !oldgag) + { // If errors occurred, this instantiation failed + errors += global.errors - olderrors; + global.endGagging(olderrors); } sc = sc->pop(); sc->pop(); @@ -4614,8 +4614,8 @@ void TemplateInstance::printInstantiationTrace() if (global.gag) return; - const unsigned max_shown = 6; - const char format[] = "instantiated from here: %s"; + const unsigned max_shown = 6; + const char format[] = "instantiated from here: %s"; // determine instantiation depth and number of recursive instantiations int n_instantiations = 1; @@ -4638,7 +4638,7 @@ void TemplateInstance::printInstantiationTrace() { for (TemplateInstance *cur = this; cur; cur = cur->tinst) { - errorSupplemental(cur->loc, format, cur->toChars()); + errorSupplemental(cur->loc, format, cur->toChars()); } } else if (n_instantiations - n_totalrecursions <= max_shown) @@ -4656,9 +4656,9 @@ void TemplateInstance::printInstantiationTrace() else { if (recursionDepth) - errorSupplemental(cur->loc, "%d recursive instantiations from here: %s", recursionDepth+2, cur->toChars()); + errorSupplemental(cur->loc, "%d recursive instantiations from here: %s", recursionDepth+2, cur->toChars()); else - errorSupplemental(cur->loc, format, cur->toChars()); + errorSupplemental(cur->loc, format, cur->toChars()); recursionDepth = 0; } } @@ -4667,15 +4667,15 @@ void TemplateInstance::printInstantiationTrace() { // Even after collapsing the recursions, the depth is too deep. // Just display the first few and last few instantiations. - unsigned i = 0; + unsigned i = 0; for (TemplateInstance *cur = this; cur; cur = cur->tinst) { if (i == max_shown / 2) - errorSupplemental(cur->loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown); + errorSupplemental(cur->loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown); if (i < max_shown / 2 || i >= n_instantiations - max_shown + max_shown / 2) - errorSupplemental(cur->loc, format, cur->toChars()); + errorSupplemental(cur->loc, format, cur->toChars()); ++i; } } @@ -4694,9 +4694,9 @@ void TemplateInstance::toObjFile(int multiobj) assert(0 && "multiobj"); else { - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->toObjFile(multiobj); } } @@ -4712,9 +4712,9 @@ void TemplateInstance::inlineScan() #endif if (!errors && members) { - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; s->inlineScan(); } } @@ -4737,7 +4737,7 @@ void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i) buf->writeByte(','); - Object *oarg = (*args)[i]; + Object *oarg = (*args)[i]; ObjectToCBuffer(buf, hgs, oarg); } nest--; @@ -4840,8 +4840,8 @@ void TemplateInstance::printInstantiationTrace() /* ======================== TemplateMixin ================================ */ TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, - Identifiers *idents, Objects *tiargs) - : TemplateInstance(loc, idents->tdata()[idents->dim - 1]) + Identifiers *idents, Objects *tiargs) + : TemplateInstance(loc, idents->tdata()[idents->dim - 1]) { //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : ""); this->ident = ident; @@ -4853,11 +4853,11 @@ TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) { TemplateMixin *tm; - Identifiers *ids = new Identifiers(); + Identifiers *ids = new Identifiers(); ids->setDim(idents->dim); - for (size_t i = 0; i < idents->dim; i++) + for (size_t i = 0; i < idents->dim; i++) { // Matches TypeQualified::syntaxCopyHelper() - Identifier *id = idents->tdata()[i]; + Identifier *id = idents->tdata()[i]; if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; @@ -4916,7 +4916,7 @@ void TemplateMixin::semantic(Scope *sc) // Follow qualifications to find the TemplateDeclaration if (!tempdecl) { Dsymbol *s; - size_t i; + size_t i; Identifier *id; if (tqual) @@ -4926,7 +4926,7 @@ void TemplateMixin::semantic(Scope *sc) else { i = 1; - id = idents->tdata()[0]; + id = idents->tdata()[0]; switch (id->dyncast()) { case DYNCAST_IDENTIFIER: @@ -4949,7 +4949,7 @@ void TemplateMixin::semantic(Scope *sc) { if (!s) break; - id = idents->tdata()[i]; + id = idents->tdata()[i]; s = s->searchX(loc, sc, id); } if (!s) @@ -4997,7 +4997,7 @@ void TemplateMixin::semantic(Scope *sc) // Run semantic on each argument, place results in tiargs[] semanticTiargs(sc); - if (errors || arrayObjectIsError(tiargs)) + if (errors || arrayObjectIsError(tiargs)) return; tempdecl = findBestMatch(sc); @@ -5026,7 +5026,7 @@ void TemplateMixin::semantic(Scope *sc) if (tiargs->dim != tm->tiargs->dim) continue; - for (size_t i = 0; i < tiargs->dim; i++) + for (size_t i = 0; i < tiargs->dim; i++) { Object *o = (Object *)tiargs->data[i]; Type *ta = isType(o); Expression *ea = isExpression(o); @@ -5122,7 +5122,7 @@ void TemplateMixin::semantic(Scope *sc) fatal(); } - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->semantic(sc2); @@ -5165,7 +5165,7 @@ void TemplateMixin::semantic(Scope *sc) } void TemplateMixin::semantic2(Scope *sc) -{ +{ if (semanticRun >= 2) return; semanticRun = 2; @@ -5177,7 +5177,7 @@ void TemplateMixin::semantic2(Scope *sc) assert(sc); sc = sc->push(argsym); sc = sc->push(this); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; #if LOG @@ -5194,7 +5194,7 @@ void TemplateMixin::semantic2(Scope *sc) } void TemplateMixin::semantic3(Scope *sc) -{ +{ if (semanticRun >= 3) return; semanticRun = 3; @@ -5205,7 +5205,7 @@ void TemplateMixin::semantic3(Scope *sc) { sc = sc->push(argsym); sc = sc->push(this); - for (size_t i = 0; i < members->dim; i++) + for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (Dsymbol *)members->data[i]; s->semantic3(sc); @@ -5233,11 +5233,11 @@ int TemplateMixin::oneMember(Dsymbol **ps) int TemplateMixin::hasPointers() { //printf("TemplateMixin::hasPointers() %s\n", toChars()); - - if (members) + + if (members) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = (*members)[i]; + Dsymbol *s = (*members)[i]; //printf(" s = %s %s\n", s->kind(), s->toChars()); if (s->hasPointers()) { @@ -5263,7 +5263,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("mixin "); - for (size_t i = 0; i < idents->dim; i++) + for (size_t i = 0; i < idents->dim; i++) { Identifier *id = (Identifier *)idents->data[i]; if (i) @@ -5273,7 +5273,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("!("); if (tiargs) { - for (size_t i = 0; i < tiargs->dim; i++) + for (size_t i = 0; i < tiargs->dim; i++) { if (i) buf->writebyte(','); Object *oarg = (Object *)tiargs->data[i]; diff --git a/dmd/template.h b/dmd/template.h index 8904719a..77780a03 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -55,7 +55,7 @@ struct TemplateDeclaration : ScopeDsymbol TemplateParameters *origParameters; // originals for Ddoc Expression *constraint; - TemplateInstances instances; // array of TemplateInstance's + TemplateInstances instances; // array of TemplateInstance's TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overroot; // first in overnext list @@ -65,12 +65,12 @@ struct TemplateDeclaration : ScopeDsymbol Dsymbol *onemember; // if !=NULL then one member of this template TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, - Expression *constraint, Dsymbols *decldefs); + Expression *constraint, Dsymbols *decldefs); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); int overloadInsert(Dsymbol *s); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - bool hasStaticCtorOrDtor(); + bool hasStaticCtorOrDtor(); const char *kind(); char *toChars(); @@ -141,7 +141,7 @@ struct TemplateParameter /* Match actual argument against parameter. */ - virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0; + virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0; /* Create dummy argument based on parameter. */ @@ -167,7 +167,7 @@ struct TemplateTypeParameter : TemplateParameter Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); + MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); void *dummyArg(); }; @@ -198,7 +198,7 @@ struct TemplateValueParameter : TemplateParameter Expression *specValue; Expression *defaultValue; - static AA *edummies; + static AA *edummies; TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue); @@ -211,7 +211,7 @@ struct TemplateValueParameter : TemplateParameter Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); + MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); void *dummyArg(); }; @@ -239,7 +239,7 @@ struct TemplateAliasParameter : TemplateParameter Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); + MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); void *dummyArg(); }; @@ -260,7 +260,7 @@ struct TemplateTupleParameter : TemplateParameter Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); - MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); + MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags); void *dummyArg(); }; @@ -272,7 +272,7 @@ struct TemplateInstance : ScopeDsymbol * tiargs = args */ Identifier *name; - //Identifiers idents; + //Identifiers idents; Objects *tiargs; // Array of Types/Expressions of template // instance arguments [int*, char, 10*10] @@ -293,7 +293,7 @@ struct TemplateInstance : ScopeDsymbol int havetempdecl; // 1 if used second constructor Dsymbol *isnested; // if referencing local symbols, this is the context int errors; // 1 if compiled with errors - int speculative; // 1 if only instantiated with errors gagged + int speculative; // 1 if only instantiated with errors gagged #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol will be emitted in the output or not before the symbol @@ -345,10 +345,10 @@ struct TemplateInstance : ScopeDsymbol struct TemplateMixin : TemplateInstance { - Identifiers *idents; + Identifiers *idents; Type *tqual; - TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Identifiers *idents, Objects *tiargs); + TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Identifiers *idents, Objects *tiargs); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); diff --git a/dmd/unialpha.c b/dmd/unialpha.c index b9fef9fd..5c407180 100644 --- a/dmd/unialpha.c +++ b/dmd/unialpha.c @@ -1,323 +1,323 @@ - -// Copyright (c) 2003 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 - -/******************************* - * Return !=0 if unicode alpha. - * Use table from C99 Appendix D. - */ - -int isUniAlpha(unsigned u) -{ - static unsigned short table[][2] = - { - { 0x00AA, 0x00AA }, - { 0x00B5, 0x00B5 }, - { 0x00B7, 0x00B7 }, - { 0x00BA, 0x00BA }, - { 0x00C0, 0x00D6 }, - { 0x00D8, 0x00F6 }, - { 0x00F8, 0x01F5 }, - { 0x01FA, 0x0217 }, - { 0x0250, 0x02A8 }, - { 0x02B0, 0x02B8 }, - { 0x02BB, 0x02BB }, - { 0x02BD, 0x02C1 }, - { 0x02D0, 0x02D1 }, - { 0x02E0, 0x02E4 }, - { 0x037A, 0x037A }, - { 0x0386, 0x0386 }, - { 0x0388, 0x038A }, - { 0x038C, 0x038C }, - { 0x038E, 0x03A1 }, - { 0x03A3, 0x03CE }, - { 0x03D0, 0x03D6 }, - { 0x03DA, 0x03DA }, - { 0x03DC, 0x03DC }, - { 0x03DE, 0x03DE }, - { 0x03E0, 0x03E0 }, - { 0x03E2, 0x03F3 }, - { 0x0401, 0x040C }, - { 0x040E, 0x044F }, - { 0x0451, 0x045C }, - { 0x045E, 0x0481 }, - { 0x0490, 0x04C4 }, - { 0x04C7, 0x04C8 }, - { 0x04CB, 0x04CC }, - { 0x04D0, 0x04EB }, - { 0x04EE, 0x04F5 }, - { 0x04F8, 0x04F9 }, - { 0x0531, 0x0556 }, - { 0x0559, 0x0559 }, - { 0x0561, 0x0587 }, - { 0x05B0, 0x05B9 }, - { 0x05BB, 0x05BD }, - { 0x05BF, 0x05BF }, - { 0x05C1, 0x05C2 }, - { 0x05D0, 0x05EA }, - { 0x05F0, 0x05F2 }, - { 0x0621, 0x063A }, - { 0x0640, 0x0652 }, - { 0x0660, 0x0669 }, - { 0x0670, 0x06B7 }, - { 0x06BA, 0x06BE }, - { 0x06C0, 0x06CE }, - { 0x06D0, 0x06DC }, - { 0x06E5, 0x06E8 }, - { 0x06EA, 0x06ED }, - { 0x06F0, 0x06F9 }, - { 0x0901, 0x0903 }, - { 0x0905, 0x0939 }, - { 0x093D, 0x093D }, - { 0x093E, 0x094D }, - { 0x0950, 0x0952 }, - { 0x0958, 0x0963 }, - { 0x0966, 0x096F }, - { 0x0981, 0x0983 }, - { 0x0985, 0x098C }, - { 0x098F, 0x0990 }, - { 0x0993, 0x09A8 }, - { 0x09AA, 0x09B0 }, - { 0x09B2, 0x09B2 }, - { 0x09B6, 0x09B9 }, - { 0x09BE, 0x09C4 }, - { 0x09C7, 0x09C8 }, - { 0x09CB, 0x09CD }, - { 0x09DC, 0x09DD }, - { 0x09DF, 0x09E3 }, - { 0x09E6, 0x09EF }, - { 0x09F0, 0x09F1 }, - { 0x0A02, 0x0A02 }, - { 0x0A05, 0x0A0A }, - { 0x0A0F, 0x0A10 }, - { 0x0A13, 0x0A28 }, - { 0x0A2A, 0x0A30 }, - { 0x0A32, 0x0A33 }, - { 0x0A35, 0x0A36 }, - { 0x0A38, 0x0A39 }, - { 0x0A3E, 0x0A42 }, - { 0x0A47, 0x0A48 }, - { 0x0A4B, 0x0A4D }, - { 0x0A59, 0x0A5C }, - { 0x0A5E, 0x0A5E }, - { 0x0A66, 0x0A6F }, - { 0x0A74, 0x0A74 }, - { 0x0A81, 0x0A83 }, - { 0x0A85, 0x0A8B }, - { 0x0A8D, 0x0A8D }, - { 0x0A8F, 0x0A91 }, - { 0x0A93, 0x0AA8 }, - { 0x0AAA, 0x0AB0 }, - { 0x0AB2, 0x0AB3 }, - { 0x0AB5, 0x0AB9 }, - { 0x0ABD, 0x0AC5 }, - { 0x0AC7, 0x0AC9 }, - { 0x0ACB, 0x0ACD }, - { 0x0AD0, 0x0AD0 }, - { 0x0AE0, 0x0AE0 }, - { 0x0AE6, 0x0AEF }, - { 0x0B01, 0x0B03 }, - { 0x0B05, 0x0B0C }, - { 0x0B0F, 0x0B10 }, - { 0x0B13, 0x0B28 }, - { 0x0B2A, 0x0B30 }, - { 0x0B32, 0x0B33 }, - { 0x0B36, 0x0B39 }, - { 0x0B3D, 0x0B3D }, - { 0x0B3E, 0x0B43 }, - { 0x0B47, 0x0B48 }, - { 0x0B4B, 0x0B4D }, - { 0x0B5C, 0x0B5D }, - { 0x0B5F, 0x0B61 }, - { 0x0B66, 0x0B6F }, - { 0x0B82, 0x0B83 }, - { 0x0B85, 0x0B8A }, - { 0x0B8E, 0x0B90 }, - { 0x0B92, 0x0B95 }, - { 0x0B99, 0x0B9A }, - { 0x0B9C, 0x0B9C }, - { 0x0B9E, 0x0B9F }, - { 0x0BA3, 0x0BA4 }, - { 0x0BA8, 0x0BAA }, - { 0x0BAE, 0x0BB5 }, - { 0x0BB7, 0x0BB9 }, - { 0x0BBE, 0x0BC2 }, - { 0x0BC6, 0x0BC8 }, - { 0x0BCA, 0x0BCD }, - { 0x0BE7, 0x0BEF }, - { 0x0C01, 0x0C03 }, - { 0x0C05, 0x0C0C }, - { 0x0C0E, 0x0C10 }, - { 0x0C12, 0x0C28 }, - { 0x0C2A, 0x0C33 }, - { 0x0C35, 0x0C39 }, - { 0x0C3E, 0x0C44 }, - { 0x0C46, 0x0C48 }, - { 0x0C4A, 0x0C4D }, - { 0x0C60, 0x0C61 }, - { 0x0C66, 0x0C6F }, - { 0x0C82, 0x0C83 }, - { 0x0C85, 0x0C8C }, - { 0x0C8E, 0x0C90 }, - { 0x0C92, 0x0CA8 }, - { 0x0CAA, 0x0CB3 }, - { 0x0CB5, 0x0CB9 }, - { 0x0CBE, 0x0CC4 }, - { 0x0CC6, 0x0CC8 }, - { 0x0CCA, 0x0CCD }, - { 0x0CDE, 0x0CDE }, - { 0x0CE0, 0x0CE1 }, - { 0x0CE6, 0x0CEF }, - { 0x0D02, 0x0D03 }, - { 0x0D05, 0x0D0C }, - { 0x0D0E, 0x0D10 }, - { 0x0D12, 0x0D28 }, - { 0x0D2A, 0x0D39 }, - { 0x0D3E, 0x0D43 }, - { 0x0D46, 0x0D48 }, - { 0x0D4A, 0x0D4D }, - { 0x0D60, 0x0D61 }, - { 0x0D66, 0x0D6F }, - { 0x0E01, 0x0E3A }, - { 0x0E40, 0x0E5B }, -// { 0x0E50, 0x0E59 }, - { 0x0E81, 0x0E82 }, - { 0x0E84, 0x0E84 }, - { 0x0E87, 0x0E88 }, - { 0x0E8A, 0x0E8A }, - { 0x0E8D, 0x0E8D }, - { 0x0E94, 0x0E97 }, - { 0x0E99, 0x0E9F }, - { 0x0EA1, 0x0EA3 }, - { 0x0EA5, 0x0EA5 }, - { 0x0EA7, 0x0EA7 }, - { 0x0EAA, 0x0EAB }, - { 0x0EAD, 0x0EAE }, - { 0x0EB0, 0x0EB9 }, - { 0x0EBB, 0x0EBD }, - { 0x0EC0, 0x0EC4 }, - { 0x0EC6, 0x0EC6 }, - { 0x0EC8, 0x0ECD }, - { 0x0ED0, 0x0ED9 }, - { 0x0EDC, 0x0EDD }, - { 0x0F00, 0x0F00 }, - { 0x0F18, 0x0F19 }, - { 0x0F20, 0x0F33 }, - { 0x0F35, 0x0F35 }, - { 0x0F37, 0x0F37 }, - { 0x0F39, 0x0F39 }, - { 0x0F3E, 0x0F47 }, - { 0x0F49, 0x0F69 }, - { 0x0F71, 0x0F84 }, - { 0x0F86, 0x0F8B }, - { 0x0F90, 0x0F95 }, - { 0x0F97, 0x0F97 }, - { 0x0F99, 0x0FAD }, - { 0x0FB1, 0x0FB7 }, - { 0x0FB9, 0x0FB9 }, - { 0x10A0, 0x10C5 }, - { 0x10D0, 0x10F6 }, - { 0x1E00, 0x1E9B }, - { 0x1EA0, 0x1EF9 }, - { 0x1F00, 0x1F15 }, - { 0x1F18, 0x1F1D }, - { 0x1F20, 0x1F45 }, - { 0x1F48, 0x1F4D }, - { 0x1F50, 0x1F57 }, - { 0x1F59, 0x1F59 }, - { 0x1F5B, 0x1F5B }, - { 0x1F5D, 0x1F5D }, - { 0x1F5F, 0x1F7D }, - { 0x1F80, 0x1FB4 }, - { 0x1FB6, 0x1FBC }, - { 0x1FBE, 0x1FBE }, - { 0x1FC2, 0x1FC4 }, - { 0x1FC6, 0x1FCC }, - { 0x1FD0, 0x1FD3 }, - { 0x1FD6, 0x1FDB }, - { 0x1FE0, 0x1FEC }, - { 0x1FF2, 0x1FF4 }, - { 0x1FF6, 0x1FFC }, - { 0x203F, 0x2040 }, - { 0x207F, 0x207F }, - { 0x2102, 0x2102 }, - { 0x2107, 0x2107 }, - { 0x210A, 0x2113 }, - { 0x2115, 0x2115 }, - { 0x2118, 0x211D }, - { 0x2124, 0x2124 }, - { 0x2126, 0x2126 }, - { 0x2128, 0x2128 }, - { 0x212A, 0x2131 }, - { 0x2133, 0x2138 }, - { 0x2160, 0x2182 }, - { 0x3005, 0x3007 }, - { 0x3021, 0x3029 }, - { 0x3041, 0x3093 }, - { 0x309B, 0x309C }, - { 0x30A1, 0x30F6 }, - { 0x30FB, 0x30FC }, - { 0x3105, 0x312C }, - { 0x4E00, 0x9FA5 }, - { 0xAC00, 0xD7A3 }, - }; - -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - //printf("%x\n", table[i][0]); - assert(table[i][0] <= table[i][1]); - if (i < sizeof(table) / sizeof(table[0]) - 1) - assert(table[i][1] < table[i + 1][0]); - } -#endif - - if (u > 0xD7A3) - goto Lisnot; - - // Binary search - int mid; - int low; - int high; - - low = 0; - high = sizeof(table) / sizeof(table[0]) - 1; - while (low <= high) - { - mid = (low + high) >> 1; - if (u < table[mid][0]) - high = mid - 1; - else if (u > table[mid][1]) - low = mid + 1; - else - goto Lis; - } - -Lisnot: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - assert(u < table[i][0] || u > table[i][1]); - } -#endif - return 0; - -Lis: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - if (u >= table[i][0] && u <= table[i][1]) - return 1; - } - assert(0); // should have been in table -#endif - return 1; -} - + +// Copyright (c) 2003 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 + +/******************************* + * Return !=0 if unicode alpha. + * Use table from C99 Appendix D. + */ + +int isUniAlpha(unsigned u) +{ + static unsigned short table[][2] = + { + { 0x00AA, 0x00AA }, + { 0x00B5, 0x00B5 }, + { 0x00B7, 0x00B7 }, + { 0x00BA, 0x00BA }, + { 0x00C0, 0x00D6 }, + { 0x00D8, 0x00F6 }, + { 0x00F8, 0x01F5 }, + { 0x01FA, 0x0217 }, + { 0x0250, 0x02A8 }, + { 0x02B0, 0x02B8 }, + { 0x02BB, 0x02BB }, + { 0x02BD, 0x02C1 }, + { 0x02D0, 0x02D1 }, + { 0x02E0, 0x02E4 }, + { 0x037A, 0x037A }, + { 0x0386, 0x0386 }, + { 0x0388, 0x038A }, + { 0x038C, 0x038C }, + { 0x038E, 0x03A1 }, + { 0x03A3, 0x03CE }, + { 0x03D0, 0x03D6 }, + { 0x03DA, 0x03DA }, + { 0x03DC, 0x03DC }, + { 0x03DE, 0x03DE }, + { 0x03E0, 0x03E0 }, + { 0x03E2, 0x03F3 }, + { 0x0401, 0x040C }, + { 0x040E, 0x044F }, + { 0x0451, 0x045C }, + { 0x045E, 0x0481 }, + { 0x0490, 0x04C4 }, + { 0x04C7, 0x04C8 }, + { 0x04CB, 0x04CC }, + { 0x04D0, 0x04EB }, + { 0x04EE, 0x04F5 }, + { 0x04F8, 0x04F9 }, + { 0x0531, 0x0556 }, + { 0x0559, 0x0559 }, + { 0x0561, 0x0587 }, + { 0x05B0, 0x05B9 }, + { 0x05BB, 0x05BD }, + { 0x05BF, 0x05BF }, + { 0x05C1, 0x05C2 }, + { 0x05D0, 0x05EA }, + { 0x05F0, 0x05F2 }, + { 0x0621, 0x063A }, + { 0x0640, 0x0652 }, + { 0x0660, 0x0669 }, + { 0x0670, 0x06B7 }, + { 0x06BA, 0x06BE }, + { 0x06C0, 0x06CE }, + { 0x06D0, 0x06DC }, + { 0x06E5, 0x06E8 }, + { 0x06EA, 0x06ED }, + { 0x06F0, 0x06F9 }, + { 0x0901, 0x0903 }, + { 0x0905, 0x0939 }, + { 0x093D, 0x093D }, + { 0x093E, 0x094D }, + { 0x0950, 0x0952 }, + { 0x0958, 0x0963 }, + { 0x0966, 0x096F }, + { 0x0981, 0x0983 }, + { 0x0985, 0x098C }, + { 0x098F, 0x0990 }, + { 0x0993, 0x09A8 }, + { 0x09AA, 0x09B0 }, + { 0x09B2, 0x09B2 }, + { 0x09B6, 0x09B9 }, + { 0x09BE, 0x09C4 }, + { 0x09C7, 0x09C8 }, + { 0x09CB, 0x09CD }, + { 0x09DC, 0x09DD }, + { 0x09DF, 0x09E3 }, + { 0x09E6, 0x09EF }, + { 0x09F0, 0x09F1 }, + { 0x0A02, 0x0A02 }, + { 0x0A05, 0x0A0A }, + { 0x0A0F, 0x0A10 }, + { 0x0A13, 0x0A28 }, + { 0x0A2A, 0x0A30 }, + { 0x0A32, 0x0A33 }, + { 0x0A35, 0x0A36 }, + { 0x0A38, 0x0A39 }, + { 0x0A3E, 0x0A42 }, + { 0x0A47, 0x0A48 }, + { 0x0A4B, 0x0A4D }, + { 0x0A59, 0x0A5C }, + { 0x0A5E, 0x0A5E }, + { 0x0A66, 0x0A6F }, + { 0x0A74, 0x0A74 }, + { 0x0A81, 0x0A83 }, + { 0x0A85, 0x0A8B }, + { 0x0A8D, 0x0A8D }, + { 0x0A8F, 0x0A91 }, + { 0x0A93, 0x0AA8 }, + { 0x0AAA, 0x0AB0 }, + { 0x0AB2, 0x0AB3 }, + { 0x0AB5, 0x0AB9 }, + { 0x0ABD, 0x0AC5 }, + { 0x0AC7, 0x0AC9 }, + { 0x0ACB, 0x0ACD }, + { 0x0AD0, 0x0AD0 }, + { 0x0AE0, 0x0AE0 }, + { 0x0AE6, 0x0AEF }, + { 0x0B01, 0x0B03 }, + { 0x0B05, 0x0B0C }, + { 0x0B0F, 0x0B10 }, + { 0x0B13, 0x0B28 }, + { 0x0B2A, 0x0B30 }, + { 0x0B32, 0x0B33 }, + { 0x0B36, 0x0B39 }, + { 0x0B3D, 0x0B3D }, + { 0x0B3E, 0x0B43 }, + { 0x0B47, 0x0B48 }, + { 0x0B4B, 0x0B4D }, + { 0x0B5C, 0x0B5D }, + { 0x0B5F, 0x0B61 }, + { 0x0B66, 0x0B6F }, + { 0x0B82, 0x0B83 }, + { 0x0B85, 0x0B8A }, + { 0x0B8E, 0x0B90 }, + { 0x0B92, 0x0B95 }, + { 0x0B99, 0x0B9A }, + { 0x0B9C, 0x0B9C }, + { 0x0B9E, 0x0B9F }, + { 0x0BA3, 0x0BA4 }, + { 0x0BA8, 0x0BAA }, + { 0x0BAE, 0x0BB5 }, + { 0x0BB7, 0x0BB9 }, + { 0x0BBE, 0x0BC2 }, + { 0x0BC6, 0x0BC8 }, + { 0x0BCA, 0x0BCD }, + { 0x0BE7, 0x0BEF }, + { 0x0C01, 0x0C03 }, + { 0x0C05, 0x0C0C }, + { 0x0C0E, 0x0C10 }, + { 0x0C12, 0x0C28 }, + { 0x0C2A, 0x0C33 }, + { 0x0C35, 0x0C39 }, + { 0x0C3E, 0x0C44 }, + { 0x0C46, 0x0C48 }, + { 0x0C4A, 0x0C4D }, + { 0x0C60, 0x0C61 }, + { 0x0C66, 0x0C6F }, + { 0x0C82, 0x0C83 }, + { 0x0C85, 0x0C8C }, + { 0x0C8E, 0x0C90 }, + { 0x0C92, 0x0CA8 }, + { 0x0CAA, 0x0CB3 }, + { 0x0CB5, 0x0CB9 }, + { 0x0CBE, 0x0CC4 }, + { 0x0CC6, 0x0CC8 }, + { 0x0CCA, 0x0CCD }, + { 0x0CDE, 0x0CDE }, + { 0x0CE0, 0x0CE1 }, + { 0x0CE6, 0x0CEF }, + { 0x0D02, 0x0D03 }, + { 0x0D05, 0x0D0C }, + { 0x0D0E, 0x0D10 }, + { 0x0D12, 0x0D28 }, + { 0x0D2A, 0x0D39 }, + { 0x0D3E, 0x0D43 }, + { 0x0D46, 0x0D48 }, + { 0x0D4A, 0x0D4D }, + { 0x0D60, 0x0D61 }, + { 0x0D66, 0x0D6F }, + { 0x0E01, 0x0E3A }, + { 0x0E40, 0x0E5B }, +// { 0x0E50, 0x0E59 }, + { 0x0E81, 0x0E82 }, + { 0x0E84, 0x0E84 }, + { 0x0E87, 0x0E88 }, + { 0x0E8A, 0x0E8A }, + { 0x0E8D, 0x0E8D }, + { 0x0E94, 0x0E97 }, + { 0x0E99, 0x0E9F }, + { 0x0EA1, 0x0EA3 }, + { 0x0EA5, 0x0EA5 }, + { 0x0EA7, 0x0EA7 }, + { 0x0EAA, 0x0EAB }, + { 0x0EAD, 0x0EAE }, + { 0x0EB0, 0x0EB9 }, + { 0x0EBB, 0x0EBD }, + { 0x0EC0, 0x0EC4 }, + { 0x0EC6, 0x0EC6 }, + { 0x0EC8, 0x0ECD }, + { 0x0ED0, 0x0ED9 }, + { 0x0EDC, 0x0EDD }, + { 0x0F00, 0x0F00 }, + { 0x0F18, 0x0F19 }, + { 0x0F20, 0x0F33 }, + { 0x0F35, 0x0F35 }, + { 0x0F37, 0x0F37 }, + { 0x0F39, 0x0F39 }, + { 0x0F3E, 0x0F47 }, + { 0x0F49, 0x0F69 }, + { 0x0F71, 0x0F84 }, + { 0x0F86, 0x0F8B }, + { 0x0F90, 0x0F95 }, + { 0x0F97, 0x0F97 }, + { 0x0F99, 0x0FAD }, + { 0x0FB1, 0x0FB7 }, + { 0x0FB9, 0x0FB9 }, + { 0x10A0, 0x10C5 }, + { 0x10D0, 0x10F6 }, + { 0x1E00, 0x1E9B }, + { 0x1EA0, 0x1EF9 }, + { 0x1F00, 0x1F15 }, + { 0x1F18, 0x1F1D }, + { 0x1F20, 0x1F45 }, + { 0x1F48, 0x1F4D }, + { 0x1F50, 0x1F57 }, + { 0x1F59, 0x1F59 }, + { 0x1F5B, 0x1F5B }, + { 0x1F5D, 0x1F5D }, + { 0x1F5F, 0x1F7D }, + { 0x1F80, 0x1FB4 }, + { 0x1FB6, 0x1FBC }, + { 0x1FBE, 0x1FBE }, + { 0x1FC2, 0x1FC4 }, + { 0x1FC6, 0x1FCC }, + { 0x1FD0, 0x1FD3 }, + { 0x1FD6, 0x1FDB }, + { 0x1FE0, 0x1FEC }, + { 0x1FF2, 0x1FF4 }, + { 0x1FF6, 0x1FFC }, + { 0x203F, 0x2040 }, + { 0x207F, 0x207F }, + { 0x2102, 0x2102 }, + { 0x2107, 0x2107 }, + { 0x210A, 0x2113 }, + { 0x2115, 0x2115 }, + { 0x2118, 0x211D }, + { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, + { 0x2128, 0x2128 }, + { 0x212A, 0x2131 }, + { 0x2133, 0x2138 }, + { 0x2160, 0x2182 }, + { 0x3005, 0x3007 }, + { 0x3021, 0x3029 }, + { 0x3041, 0x3093 }, + { 0x309B, 0x309C }, + { 0x30A1, 0x30F6 }, + { 0x30FB, 0x30FC }, + { 0x3105, 0x312C }, + { 0x4E00, 0x9FA5 }, + { 0xAC00, 0xD7A3 }, + }; + +#ifdef DEBUG + for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) + { + //printf("%x\n", table[i][0]); + assert(table[i][0] <= table[i][1]); + if (i < sizeof(table) / sizeof(table[0]) - 1) + assert(table[i][1] < table[i + 1][0]); + } +#endif + + if (u > 0xD7A3) + goto Lisnot; + + // Binary search + int mid; + int low; + int high; + + low = 0; + high = sizeof(table) / sizeof(table[0]) - 1; + while (low <= high) + { + mid = (low + high) >> 1; + if (u < table[mid][0]) + high = mid - 1; + else if (u > table[mid][1]) + low = mid + 1; + else + goto Lis; + } + +Lisnot: +#ifdef DEBUG + for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) + { + assert(u < table[i][0] || u > table[i][1]); + } +#endif + return 0; + +Lis: +#ifdef DEBUG + for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) + { + if (u >= table[i][0] && u <= table[i][1]) + return 1; + } + assert(0); // should have been in table +#endif + return 1; +} + diff --git a/dmd/utf.c b/dmd/utf.c index 6350056e..8aac2ee7 100644 --- a/dmd/utf.c +++ b/dmd/utf.c @@ -1,320 +1,320 @@ -// utf.c -// Copyright (c) 2003-2010 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. - -// Description of UTF-8 at: -// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - -#include -#include -#include - -#include "utf.h" - -int utf_isValidDchar(dchar_t c) -{ - return c < 0xD800 || - (c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF); -} - -static const unsigned char UTF8stride[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, -}; - -/** - * stride() returns the length of a UTF-8 sequence starting at index i - * in string s. - * Returns: - * The number of bytes in the UTF-8 sequence or - * 0xFF meaning s[i] is not the start of of UTF-8 sequence. - */ - -unsigned stride(unsigned char* s, size_t i) -{ - unsigned result = UTF8stride[s[i]]; - return result; -} - -/******************************************** - * Decode a single UTF-8 character sequence. - * Returns: - * NULL success - * !=NULL error message string - */ - -const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult) -{ - dchar_t V; - size_t i = *pidx; - unsigned char u = s[i]; - - //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); - - assert(i >= 0 && i < len); - - if (u & 0x80) - { unsigned n; - unsigned char u2; - - /* The following encodings are valid, except for the 5 and 6 byte - * combinations: - * 0xxxxxxx - * 110xxxxx 10xxxxxx - * 1110xxxx 10xxxxxx 10xxxxxx - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - for (n = 1; ; n++) - { - if (n > 4) - goto Lerr; // only do the first 4 of 6 encodings - if (((u << n) & 0x80) == 0) - { - if (n == 1) - goto Lerr; - break; - } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = (dchar_t)(u & ((1 << (7 - n)) - 1)); - - if (i + (n - 1) >= len) - goto Lerr; // off end of string - - /* The following combinations are overlong, and illegal: - * 1100000x (10xxxxxx) - * 11100000 100xxxxx (10xxxxxx) - * 11110000 1000xxxx (10xxxxxx 10xxxxxx) - * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) - * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) - */ - u2 = s[i + 1]; - if ((u & 0xFE) == 0xC0 || - (u == 0xE0 && (u2 & 0xE0) == 0x80) || - (u == 0xF0 && (u2 & 0xF0) == 0x80) || - (u == 0xF8 && (u2 & 0xF8) == 0x80) || - (u == 0xFC && (u2 & 0xFC) == 0x80)) - goto Lerr; // overlong combination - - for (unsigned j = 1; j != n; j++) - { - u = s[i + j]; - if ((u & 0xC0) != 0x80) - goto Lerr; // trailing bytes are 10xxxxxx - V = (V << 6) | (u & 0x3F); - } - if (!utf_isValidDchar(V)) - goto Lerr; - i += n; - } - else - { - V = (dchar_t) u; - i++; - } - - assert(utf_isValidDchar(V)); - *pidx = i; - *presult = V; - return NULL; - - Lerr: - *presult = (dchar_t) s[i]; - *pidx = i + 1; - return "invalid UTF-8 sequence"; -} - -/*************************************************** - * Validate a UTF-8 string. - * Returns: - * NULL success - * !=NULL error message string - */ - -const char *utf_validateString(unsigned char *s, size_t len) -{ - size_t idx; - const char *err = NULL; - dchar_t dc; - - for (idx = 0; idx < len; ) - { - err = utf_decodeChar(s, len, &idx, &dc); - if (err) - break; - } - return err; -} - - -/******************************************** - * Decode a single UTF-16 character sequence. - * Returns: - * NULL success - * !=NULL error message string - */ - - -const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult) -{ - const char *msg; - size_t i = *pidx; - unsigned u = s[i]; - - assert(i >= 0 && i < len); - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { unsigned u2; - - if (i + 1 == len) - { msg = "surrogate UTF-16 high value past end of string"; - goto Lerr; - } - u2 = s[i + 1]; - if (u2 < 0xDC00 || u2 > 0xDFFF) - { msg = "surrogate UTF-16 low value out of range"; - goto Lerr; - } - u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); - i += 2; - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { msg = "unpaired surrogate UTF-16 value"; - goto Lerr; - } - else if (u == 0xFFFE || u == 0xFFFF) - { msg = "illegal UTF-16 value"; - goto Lerr; - } - else - i++; - } - else - { - i++; - } - - assert(utf_isValidDchar(u)); - *pidx = i; - *presult = (dchar_t)u; - return NULL; - - Lerr: - *presult = (dchar_t)s[i]; - *pidx = i + 1; - return msg; -} - -void utf_encodeChar(unsigned char *s, dchar_t c) -{ - if (c <= 0x7F) - { - s[0] = (char) c; - } - else if (c <= 0x7FF) - { - s[0] = (char)(0xC0 | (c >> 6)); - s[1] = (char)(0x80 | (c & 0x3F)); - } - else if (c <= 0xFFFF) - { - s[0] = (char)(0xE0 | (c >> 12)); - s[1] = (char)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (char)(0x80 | (c & 0x3F)); - } - else if (c <= 0x10FFFF) - { - s[0] = (char)(0xF0 | (c >> 18)); - s[1] = (char)(0x80 | ((c >> 12) & 0x3F)); - s[2] = (char)(0x80 | ((c >> 6) & 0x3F)); - s[3] = (char)(0x80 | (c & 0x3F)); - } - else - assert(0); -} - -void utf_encodeWchar(unsigned short *s, dchar_t c) -{ - if (c <= 0xFFFF) - { - s[0] = (wchar_t) c; - } - else - { - s[0] = (wchar_t) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - s[1] = (wchar_t) (((c - 0x10000) & 0x3FF) + 0xDC00); - } -} - - -/** - * Returns the code length of c in the encoding. - * The code is returned in character count, not in bytes. - */ - -int utf_codeLengthChar(dchar_t c) -{ - return - c <= 0x7F ? 1 - : c <= 0x7FF ? 2 - : c <= 0xFFFF ? 3 - : c <= 0x10FFFF ? 4 - : (assert(false), 6); -} - -int utf_codeLengthWchar(dchar_t c) -{ - return c <= 0xFFFF ? 1 : 2; -} - -/** - * Returns the code length of c in the encoding. - * sz is the encoding: 1 = utf8, 2 = utf16, 4 = utf32. - * The code is returned in character count, not in bytes. - */ -int utf_codeLength(int sz, dchar_t c) -{ - if (sz == 1) - return utf_codeLengthChar(c); - if (sz == 2) - return utf_codeLengthWchar(c); - assert(sz == 4); - return 1; -} - -void utf_encode(int sz, void *s, dchar_t c) -{ - if (sz == 1) - utf_encodeChar((unsigned char *)s, c); - else if (sz == 2) - utf_encodeWchar((unsigned short *)s, c); - else - { - assert(sz == 4); - memcpy((unsigned char *)s, &c, sz); - } -} - +// utf.c +// Copyright (c) 2003-2010 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. + +// Description of UTF-8 at: +// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + +#include +#include +#include + +#include "utf.h" + +int utf_isValidDchar(dchar_t c) +{ + return c < 0xD800 || + (c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF); +} + +static const unsigned char UTF8stride[256] = +{ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, +}; + +/** + * stride() returns the length of a UTF-8 sequence starting at index i + * in string s. + * Returns: + * The number of bytes in the UTF-8 sequence or + * 0xFF meaning s[i] is not the start of of UTF-8 sequence. + */ + +unsigned stride(unsigned char* s, size_t i) +{ + unsigned result = UTF8stride[s[i]]; + return result; +} + +/******************************************** + * Decode a single UTF-8 character sequence. + * Returns: + * NULL success + * !=NULL error message string + */ + +const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult) +{ + dchar_t V; + size_t i = *pidx; + unsigned char u = s[i]; + + //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); + + assert(i >= 0 && i < len); + + if (u & 0x80) + { unsigned n; + unsigned char u2; + + /* The following encodings are valid, except for the 5 and 6 byte + * combinations: + * 0xxxxxxx + * 110xxxxx 10xxxxxx + * 1110xxxx 10xxxxxx 10xxxxxx + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ + for (n = 1; ; n++) + { + if (n > 4) + goto Lerr; // only do the first 4 of 6 encodings + if (((u << n) & 0x80) == 0) + { + if (n == 1) + goto Lerr; + break; + } + } + + // Pick off (7 - n) significant bits of B from first byte of octet + V = (dchar_t)(u & ((1 << (7 - n)) - 1)); + + if (i + (n - 1) >= len) + goto Lerr; // off end of string + + /* The following combinations are overlong, and illegal: + * 1100000x (10xxxxxx) + * 11100000 100xxxxx (10xxxxxx) + * 11110000 1000xxxx (10xxxxxx 10xxxxxx) + * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) + * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) + */ + u2 = s[i + 1]; + if ((u & 0xFE) == 0xC0 || + (u == 0xE0 && (u2 & 0xE0) == 0x80) || + (u == 0xF0 && (u2 & 0xF0) == 0x80) || + (u == 0xF8 && (u2 & 0xF8) == 0x80) || + (u == 0xFC && (u2 & 0xFC) == 0x80)) + goto Lerr; // overlong combination + + for (unsigned j = 1; j != n; j++) + { + u = s[i + j]; + if ((u & 0xC0) != 0x80) + goto Lerr; // trailing bytes are 10xxxxxx + V = (V << 6) | (u & 0x3F); + } + if (!utf_isValidDchar(V)) + goto Lerr; + i += n; + } + else + { + V = (dchar_t) u; + i++; + } + + assert(utf_isValidDchar(V)); + *pidx = i; + *presult = V; + return NULL; + + Lerr: + *presult = (dchar_t) s[i]; + *pidx = i + 1; + return "invalid UTF-8 sequence"; +} + +/*************************************************** + * Validate a UTF-8 string. + * Returns: + * NULL success + * !=NULL error message string + */ + +const char *utf_validateString(unsigned char *s, size_t len) +{ + size_t idx; + const char *err = NULL; + dchar_t dc; + + for (idx = 0; idx < len; ) + { + err = utf_decodeChar(s, len, &idx, &dc); + if (err) + break; + } + return err; +} + + +/******************************************** + * Decode a single UTF-16 character sequence. + * Returns: + * NULL success + * !=NULL error message string + */ + + +const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult) +{ + const char *msg; + size_t i = *pidx; + unsigned u = s[i]; + + assert(i >= 0 && i < len); + if (u & ~0x7F) + { if (u >= 0xD800 && u <= 0xDBFF) + { unsigned u2; + + if (i + 1 == len) + { msg = "surrogate UTF-16 high value past end of string"; + goto Lerr; + } + u2 = s[i + 1]; + if (u2 < 0xDC00 || u2 > 0xDFFF) + { msg = "surrogate UTF-16 low value out of range"; + goto Lerr; + } + u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); + i += 2; + } + else if (u >= 0xDC00 && u <= 0xDFFF) + { msg = "unpaired surrogate UTF-16 value"; + goto Lerr; + } + else if (u == 0xFFFE || u == 0xFFFF) + { msg = "illegal UTF-16 value"; + goto Lerr; + } + else + i++; + } + else + { + i++; + } + + assert(utf_isValidDchar(u)); + *pidx = i; + *presult = (dchar_t)u; + return NULL; + + Lerr: + *presult = (dchar_t)s[i]; + *pidx = i + 1; + return msg; +} + +void utf_encodeChar(unsigned char *s, dchar_t c) +{ + if (c <= 0x7F) + { + s[0] = (char) c; + } + else if (c <= 0x7FF) + { + s[0] = (char)(0xC0 | (c >> 6)); + s[1] = (char)(0x80 | (c & 0x3F)); + } + else if (c <= 0xFFFF) + { + s[0] = (char)(0xE0 | (c >> 12)); + s[1] = (char)(0x80 | ((c >> 6) & 0x3F)); + s[2] = (char)(0x80 | (c & 0x3F)); + } + else if (c <= 0x10FFFF) + { + s[0] = (char)(0xF0 | (c >> 18)); + s[1] = (char)(0x80 | ((c >> 12) & 0x3F)); + s[2] = (char)(0x80 | ((c >> 6) & 0x3F)); + s[3] = (char)(0x80 | (c & 0x3F)); + } + else + assert(0); +} + +void utf_encodeWchar(unsigned short *s, dchar_t c) +{ + if (c <= 0xFFFF) + { + s[0] = (wchar_t) c; + } + else + { + s[0] = (wchar_t) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); + s[1] = (wchar_t) (((c - 0x10000) & 0x3FF) + 0xDC00); + } +} + + +/** + * Returns the code length of c in the encoding. + * The code is returned in character count, not in bytes. + */ + +int utf_codeLengthChar(dchar_t c) +{ + return + c <= 0x7F ? 1 + : c <= 0x7FF ? 2 + : c <= 0xFFFF ? 3 + : c <= 0x10FFFF ? 4 + : (assert(false), 6); +} + +int utf_codeLengthWchar(dchar_t c) +{ + return c <= 0xFFFF ? 1 : 2; +} + +/** + * Returns the code length of c in the encoding. + * sz is the encoding: 1 = utf8, 2 = utf16, 4 = utf32. + * The code is returned in character count, not in bytes. + */ +int utf_codeLength(int sz, dchar_t c) +{ + if (sz == 1) + return utf_codeLengthChar(c); + if (sz == 2) + return utf_codeLengthWchar(c); + assert(sz == 4); + return 1; +} + +void utf_encode(int sz, void *s, dchar_t c) +{ + if (sz == 1) + utf_encodeChar((unsigned char *)s, c); + else if (sz == 2) + utf_encodeWchar((unsigned short *)s, c); + else + { + assert(sz == 4); + memcpy((unsigned char *)s, &c, sz); + } +} + diff --git a/dmd/utf.h b/dmd/utf.h index 21974c2b..22d8d3eb 100644 --- a/dmd/utf.h +++ b/dmd/utf.h @@ -1,35 +1,35 @@ -// Compiler implementation of the D programming language -// utf.h -// Copyright (c) 2003-2010 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. - -#ifndef DMD_UTF_H -#define DMD_UTF_H - - -typedef unsigned dchar_t; - -int utf_isValidDchar(dchar_t c); - -const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult); -const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult); - -const char *utf_validateString(unsigned char *s, size_t len); - -extern int isUniAlpha(dchar_t); - -void utf_encodeChar(unsigned char *s, dchar_t c); -void utf_encodeWchar(unsigned short *s, dchar_t c); - -int utf_codeLengthChar(dchar_t c); -int utf_codeLengthWchar(dchar_t c); - -int utf_codeLength(int sz, dchar_t c); -void utf_encode(int sz, void *s, dchar_t c); - -#endif +// Compiler implementation of the D programming language +// utf.h +// Copyright (c) 2003-2010 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. + +#ifndef DMD_UTF_H +#define DMD_UTF_H + + +typedef unsigned dchar_t; + +int utf_isValidDchar(dchar_t c); + +const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult); +const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult); + +const char *utf_validateString(unsigned char *s, size_t len); + +extern int isUniAlpha(dchar_t); + +void utf_encodeChar(unsigned char *s, dchar_t c); +void utf_encodeWchar(unsigned short *s, dchar_t c); + +int utf_codeLengthChar(dchar_t c); +int utf_codeLengthWchar(dchar_t c); + +int utf_codeLength(int sz, dchar_t c); +void utf_encode(int sz, void *s, dchar_t c); + +#endif diff --git a/dmd/version.c b/dmd/version.c index 22d415a2..37f33c06 100644 --- a/dmd/version.c +++ b/dmd/version.c @@ -1,181 +1,181 @@ - -// Copyright (c) 1999-2005 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 -#include - -#include "root.h" - -#include "identifier.h" -#include "dsymbol.h" -#include "cond.h" -#include "version.h" -#include "module.h" - -/* ================================================== */ - -/* DebugSymbol's happen for statements like: - * debug = identifier; - * debug = integer; - */ - -DebugSymbol::DebugSymbol(Loc loc, Identifier *ident) - : Dsymbol(ident) -{ - this->loc = loc; -} - -DebugSymbol::DebugSymbol(Loc loc, unsigned level) - : Dsymbol() -{ - this->level = level; - this->loc = loc; -} - -Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s) -{ - assert(!s); - DebugSymbol *ds = new DebugSymbol(loc, ident); - ds->level = level; - return ds; -} - -int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) -{ - //printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); - Module *m; - - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - m = sd->isModule(); - if (ident) - { - if (!m) - error("declaration must be at module level"); - else - { - if (findCondition(m->debugidsNot, ident)) - error("defined after use"); - if (!m->debugids) - m->debugids = new Strings(); - m->debugids->push(ident->toChars()); - } - } - else - { - if (!m) - error("level declaration must be at module level"); - else - m->debuglevel = level; - } - return 0; -} - -void DebugSymbol::semantic(Scope *sc) -{ - //printf("DebugSymbol::semantic() %s\n", toChars()); -} - -void DebugSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("debug = "); - if (ident) - buf->writestring(ident->toChars()); - else - buf->printf("%u", level); - buf->writestring(";"); - buf->writenl(); -} - -const char *DebugSymbol::kind() -{ - return "debug"; -} - -/* ================================================== */ - -/* VersionSymbol's happen for statements like: - * version = identifier; - * version = integer; - */ - -VersionSymbol::VersionSymbol(Loc loc, Identifier *ident) - : Dsymbol(ident) -{ - this->loc = loc; -} - -VersionSymbol::VersionSymbol(Loc loc, unsigned level) - : Dsymbol() -{ - this->level = level; - this->loc = loc; -} - -Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s) -{ - assert(!s); - VersionSymbol *ds = new VersionSymbol(loc, ident); - ds->level = level; - return ds; -} - -int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) -{ - //printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); - Module *m; - - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - m = sd->isModule(); - if (ident) - { - VersionCondition::checkPredefined(loc, ident->toChars()); - if (!m) - error("declaration must be at module level"); - else - { - if (findCondition(m->versionidsNot, ident)) - error("defined after use"); - if (!m->versionids) - m->versionids = new Strings(); - m->versionids->push(ident->toChars()); - } - } - else - { - if (!m) - error("level declaration must be at module level"); - else - m->versionlevel = level; - } - return 0; -} - -void VersionSymbol::semantic(Scope *sc) -{ -} - -void VersionSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("version = "); - if (ident) - buf->writestring(ident->toChars()); - else - buf->printf("%u", level); - buf->writestring(";"); - buf->writenl(); -} - -const char *VersionSymbol::kind() -{ - return "version"; -} - - + +// Copyright (c) 1999-2005 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 +#include + +#include "root.h" + +#include "identifier.h" +#include "dsymbol.h" +#include "cond.h" +#include "version.h" +#include "module.h" + +/* ================================================== */ + +/* DebugSymbol's happen for statements like: + * debug = identifier; + * debug = integer; + */ + +DebugSymbol::DebugSymbol(Loc loc, Identifier *ident) + : Dsymbol(ident) +{ + this->loc = loc; +} + +DebugSymbol::DebugSymbol(Loc loc, unsigned level) + : Dsymbol() +{ + this->level = level; + this->loc = loc; +} + +Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s) +{ + assert(!s); + DebugSymbol *ds = new DebugSymbol(loc, ident); + ds->level = level; + return ds; +} + +int DebugSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) +{ + //printf("DebugSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); + Module *m; + + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + m = sd->isModule(); + if (ident) + { + if (!m) + error("declaration must be at module level"); + else + { + if (findCondition(m->debugidsNot, ident)) + error("defined after use"); + if (!m->debugids) + m->debugids = new Strings(); + m->debugids->push(ident->toChars()); + } + } + else + { + if (!m) + error("level declaration must be at module level"); + else + m->debuglevel = level; + } + return 0; +} + +void DebugSymbol::semantic(Scope *sc) +{ + //printf("DebugSymbol::semantic() %s\n", toChars()); +} + +void DebugSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("debug = "); + if (ident) + buf->writestring(ident->toChars()); + else + buf->printf("%u", level); + buf->writestring(";"); + buf->writenl(); +} + +const char *DebugSymbol::kind() +{ + return "debug"; +} + +/* ================================================== */ + +/* VersionSymbol's happen for statements like: + * version = identifier; + * version = integer; + */ + +VersionSymbol::VersionSymbol(Loc loc, Identifier *ident) + : Dsymbol(ident) +{ + this->loc = loc; +} + +VersionSymbol::VersionSymbol(Loc loc, unsigned level) + : Dsymbol() +{ + this->level = level; + this->loc = loc; +} + +Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s) +{ + assert(!s); + VersionSymbol *ds = new VersionSymbol(loc, ident); + ds->level = level; + return ds; +} + +int VersionSymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) +{ + //printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars()); + Module *m; + + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + m = sd->isModule(); + if (ident) + { + VersionCondition::checkPredefined(loc, ident->toChars()); + if (!m) + error("declaration must be at module level"); + else + { + if (findCondition(m->versionidsNot, ident)) + error("defined after use"); + if (!m->versionids) + m->versionids = new Strings(); + m->versionids->push(ident->toChars()); + } + } + else + { + if (!m) + error("level declaration must be at module level"); + else + m->versionlevel = level; + } + return 0; +} + +void VersionSymbol::semantic(Scope *sc) +{ +} + +void VersionSymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("version = "); + if (ident) + buf->writestring(ident->toChars()); + else + buf->printf("%u", level); + buf->writestring(";"); + buf->writenl(); +} + +const char *VersionSymbol::kind() +{ + return "version"; +} + + diff --git a/dmd/version.h b/dmd/version.h index 286accff..b5ae51d2 100644 --- a/dmd/version.h +++ b/dmd/version.h @@ -1,51 +1,51 @@ - -// 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. - -#ifndef DMD_VERSION_H -#define DMD_VERSION_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "dsymbol.h" - -struct OutBuffer; -struct HdrGenState; - -struct DebugSymbol : Dsymbol -{ - unsigned level; - - DebugSymbol(Loc loc, Identifier *ident); - DebugSymbol(Loc loc, unsigned level); - Dsymbol *syntaxCopy(Dsymbol *); - - int addMember(Scope *sc, ScopeDsymbol *s, int memnum); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - const char *kind(); -}; - -struct VersionSymbol : Dsymbol -{ - unsigned level; - - VersionSymbol(Loc loc, Identifier *ident); - VersionSymbol(Loc loc, unsigned level); - Dsymbol *syntaxCopy(Dsymbol *); - - int addMember(Scope *sc, ScopeDsymbol *s, int memnum); - void semantic(Scope *sc); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - const char *kind(); -}; - -#endif /* DMD_VERSION_H */ + +// 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. + +#ifndef DMD_VERSION_H +#define DMD_VERSION_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "dsymbol.h" + +struct OutBuffer; +struct HdrGenState; + +struct DebugSymbol : Dsymbol +{ + unsigned level; + + DebugSymbol(Loc loc, Identifier *ident); + DebugSymbol(Loc loc, unsigned level); + Dsymbol *syntaxCopy(Dsymbol *); + + int addMember(Scope *sc, ScopeDsymbol *s, int memnum); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); +}; + +struct VersionSymbol : Dsymbol +{ + unsigned level; + + VersionSymbol(Loc loc, Identifier *ident); + VersionSymbol(Loc loc, unsigned level); + Dsymbol *syntaxCopy(Dsymbol *); + + int addMember(Scope *sc, ScopeDsymbol *s, int memnum); + void semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + const char *kind(); +}; + +#endif /* DMD_VERSION_H */