diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index df9cae7f69..518cae134b 100644 --- a/dmd2/aggregate.h +++ b/dmd2/aggregate.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -18,6 +18,7 @@ #include "root.h" #include "dsymbol.h" +#include "declaration.h" #if IN_LLVM #include @@ -74,18 +75,25 @@ struct AggregateDeclaration : ScopeDsymbol bool isdeprecated; // !=0 if deprecated #if DMDV2 - bool isnested; // !=0 if is nested + Dsymbol *enclosing; /* !=NULL if is nested + * pointing to the dsymbol that directly enclosing it. + * 1. The function that enclosing it (nested struct and class) + * 2. The class that enclosing it (nested class only) + * 3. If enclosing aggregate is template, its enclosing dsymbol. + * See AggregateDeclaraton::makeNested for the details. + */ VarDeclaration *vthis; // 'this' parameter if this aggregate is nested #endif // Special member functions - InvariantDeclaration *inv; // invariant + FuncDeclarations invs; // Array of invariants + FuncDeclaration *inv; // invariant NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator #if DMDV2 - //CtorDeclaration *ctor; Dsymbol *ctor; // CtorDeclaration or TemplateDeclaration - CtorDeclaration *defaultCtor; // default constructor + CtorDeclaration *defaultCtor; // default constructor - should have no arguments, because + // it would be stored in TypeInfo_Class.defaultConstructor Dsymbol *aliasthis; // forward unresolved lookups to aliasthis bool noDefaultCtor; // no default construction #endif @@ -93,10 +101,6 @@ struct AggregateDeclaration : ScopeDsymbol FuncDeclarations dtors; // Array of destructors FuncDeclaration *dtor; // aggregate destructor -#ifdef IN_GCC - Expressions *attributes; // GCC decl/type attributes -#endif - Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this) AggregateDeclaration(Loc loc, Identifier *id); @@ -112,18 +116,21 @@ struct AggregateDeclaration : ScopeDsymbol Type *getType(); 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? + bool isDeprecated(); // is aggregate deprecated? FuncDeclaration *buildDtor(Scope *sc); - int isNested(); + FuncDeclaration *buildInv(Scope *sc); + bool isNested(); + void makeNested(); int isExport(); void emitComment(Scope *sc); void toJson(JsonOut *json); void toDocBuffer(OutBuffer *buf, Scope *sc); - FuncDeclaration *hasIdentityOpAssign(Scope *sc, Dsymbol *assign); + FuncDeclaration *hasIdentityOpAssign(Scope *sc); + FuncDeclaration *hasIdentityOpEquals(Scope *sc); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); // For access checking virtual PROT getAccess(Dsymbol *smember); // determine access to smember @@ -173,7 +180,7 @@ struct StructDeclaration : AggregateDeclaration void semantic(Scope *sc); Dsymbol *search(Loc, Identifier *ident, int flags); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); const char *kind(); void finalizeSize(Scope *sc); bool isPOD(); @@ -184,12 +191,10 @@ struct StructDeclaration : AggregateDeclaration int needOpAssign(); int needOpEquals(); FuncDeclaration *buildOpAssign(Scope *sc); - FuncDeclaration *buildOpEquals(Scope *sc); FuncDeclaration *buildPostBlit(Scope *sc); FuncDeclaration *buildCpCtor(Scope *sc); - + FuncDeclaration *buildOpEquals(Scope *sc); FuncDeclaration *buildXopEquals(Scope *sc); - void makeNested(); #endif void toDocBuffer(OutBuffer *buf, Scope *sc); @@ -273,16 +278,16 @@ struct ClassDeclaration : AggregateDeclaration BaseClasses *vtblInterfaces; // array of base interfaces that have // their own vtbl[] + TypeInfoClassDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration int com; // !=0 if this is a COM class (meaning // it derives from IUnknown) - int isscope; // !=0 if this is an auto class + int isscope; // !=0 if this is an auto class int isabstract; // !=0 if abstract class -#if DMDV1 - bool isnested; // !=0 if is nested - VarDeclaration *vthis; // 'this' parameter if this class is nested -#endif int inuse; // to prevent recursive attempts + enum Semantic doAncestorsSemantic; // Before searching symbol, whole ancestors should finish + // calling semantic() at least once, due to fill symtab + // and do addMember(). [== Semantic(Start,In,Done)] ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses); Dsymbol *syntaxCopy(Dsymbol *s); @@ -295,15 +300,12 @@ struct ClassDeclaration : AggregateDeclaration virtual int isBaseInfoComplete(); Dsymbol *search(Loc, Identifier *ident, int flags); - Dsymbol *searchBase(Loc, Identifier *ident); + ClassDeclaration *searchBase(Loc, Identifier *ident); #if DMDV2 int isFuncHidden(FuncDeclaration *fd); #endif FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf); void interfaceSemantic(Scope *sc); -#if DMDV1 - int isNested(); -#endif int isCOMclass(); virtual int isCOMinterface(); #if DMDV2 @@ -312,7 +314,7 @@ struct ClassDeclaration : AggregateDeclaration int isAbstract(); virtual int vtblOffset(); const char *kind(); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); void toDocBuffer(OutBuffer *buf, Scope *sc); PROT getAccess(Dsymbol *smember); // determine access to smember diff --git a/dmd2/aliasthis.c b/dmd2/aliasthis.c index b26731b932..68e1609fa1 100644 --- a/dmd2/aliasthis.c +++ b/dmd2/aliasthis.c @@ -36,8 +36,22 @@ Expression *resolveAliasThis(Scope *sc, Expression *e) L1: if (ad && ad->aliasthis) { + bool isstatic = (e->op == TOKtype); e = new DotIdExp(e->loc, e, ad->aliasthis->ident); e = e->semantic(sc); + if (isstatic && ad->aliasthis->needThis()) + { + /* non-@property function is not called inside typeof(), + * so resolve it ahead. + */ + int save = sc->intypeof; + sc->intypeof = 1; // bypass "need this" error check + e = resolveProperties(sc, e); + sc->intypeof = save; + + e = new TypeExp(e->loc, new TypeTypeof(e->loc, e)); + e = e->semantic(sc); + } e = resolveProperties(sc, e); } } @@ -74,7 +88,7 @@ void AliasThis::semantic(Scope *sc) assert(ad->members); Dsymbol *s = ad->search(loc, ident, 0); if (!s) - { s = sc->search(loc, ident, 0); + { s = sc->search(loc, ident, NULL); if (s) ::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars()); else diff --git a/dmd2/apply.c b/dmd2/apply.c index e05a343e5e..320b24a84b 100644 --- a/dmd2/apply.c +++ b/dmd2/apply.c @@ -36,12 +36,7 @@ int Expression::apply(fp_t fp, void *param) /****************************** * Perform apply() on an t if not null */ -template -int condApply(T* t, fp_t fp, void* param) -{ - return t ? t->apply(fp, param) : 0; -} - +#define condApply(t, fp, param) (t ? t->apply(fp, param) : 0) int NewExp::apply(int (*fp)(Expression *, void *), void *param) { @@ -129,14 +124,20 @@ int AssocArrayLiteralExp::apply(fp_t fp, void *param) int StructLiteralExp::apply(fp_t fp, void *param) { - return condApply(elements, fp, param) || + if(stageflags & stageApply) return 0; + int old = stageflags; + stageflags |= stageApply; + int ret = condApply(elements, fp, param) || (*fp)(this, param); + stageflags = old; + return ret; } int TupleExp::apply(fp_t fp, void *param) { - return condApply(exps, fp, param) || + return (e0 ? (*fp)(e0, param) : 0) || + condApply(exps, fp, param) || (*fp)(this, param); } diff --git a/dmd2/argtypes.c b/dmd2/argtypes.c index a26a116645..0030cc2f42 100644 --- a/dmd2/argtypes.c +++ b/dmd2/argtypes.c @@ -26,9 +26,6 @@ #include "aggregate.h" #include "hdrgen.h" -#define tfloat2 tfloat64 -//#define tfloat2 tcomplex32 - /**************************************************** * This breaks a type down into 'simpler' types that can be passed to a function * in registers, and returned in registers. @@ -84,7 +81,7 @@ TypeTuple *TypeBasic::toArgTypes() case Tcomplex32: if (global.params.is64bit) - t1 = Type::tfloat2; + t1 = Type::tfloat64; else { t1 = Type::tfloat64; @@ -223,8 +220,8 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2) if (!t2) return t1; - unsigned sz1 = t1->size(0); - unsigned sz2 = t2->size(0); + unsigned sz1 = t1->size(Loc()); + unsigned sz2 = t2->size(Loc()); if (t1->ty != t2->ty && (t1->ty == Tfloat80 || t2->ty == Tfloat80)) @@ -232,7 +229,7 @@ Type *argtypemerge(Type *t1, Type *t2, unsigned offset2) // [float,float] => [cfloat] if (t1->ty == Tfloat32 && t2->ty == Tfloat32 && offset2 == 4) - return Type::tfloat2; + return Type::tfloat64; // Merging floating and non-floating types produces the non-floating type if (t1->isfloating()) @@ -287,7 +284,7 @@ TypeTuple *TypeStruct::toArgTypes() } Type *t1 = NULL; Type *t2 = NULL; - d_uns64 sz = size(0); + d_uns64 sz = size(Loc()); assert(sz < 0xFFFFFFFF); switch ((unsigned)sz) { @@ -349,7 +346,7 @@ TypeTuple *TypeStruct::toArgTypes() goto Lmemory; // Fields that overlap the 8byte boundary goto Lmemory - unsigned fieldsz = f->type->size(0); + unsigned fieldsz = f->type->size(Loc()); if (f->offset < 8 && (f->offset + fieldsz) > 8) goto Lmemory; } diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index 17b90dad43..d0bad81ac3 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -52,6 +52,283 @@ int binary(const char *p , const char **tab, int high) } #endif +/************************************** + * Structure to contain information needed to insert an array op call + */ + +struct ArrayOp +{ + FuncDeclaration *cFunc; // Stub for optimized druntime version + FuncDeclaration *dFunc; // Full D version for ctfe +}; + +/************************************** + * Search for a druntime array op + */ +int isDruntimeArrayOp(Identifier *ident) +{ + /* Some of the array op functions are written as library functions, + * presumably to optimize them with special CPU vector instructions. + * List those library functions here, in alpha order. + */ + 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", + }; + char *name = ident->toChars(); + int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); + if (i != -1) + return 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 + return 0; +} + +ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc) +{ + ArrayOp *op = new ArrayOp; +#if IN_LLVM + Parameters *fparams = new Parameters(); + Expression *loopbody = exp->buildArrayLoop(fparams); + if (isDruntimeArrayOp(ident)) + { + op->cFunc = FuncDeclaration::genCfunc(fparams, exp->type, ident); + op->cFunc->isArrayOp = 2; + } +#else + if (isDruntimeArrayOp(ident)) + op->cFunc = FuncDeclaration::genCfunc(exp->type, ident); +#endif + else + op->cFunc = NULL; + + /* Construct the function body: + * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) + * loopbody; + * return p; + */ +#if !IN_LLVM + Parameters *fparams = new Parameters(); + Expression *loopbody = exp->buildArrayLoop(fparams); +#endif + 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 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)); +#else + // foreach (i; 0 .. p.length) + Statement *s1 = new ForeachRangeStatement(Loc(), TOKforeach, + new Parameter(0, NULL, Id::p, NULL), + new IntegerExp(Loc(), 0, Type::tsize_t), + new ArrayLengthExp(Loc(), new IdentifierExp(Loc(), p->ident)), + new ExpStatement(Loc(), loopbody)); +#endif + //printf("%s\n", s1->toChars()); + Statement *s2 = new ReturnStatement(Loc(), new IdentifierExp(Loc(), p->ident)); + //printf("s2: %s\n", s2->toChars()); + Statement *fbody = new CompoundStatement(Loc(), s1, s2); + + /* Construct the function + */ + TypeFunction *ftype = new TypeFunction(fparams, exp->type, 0, LINKc); + //printf("ftype: %s\n", ftype->toChars()); + FuncDeclaration *fd = new FuncDeclaration(Loc(), Loc(), ident, STCundefined, ftype); + fd->fbody = fbody; + fd->protection = PROTpublic; + fd->linkage = LINKc; + fd->isArrayOp = 1; + + if (!op->cFunc) + sc->module->importedFrom->members->push(fd); + + sc = sc->push(); + sc->parent = sc->module->importedFrom; + sc->stc = 0; + sc->linkage = LINKc; + fd->semantic(sc); + fd->semantic2(sc); + fd->semantic3(sc); + sc->pop(); + + if (op->cFunc) + { + op->cFunc->dArrayOp = fd; + op->cFunc->type = fd->type; + } + op->dFunc = fd; + return op; +} + /********************************************** * Check that there are no uses of arrays without []. */ @@ -147,270 +424,23 @@ Expression *BinExp::arrayOp(Scope *sc) char *name = buf.toChars(); Identifier *ident = Lexer::idPool(name); - /* Look up name in hash table - */ #if IN_LLVM - FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&sc->module->arrayfuncs, ident); + ArrayOp **pOp = (ArrayOp **)_aaGet(&sc->module->arrayfuncs, ident); #else - FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident); + ArrayOp **pOp = (ArrayOp **)_aaGet(&arrayfuncs, ident); #endif - FuncDeclaration *fd = (FuncDeclaration *)*pfd; - if (!fd) - { - /* Some of the array op functions are written as library functions, - * presumably to optimize them with special CPU vector instructions. - * List those library functions here, in alpha order. - */ - 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", + ArrayOp *op = *pOp; - "_arrayExpSliceDivass_d", // T[]/=T - "_arrayExpSliceDivass_f", // T[]/=T + if (!op) + op = buildArrayOp(ident, this, sc, loc); - "_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", + *pOp = op; - "_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 - /* Not in library, so generate it. - * Construct the function body: - * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) - * loopbody; - * return p; - */ - - Parameters *fparams = new Parameters(); - Expression *loopbody = buildArrayLoop(fparams); - 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 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)); -#else - // foreach (i; 0 .. p.length) - Statement *s1 = new ForeachRangeStatement(0, TOKforeach, - new Parameter(0, NULL, Id::p, NULL), - new IntegerExp(0, 0, Type::tsize_t), - new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), - new ExpStatement(0, loopbody)); -#endif - Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident)); - //printf("s2: %s\n", s2->toChars()); - Statement *fbody = new CompoundStatement(0, s1, s2); - - /* Construct the function - */ - TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); - //printf("ftype: %s\n", ftype->toChars()); - fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype); - fd->fbody = fbody; - fd->protection = PROTpublic; - fd->linkage = LINKd; - fd->isArrayOp = 1; - - sc->module->importedFrom->members->push(fd); - - sc = sc->push(); - sc->parent = sc->module->importedFrom; - sc->stc = 0; - sc->linkage = LINKc; - fd->semantic(sc); - fd->semantic2(sc); - fd->semantic3(sc); - sc->pop(); - } -#if IN_LLVM - else - { /* In library, refer to it. - */ - Parameters *fparams = new Parameters(); - buildArrayLoop(fparams); - fd = FuncDeclaration::genCfunc(fparams, type, ident); - fd->isArrayOp = 2; - } -#else - else - { /* In library, refer to it. - */ - fd = FuncDeclaration::genCfunc(type, ident); - } -#endif - *pfd = fd; // cache symbol in hash table - } - - /* Call the function fd(arguments) - */ - Expression *ec = new VarExp(0, fd); + FuncDeclaration *fd = op->cFunc ? op->cFunc : op->dFunc; + Expression *ec = new VarExp(loc, fd); Expression *e = new CallExp(loc, ec, arguments); - e->type = type; - return e; + + return e->semantic(sc); } Expression *BinAssignExp::arrayOp(Scope *sc) @@ -538,7 +568,7 @@ Expression *Expression::buildArrayLoop(Parameters *fparams) Identifier *id = Identifier::generateId("c", fparams->dim); Parameter *param = new Parameter(0, type, id, NULL); fparams->shift(param); - Expression *e = new IdentifierExp(0, id); + Expression *e = new IdentifierExp(Loc(), id); return e; } @@ -558,11 +588,11 @@ Expression *SliceExp::buildArrayLoop(Parameters *fparams) Identifier *id = Identifier::generateId("p", fparams->dim); Parameter *param = new Parameter(STCconst, type, id, NULL); fparams->shift(param); - Expression *e = new IdentifierExp(0, id); + Expression *e = new IdentifierExp(Loc(), id); Expressions *arguments = new Expressions(); - Expression *index = new IdentifierExp(0, Id::p); + Expression *index = new IdentifierExp(Loc(), Id::p); arguments->push(index); - e = new ArrayExp(0, e, arguments); + e = new ArrayExp(Loc(), e, arguments); return e; } @@ -577,12 +607,12 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams) * where b is a byte fails because (c + p[i]) is an int * which cannot be implicitly cast to byte. */ - ex2 = new CastExp(0, ex2, e1->type->nextOf()); + ex2 = new CastExp(Loc(), ex2, e1->type->nextOf()); #endif Expression *ex1 = e1->buildArrayLoop(fparams); Parameter *param = (*fparams)[0]; param->storageClass = 0; - Expression *e = new AssignExp(0, ex1, ex2); + Expression *e = new AssignExp(Loc(), ex1, ex2); return e; } @@ -616,14 +646,14 @@ X(Pow) Expression *NegExp::buildArrayLoop(Parameters *fparams) { Expression *ex1 = e1->buildArrayLoop(fparams); - Expression *e = new NegExp(0, ex1); + Expression *e = new NegExp(Loc(), ex1); return e; } Expression *ComExp::buildArrayLoop(Parameters *fparams) { Expression *ex1 = e1->buildArrayLoop(fparams); - Expression *e = new ComExp(0, ex1); + Expression *e = new ComExp(Loc(), ex1); return e; } @@ -634,7 +664,7 @@ Expression *Str##Exp::buildArrayLoop(Parameters *fparams) \ */ \ Expression *ex1 = e1->buildArrayLoop(fparams); \ Expression *ex2 = e2->buildArrayLoop(fparams); \ - Expression *e = new Str##Exp(0, ex1, ex2); \ + Expression *e = new Str##Exp(Loc(), ex1, ex2); \ return e; \ } diff --git a/dmd2/arraytypes.h b/dmd2/arraytypes.h index e40009ac5e..9e54239afa 100644 --- a/dmd2/arraytypes.h +++ b/dmd2/arraytypes.h @@ -76,4 +76,5 @@ typedef ArrayBase Blocks; typedef ArrayBase Symbols; +typedef ArrayBase Dts; #endif diff --git a/dmd2/attrib.c b/dmd2/attrib.c index d8defdf168..3b1135f1cf 100644 --- a/dmd2/attrib.c +++ b/dmd2/attrib.c @@ -27,15 +27,11 @@ #include "module.h" #include "parse.h" #include "template.h" +#include "hdrgen.h" #if IN_LLVM #include "../gen/pragma.h" #endif -#if IN_DMD -extern bool obj_includelib(const char *name); -void obj_startaddress(Symbol *s); -#endif - /********************************* AttribDeclaration ****************************/ @@ -252,22 +248,6 @@ void AttribDeclaration::emitComment(Scope *sc) } } -#if IN_DMD - -void AttribDeclaration::toObjFile(int multiobj) -{ - Dsymbols *d = include(NULL, NULL); - - if (d) - { - for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = (*d)[i]; - s->toObjFile(multiobj); - } - } -} -#endif - void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { Dsymbols *d = include(NULL, NULL); @@ -361,6 +341,10 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (decl->dim == 0) buf->writestring("{}"); + else if (hgs->hdrgen && decl->dim == 1 && (*decl)[0]->isUnitTestDeclaration()) + { // hack for bugzilla 8081 + buf->writestring("{}"); + } else if (decl->dim == 1) ((*decl)[0])->toCBuffer(buf, hgs); else @@ -519,7 +503,7 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) { STCnothrow, TOKnothrow }, { STCpure, TOKpure }, { STCref, TOKref }, - { STCtls, TOKtls }, + { STCtls }, { STCgshared, TOKgshared }, { STCproperty, TOKat, Id::property }, { STCsafe, TOKat, Id::safe }, @@ -536,6 +520,9 @@ const char *StorageClassDeclaration::stcToChars(char tmp[], StorageClass& stc) if (stc & tbl) { stc &= ~tbl; + if (tbl == STCtls) // TOKtls was removed + return "__thread"; + enum TOK tok = table[i].tok; #if DMDV2 if (tok == TOKat) @@ -560,7 +547,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc) const char *p = stcToChars(tmp, stc); if (!p) break; - assert(strlen(p) < sizeof(tmp)); + assert(strlen(p) < sizeof(tmp) / sizeof(tmp[0])); buf->writestring(p); buf->writeByte(' '); } @@ -984,6 +971,30 @@ void PragmaDeclaration::setScope(Scope *sc) { } +static unsigned setMangleOverride(Dsymbol *s, char *sym) +{ + AttribDeclaration *ad = s->isAttribDeclaration(); + + if (ad) + { + Dsymbols *decls = ad->include(NULL, NULL); + unsigned nestedCount = 0; + + if (decls && decls->dim) + for (size_t i = 0; i < decls->dim; ++i) + nestedCount += setMangleOverride((*decls)[i], sym); + + return nestedCount; + } + else if (s->isFuncDeclaration() || s->isVarDeclaration()) + { + s->isDeclaration()->mangleOverride = sym; + return 1; + } + else + return 0; +} + void PragmaDeclaration::semantic(Scope *sc) { // Should be merged with PragmaStatement @@ -1001,7 +1012,7 @@ void PragmaDeclaration::semantic(Scope *sc) { Expression *e = (*args)[i]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); if (e->op != TOKerror && e->op != TOKtype) e = e->ctfeInterpret(); @@ -1012,12 +1023,12 @@ void PragmaDeclaration::semantic(Scope *sc) StringExp *se = e->toString(); if (se) { - fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); + fprintf(stderr, "%.*s", (int)se->len, (char *)se->string); } else - fprintf(stdmsg, "%s", e->toChars()); + fprintf(stderr, "%s", e->toChars()); } - fprintf(stdmsg, "\n"); + fprintf(stderr, "\n"); } goto Lnodecl; } @@ -1029,7 +1040,7 @@ void PragmaDeclaration::semantic(Scope *sc) { Expression *e = (*args)[0]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); (*args)[0] = e; @@ -1049,44 +1060,6 @@ void PragmaDeclaration::semantic(Scope *sc) } goto Lnodecl; } -#ifdef IN_GCC - else if (ident == Id::GNU_asm) - { - if (! args || args->dim != 2) - error("identifier and string expected for asm name"); - else - { - Expression *e; - Declaration *d = NULL; - StringExp *s = NULL; - - e = (*args)[0]; - e = e->semantic(sc); - if (e->op == TOKvar) - { - d = ((VarExp *)e)->var; - if (! d->isFuncDeclaration() && ! d->isVarDeclaration()) - d = NULL; - } - if (!d) - error("first argument of GNU_asm must be a function or variable declaration"); - - e = (*args)[1]; - e = e->semantic(sc); - e = resolveProperties(sc, e); - e = e->ctfeInterpret(); - e = e->toString(); - if (e && ((StringExp *)e)->sz == 1) - s = ((StringExp *)e); - else - error("second argument of GNU_asm must be a character string"); - - if (d && s) - d->c_ident = Lexer::idPool((char*) s->string); - } - goto Lnodecl; - } -#endif #if DMDV2 else if (ident == Id::startaddress) { @@ -1095,7 +1068,7 @@ void PragmaDeclaration::semantic(Scope *sc) else { Expression *e = (*args)[0]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); (*args)[0] = e; @@ -1106,6 +1079,36 @@ void PragmaDeclaration::semantic(Scope *sc) goto Lnodecl; } #endif + else if (ident == Id::mangle) + { + if (!args || args->dim != 1) + error("string expected for mangled name"); + else + { + Expression *e = (*args)[0]; + + e = e->semantic(sc); + e = e->ctfeInterpret(); + (*args)[0] = e; + + if (e->op == TOKerror) + goto Lnodecl; + + StringExp *se = e->toString(); + + if (!se) + { + error("string expected for mangled name, not '%s'", e->toChars()); + return; + } + + if (!se->len) + error("zero-length string not allowed for mangled name"); + + if (se->sz != 1) + error("mangled name characters can only be of type char"); + } + } #if IN_LLVM else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone) { @@ -1124,11 +1127,13 @@ void PragmaDeclaration::semantic(Scope *sc) for (size_t i = 0; i < args->dim; i++) { Expression *e = (*args)[i]; + +#if IN_LLVM // ignore errors in ignored pragmas. global.gag++; unsigned errors_save = global.errors; - - e = e->semantic(sc); +#endif + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); if (i == 0) @@ -1137,9 +1142,11 @@ void PragmaDeclaration::semantic(Scope *sc) printf(","); printf("%s", e->toChars()); +#if IN_LLVM // restore error state. global.gag--; global.errors = errors_save; +#endif } if (args->dim) printf(")"); @@ -1159,9 +1166,26 @@ Ldecl: s->semantic(sc); + if (ident == Id::mangle) + { + StringExp *e = (*args)[0]->toString(); + + char *name = (char *)mem.malloc(e->len + 1); + memcpy(name, e->string, e->len); + name[e->len] = 0; + + unsigned cnt = setMangleOverride(s, name); + + if (cnt > 1) + error("can only apply to a single declaration"); + } #if IN_LLVM - DtoCheckPragma(this, s, llvm_internal, arg1str); + else + { + DtoCheckPragma(this, s, llvm_internal, arg1str); + } #endif + } } return; @@ -1185,51 +1209,6 @@ const char *PragmaDeclaration::kind() return "pragma"; } -#if IN_DMD -void PragmaDeclaration::toObjFile(int multiobj) -{ - if (ident == Id::lib) - { - assert(args && args->dim == 1); - - Expression *e = (*args)[0]; - - assert(e->op == TOKstring); - - StringExp *se = (StringExp *)e; - char *name = (char *)mem.malloc(se->len + 1); - memcpy(name, se->string, se->len); - name[se->len] = 0; - - /* Embed the library names into the object file. - * The linker will then automatically - * search that library, too. - */ - if (!obj_includelib(name)) - { - /* The format does not allow embedded library names, - * so instead append the library name to the list to be passed - * to the linker. - */ - global.params.libfiles->push(name); - } - } -#if DMDV2 - else if (ident == Id::startaddress) - { - assert(args && args->dim == 1); - Expression *e = (*args)[0]; - Dsymbol *sa = getDsymbol(e); - FuncDeclaration *f = sa->isFuncDeclaration(); - assert(f); - Symbol *s = f->toSymbol(); - obj_startaddress(s); - } -#endif - AttribDeclaration::toObjFile(multiobj); -} -#endif - void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("pragma (%s", ident->toChars()); @@ -1435,7 +1414,13 @@ Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *sd) if (condition->inc == 0) { + /* Bugzilla 10101: Condition evaluation may cause self-recursive + * condition evaluation. To resolve it, temporarily save sc into scope. + */ + bool x = !scope && sc; + if (x) scope = sc; Dsymbols *d = ConditionalDeclaration::include(sc, sd); + if (x) scope = NULL; // Set the scopes lazily. if (scope && d) @@ -1558,7 +1543,7 @@ int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) void CompileDeclaration::compileIt(Scope *sc) { //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars()); - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); exp = resolveProperties(sc, exp); exp = exp->ctfeInterpret(); StringExp *se = exp->toString(); @@ -1666,8 +1651,8 @@ Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *u * (do not append to left operand, as this is a copy-on-write operation) */ udas = new Expressions(); - udas->push(new TupleExp(0, udas1)); - udas->push(new TupleExp(0, udas2)); + udas->push(new TupleExp(Loc(), udas1)); + udas->push(new TupleExp(Loc(), udas2)); } return udas; } @@ -1692,8 +1677,8 @@ void UserAttributeDeclaration::setScope(Scope *sc) { // Create a tuple that combines them Expressions *exps = new Expressions(); - exps->push(new TupleExp(0, newsc->userAttributes)); - exps->push(new TupleExp(0, atts)); + exps->push(new TupleExp(Loc(), newsc->userAttributes)); + exps->push(new TupleExp(Loc(), atts)); newsc->userAttributes = exps; } } diff --git a/dmd2/builtin.c b/dmd2/builtin.c index ee51b891f7..ae3542c314 100644 --- a/dmd2/builtin.c +++ b/dmd2/builtin.c @@ -163,27 +163,27 @@ Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments) { case BUILTINsin: if (arg0->op == TOKfloat64) - e = new RealExp(0, sinl(arg0->toReal()), arg0->type); + e = new RealExp(Loc(), sinl(arg0->toReal()), arg0->type); break; case BUILTINcos: if (arg0->op == TOKfloat64) - e = new RealExp(0, cosl(arg0->toReal()), arg0->type); + e = new RealExp(Loc(), cosl(arg0->toReal()), arg0->type); break; case BUILTINtan: if (arg0->op == TOKfloat64) - e = new RealExp(0, tanl(arg0->toReal()), arg0->type); + e = new RealExp(Loc(), tanl(arg0->toReal()), arg0->type); break; case BUILTINsqrt: if (arg0->op == TOKfloat64) - e = new RealExp(0, sqrtl(arg0->toReal()), arg0->type); + e = new RealExp(Loc(), sqrtl(arg0->toReal()), arg0->type); break; case BUILTINfabs: if (arg0->op == TOKfloat64) - e = new RealExp(0, fabsl(arg0->toReal()), arg0->type); + e = new RealExp(Loc(), fabsl(arg0->toReal()), arg0->type); break; // These math intrinsics are not yet implemented case BUILTINatan2: diff --git a/dmd2/cast.c b/dmd2/cast.c index 27ca1ef82e..ede3f49fbd 100644 --- a/dmd2/cast.c +++ b/dmd2/cast.c @@ -20,6 +20,7 @@ #include "aggregate.h" #include "template.h" #include "scope.h" +#include "id.h" //#define DUMP .dump(__PRETTY_FUNCTION__, this) #define DUMP @@ -280,7 +281,11 @@ MATCH IntegerExp::implicitConvTo(Type *t) goto Lyes; case Tint8: - if ((signed char)value != value) + if (ty == Tuns64 && value & ~0x7FUL) + goto Lno; + //else if (ty == Tint64 && 0x7FUL < value && value < ~0x7FUL) + // goto Lno; + else if ((signed char)value != value) goto Lno; goto Lyes; @@ -294,7 +299,11 @@ MATCH IntegerExp::implicitConvTo(Type *t) goto Lyes; case Tint16: - if ((short)value != value) + if (ty == Tuns64 && value & ~0x7FFFUL) + goto Lno; + //else if (ty == Tint64 && 0x7FFFUL < value && value < ~0x7FFFUL) + // goto Lno; + else if ((short)value != value) goto Lno; goto Lyes; @@ -310,6 +319,10 @@ MATCH IntegerExp::implicitConvTo(Type *t) if (ty == Tuns32) { } + else if (ty == Tuns64 && value & ~0x7FFFFFFFUL) + goto Lno; + //else if (ty == Tint64 && 0x7FFFFFFFUL < value && value < ~0x7FFFFFFFUL) + // goto Lno; else if ((int)value != value) goto Lno; goto Lyes; @@ -439,9 +452,12 @@ MATCH StructLiteralExp::implicitConvTo(Type *t) { m = MATCHconst; for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (*elements)[i]; + { + Expression *e = (*elements)[i]; + if (!e) + continue; Type *te = e->type; - te = te->castMod(t->mod); + te = sd->fields[i]->type->addMod(t->mod); MATCH m2 = e->implicitConvTo(te); //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2); if (m2 < m) @@ -638,9 +654,36 @@ MATCH CallExp::implicitConvTo(Type *t) /* Allow the result of strongly pure functions to * convert to immutable */ - if (f && f->isPure() == PUREstrong && !f->type->hasWild()) + if (f && f->isolateReturn()) return type->invariantOf()->implicitConvTo(t); + /* The result of arr.dup and arr.idup can be unique essentially. + * So deal with this case specially. + */ + if (!f && e1->op == TOKvar && ((VarExp *)e1)->var->ident == Id::adDup && + t->toBasetype()->ty == Tarray) + { + assert(type->toBasetype()->ty == Tarray); + assert(arguments->dim == 2); + Expression *eorg = (*arguments)[1]; + Type *tn = t->nextOf(); + if (type->nextOf()->implicitConvTo(tn) < MATCHconst) + { + /* If the operand is an unique array literal, then allow conversion. + */ + if (eorg->op != TOKarrayliteral) + return MATCHnomatch; + Expressions *elements = ((ArrayLiteralExp *)eorg)->elements; + for (size_t i = 0; i < elements->dim; i++) + { + if (!(*elements)[i]->implicitConvTo(tn)) + return MATCHnomatch; + } + } + m = type->invariantOf()->implicitConvTo(t); + return m; + } + return MATCHnomatch; } @@ -969,6 +1012,39 @@ MATCH NewExp::implicitConvTo(Type *t) return MATCHnomatch; } +Type *SliceExp::toStaticArrayType() +{ + if (lwr && upr) + { + Expression *lwr = this->lwr->optimize(WANTvalue); + Expression *upr = this->upr->optimize(WANTvalue); + if (lwr->isConst() && upr->isConst()) + { + size_t len = upr->toUInteger() - lwr->toUInteger(); + return new TypeSArray(type->toBasetype()->nextOf(), + new IntegerExp(Loc(), len, Type::tindex)); + } + } + return NULL; +} + +MATCH SliceExp::implicitConvTo(Type *t) +{ + MATCH result = Expression::implicitConvTo(t); + + Type *tb = t->toBasetype(); + Type *typeb = type->toBasetype(); + if (result == MATCHnomatch && + tb->ty == Tsarray && typeb->ty == Tarray && + lwr && upr) + { + typeb = toStaticArrayType(); + if (typeb) + result = typeb->implicitConvTo(t); + } + return result; +} + /* ==================== castTo ====================== */ /************************************** @@ -984,6 +1060,15 @@ Expression *Expression::castTo(Scope *sc, Type *t) #endif if (type == t) return this; + if (op == TOKvar) + { + VarDeclaration *v = ((VarExp *)this)->var->isVarDeclaration(); + if (v && v->storage_class & STCmanifest) + { + Expression *e = optimize(WANTvalue | WANTinterpret); + return e->castTo(sc, t); + } + } Expression *e = this; Type *tb = t->toBasetype(); Type *typeb = type->toBasetype(); @@ -1162,6 +1247,14 @@ Expression *NullExp::castTo(Scope *sc, Type *t) return e; } +Expression *StructLiteralExp::castTo(Scope *sc, Type *t) +{ + Expression *e = Expression::castTo(sc, t); + if (e->op == TOKstructliteral) + ((StructLiteralExp *)e)->stype = t; // commit type + return e; +} + Expression *StringExp::castTo(Scope *sc, Type *t) { /* This follows copy-on-write; any changes to 'this' @@ -1465,7 +1558,9 @@ Expression *AddrExp::castTo(Scope *sc, Type *t) Expression *TupleExp::castTo(Scope *sc, Type *t) -{ TupleExp *e = (TupleExp *)copy(); +{ + TupleExp *e = (TupleExp *)copy(); + e->e0 = e0 ? e0->copy() : NULL; e->exps = (Expressions *)exps->copy(); for (size_t i = 0; i < e->exps->dim; i++) { Expression *ex = (*e->exps)[i]; @@ -1490,7 +1585,9 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) if ((tb->ty == Tarray || tb->ty == Tsarray) && (typeb->ty == Tarray || typeb->ty == Tsarray) && // Not trying to convert non-void[] to void[] - !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid)) + !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid) && + // Not trying to convert void[n] to others + !(typeb->ty == Tsarray && typeb->nextOf()->toBasetype()->ty == Tvoid)) { if (tb->ty == Tsarray) { TypeSArray *tsa = (TypeSArray *)tb; @@ -1699,7 +1796,8 @@ Expression *FuncExp::castTo(Scope *sc, Type *t) e = e->castTo(sc, t); else if (!e->type->equals(t)) { - assert(e->type->nextOf()->covariant(t->nextOf()) == 1); + assert(t->ty == Tpointer && t->nextOf()->ty == Tvoid || // Bugzilla 9928 + e->type->nextOf()->covariant(t->nextOf()) == 1); e = e->copy(); e->type = t; } @@ -1741,19 +1839,42 @@ Expression *CommaExp::castTo(Scope *sc, Type *t) return e; } +Expression *SliceExp::castTo(Scope *sc, Type *t) +{ + Type *typeb = type->toBasetype(); + Type *tb = t->toBasetype(); + Expression *e; + if (typeb->ty == Tarray && tb->ty == Tsarray) + { + /* If a SliceExp has Tsarray, it will become lvalue. + * That's handled in SliceExp::isLvalue and toLvalue + */ + e = copy(); + e->type = t; + } + else + { + e = Expression::castTo(sc, t); + } + return e; +} + /* ==================== inferType ====================== */ /**************************************** * Set type inference target + * t Target type * flag 1: don't put an error when inference fails + * sc it is used for the semantic of t, when != NULL + * tparams template parameters should be inferred */ -Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams) +Expression *Expression::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams) { return this; } -Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +Expression *ArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams) { if (t) { @@ -1764,7 +1885,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp for (size_t i = 0; i < elements->dim; i++) { Expression *e = (*elements)[i]; if (e) - { e = e->inferType(tn, flag, tparams); + { e = e->inferType(tn, flag, sc, tparams); (*elements)[i] = e; } } @@ -1773,7 +1894,7 @@ Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tp return this; } -Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams) { if (t) { @@ -1785,14 +1906,14 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter for (size_t i = 0; i < keys->dim; i++) { Expression *e = (*keys)[i]; if (e) - { e = e->inferType(ti, flag, tparams); + { e = e->inferType(ti, flag, sc, tparams); (*keys)[i] = e; } } for (size_t i = 0; i < values->dim; i++) { Expression *e = (*values)[i]; if (e) - { e = e->inferType(tv, flag, tparams); + { e = e->inferType(tv, flag, sc, tparams); (*values)[i] = e; } } @@ -1801,7 +1922,7 @@ Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameter return this; } -Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) +Expression *FuncExp::inferType(Type *to, int flag, Scope *sc, TemplateParameters *tparams) { if (!to) return this; @@ -1859,7 +1980,10 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) Type *tprm = p->type; if (tprm->reliesOnTident(tparams)) goto L1; - tprm = tprm->semantic(loc, td->scope); + if (sc) + tprm = tprm->semantic(loc, sc); + if (tprm->ty == Terror) + goto L1; tiargs->push(tprm); u = dim; // break inner loop } @@ -1915,13 +2039,13 @@ L1: return e; } -Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams) +Expression *CondExp::inferType(Type *t, int flag, Scope *sc, TemplateParameters *tparams) { if (t) { t = t->toBasetype(); - e1 = e1->inferType(t, flag, tparams); - e2 = e2->inferType(t, flag, tparams); + e1 = e1->inferType(t, flag, sc, tparams); + e2 = e2->inferType(t, flag, sc, tparams); } return this; } @@ -1947,8 +2071,8 @@ Expression *BinExp::scaleFactor(Scope *sc) stride = t1b->nextOf()->size(loc); if (!t->equals(t2b)) e2 = e2->castTo(sc, t); - e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t)); eoff = e2; + e2 = new MulExp(loc, e2, new IntegerExp(Loc(), stride, t)); e2->type = t; type = e1->type; } @@ -1963,8 +2087,8 @@ Expression *BinExp::scaleFactor(Scope *sc) e = e1->castTo(sc, t); else e = e1; - e = new MulExp(loc, e, new IntegerExp(0, stride, t)); eoff = e; + e = new MulExp(loc, e, new IntegerExp(Loc(), stride, t)); e->type = t; type = e2->type; e1 = e2; @@ -2049,6 +2173,14 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression assert(t1); Type *t = t1; + /* The start type of alias this type recursion. + * In following case, we should save A, and stop recursion + * if it appears again. + * X -> Y -> [A] -> B -> A -> B -> ... + */ + Type *att1 = NULL; + Type *att2 = NULL; + //if (t1) printf("\tt1 = %s\n", t1->toChars()); //if (t2) printf("\tt2 = %s\n", t2->toChars()); #ifdef DEBUG @@ -2356,12 +2488,22 @@ Lcc: } else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { + if (att1 && e1->type == att1) + goto Lincompatible; + if (!att1 && e1->type->checkAliasThisRec()) + att1 = e1->type; + //printf("att tmerge(c || c) e1 = %s\n", e1->type->toChars()); e1 = resolveAliasThis(sc, e1); t1 = e1->type; continue; } else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { + if (att2 && e2->type == att2) + goto Lincompatible; + if (!att2 && e2->type->checkAliasThisRec()) + att2 = e2->type; + //printf("att tmerge(c || c) e2 = %s\n", e2->type->toChars()); e2 = resolveAliasThis(sc, e2); t2 = e2->type; continue; @@ -2397,11 +2539,21 @@ Lcc: Expression *e2b = NULL; if (ts2->sym->aliasthis) { + if (att2 && e2->type == att2) + goto Lincompatible; + if (!att2 && e2->type->checkAliasThisRec()) + att2 = e2->type; + //printf("att tmerge(s && s) e2 = %s\n", e2->type->toChars()); e2b = resolveAliasThis(sc, e2); i1 = e2b->implicitConvTo(t1); } if (ts1->sym->aliasthis) { + if (att1 && e1->type == att1) + goto Lincompatible; + if (!att1 && e1->type->checkAliasThisRec()) + att1 = e1->type; + //printf("att tmerge(s && s) e1 = %s\n", e1->type->toChars()); e1b = resolveAliasThis(sc, e1); i2 = e1b->implicitConvTo(t2); } @@ -2429,6 +2581,11 @@ Lcc: { if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { + if (att1 && e1->type == att1) + goto Lincompatible; + if (!att1 && e1->type->checkAliasThisRec()) + att1 = e1->type; + //printf("att tmerge(s || s) e1 = %s\n", e1->type->toChars()); e1 = resolveAliasThis(sc, e1); t1 = e1->type; t = t1; @@ -2436,6 +2593,11 @@ Lcc: } if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { + if (att2 && e2->type == att2) + goto Lincompatible; + if (!att2 && e2->type->checkAliasThisRec()) + att2 = e2->type; + //printf("att tmerge(s || s) e2 = %s\n", e2->type->toChars()); e2 = resolveAliasThis(sc, e2); t2 = e2->type; t = t2; @@ -2472,6 +2634,7 @@ Lcc: { e2 = e2->castTo(sc, t1); t2 = t1; + t = t1; goto Lagain; } else if (t2->ty == Tvector && t1->ty != Tvector && @@ -2479,6 +2642,7 @@ Lcc: { e1 = e1->castTo(sc, t2); t1 = t2; + t = t1; goto Lagain; } else if (t1->isintegral() && t2->isintegral()) @@ -2576,6 +2740,11 @@ Expression *BinExp::typeCombine(Scope *sc) if (!typeMerge(sc, this, &type, &e1, &e2)) goto Lerror; + // If the types have no value, return an error + if (e1->op == TOKerror) + return e1; + if (e2->op == TOKerror) + return e2; return this; Lerror: @@ -2615,6 +2784,8 @@ Expression *Expression::integralPromotions(Scope *sc) case Tdchar: e = e->castTo(sc, Type::tuns32); break; + default: + break; } return e; } diff --git a/dmd2/class.c b/dmd2/class.c index 1621b43c34..ce85a096e0 100644 --- a/dmd2/class.c +++ b/dmd2/class.c @@ -15,6 +15,7 @@ #include "root.h" #include "rmem.h" +#include "target.h" #include "enum.h" #include "init.h" @@ -220,11 +221,16 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla } #if !MODULEINFO_IS_STRUCT + #ifdef DMDV2 + if (id == Id::ModuleInfo && !Module::moduleinfo) + Module::moduleinfo = this; + #else if (id == Id::ModuleInfo) { if (Module::moduleinfo) Module::moduleinfo->error("%s", msg); Module::moduleinfo = this; } + #endif #endif } @@ -232,6 +238,7 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla isscope = 0; isabstract = 0; inuse = 0; + doAncestorsSemantic = SemanticStart; } Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) @@ -280,7 +287,7 @@ void ClassDeclaration::semantic(Scope *sc) type = type->semantic(loc, sc); handle = type; - if (!members) // if forward reference + if (!members) // if opaque declaration { //printf("\tclass '%s' is forward referenced\n", toChars()); return; } @@ -300,7 +307,7 @@ void ClassDeclaration::semantic(Scope *sc) scope = NULL; } unsigned dprogress_save = Module::dprogress; - int errors = global.gaggedErrors; + int errors = global.errors; if (sc->stc & STCdeprecated) { @@ -376,7 +383,7 @@ void ClassDeclaration::semantic(Scope *sc) } if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone) { // Try to resolve forward reference - if (/*sc->mustsemantic &&*/ tc->sym->scope) + if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope) tc->sym->semantic(NULL); } if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone) @@ -444,7 +451,7 @@ void ClassDeclaration::semantic(Scope *sc) if (!tc->sym->symtab) { // Try to resolve forward reference - if (/*sc->mustsemantic &&*/ tc->sym->scope) + if (/*doAncestorsSemantic == SemanticIn &&*/ tc->sym->scope) tc->sym->semantic(NULL); } @@ -464,6 +471,8 @@ void ClassDeclaration::semantic(Scope *sc) } i++; } + if (doAncestorsSemantic == SemanticIn) + doAncestorsSemantic = SemanticDone; // If no base class, and this is not an Object, use Object as base class @@ -508,6 +517,7 @@ void ClassDeclaration::semantic(Scope *sc) com = baseClass->isCOMclass(); isscope = baseClass->isscope; vthis = baseClass->vthis; + enclosing = baseClass->enclosing; storage_class |= baseClass->storage_class & STC_TYPECTOR; } else @@ -535,7 +545,6 @@ void ClassDeclaration::semantic(Scope *sc) */ if (vthis) // if inheriting from nested class { // Use the base class's 'this' member - isnested = true; if (storage_class & STCstatic) error("static class cannot inherit from nested class %s", baseClass->toChars()); if (toParent2() != baseClass->toParent2() && @@ -556,41 +565,11 @@ void ClassDeclaration::semantic(Scope *sc) baseClass->toChars(), baseClass->toParent2()->toChars()); } - isnested = false; - } - } - else if (!(storage_class & STCstatic)) - { Dsymbol *s = toParent2(); - if (s) - { - AggregateDeclaration *ad = s->isClassDeclaration(); - FuncDeclaration *fd = s->isFuncDeclaration(); - - - if (ad || fd) - { isnested = true; - Type *t; - if (ad) - t = ad->handle; - else if (fd) - { AggregateDeclaration *ad2 = fd->isMember2(); - if (ad2) - t = ad2->handle; - else - { - t = Type::tvoidptr; - } - } - else - assert(0); - if (t->ty == Tstruct) // ref to struct - t = Type::tvoidptr; - assert(!vthis); - vthis = new ThisDeclaration(loc, t); - members->push(vthis); - } + enclosing = NULL; } } + else + makeNested(); } if (storage_class & STCauto) @@ -627,12 +606,12 @@ void ClassDeclaration::semantic(Scope *sc) if (baseClass) { sc->offset = baseClass->structsize; alignsize = baseClass->alignsize; -// if (isnested) -// sc->offset += PTRSIZE; // room for uplevel context pointer +// if (enclosing) +// sc->offset += Target::ptrsize; // room for uplevel context pointer } else - { sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor - alignsize = PTRSIZE; + { sc->offset = Target::ptrsize * 2; // allow room for __vptr and __monitor + alignsize = Target::ptrsize; } sc->userAttributes = NULL; structsize = sc->offset; @@ -674,8 +653,8 @@ void ClassDeclaration::semantic(Scope *sc) } sc->offset = structsize; - if (global.gag && global.gaggedErrors != errors) - { // The type is no good, yet the error messages were gagged. + if (global.errors != errors) + { // The type is no good. type = Type::terror; } @@ -713,43 +692,57 @@ void ClassDeclaration::semantic(Scope *sc) /* Look for special member functions. * They must be in this class, not in a base class. */ - ctor = search(0, Id::ctor, 0); + ctor = search(Loc(), Id::ctor, 0); #if DMDV1 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) ctor = NULL; #else if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration()))) ctor = NULL; // search() looks through ancestor classes + if (!ctor && noDefaultCtor) + { + // A class object is always created by constructor, so this check is legitimate. + for (size_t i = 0; i < fields.dim; i++) + { + VarDeclaration *v = fields[i]->isVarDeclaration(); + if (v->storage_class & STCnodefaultctor) + ::error(v->loc, "field %s must be initialized in constructor", v->toChars()); + } + } #endif // dtor = (DtorDeclaration *)search(Id::dtor, 0); // if (dtor && dtor->toParent() != this) // dtor = NULL; -// inv = (InvariantDeclaration *)search(Id::classInvariant, 0); -// if (inv && inv->toParent() != this) -// inv = NULL; + inv = buildInv(sc); // Can be in base class - aggNew = (NewDeclaration *)search(0, Id::classNew, 0); - aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); + aggNew = (NewDeclaration *)search(Loc(), Id::classNew, 0); + aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete, 0); - // If this class has no constructor, but base class does, create - // a constructor: + // If this class has no constructor, but base class has a default + // ctor, create a constructor: // this() { } if (!ctor && baseClass && baseClass->ctor) { - //printf("Creating default this(){} for class %s\n", toChars()); - Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0); - CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf); - ctor->isImplicit = true; - ctor->fbody = new CompoundStatement(0, new Statements()); - members->push(ctor); - ctor->addMember(sc, this, 1); - *sc = scsave; // why? What about sc->nofree? - ctor->semantic(sc); - this->ctor = ctor; - defaultCtor = ctor; + if (resolveFuncCall(loc, sc, baseClass->ctor, NULL, NULL, NULL, 1)) + { + //printf("Creating default this(){} for class %s\n", toChars()); + Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0); + CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf); + ctor->fbody = new CompoundStatement(Loc(), new Statements()); + members->push(ctor); + ctor->addMember(sc, this, 1); + *sc = scsave; // why? What about sc->nofree? + ctor->semantic(sc); + this->ctor = ctor; + defaultCtor = ctor; + } + else + { + error("Cannot implicitly generate a default ctor when base class %s is missing a default ctor", baseClass->toPrettyChars()); + } } #if 0 @@ -766,7 +759,7 @@ void ClassDeclaration::semantic(Scope *sc) for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (*vtblInterfaces)[i]; - unsigned thissize = PTRSIZE; + unsigned thissize = Target::ptrsize; alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset); assert(b->offset == 0); @@ -795,13 +788,10 @@ void ClassDeclaration::semantic(Scope *sc) Module::dprogress++; dtor = buildDtor(sc); - if (Dsymbol *assign = search_function(this, Id::assign)) + if (FuncDeclaration *f = hasIdentityOpAssign(sc)) { - if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign)) - { - if (!(f->storage_class & STCdisable)) - error("identity assignment operator overload is illegal"); - } + if (!(f->storage_class & STCdisable)) + error("identity assignment operator overload is illegal"); } sc->pop(); @@ -821,6 +811,15 @@ void ClassDeclaration::semantic(Scope *sc) deferred->semantic2(sc); deferred->semantic3(sc); } + +#if 0 + if (type->ty == Tclass && ((TypeClass *)type)->sym != this) + { + printf("this = %p %s\n", this, this->toChars()); + printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym); + } +#endif + assert(type->ty != Tclass || ((TypeClass *)type)->sym == this); } void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -837,7 +836,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) BaseClass *b = (*baseclasses)[i]; if (i) - buf->writeByte(','); + buf->writestring(", "); //buf->writestring(b->base->ident->toChars()); b->type->toCBuffer(buf, NULL, hgs); } @@ -941,19 +940,24 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) Dsymbol *s; //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); - if (scope && !symtab) - { Scope *sc = scope; - sc->mustsemantic++; + //if (scope) printf("%s doAncestorsSemantic = %d\n", toChars(), doAncestorsSemantic); + if (scope && doAncestorsSemantic == SemanticStart) + { + // must semantic on base class/interfaces + doAncestorsSemantic = SemanticIn; + // If speculatively gagged, ungag now. unsigned oldgag = global.gag; if (global.isSpeculativeGagging()) global.gag = 0; - semantic(sc); + semantic(scope); global.gag = oldgag; - sc->mustsemantic--; + + if (doAncestorsSemantic != SemanticDone) + doAncestorsSemantic = SemanticStart; } - if (!members || !symtab) + if (!members || !symtab) // opaque or semantic() is not yet called { error("is forward referenced when looking for '%s'", ident->toChars()); //*(char*)0=0; @@ -987,17 +991,17 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) return s; } -Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident) +ClassDeclaration *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(); + ClassDeclaration *cdb = b->type->isClassHandle(); if (cdb->ident->equals(ident)) return cdb; - cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident); + cdb = cdb->searchBase(loc, ident); if (cdb) return cdb; } @@ -1019,7 +1023,7 @@ int isf(void *param, FuncDeclaration *fd) int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) { //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars()); - Dsymbol *s = search(0, fd->ident, 4|2); + Dsymbol *s = search(Loc(), fd->ident, 4|2); if (!s) { //printf("not found\n"); /* Because, due to a hack, if there are multiple definitions @@ -1289,7 +1293,7 @@ void InterfaceDeclaration::semantic(Scope *sc) scope = NULL; } - int errors = global.gaggedErrors; + int errors = global.errors; if (sc->stc & STCdeprecated) { @@ -1359,7 +1363,7 @@ void InterfaceDeclaration::semantic(Scope *sc) } if (!b->base->symtab) { // Try to resolve forward reference - if (sc->mustsemantic && b->base->scope) + if (doAncestorsSemantic == SemanticIn && b->base->scope) b->base->semantic(NULL); } if (!b->base->symtab || b->base->scope || b->base->inuse) @@ -1379,6 +1383,8 @@ void InterfaceDeclaration::semantic(Scope *sc) #endif i++; } + if (doAncestorsSemantic == SemanticIn) + doAncestorsSemantic = SemanticDone; interfaces_dim = baseclasses->dim; interfaces = baseclasses->tdata(); @@ -1438,7 +1444,7 @@ void InterfaceDeclaration::semantic(Scope *sc) sc->protection = PROTpublic; sc->explicitProtection = 0; // structalign = sc->structalign; - sc->offset = PTRSIZE * 2; + sc->offset = Target::ptrsize * 2; sc->userAttributes = NULL; structsize = sc->offset; inuse++; @@ -1464,8 +1470,8 @@ void InterfaceDeclaration::semantic(Scope *sc) s->semantic(sc); } - if (global.gag && global.gaggedErrors != errors) - { // The type is no good, yet the error messages were gagged. + if (global.errors != errors) + { // The type is no good. type = Type::terror; } @@ -1473,6 +1479,15 @@ void InterfaceDeclaration::semantic(Scope *sc) //members->print(); sc->pop(); //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); + +#if 0 + if (type->ty == Tclass && ((TypeClass *)type)->sym != this) + { + printf("this = %p %s\n", this, this->toChars()); + printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym); + } +#endif + assert(type->ty != Tclass || ((TypeClass *)type)->sym == this); } @@ -1664,8 +1679,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins if (newinstance && fd->toParent() != cd && ifd->toParent() == base) - cd->error("interface function %s.%s is not implemented", - id->toChars(), ifd->ident->toChars()); + cd->error("interface function '%s' is not implemented", ifd->toFullSignature()); if (fd->toParent() == cd) result = 1; @@ -1675,9 +1689,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins //printf(" not found\n"); // BUG: should mark this class as abstract? if (!cd->isAbstract()) - cd->error("interface function %s.%s%s isn't implemented", - id->toChars(), ifd->ident->toChars(), - Parameter::argsTypesToChars(tf->parameters, tf->varargs)); + cd->error("interface function '%s' is not implemented", ifd->toFullSignature()); fd = NULL; } diff --git a/dmd2/clone.c b/dmd2/clone.c index c0a0b97a4f..03ea82c2f9 100644 --- a/dmd2/clone.c +++ b/dmd2/clone.c @@ -24,44 +24,72 @@ #include "template.h" +/******************************************* + * Merge function attributes pure, nothrow, @safe, and @disable + */ +StorageClass mergeFuncAttrs(StorageClass s1, StorageClass s2) +{ + StorageClass stc = 0; + StorageClass sa = s1 & s2; + StorageClass so = s1 | s2; + + if (so & STCsystem) + stc |= STCsystem; + else if (sa & STCtrusted) + stc |= STCtrusted; + else if ((so & (STCtrusted | STCsafe)) == (STCtrusted | STCsafe)) + stc |= STCtrusted; + else if (sa & STCsafe) + stc |= STCsafe; + + if (sa & STCpure) + stc |= STCpure; + + if (sa & STCnothrow) + stc |= STCnothrow; + + if (so & STCdisable) + stc |= STCdisable; + + return stc; +} + /******************************************* * Check given opAssign symbol is really identity opAssign or not. */ -FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc, Dsymbol *assign) +FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc) { + Dsymbol *assign = search_function(this, Id::assign); if (assign) { - assert(assign->ident == Id::assign); - /* check identity opAssign exists */ Expression *er = new NullExp(loc, type); // dummy rvalue Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue el->type = type; - Expressions ar; ar.push(er); - Expressions al; al.push(el); + Expressions *a = new Expressions(); + a->setDim(1); FuncDeclaration *f = NULL; - if (FuncDeclaration *fd = assign->isFuncDeclaration()) - { - f = fd->overloadResolve(loc, er, &ar, 1); - if (!f) f = fd->overloadResolve(loc, er, &al, 1); - } - if (TemplateDeclaration *td = assign->isTemplateDeclaration()) - { - unsigned errors = global.startGagging(); // Do not report errors, even if the - unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. - global.speculativeGag = global.gag; - Scope *sc2 = sc->push(); - sc2->speculative = true; - f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &ar, 1); - if (!f) f = td->deduceFunctionTemplate(sc2, loc, NULL, er, &al, 1); + unsigned errors = global.startGagging(); // Do not report errors, even if the + unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. + global.speculativeGag = global.gag; + sc = sc->push(); + sc->speculative = true; - sc2->pop(); - global.speculativeGag = oldspec; - global.endGagging(errors); + for (size_t i = 0; i < 2; i++) + { + (*a)[0] = (i == 0 ? er : el); + f = resolveFuncCall(loc, sc, assign, NULL, type, a, 1); + if (f) + break; } + + sc = sc->pop(); + global.speculativeGag = oldspec; + global.endGagging(errors); + if (f) { int varargs; @@ -104,7 +132,7 @@ int StructDeclaration::needOpAssign() { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); @@ -133,41 +161,53 @@ Lneed: * Build opAssign for struct. * ref S opAssign(S s) { ... } * - * Note that s will be constructed onto the stack, probably copy-constructed. - * Then, the body is: - * S tmp = this; // bit copy - * this = s; // bit copy - * tmp.dtor(); + * Note that s will be constructed onto the stack, and probably + * copy-constructed in caller site. + * + * If S has copy copy construction and/or destructor, + * the body will make bit-wise object swap: + * S __tmp = this; // bit copy + * this = s; // bit copy + * __tmp.dtor(); * Instead of running the destructor on s, run it on tmp instead. + * + * Otherwise, the body will make member-wise assignments: + * Then, the body is: + * this.field1 = s.field1; + * this.field2 = s.field2; + * ...; */ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) { - Dsymbol *assign = search_function(this, Id::assign); - if (assign) + if (FuncDeclaration *f = hasIdentityOpAssign(sc)) { - if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign)) - return f; - // Even if non-identity opAssign is defined, built-in identity opAssign - // will be defined. (Is this an exception of operator overloading rule?) + hasIdentityAssign = 1; + return f; } + // Even if non-identity opAssign is defined, built-in identity opAssign + // will be defined. if (!needOpAssign()) return NULL; //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); + StorageClass stc = STCundefined; + Loc declLoc = this->loc; + Loc loc = Loc(); // internal code should have no loc to prevent coverage Parameters *fparams = new Parameters; fparams->push(new Parameter(STCnodtor, type, Id::p, NULL)); Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd); ((TypeFunction *)ftype)->isref = 1; - FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype); + FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, ftype); Expression *e = NULL; - if (postblit) - { /* Swap: - * tmp = *this; *this = s; tmp.dtor(); + if (dtor || postblit) + { + /* Do swap this and rhs + * tmp = this; this = s; tmp.dtor(); */ //printf("\tswap copy\n"); Identifier *idtmp = Lexer::uniqueId("__tmp"); @@ -175,20 +215,20 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) AssignExp *ec = NULL; if (dtor) { - tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0)); + tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc)); tmp->noscope = 1; tmp->storage_class |= STCctfe; - e = new DeclarationExp(0, tmp); - ec = new AssignExp(0, - new VarExp(0, tmp), - new ThisExp(0) + e = new DeclarationExp(loc, tmp); + ec = new AssignExp(loc, + new VarExp(loc, tmp), + new ThisExp(loc) ); ec->op = TOKblit; e = Expression::combine(e, ec); } - ec = new AssignExp(0, - new ThisExp(0), - new IdentifierExp(0, Id::p)); + ec = new AssignExp(loc, + new ThisExp(loc), + new IdentifierExp(loc, Id::p)); ec->op = TOKblit; e = Expression::combine(e, ec); if (dtor) @@ -196,38 +236,41 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) /* Instead of running the destructor on s, run it * on tmp. This avoids needing to copy tmp back in to s. */ - Expression *ec2 = new DotVarExp(0, new VarExp(0, tmp), dtor, 0); - ec2 = new CallExp(0, ec2); + Expression *ec2 = new DotVarExp(loc, new VarExp(loc, tmp), dtor, 0); + ec2 = new CallExp(loc, ec2); e = Expression::combine(e, ec2); } } else - { /* Do memberwise copy + { + /* Do memberwise copy */ //printf("\tmemberwise copy\n"); for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); // this.v = s.v; - AssignExp *ec = new AssignExp(0, - new DotVarExp(0, new ThisExp(0), v, 0), - new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0)); + AssignExp *ec = new AssignExp(loc, + new DotVarExp(loc, new ThisExp(loc), v, 0), + new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0)); e = Expression::combine(e, ec); } } - Statement *s1 = new ExpStatement(0, e); + Statement *s1 = new ExpStatement(loc, e); /* Add: * return this; */ - e = new ThisExp(0); - Statement *s2 = new ReturnStatement(0, e); + e = new ThisExp(loc); + Statement *s2 = new ReturnStatement(loc, e); - fop->fbody = new CompoundStatement(0, s1, s2); + fop->fbody = new CompoundStatement(loc, s1, s2); Dsymbol *s = fop; +#if 1 // workaround until fixing issue 1528 + Dsymbol *assign = search_function(this, Id::assign); if (assign && assign->isTemplateDeclaration()) { // Wrap a template around the function declaration @@ -238,6 +281,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0); s = tempdecl; } +#endif members->push(s); s->addMember(sc, this, 1); this->hasIdentityAssign = 1; // temporary mark identity assignable @@ -281,10 +325,8 @@ int StructDeclaration::needOpEquals() if (hasIdentityEquals) goto Lneed; -#if 0 if (isUnionDeclaration()) goto Ldontneed; -#endif /* If any of the fields has an opEquals, then we * need it too. @@ -293,18 +335,18 @@ int StructDeclaration::needOpEquals() { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); -#if 0 if (tv->isfloating()) goto Lneed; if (tv->ty == Tarray) goto Lneed; + if (tv->ty == Taarray) + goto Lneed; if (tv->ty == Tclass) goto Lneed; -#endif while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; tv = tv->nextOf()->toBasetype(); @@ -326,128 +368,107 @@ Lneed: #undef X } -/****************************************** - * Build opEquals for struct. - * const bool opEquals(const S s) { ... } - */ - -FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc) +FuncDeclaration *AggregateDeclaration::hasIdentityOpEquals(Scope *sc) { Dsymbol *eq = search_function(this, Id::eq); if (eq) { - for (size_t i = 0; i <= 1; i++) + /* check identity opEquals exists + */ + Expression *er = new NullExp(loc, NULL); // dummy rvalue + Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue + Expressions *a = new Expressions(); + a->setDim(1); + for (size_t i = 0; ; i++) { - Expression *e = - i == 0 ? new NullExp(loc, type->constOf()) // dummy rvalue - : type->constOf()->defaultInit(); // dummy lvalue - Expressions *arguments = new Expressions(); - arguments->push(e); + Type *tthis; + if (i == 0) tthis = type; + if (i == 1) tthis = type->constOf(); + if (i == 2) tthis = type->invariantOf(); + if (i == 3) tthis = type->sharedOf(); + if (i == 4) tthis = type->sharedConstOf(); + if (i == 5) break; + FuncDeclaration *f = NULL; - // check identity opEquals exists - FuncDeclaration *fd = eq->isFuncDeclaration(); - if (fd) - { fd = fd->overloadResolve(loc, e, arguments, 1); - if (fd && !(fd->storage_class & STCdisable)) - return fd; + unsigned errors = global.startGagging(); // Do not report errors, even if the + unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. + global.speculativeGag = global.gag; + sc = sc->push(); + sc->speculative = true; + + for (size_t j = 0; j < 2; j++) + { + (*a)[0] = (j == 0 ? er : el); + (*a)[0]->type = tthis; + f = resolveFuncCall(loc, sc, eq, NULL, tthis, a, 1); + if (f) + break; } - TemplateDeclaration *td = eq->isTemplateDeclaration(); - if (td) - { fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1); - if (fd && !(fd->storage_class & STCdisable)) - return fd; - } + sc = sc->pop(); + global.speculativeGag = oldspec; + global.endGagging(errors); + + if (f) + return f; } - return NULL; } + return NULL; +} - if (!needOpEquals()) - return NULL; +/****************************************** + * Build opEquals for struct. + * const bool opEquals(const S s) { ... } + * + * By fixing bugzilla 3789, opEquals is changed to be never implicitly generated. + * Now, struct objects comparison s1 == s2 is translated to: + * s1.tupleof == s2.tupleof + * to calculate structural equality. See EqualExp::semantic. + */ - //printf("StructDeclaration::buildOpEquals() %s\n", toChars()); - - Parameters *parameters = new Parameters; - parameters->push(new Parameter(STCin, type, Id::p, NULL)); - TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd); - tf->mod = MODconst; - tf = (TypeFunction *)tf->semantic(loc, sc); - - FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, tf); - - Expression *e = NULL; - /* Do memberwise compare - */ - //printf("\tmemberwise compare\n"); - for (size_t i = 0; i < fields.dim; i++) +FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc) +{ + if (FuncDeclaration *f = hasIdentityOpEquals(sc)) { - Dsymbol *s = fields[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); - if (v->storage_class & STCref) - assert(0); // what should we do with this? - // this.v == s.v; - EqualExp *ec = new EqualExp(TOKequal, loc, - new DotVarExp(loc, new ThisExp(loc), v, 0), - new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0)); - if (e) - e = new AndAndExp(loc, e, ec); - else - e = ec; + hasIdentityEquals = 1; } - if (!e) - e = new IntegerExp(loc, 1, Type::tbool); - fop->fbody = new ReturnStatement(loc, e); - - members->push(fop); - fop->addMember(sc, this, 1); - - sc = sc->push(); - sc->stc = 0; - sc->linkage = LINKd; - - fop->semantic(sc); - - sc->pop(); - - //printf("-StructDeclaration::buildOpEquals() %s\n", toChars()); - - return fop; + return NULL; } /****************************************** * Build __xopEquals for TypeInfo_Struct - * bool __xopEquals(in void* p, in void* q) { ... } + * static bool __xopEquals(ref const S p, ref const S q) + * { + * return p == q; + * } + * + * This is called by TypeInfo.equals(p1, p2). If the struct does not support + * const objects comparison, it will throw "not implemented" Error in runtime. */ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) { - if (!search_function(this, Id::eq)) + if (!needOpEquals()) return NULL; - /* static bool__xopEquals(in void* p, in void* q) { - * return ( *cast(const S*)(p) ).opEquals( *cast(const S*)(q) ); - * } - */ + //printf("StructDeclaration::buildXopEquals() %s\n", toChars()); + Loc declLoc = Loc(); // loc is unnecessary so __xopEquals is never called directly + Loc loc = Loc(); // loc is unnecessary so errors are gagged Parameters *parameters = new Parameters; - parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL)); - parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL)); + parameters->push(new Parameter(STCref | STCconst, type, Id::p, NULL)); + parameters->push(new Parameter(STCref | STCconst, type, Id::q, NULL)); TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd); - tf = (TypeFunction *)tf->semantic(0, sc); + tf = (TypeFunction *)tf->semantic(loc, sc); Identifier *id = Lexer::idPool("__xopEquals"); - FuncDeclaration *fop = new FuncDeclaration(0, 0, id, STCstatic, tf); + FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), id, STCstatic, tf); - Expression *e = new CallExp(0, - new DotIdExp(0, - new PtrExp(0, new CastExp(0, - new IdentifierExp(0, Id::p), type->pointerTo()->constOf())), - Id::eq), - new PtrExp(0, new CastExp(0, - new IdentifierExp(0, Id::q), type->pointerTo()->constOf()))); + Expression *e1 = new IdentifierExp(loc, Id::p); + Expression *e2 = new IdentifierExp(loc, Id::q); + Expression *e = new EqualExp(TOKequal, loc, e1, e2); - fop->fbody = new ReturnStatement(0, e); + fop->fbody = new ReturnStatement(loc, e); size_t index = members->dim; members->push(fop); @@ -472,9 +493,9 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) if (!xerreq) { - Expression *e = new IdentifierExp(0, Id::empty); - e = new DotIdExp(0, e, Id::object); - e = new DotIdExp(0, e, Lexer::idPool("_xopEquals")); + Expression *e = new IdentifierExp(loc, Id::empty); + e = new DotIdExp(loc, e, Id::object); + e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals")); e = e->semantic(sc); Dsymbol *s = getDsymbol(e); FuncDeclaration *fd = s->isFuncDeclaration(); @@ -489,17 +510,17 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) return fop; } - /******************************************* * Build copy constructor for struct. + * void __cpctpr(ref const S s) const [pure nothrow @trusted] + * { + * (*cast(S*)&this) = *cast(S*)s; + * (*cast(S*)&this).postBlit(); + * } + * * Copy constructors are compiler generated only, and are only * callable from the compiler. They are not user accessible. - * A copy constructor is: - * void cpctpr(ref const S s) const - * { - * (*cast(S*)&this) = *cast(S*)s; - * (*cast(S*)&this).postBlit(); - * } + * * This is done so: * - postBlit() never sees uninitialized data * - memcpy can be much more efficient than memberwise copy @@ -508,62 +529,59 @@ FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc) FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc) { - //printf("StructDeclaration::buildCpCtor() %s\n", toChars()); - FuncDeclaration *fcp = NULL; - /* Copy constructor is only necessary if there is a postblit function, * otherwise the code generator will just do a bit copy. */ - if (postblit) + if (!postblit) + return NULL; + + //printf("StructDeclaration::buildCpCtor() %s\n", toChars()); + StorageClass stc = STCsafe | STCnothrow | STCpure; + Loc declLoc = postblit->loc; + Loc loc = Loc(); // internal code should have no loc to prevent coverage + + stc = mergeFuncAttrs(stc, postblit->storage_class); + if (stc & STCsafe) // change to @trusted for unsafe casts + stc = stc & ~STCsafe | STCtrusted; + + Parameters *fparams = new Parameters; + fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL)); + Type *ftype = new TypeFunction(fparams, Type::tvoid, 0, LINKd, stc); + ftype->mod = MODconst; + + FuncDeclaration *fcp = new FuncDeclaration(declLoc, Loc(), Id::cpctor, stc, ftype); + + if (!(stc & STCdisable)) { - //printf("generating cpctor\n"); + // Build *this = p; + Expression *e = new ThisExp(loc); + AssignExp *ea = new AssignExp(loc, + new PtrExp(loc, new CastExp(loc, new AddrExp(loc, e), type->mutableOf()->pointerTo())), + new PtrExp(loc, new CastExp(loc, new AddrExp(loc, new IdentifierExp(loc, Id::p)), type->mutableOf()->pointerTo())) + ); + ea->op = TOKblit; + Statement *s = new ExpStatement(loc, ea); - StorageClass stc = postblit->storage_class & - (STCdisable | STCsafe | STCtrusted | STCsystem | STCpure | STCnothrow); - if (stc & (STCsafe | STCtrusted)) - stc = stc & ~STCsafe | STCtrusted; + // Build postBlit(); + e = new ThisExp(loc); + e = new PtrExp(loc, new CastExp(loc, new AddrExp(loc, e), type->mutableOf()->pointerTo())); + e = new DotVarExp(loc, e, postblit, 0); + e = new CallExp(loc, e); - Parameters *fparams = new Parameters; - fparams->push(new Parameter(STCref, type->constOf(), Id::p, NULL)); - Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd, stc); - ftype->mod = MODconst; - - fcp = new FuncDeclaration(loc, 0, Id::cpctor, stc, ftype); - - if (!(fcp->storage_class & STCdisable)) - { - // Build *this = p; - Expression *e = new ThisExp(0); - AssignExp *ea = new AssignExp(0, - new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())), - new PtrExp(0, new CastExp(0, new AddrExp(0, new IdentifierExp(0, Id::p)), type->mutableOf()->pointerTo())) - ); - ea->op = TOKblit; - Statement *s = new ExpStatement(0, ea); - - // Build postBlit(); - e = new ThisExp(0); - e = new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())); - e = new DotVarExp(0, e, postblit, 0); - e = new CallExp(0, e); - - s = new CompoundStatement(0, s, new ExpStatement(0, e)); - fcp->fbody = s; - } - else - fcp->fbody = new ExpStatement(0, (Expression *)NULL); - - members->push(fcp); - - sc = sc->push(); - sc->stc = 0; - sc->linkage = LINKd; - - fcp->semantic(sc); - - sc->pop(); + s = new CompoundStatement(loc, s, new ExpStatement(loc, e)); + fcp->fbody = s; } + members->push(fcp); + + sc = sc->push(); + sc->stc = 0; + sc->linkage = LINKd; + + fcp->semantic(sc); + + sc->pop(); + return fcp; } @@ -579,14 +597,16 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc) FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) { //printf("StructDeclaration::buildPostBlit() %s\n", toChars()); - Expression *e = NULL; - StorageClass stc = 0; + StorageClass stc = STCsafe | STCnothrow | STCpure; + Loc declLoc = postblits.dim ? postblits[0]->loc : this->loc; + Loc loc = Loc(); // internal code should have no loc to prevent coverage + Expression *e = NULL; for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); @@ -601,8 +621,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) StructDeclaration *sd = ts->sym; if (sd->postblit && dim) { - stc |= sd->postblit->storage_class & STCdisable; - + stc = mergeFuncAttrs(stc, sd->postblit->storage_class); if (stc & STCdisable) { e = NULL; @@ -610,24 +629,24 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) } // this.v - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); + Expression *ex = new ThisExp(loc); + ex = new DotVarExp(loc, ex, v, 0); if (v->type->toBasetype()->ty == Tstruct) { // this.v.postblit() - ex = new DotVarExp(0, ex, sd->postblit, 0); - ex = new CallExp(0, ex); + ex = new DotVarExp(loc, ex, sd->postblit, 0); + ex = new CallExp(loc, ex); } else { // Typeinfo.postblit(cast(void*)&this.v); - Expression *ea = new AddrExp(0, ex); - ea = new CastExp(0, ea, Type::tvoid->pointerTo()); + Expression *ea = new AddrExp(loc, ex); + ea = new CastExp(loc, ea, Type::tvoid->pointerTo()); Expression *et = v->type->getTypeInfo(sc); - et = new DotIdExp(0, et, Id::postblit); + et = new DotIdExp(loc, et, Id::postblit); - ex = new CallExp(0, et, ea); + ex = new CallExp(loc, et, ea); } e = Expression::combine(e, ex); // combine in forward order } @@ -638,8 +657,8 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) */ if (e || (stc & STCdisable)) { //printf("Building __fieldPostBlit()\n"); - PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__fieldPostBlit")); - dd->fbody = new ExpStatement(0, e); + PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Lexer::idPool("__fieldPostBlit")); + dd->fbody = new ExpStatement(loc, e); postblits.shift(dd); members->push(dd); dd->semantic(sc); @@ -655,21 +674,23 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) default: e = NULL; + stc = STCsafe | STCnothrow | STCpure; for (size_t i = 0; i < postblits.dim; i++) - { FuncDeclaration *fd = postblits[i]; - stc |= fd->storage_class & STCdisable; + { + FuncDeclaration *fd = postblits[i]; + stc = mergeFuncAttrs(stc, fd->storage_class); if (stc & STCdisable) { e = NULL; break; } - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, fd, 0); - ex = new CallExp(0, ex); + Expression *ex = new ThisExp(loc); + ex = new DotVarExp(loc, ex, fd, 0); + ex = new CallExp(loc, ex); e = Expression::combine(e, ex); } - PostBlitDeclaration *dd = new PostBlitDeclaration(loc, 0, stc, Lexer::idPool("__aggrPostBlit")); - dd->fbody = new ExpStatement(0, e); + PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Lexer::idPool("__aggrPostBlit")); + dd->fbody = new ExpStatement(loc, e); members->push(dd); dd->semantic(sc); return dd; @@ -689,14 +710,17 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) { //printf("AggregateDeclaration::buildDtor() %s\n", toChars()); - Expression *e = NULL; + StorageClass stc = STCsafe | STCnothrow | STCpure; + Loc declLoc = dtors.dim ? dtors[0]->loc : this->loc; + Loc loc = Loc(); // internal code should have no loc to prevent coverage + Expression *e = NULL; #if DMDV2 for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); @@ -710,27 +734,33 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) { TypeStruct *ts = (TypeStruct *)tv; StructDeclaration *sd = ts->sym; if (sd->dtor && dim) - { Expression *ex; + { + stc = mergeFuncAttrs(stc, sd->dtor->storage_class); + if (stc & STCdisable) + { + e = NULL; + break; + } // this.v - ex = new ThisExp(0); - ex = new DotVarExp(0, ex, v, 0); + Expression *ex = new ThisExp(loc); + ex = new DotVarExp(loc, ex, v, 0); if (v->type->toBasetype()->ty == Tstruct) { // this.v.dtor() - ex = new DotVarExp(0, ex, sd->dtor, 0); - ex = new CallExp(0, ex); + ex = new DotVarExp(loc, ex, sd->dtor, 0); + ex = new CallExp(loc, ex); } else { // Typeinfo.destroy(cast(void*)&this.v); - Expression *ea = new AddrExp(0, ex); - ea = new CastExp(0, ea, Type::tvoid->pointerTo()); + Expression *ea = new AddrExp(loc, ex); + ea = new CastExp(loc, ea, Type::tvoid->pointerTo()); Expression *et = v->type->getTypeInfo(sc); - et = new DotIdExp(0, et, Id::destroy); + et = new DotIdExp(loc, et, Id::destroy); - ex = new CallExp(0, et, ea); + ex = new CallExp(loc, et, ea); } e = Expression::combine(ex, e); // combine in reverse order } @@ -739,10 +769,10 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) /* Build our own "destructor" which executes e */ - if (e) + if (e || (stc & STCdisable)) { //printf("Building __fieldDtor()\n"); - DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__fieldDtor")); - dd->fbody = new ExpStatement(0, e); + DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Lexer::idPool("__fieldDtor")); + dd->fbody = new ExpStatement(loc, e); dtors.shift(dd); members->push(dd); dd->semantic(sc); @@ -759,19 +789,82 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) default: e = NULL; + stc = STCsafe | STCnothrow | STCpure; for (size_t i = 0; i < dtors.dim; i++) - { FuncDeclaration *fd = dtors[i]; - Expression *ex = new ThisExp(0); - ex = new DotVarExp(0, ex, fd, 0); - ex = new CallExp(0, ex); + { + FuncDeclaration *fd = dtors[i]; + stc = mergeFuncAttrs(stc, fd->storage_class); + if (stc & STCdisable) + { + e = NULL; + break; + } + Expression *ex = new ThisExp(loc); + ex = new DotVarExp(loc, ex, fd, 0); + ex = new CallExp(loc, ex); e = Expression::combine(ex, e); } - DtorDeclaration *dd = new DtorDeclaration(loc, 0, Lexer::idPool("__aggrDtor")); - dd->fbody = new ExpStatement(0, e); + DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Lexer::idPool("__aggrDtor")); + dd->fbody = new ExpStatement(loc, e); members->push(dd); dd->semantic(sc); return dd; } } +/****************************************** + * Create inclusive invariant for struct/class by aggregating + * all the invariants in invs[]. + * void __invariant() const [pure nothrow @trusted] + * { + * invs[0](), invs[1](), ...; + * } + */ + +FuncDeclaration *AggregateDeclaration::buildInv(Scope *sc) +{ + StorageClass stc = STCsafe | STCnothrow | STCpure; + Loc declLoc = this->loc; + Loc loc = Loc(); // internal code should have no loc to prevent coverage + + switch (invs.dim) + { + case 0: + return NULL; + + case 1: + // Don't return invs[0] so it has uniquely generated name. + /* fall through */ + + default: + Expression *e = NULL; + StorageClass stcx = 0; + for (size_t i = 0; i < invs.dim; i++) + { + stc = mergeFuncAttrs(stc, invs[i]->storage_class); + if (stc & STCdisable) + { + // What should do? + } + StorageClass stcy = invs[i]->storage_class & (STCshared | STCsynchronized); + if (i == 0) + stcx = stcy; + else if (stcx ^ stcy) + { + #if 1 // currently rejects + error(invs[i]->loc, "mixing invariants with shared/synchronized differene is not supported"); + e = NULL; + break; + #endif + } + e = Expression::combine(e, new CallExp(loc, new VarExp(loc, invs[i]))); + } + InvariantDeclaration *inv; + inv = new InvariantDeclaration(declLoc, Loc(), stc | stcx, Id::classInvariant); + inv->fbody = new ExpStatement(loc, e); + members->push(inv); + inv->semantic(sc); + return inv; + } +} diff --git a/dmd2/cond.c b/dmd2/cond.c index 5846ee6c56..87666ed2fa 100644 --- a/dmd2/cond.c +++ b/dmd2/cond.c @@ -52,7 +52,7 @@ Condition::Condition(Loc loc) /* ============================================================ */ DVCondition::DVCondition(Module *mod, unsigned level, Identifier *ident) - : Condition(0) + : Condition(Loc()) { this->mod = mod; this->level = level; @@ -127,20 +127,83 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident) { static const char* reserved[] = { - "DigitalMars", "X86", "X86_64", - "Windows", "Win32", "Win64", + "DigitalMars", + "GNU", + "LDC", + "SDC", + "Windows", + "Win32", + "Win64", "linux", -#if DMDV2 - /* Although Posix is predefined by D1, disallowing its - * redefinition breaks makefiles and older builds. - */ - "Posix", - "D_NET", -#endif - "OSX", "FreeBSD", + "OSX", + "FreeBSD", "OpenBSD", + "NetBSD", + "DragonFlyBSD", + "BSD", "Solaris", - "LittleEndian", "BigEndian", + "Posix", + "AIX", + "Haiku", + "SkyOS", + "SysV3", + "SysV4", + "Hurd", + "Android", + "Cygwin", + "MinGW", + "X86", + "X86_64", + "ARM", + "ARM_Thumb", + "ARM_SoftFloat", + "ARM_SoftFP", + "ARM_HardFloat", + "AArch64", + "PPC", + "PPC_SoftFloat", + "PPC_HardFloat", + "PPC64", + "IA64", + "MIPS32", + "MIPS64", + "MIPS_O32", + "MIPS_N32", + "MIPS_O64", + "MIPS_N64", + "MIPS_EABI", + "MIPS_SoftFloat", + "MIPS_HardFloat", + "SPARC", + "SPARC_V8Plus", + "SPARC_SoftFloat", + "SPARC_HardFloat", + "SPARC64", + "S390", + "S390X", + "HPPA", + "HPPA64", + "SH", + "SH64", + "Alpha", + "Alpha_SoftFloat", + "Alpha_HardFloat", + "LittleEndian", + "BigEndian", + "D_Coverage", + "D_Ddoc", + "D_InlineAsm_X86", + "D_InlineAsm_X86_64", + "D_LP64", + "D_X32", + "D_HardFloat", + "D_SoftFloat", + "D_PIC", + "D_SIMD", + "D_Version2", + "D_NoBoundsChecks", + "unittest", + "assert", "all", "none", @@ -168,7 +231,7 @@ void VersionCondition::checkPredefined(Loc loc, const char *ident) void VersionCondition::addGlobalIdent(const char *ident) { - checkPredefined(0, ident); + checkPredefined(Loc(), ident); addPredefinedGlobalIdent(ident); } @@ -265,7 +328,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) sc = sc->push(sc->scopesym); sc->sd = s; // s gets any addMember() sc->flags |= SCOPEstaticif; - Expression *e = exp->semantic(sc); + Expression *e = exp->ctfeSemantic(sc); e = resolveProperties(sc, e); sc->pop(); if (!e->type->checkBoolean()) @@ -296,136 +359,7 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) void StaticIfCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - buf->writestring("static if("); + buf->writestring("static if ("); exp->toCBuffer(buf, hgs); buf->writeByte(')'); } - - -/**************************** IftypeCondition *******************************/ - -IftypeCondition::IftypeCondition(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec) - : Condition(loc) -{ - this->targ = targ; - this->id = id; - this->tok = tok; - this->tspec = tspec; -} - -Condition *IftypeCondition::syntaxCopy() -{ - return new IftypeCondition(loc, - targ->syntaxCopy(), - id, - tok, - tspec ? tspec->syntaxCopy() : NULL); -} - -int IftypeCondition::include(Scope *sc, ScopeDsymbol *sd) -{ - //printf("IftypeCondition::include()\n"); - if (inc == 0) - { - if (!sc) - { - error(loc, "iftype conditional cannot be at global scope"); - inc = 2; - return 0; - } - Type *t = targ->trySemantic(loc, sc); - if (t) - targ = t; - else - inc = 2; // condition is false - - if (!t) - { - } - else if (id && tspec) - { - /* Evaluate to TRUE if targ matches tspec. - * If TRUE, declare id as an alias for the specialized type. - */ - - MATCH m; - TemplateTypeParameter tp(loc, id, NULL, NULL); - - TemplateParameters parameters; - parameters.setDim(1); - parameters[0] = &tp; - - Objects dedtypes; - dedtypes.setDim(1); - - m = targ->deduceType(sc, tspec, ¶meters, &dedtypes); - if (m == MATCHnomatch || - (m != MATCHexact && tok == TOKequal)) - inc = 2; - else - { - inc = 1; - Type *tded = (Type *)dedtypes[0]; - if (!tded) - tded = targ; - Dsymbol *s = new AliasDeclaration(loc, id, tded); - s->semantic(sc); - sc->insert(s); - if (sd) - s->addMember(sc, sd, 1); - } - } - else if (id) - { - /* Declare id as an alias for type targ. Evaluate to TRUE - */ - Dsymbol *s = new AliasDeclaration(loc, id, targ); - s->semantic(sc); - sc->insert(s); - if (sd) - s->addMember(sc, sd, 1); - inc = 1; - } - else if (tspec) - { - /* Evaluate to TRUE if targ matches tspec - */ - tspec = tspec->semantic(loc, sc); - //printf("targ = %s\n", targ->toChars()); - //printf("tspec = %s\n", tspec->toChars()); - if (tok == TOKcolon) - { if (targ->implicitConvTo(tspec)) - inc = 1; - else - inc = 2; - } - else /* == */ - { if (targ->equals(tspec)) - inc = 1; - else - inc = 2; - } - } - else - inc = 1; - //printf("inc = %d\n", inc); - } - return (inc == 1); -} - -void IftypeCondition::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("iftype("); - targ->toCBuffer(buf, id, hgs); - if (tspec) - { - if (tok == TOKcolon) - buf->writestring(" : "); - else - buf->writestring(" == "); - tspec->toCBuffer(buf, NULL, hgs); - } - buf->writeByte(')'); -} - - diff --git a/dmd2/cond.h b/dmd2/cond.h index 71400314ef..9b297569dd 100644 --- a/dmd2/cond.h +++ b/dmd2/cond.h @@ -54,7 +54,6 @@ 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); @@ -87,20 +86,4 @@ struct StaticIfCondition : Condition 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/dmd2/constfold.c b/dmd2/constfold.c index 1afc55b963..06f9b302c8 100644 --- a/dmd2/constfold.c +++ b/dmd2/constfold.c @@ -1374,6 +1374,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; e = (*ale->elements)[i]; e->type = type; + e->loc = loc; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; } @@ -1392,6 +1393,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) else { e = (*ale->elements)[i]; e->type = type; + e->loc = loc; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; } @@ -1412,6 +1414,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) if (ex->isBool(TRUE)) { e = (*ae->values)[i]; e->type = type; + e->loc = loc; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; break; diff --git a/dmd2/ctfe.h b/dmd2/ctfe.h index d5d729080a..7dc157c3f5 100644 --- a/dmd2/ctfe.h +++ b/dmd2/ctfe.h @@ -14,6 +14,7 @@ #pragma once #endif /* __DMC__ */ +#include "arraytypes.h" /** Global status of the CTFE engine. Mostly used for performance diagnostics @@ -44,7 +45,7 @@ struct ClassReferenceExp : Expression StructLiteralExp *value; ClassReferenceExp(Loc loc, StructLiteralExp *lit, Type *type); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); - char *toChars(); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); ClassDeclaration *originalClass(); VarDeclaration *getFieldAt(unsigned index); @@ -53,6 +54,16 @@ struct ClassReferenceExp : Expression /// 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); +#if IN_LLVM + llvm::Constant* toConstElem(IRState *irs); +#else + dt_t **toDt(dt_t **pdt); + dt_t **toDtI(dt_t **pdt, int offset); + Symbol* toSymbol(); + dt_t **toInstanceDt(dt_t **pdt); + dt_t **toDt2(dt_t **pdt, ClassDeclaration *cd, Dts *dts); + elem *toElem(IRState *irs); +#endif }; /// Return index of the field, or -1 if not found @@ -201,6 +212,9 @@ TypeAArray *toBuiltinAAType(Type *t); */ Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2); +/// True if type is TypeInfo_Class +bool isTypeInfo_Class(Type *type); + /*********************************************** In-place integer operations ***********************************************/ diff --git a/dmd2/ctfeexpr.c b/dmd2/ctfeexpr.c index d14ddda72f..3ca582d6f7 100644 --- a/dmd2/ctfeexpr.c +++ b/dmd2/ctfeexpr.c @@ -40,9 +40,9 @@ Expression *ClassReferenceExp::interpret(InterState *istate, CtfeGoal goal) return this; } -char *ClassReferenceExp::toChars() +void ClassReferenceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - return value->toChars(); + buf->writestring(value->toChars()); } ClassDeclaration *ClassReferenceExp::originalClass() @@ -306,6 +306,7 @@ Expression *copyLiteral(Expression *e) #endif r->type = e->type; r->ownedByCtfe = true; + r->origin = ((StructLiteralExp*)e)->origin; return r; } else if (e->op == TOKfunction || e->op == TOKdelegate @@ -379,13 +380,13 @@ Expression *paintTypeOntoLiteral(Type *type, Expression *lit) else if (lit->op == TOKarrayliteral) { e = new SliceExp(lit->loc, lit, - new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); + new IntegerExp(Loc(), 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)); + new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit)); } else if (lit->op == TOKassocarrayliteral) { @@ -532,6 +533,16 @@ TypeAArray *toBuiltinAAType(Type *t) #endif } +/************** TypeInfo operations ************************************/ + +// Return true if type is TypeInfo_Class +bool isTypeInfo_Class(Type *type) +{ + return type->ty == Tclass && + (( Type::typeinfo == ((TypeClass*)type)->sym) + || Type::typeinfo->isBaseOf(((TypeClass*)type)->sym, NULL)); +} + /************** Pointer operations ************************************/ // Return true if t is a pointer (not a function pointer) @@ -574,6 +585,8 @@ Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs) *ofs = 0; if (e->op == TOKaddress) e = ((AddrExp *)e)->e1; + if (e->op == TOKsymoff) + *ofs = ((SymOffExp *)e)->offset; if (e->op == TOKdotvar) { Expression *ex = ((DotVarExp *)e)->e1; @@ -607,11 +620,19 @@ Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs) */ bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2) { + // For integers cast to pointers, we regard them as non-comparable + // unless they are identical. (This may be overly strict). + if (agg1->op == TOKint64 && agg2->op == TOKint64 + && agg1->toInteger() == agg2->toInteger()) + return true; + // Note that type painting can occur with VarExp, so we // must compare the variables being pointed to. return agg1 == agg2 || (agg1->op == TOKvar && agg2->op == TOKvar && - ((VarExp *)agg1)->var == ((VarExp *)agg2)->var); + ((VarExp *)agg1)->var == ((VarExp *)agg2)->var) || + (agg1->op == TOKsymoff && agg2->op == TOKsymoff && + ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var); } // return e1 - e2 as an integer, or error if not possible @@ -630,11 +651,16 @@ Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e { 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); + Type *pointee = ((TypePointer *)agg1->type)->next; + dinteger_t sz = pointee->size(); + return new IntegerExp(loc, (ofs1-ofs2)*sz, type); } } + else if (agg1->op == TOKsymoff && agg2->op == TOKsymoff && + ((SymOffExp *)agg1)->var == ((SymOffExp *)agg2)->var) + { + return new IntegerExp(loc, ofs1-ofs2, type); + } error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract " "pointers to two different memory blocks", e1->toChars(), e2->toChars()); @@ -655,21 +681,36 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, if (eptr->op == TOKaddress) eptr = ((AddrExp *)eptr)->e1; Expression *agg1 = getAggregateFromPointer(eptr, &ofs1); - if (agg1->op != TOKstring && agg1->op != TOKarrayliteral) + if (agg1->op == TOKsymoff) + { + if (((SymOffExp *)agg1)->var->type->ty != Tsarray) + { + error(loc, "cannot perform pointer arithmetic on arrays of unknown length at compile time"); + return EXP_CANT_INTERPRET; + } + } + else 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; + sinteger_t indx = ofs1; dinteger_t sz = pointee->size(); - Expression *dollar = ArrayLength(Type::tsize_t, agg1); - assert(dollar != EXP_CANT_INTERPRET); + Expression *dollar; + if (agg1->op == TOKsymoff) + { + dollar = ((TypeSArray *)(((SymOffExp *)agg1)->var->type))->dim; + indx = ofs1/sz; + } + else + { + dollar = ArrayLength(Type::tsize_t, agg1); + assert(dollar != EXP_CANT_INTERPRET); + } dinteger_t len = dollar->toInteger(); - Expression *val = agg1; - TypeArray *tar = (TypeArray *)val->type; - sinteger_t indx = ofs1; if (op == TOKadd || op == TOKaddass || op == TOKplusplus) indx = indx + ofs2/sz; else if (op == TOKmin || op == TOKminass || op == TOKminusminus) @@ -679,17 +720,27 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, 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 %lld inside memory block [0..%lld]", indx, len); return EXP_CANT_INTERPRET; } + if (agg1->op == TOKsymoff) + { + SymOffExp *se = new SymOffExp(loc, ((SymOffExp *)agg1)->var, indx*sz); + se->type = type; + return se; + } + + Expression *val = agg1; + if (val->op != TOKarrayliteral && val->op != TOKstring) + { + error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars()); + return EXP_CANT_INTERPRET; + } + IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t); IndexExp *ie = new IndexExp(loc, val, ofs); ie->type = type; @@ -1408,7 +1459,9 @@ int ctfeIdentity(Loc loc, enum TOK op, Expression *e1, Expression *e2) int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2) { int n; - if (e1->type->isString() && e2->type->isString()) + Type *t1 = e1->type->toBasetype(); + Type *t2 = e2->type->toBasetype(); + if (t1->isString() && t2->isString()) { int cmp = ctfeRawCmp(loc, e1, e2); switch (op) @@ -1431,15 +1484,15 @@ int ctfeCmp(Loc loc, enum TOK op, Expression *e1, Expression *e2) assert(0); } } - else if (e1->type->isreal()) + else if (t1->isreal()) { n = realCmp(op, e1->toReal(), e2->toReal()); } - else if (e1->type->isimaginary()) + else if (t1->isimaginary()) { n = realCmp(op, e1->toImaginary(), e2->toImaginary()); } - else if (e1->type->isunsigned() || e2->type->isunsigned()) + else if (t1->isunsigned() || t2->isunsigned()) { n = intUnsignedCmp(op, e1->toInteger(), e2->toInteger()); } @@ -1598,6 +1651,10 @@ Expression *ctfeCast(Loc loc, Type *type, Type *to, Expression *e) else return new NullExp(loc, to); } + // Allow TypeInfo type painting + if (isTypeInfo_Class(e->type) && e->type->implicitConvTo(to)) + return paintTypeOntoLiteral(to, e); + 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()); @@ -1765,7 +1822,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *changeArrayLiteralLength(Loc loc, TypeArray *arrayType, Expression *oldval, size_t oldlen, size_t newlen) { - Type *elemType = elemType = arrayType->next; + Type *elemType = arrayType->next; assert(elemType); Expression *defaultElem = elemType->defaultInitLiteral(loc); Expressions *elements = new Expressions(); @@ -1895,8 +1952,9 @@ bool isCtfeValueValid(Expression *newval) { if (((SymOffExp *)newval)->var->isFuncDeclaration()) return true; + if (((SymOffExp *)newval)->var->isDataseg()) + return true; // pointer to static variable } - if (newval->op == TOKint64 || newval->op == TOKfloat64 || newval->op == TOKchar || newval->op == TOKcomplex80) return true; diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 5ee94b48ca..a266be82d2 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -24,12 +24,14 @@ #include "expression.h" #include "statement.h" #include "hdrgen.h" +#include "ctfe.h" +#include "target.h" AggregateDeclaration *isAggregate(Type *t); // from opover.c void checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad) { - if (!ad->isnested) + if (!ad->isNested()) return; Dsymbol *s = sc->func; @@ -82,6 +84,7 @@ Declaration::Declaration(Identifier *id) linkage = LINKdefault; inuse = 0; sem = SemanticStart; + mangleOverride = NULL; } void Declaration::semantic(Scope *sc) @@ -137,18 +140,20 @@ int Declaration::checkModify(Loc loc, Scope *sc, Type *t, Expression *e1, int fl if (v && v->canassign) return 2; - if ((sc->flags & SCOPEcontract) && isParameter()) + if (isParameter() || isResult()) { - if (!flag) error(loc, "cannot modify parameter '%s' in contract", toChars()); - return 0; - } - if ((sc->flags & SCOPEcontract) && isResult()) - { - if (!flag) error(loc, "cannot modify result '%s' in contract", toChars()); - return 0; + for (Scope *scx = sc; scx; scx = scx->enclosing) + { + if (scx->func == parent && (scx->flags & SCOPEcontract)) + { + const char *s = isParameter() && parent->ident != Id::ensure ? "parameter" : "result"; + if (!flag) error(loc, "cannot modify %s '%s' in contract", s, toChars()); + return 0; + } + } } - if (v && isCtorinit()) + if (v && (isCtorinit() || isField())) { // It's only modifiable if inside the right constructor if ((storage_class & (STCforeach | STCref)) == (STCforeach | STCref)) return 2; @@ -242,7 +247,7 @@ Type *TupleDeclaration::getType() tupletype = new TypeTuple(args); if (hasdeco) - return tupletype->semantic(0, NULL); + return tupletype->semantic(Loc(), NULL); } return tupletype; @@ -387,7 +392,7 @@ void TypedefDeclaration::semantic2(Scope *sc) Initializer *savedinit = init; int errors = global.errors; init = init->semantic(sc, basetype, INITinterpret); - if (errors != global.errors) + if (errors != global.errors || init->isErrorInitializer()) { init = savedinit; return; @@ -441,7 +446,6 @@ AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) this->haliassym = NULL; this->overnext = NULL; this->inSemantic = 0; - this->importprot = PROTundefined; assert(type); } @@ -535,6 +539,12 @@ void AliasDeclaration::semantic(Scope *sc) * try to alias y to 3. */ s = type->toDsymbol(sc); + if (s && s == this) + { + error("cannot resolve"); + s = NULL; + type = Type::terror; + } if (s #if DMDV2 && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) @@ -576,7 +586,7 @@ void AliasDeclaration::semantic(Scope *sc) //printf("\talias resolved to type %s\n", type->toChars()); } if (overnext) - ScopeDsymbol::multiplyDefined(0, overnext, this); + ScopeDsymbol::multiplyDefined(Loc(), overnext, this); this->inSemantic = 0; if (global.gag && errors != global.errors) @@ -601,11 +611,8 @@ void AliasDeclaration::semantic(Scope *sc) if (overnext) { FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); -#if IN_LLVM - fa->importprot = importprot; -#endif if (!fa->overloadInsert(overnext)) - ScopeDsymbol::multiplyDefined(0, overnext, f); + ScopeDsymbol::multiplyDefined(Loc(), overnext, f); overnext = NULL; s = fa; s->parent = sc->parent; @@ -623,7 +630,7 @@ void AliasDeclaration::semantic(Scope *sc) } } if (overnext) - ScopeDsymbol::multiplyDefined(0, overnext, this); + ScopeDsymbol::multiplyDefined(Loc(), overnext, this); if (s == this) { assert(global.errors); @@ -701,9 +708,9 @@ Dsymbol *AliasDeclaration::toAlias() } else if (aliassym || type->deco) ; // semantic is already done. - else if (import) + else if (import && import->scope) { - /* If this is an internal alias for selective import, + /* If this is an internal alias for selective/renamed import, * resolve it under the correct scope. */ import->semantic(NULL); @@ -851,8 +858,10 @@ void VarDeclaration::semantic(Scope *sc) // return; // sem = SemanticIn; + Scope *scx = NULL; if (scope) { sc = scope; + scx = sc; scope = NULL; } @@ -874,6 +883,11 @@ void VarDeclaration::semantic(Scope *sc) if (!type) { inuse++; + // Infering the type requires running semantic, + // so mark the scope as ctfe if required + if (storage_class & (STCmanifest | STCstatic)) + sc->needctfe++; + //printf("inferring type for %s with init %s\n", toChars(), init->toChars()); ArrayInitializer *ai = init->isArrayInitializer(); if (ai) @@ -895,6 +909,8 @@ void VarDeclaration::semantic(Scope *sc) else type = init->inferType(sc); + if (storage_class & (STCmanifest | STCstatic)) + sc->needctfe--; // type = type->semantic(loc, sc); inuse--; @@ -914,7 +930,9 @@ void VarDeclaration::semantic(Scope *sc) else { if (!originalType) originalType = type->syntaxCopy(); + inuse++; type = type->semantic(loc, sc); + inuse--; } //printf(" semantic type = %s\n", type ? type->toChars() : "null"); @@ -968,6 +986,9 @@ void VarDeclaration::semantic(Scope *sc) FuncDeclaration *fd = parent->isFuncDeclaration(); Type *tb = type->toBasetype(); + Type *tbn = tb; + while (tbn->ty == Tsarray) + tbn = tbn->nextOf()->toBasetype(); if (tb->ty == Tvoid && !(storage_class & STClazy)) { if (inferred) @@ -1004,7 +1025,7 @@ void VarDeclaration::semantic(Scope *sc) size_t nelems = Parameter::dim(tt->arguments); Objects *exps = new Objects(); exps->setDim(nelems); - Expression *ie = init ? init->toExpression() : NULL; + Expression *ie = (init && !init->isVoidInitializer()) ? init->toExpression() : NULL; if (ie) ie = ie->semantic(sc); if (nelems > 0 && ie) @@ -1040,6 +1061,7 @@ void VarDeclaration::semantic(Scope *sc) iexps->remove(pos); iexps->insert(pos, te->exps); + (*iexps)[pos] = Expression::combine(te->e0, (*iexps)[pos]); goto Lexpand1; } else if (isAliasThisTuple(e)) @@ -1095,11 +1117,13 @@ void VarDeclaration::semantic(Scope *sc) Lnomatch: if (ie && ie->op == TOKtuple) - { size_t tedim = ((TupleExp *)ie)->exps->dim; + { + TupleExp *te = (TupleExp *)ie; + size_t tedim = te->exps->dim; if (tedim != nelems) { ::error(loc, "tuple of %d elements cannot be assigned to tuple of %d elements", (int)tedim, (int)nelems); for (size_t u = tedim; u < nelems; u++) // fill dummy expression - ((TupleExp *)ie)->exps->push(new ErrorExp()); + te->exps->push(new ErrorExp()); } } @@ -1114,7 +1138,11 @@ Lnomatch: Expression *einit = ie; if (ie && ie->op == TOKtuple) - { einit = (*((TupleExp *)ie)->exps)[i]; + { + TupleExp *te = (TupleExp *)ie; + einit = (*te->exps)[i]; + if (i == 0) + einit = Expression::combine(te->e0, einit); } Initializer *ti = init; if (einit) @@ -1164,7 +1192,10 @@ Lnomatch: else if (type->isWild()) storage_class |= STCwild; - if (isSynchronized()) + if (storage_class & (STCmanifest | STCstatic | STCgshared)) + { + } + else if (isSynchronized()) { error("variable %s cannot be synchronized", toChars()); } @@ -1189,11 +1220,21 @@ Lnomatch: AggregateDeclaration *aad = parent->isAggregateDeclaration(); if (aad) { -#if DMDV2 +#if PULL93 assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); - + if (storage_class & (STCconst | STCimmutable) && init && + global.params.vfield) + { + const char *p = loc.toChars(); + const char *s = (storage_class & STCimmutable) ? "immutable" : "const"; + fprintf(stderr, "%s: %s.%s is %s field\n", p ? p : "", ad->toPrettyChars(), toChars(), s); + } +#else if (storage_class & (STCconst | STCimmutable) && init) { + StorageClass stc = storage_class & (STCconst | STCimmutable); + warning(loc, "%s field with initializer should be static, __gshared, or an enum", + StorageClassDeclaration::stcToChars(NULL, stc)); if (!tb->isTypeBasic()) storage_class |= STCstatic; } @@ -1202,8 +1243,8 @@ Lnomatch: { storage_class |= STCfield; #if DMDV2 - if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor || - tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor) + if (tbn->ty == Tstruct && ((TypeStruct *)tbn)->sym->noDefaultCtor || + tbn->ty == Tclass && ((TypeClass *)tbn)->sym->noDefaultCtor) aad->noDefaultCtor = TRUE; #endif } @@ -1266,11 +1307,11 @@ Lnomatch: } } - if (!(storage_class & (STCctfe | STCref)) && tb->ty == Tstruct && - ((TypeStruct *)tb)->sym->noDefaultCtor) + if (!(storage_class & (STCctfe | STCref)) && tbn->ty == Tstruct && + ((TypeStruct *)tbn)->sym->noDefaultCtor) { if (!init) - { if (storage_class & STCfield) + { if (isField()) /* For fields, we'll check the constructor later to make sure it is initialized */ storage_class |= STCnodefaultctor; @@ -1307,7 +1348,7 @@ Lnomatch: error("manifest constants must have initializers"); enum TOK op = TOKconstruct; - if (!init && !sc->inunion && !isStatic() && fd && + if (!init && !sc->inunion && !(storage_class & (STCstatic | STCgshared | STCextern)) && fd && (!(storage_class & (STCfield | STCin | STCforeach | STCparameter | STCresult)) || (storage_class & STCout)) && type->size() != 0) @@ -1451,7 +1492,7 @@ Lnomatch: if (t->ty != Tsarray) break; dim *= ((TypeSArray *)t)->dim->toInteger(); - e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); + e1->type = new TypeSArray(t->nextOf(), new IntegerExp(Loc(), dim, Type::tindex)); } } e1 = new SliceExp(loc, e1, NULL, NULL); @@ -1478,7 +1519,7 @@ Lnomatch: /* Look for form of constructor call which is: * *__ctmp.ctor(arguments...) */ - if (1) + if ((*pinit)->type->implicitConvTo(t)) { CallExp *ce = (CallExp *)(*pinit); if (ce->e1->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)ce->e1; @@ -1586,6 +1627,11 @@ Lnomatch: init = init->semantic(sc, type, INITinterpret); } } + else if (parent->isAggregateDeclaration()) + { + scope = scx ? scx : new Scope(*sc); + scope->setNoFree(); + } else if (storage_class & (STCconst | STCimmutable | STCmanifest) || type->isConst() || type->isImmutable()) { @@ -1597,16 +1643,18 @@ Lnomatch: if (!global.errors && !inferred) { - unsigned errors = global.startGagging(); - Expression *exp; - Initializer *i2 = init; + unsigned errors = global.errors; inuse++; +#if DMDV2 if (ei) { + Expression *exp; exp = ei->exp->syntaxCopy(); - exp = exp->semantic(sc); + if (isDataseg() || (storage_class & STCmanifest)) + exp = exp->ctfeSemantic(sc); + else + exp = exp->semantic(sc); exp = resolveProperties(sc, exp); -#if DMDV2 Type *tb = type->toBasetype(); Type *ti = exp->type->toBasetype(); @@ -1648,77 +1696,22 @@ Lnomatch: ; } } - - // Look for implicit constructor call - if (tb->ty == Tstruct && - !(ti->ty == Tstruct && tb->toDsymbol(sc) == ti->toDsymbol(sc)) && - !exp->implicitConvTo(type)) - { - StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->ctor) - { // Look for constructor first - // Rewrite as e1.ctor(arguments) - Expression *e; - e = new StructLiteralExp(loc, sd, NULL, NULL); - e = new DotIdExp(loc, e, Id::ctor); - e = new CallExp(loc, e, exp); - e = e->semantic(sc); - exp = e->ctfeInterpret(); - } - } + ei->exp = exp; + } #endif - exp = exp->implicitCastTo(sc, type); - } - else if (si || ai) - { i2 = init->syntaxCopy(); - i2 = i2->semantic(sc, type, INITinterpret); - } + init = init->semantic(sc, type, INITinterpret); inuse--; - if (global.endGagging(errors)) // if errors happened + if (global.errors > errors) { -#if DMDV2 - /* Save scope for later use, to try again - */ - scope = new Scope(*sc); - scope->setNoFree(); -#endif + init = new ErrorInitializer(); + type = Type::terror; } - else if (ei) - { - if (isDataseg() || (storage_class & STCmanifest)) - exp = exp->ctfeInterpret(); - else - exp = exp->optimize(WANTvalue); - switch (exp->op) - { - case TOKint64: - case TOKfloat64: - case TOKstring: - case TOKarrayliteral: - case TOKassocarrayliteral: - case TOKstructliteral: - case TOKnull: - ei->exp = exp; // no errors, keep result - break; - - default: -#if DMDV2 - /* Save scope for later use, to try again - */ - scope = new Scope(*sc); - scope->setNoFree(); -#endif - break; - } - } - else - init = i2; // no errors, keep result } - } - else if (parent->isAggregateDeclaration()) - { - scope = new Scope(*sc); - scope->setNoFree(); + else + { + scope = scx ? scx : new Scope(*sc); + scope->setNoFree(); + } } sc = sc->pop(); } @@ -1738,6 +1731,9 @@ Ldtor: } sem = SemanticDone; + + if (type->toBasetype()->ty == Terror) + errors = true; } void VarDeclaration::semantic2(Scope *sc) @@ -1781,6 +1777,55 @@ void VarDeclaration::semantic2(Scope *sc) init = init->semantic(sc, type, INITinterpret); inuse--; } + if (storage_class & STCmanifest) + { + #if 0 + if ((type->ty == Tclass)&&type->isMutable()) + { + error("is mutable. Only const and immutable class enum are allowed, not %s", type->toChars()); + } + else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable()) + { + ExpInitializer *ei = init->isExpInitializer(); + if (ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral) + { + error("is a pointer to mutable struct. Only pointers to const or immutable struct enum are allowed, not %s", type->toChars()); + } + } + #else + if (type->ty == Tclass && init) + { + ExpInitializer *ei = init->isExpInitializer(); + if (ei->exp->op == TOKclassreference) + error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); + } + else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct) + { + ExpInitializer *ei = init->isExpInitializer(); + if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral) + { + error(": Unable to initialize enum with class or pointer to struct. Use static const variable instead."); + } + } + #endif + } + else if (init && isThreadlocal()) + { + if ((type->ty == Tclass)&&type->isMutable()&&!type->isShared()) + { + ExpInitializer *ei = init->isExpInitializer(); + if (ei->exp->op == TOKclassreference) + error("is mutable. Only const or immutable class thread local variable are allowed, not %s", type->toChars()); + } + else if (type->ty == Tpointer && type->nextOf()->ty == Tstruct && type->nextOf()->isMutable() &&!type->nextOf()->isShared()) + { + ExpInitializer *ei = init->isExpInitializer(); + if (ei && ei->exp->op == TOKaddress && ((AddrExp *)ei->exp)->e1->op == TOKstructliteral) + { + error("is a pointer to mutable struct. Only pointers to const, immutable or shared struct thread local variable are allowed are allowed, not %s", type->toChars()); + } + } + } sem = Semantic2Done; } @@ -1803,7 +1848,7 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, return; } - if (!(storage_class & STCfield)) + if (!isField()) return; assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls))); @@ -1824,32 +1869,9 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, { // References are the size of a pointer t = Type::tvoidptr; } - if (t->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)t; -#if DMDV2 - if (ts->sym == ad) - { - ad->error("cannot have field %s with same struct type", toChars()); - } -#endif - - if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope) - ts->sym->semantic(NULL); - if (ts->sym->sizeok != SIZEOKdone) - { - ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced - return; - } - } - if (t->ty == Tident) + if (t->ty == Tstruct || t->ty == Tsarray) { - ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced - return; - } -#if DMDV2 - else if (t->ty == Tsarray) - { - Type *tv = t->toBasetype(); + Type *tv = t; while (tv->ty == Tsarray) { tv = tv->nextOf()->toBasetype(); @@ -1857,17 +1879,29 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, if (tv->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tv; - if (ad == ts->sym) + if (ts->sym == ad) { - ad->error("cannot have field %s with same struct type", toChars()); + const char *s = (t->ty == Tsarray) ? "static array of " : ""; + ad->error("cannot have field %s with %ssame struct type", toChars(), s); + } + if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope) + ts->sym->semantic(NULL); + if (ts->sym->sizeok != SIZEOKdone) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced return; } } } -#endif + if (t->ty == Tident) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced + return; + } + unsigned memsize = t->size(loc); // size of member - unsigned memalignsize = t->alignsize(); // size of member for alignment purposes + unsigned memalignsize = Target::fieldalign(t); // size of member for alignment purposes offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment, &ad->structsize, &ad->alignsize, isunion); @@ -1936,9 +1970,10 @@ AggregateDeclaration *VarDeclaration::isThis() if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))) { +#if !PULL93 if ((storage_class & (STCconst | STCimmutable | STCwild)) && init) return NULL; - +#endif for (Dsymbol *s = this; s; s = s->parent) { ad = s->isMember(); @@ -1953,7 +1988,12 @@ AggregateDeclaration *VarDeclaration::isThis() int VarDeclaration::needThis() { //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); - return storage_class & STCfield; + return isField(); +} + +int VarDeclaration::isExport() +{ + return protection == PROTexport; } int VarDeclaration::isImportedSymbol() @@ -1967,7 +2007,7 @@ int VarDeclaration::isImportedSymbol() void VarDeclaration::checkCtorConstInit() { #if 0 /* doesn't work if more than one static ctor */ - if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) + if (ctorinit == 0 && isCtorinit() && !isField()) error("missing initializer in static constructor for const variable"); #endif } @@ -2021,6 +2061,16 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration()) { fld->tok = TOKdelegate; + + /* This is necessary to avoid breaking tests for 8751 & 8793. + * See: compilable/testInference.d + */ + if (type->isMutable() || // mutable variable + !type->implicitConvTo(type->invariantOf()) || // has any mutable indirections + !fdv->isPureBypassingInference()) // does not belong to pure function + { + fld->setImpure(); // Bugzilla 9415 + } } } @@ -2072,21 +2122,30 @@ ExpInitializer *VarDeclaration::getExpInitializer() * Otherwise, return NULL. */ -Expression *VarDeclaration::getConstInitializer() +Expression *VarDeclaration::getConstInitializer(bool needFullType) { - if ((isConst() || isImmutable() || storage_class & STCmanifest) && - storage_class & STCinit) + assert(type && init); + + // Ungag errors when not speculative + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging()) { - ExpInitializer *ei = getExpInitializer(); - if (ei) - return ei->exp; - else if (init) - { - return init->toExpression(); - } + Dsymbol *sym = toParent()->isAggregateDeclaration(); + if (sym && !sym->isSpeculative()) + global.gag = 0; } - return NULL; + if (scope) + { + inuse++; + init->semantic(scope, type, INITinterpret); + scope = NULL; + inuse--; + } + Expression *e = init->toExpression(needFullType ? type : NULL); + + global.gag = oldgag; + return e; } /************************************* @@ -2102,7 +2161,7 @@ int VarDeclaration::canTakeAddressOf() */ if ((isConst() || isImmutable()) && storage_class & STCinit && - (!(storage_class & (STCstatic | STCextern)) || (storage_class & STCfield)) && + (!(storage_class & (STCstatic | STCextern)) || isField()) && (!parent || toParent()->isModule() || toParent()->isTemplateInstance()) && type->toBasetype()->isTypeBasic() ) @@ -2287,15 +2346,24 @@ Expression *VarDeclaration::callScopeDtor(Scope *sc) void ObjectNotFound(Identifier *id) { - Type::error(0, "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars()); + Type::error(Loc(), "%s not found. object.d may be incorrectly installed or corrupt.", id->toChars()); fatal(); } +/********************************* ClassInfoDeclaration ****************************/ + +SymbolDeclaration::SymbolDeclaration(Loc loc, StructDeclaration *dsym) + : Declaration(dsym->ident) +{ + this->loc = loc; + this->dsym = dsym; + storage_class |= STCconst; +} /********************************* ClassInfoDeclaration ****************************/ ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) - : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) + : VarDeclaration(Loc(), ClassDeclaration::classinfo->type, cd->ident, NULL) { this->cd = cd; storage_class = STCstatic | STCgshared; @@ -2314,7 +2382,7 @@ void ClassInfoDeclaration::semantic(Scope *sc) /********************************* ModuleInfoDeclaration ****************************/ ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) - : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) + : VarDeclaration(Loc(), Module::moduleinfo->type, mod->ident, NULL) { this->mod = mod; storage_class = STCstatic | STCgshared; @@ -2333,7 +2401,7 @@ void ModuleInfoDeclaration::semantic(Scope *sc) /********************************* TypeInfoDeclaration ****************************/ TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) - : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) + : VarDeclaration(Loc(), Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) { this->tinfo = tinfo; storage_class = STCstatic | STCgshared; @@ -2583,13 +2651,3 @@ Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) assert(0); // should never be produced by syntax return NULL; } - -/********************** StaticStructInitDeclaration ***************************/ - -StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) - : Declaration(new Identifier("", TOKidentifier)) -{ - this->loc = loc; - this->dsym = dsym; - storage_class |= STCconst; -} diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 1c46405089..27211c5afa 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -110,10 +110,6 @@ enum PURE; STCmanifest | STCimmutable | STCshared | STCnothrow | STCpure | STCref | STCtls | \ STCgshared | STCproperty | STCsafe | STCtrusted | STCsystem | STCdisable) -#ifdef BUG6652 -#define STCbug6652 0x800000000000LL // -#endif - struct Match { int count; // number of matches found @@ -124,11 +120,13 @@ struct Match }; void overloadResolveX(Match *m, FuncDeclaration *f, - Expression *ethis, Expressions *arguments); + Type *tthis, Expressions *arguments); int overloadApply(FuncDeclaration *fstart, int (*fp)(void *, FuncDeclaration *), void *param); +void ObjectNotFound(Identifier *id); + enum Semantic { SemanticStart, // semantic has not been run @@ -147,11 +145,7 @@ struct Declaration : Dsymbol enum PROT protection; enum LINK linkage; int inuse; // used to detect cycles - -#ifdef IN_GCC - Expressions *attributes; // GCC decl/type attributes -#endif - + const char *mangleOverride; // overridden symbol with pragma(mangle, "...") enum Semantic sem; Declaration(Identifier *id); @@ -164,32 +158,33 @@ struct Declaration : Dsymbol void emitComment(Scope *sc); void toJson(JsonOut *json); - void jsonProperties(JsonOut *json); + virtual void jsonProperties(JsonOut *json); void toDocBuffer(OutBuffer *buf, Scope *sc); - char *mangle(bool isv = false); - int isStatic() { return storage_class & STCstatic; } + const char *mangle(bool isv = false); + bool isStatic() { return (storage_class & STCstatic) != 0; } virtual int isDelete(); virtual int isDataseg(); virtual int isThreadlocal(); virtual int isCodeseg(); - int isCtorinit() { return storage_class & STCctorinit; } - int isFinal() { return storage_class & STCfinal; } - int isAbstract() { return storage_class & STCabstract; } - int isConst() { return storage_class & STCconst; } - int isImmutable() { return storage_class & STCimmutable; } - int isWild() { return storage_class & STCwild; } - int isAuto() { return storage_class & STCauto; } - int isScope() { return storage_class & STCscope; } - int isSynchronized() { return storage_class & STCsynchronized; } - int isParameter() { return storage_class & STCparameter; } - int isDeprecated() { return storage_class & STCdeprecated; } - int isOverride() { return storage_class & STCoverride; } - StorageClass isResult() { return storage_class & STCresult; } + bool isCtorinit() { return (storage_class & STCctorinit) != 0; } + bool isFinal() { return (storage_class & STCfinal) != 0; } + bool isAbstract() { return (storage_class & STCabstract) != 0; } + bool isConst() { return (storage_class & STCconst) != 0; } + bool isImmutable() { return (storage_class & STCimmutable) != 0; } + bool isWild() { return (storage_class & STCwild) != 0; } + bool isAuto() { return (storage_class & STCauto) != 0; } + bool isScope() { return (storage_class & STCscope) != 0; } + bool isSynchronized() { return (storage_class & STCsynchronized) != 0; } + bool isParameter() { return (storage_class & STCparameter) != 0; } + bool isDeprecated() { return (storage_class & STCdeprecated) != 0; } + bool isOverride() { return (storage_class & STCoverride) != 0; } + bool isResult() { return (storage_class & STCresult) != 0; } + bool isField() { return (storage_class & STCfield) != 0; } - int isIn() { return storage_class & STCin; } - int isOut() { return storage_class & STCout; } - int isRef() { return storage_class & STCref; } + bool isIn() { return (storage_class & STCin) != 0; } + bool isOut() { return (storage_class & STCout) != 0; } + bool isRef() { return (storage_class & STCref) != 0; } enum PROT prot(); @@ -236,7 +231,7 @@ struct TypedefDeclaration : Declaration Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); void semantic2(Scope *sc); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); const char *kind(); Type *getType(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -273,7 +268,6 @@ struct AliasDeclaration : Declaration Dsymbol *overnext; // next in overload list Dsymbol *import; // !=NULL if unresolved internal alias for selective import int inSemantic; - PROT importprot; // if generated by import, store its protection AliasDeclaration(Loc loc, Identifier *ident, Type *type); AliasDeclaration(Loc loc, Identifier *ident, Dsymbol *s); @@ -341,6 +335,7 @@ struct VarDeclaration : Declaration Initializer *hinit; AggregateDeclaration *isThis(); int needThis(); + int isExport(); int isImportedSymbol(); int isDataseg(); int isThreadlocal(); @@ -352,17 +347,16 @@ struct VarDeclaration : Declaration #endif Expression *callScopeDtor(Scope *sc); ExpInitializer *getExpInitializer(); - Expression *getConstInitializer(); + Expression *getConstInitializer(bool needFullType = true); void checkCtorConstInit(); void checkNestedReference(Scope *sc, Loc loc); Dsymbol *toAlias(); - #if IN_DMD void toObjFile(int multiobj); // compile to .obj file Symbol *toSymbol(); int cvMember(unsigned char *p); #endif - + const char *mangle(bool isv = false); // Eliminate need for dynamic_cast VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } @@ -390,20 +384,20 @@ struct VarDeclaration : Declaration /**************************************************************/ -// LDC uses this to denote static struct initializers +// This is a shell around a back end symbol -struct StaticStructInitDeclaration : Declaration +struct SymbolDeclaration : Declaration { StructDeclaration *dsym; - StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym); + SymbolDeclaration(Loc loc, StructDeclaration *dsym); #if IN_DMD Symbol *toSymbol(); #endif // Eliminate need for dynamic_cast - StaticStructInitDeclaration *isStaticStructInitDeclaration() { return (StaticStructInitDeclaration *)this; } + SymbolDeclaration *isSymbolDeclaration() { return (SymbolDeclaration *)this; } }; struct ClassInfoDeclaration : VarDeclaration @@ -785,6 +779,7 @@ struct FuncDeclaration : Declaration #else bool isArrayOp; // !=0 if array operation #endif + FuncDeclaration *dArrayOp; // D version of array op for ctfe enum PASS semanticRun; int semantic3Errors; // !=0 if errors in semantic3 // this function's frame ptr @@ -852,7 +847,7 @@ struct FuncDeclaration : Declaration int findVtblIndex(Dsymbols *vtbl, int dim); int overloadInsert(Dsymbol *s); FuncDeclaration *overloadExactMatch(Type *t); - FuncDeclaration *overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags = 0); + FuncDeclaration *overloadResolve(Loc loc, Type *tthis, Expressions *arguments, int flags = 0); MATCH leastAsSpecialized(FuncDeclaration *g); LabelDsymbol *searchLabel(Identifier *ident); AggregateDeclaration *isThis(); @@ -860,8 +855,9 @@ struct FuncDeclaration : Declaration int getLevel(Loc loc, Scope *sc, FuncDeclaration *fd); // lexical nesting level difference void appendExp(Expression *e); void appendState(Statement *s); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); const char *toPrettyChars(); + const char *toFullSignature(); // for diagnostics, e.g. 'int foo(int x, int y) pure' int isMain(); int isWinMain(); int isDllMain(); @@ -879,6 +875,8 @@ struct FuncDeclaration : Declaration bool isSafeBypassingInference(); int isTrusted(); bool setUnsafe(); + bool isolateReturn(); + bool parametersIntersect(Type *t); virtual int isNested(); int needThis(); int isVirtualMethod(); @@ -888,7 +886,7 @@ struct FuncDeclaration : Declaration virtual int addPostInvariant(); Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL); void inlineScan(); - int canInline(int hasthis, int hdrscan = false, int statementsToo = true); + int canInline(int hasthis, int hdrscan, int statementsToo); Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps); const char *kind(); void toDocBuffer(OutBuffer *buf, Scope *sc); @@ -953,18 +951,17 @@ struct FuncDeclaration : Declaration }; #if DMDV2 -FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, +FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, Objects *tiargs, - Expression *ethis, + Type *tthis, Expressions *arguments, - int flags); + int flags = 0); #endif struct FuncAliasDeclaration : FuncDeclaration { FuncDeclaration *funcalias; int hasOverloads; - PROT importprot; // if generated by import, store its protection FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1); @@ -973,7 +970,7 @@ struct FuncAliasDeclaration : FuncDeclaration #if IN_DMD Symbol *toSymbol(); #endif - char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); } + const char *mangle(bool isv = false) { return toAliasFunc()->mangle(isv); } FuncDeclaration *toAliasFunc(); }; @@ -1014,7 +1011,6 @@ struct CtorDeclaration : FuncDeclaration int isVirtual(); int addPreInvariant(); int addPostInvariant(); - bool isImplicit; // implicitly generated ctor CtorDeclaration *isCtorDeclaration() { return this; } }; @@ -1040,7 +1036,7 @@ struct PostBlitDeclaration : FuncDeclaration struct DtorDeclaration : FuncDeclaration { DtorDeclaration(Loc loc, Loc endloc); - DtorDeclaration(Loc loc, Loc endloc, Identifier *id); + DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -1114,7 +1110,7 @@ struct SharedStaticDtorDeclaration : StaticDtorDeclaration struct InvariantDeclaration : FuncDeclaration { - InvariantDeclaration(Loc loc, Loc endloc); + InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id = NULL); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); int isVirtual(); @@ -1128,13 +1124,15 @@ struct InvariantDeclaration : FuncDeclaration struct UnitTestDeclaration : FuncDeclaration { - UnitTestDeclaration(Loc loc, Loc endloc); + char *codedoc; /** For documented unittest. */ + UnitTestDeclaration(Loc loc, Loc endloc, char *codedoc); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); AggregateDeclaration *isThis(); int isVirtual(); int addPreInvariant(); int addPostInvariant(); + void emitComment(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); UnitTestDeclaration *isUnitTestDeclaration() { return this; } diff --git a/dmd2/delegatize.c b/dmd2/delegatize.c index 3c9670f5f7..4fb060aa67 100644 --- a/dmd2/delegatize.c +++ b/dmd2/delegatize.c @@ -19,6 +19,7 @@ #include "declaration.h" #include "aggregate.h" #include "scope.h" +#include "init.h" #if IN_LLVM #include "init.h" @@ -115,41 +116,11 @@ int lambdaCheckForNestedRef(Expression *e, void *param) */ switch (e->op) { -#if IN_LLVM - // We also need to consider the initializers of VarDeclarations in - // DeclarationExps, such as generated for postblit invocation for - // function parameters. - // - // Without this check, e.g. the nested reference to a in the delegate - // create for the lazy argument is not picked up in the following case: - // --- - // struct HasPostblit { this(this) {} } - // struct Foo { HasPostblit _data; } - // void receiver(Foo) {} - // void lazyFunc(E)(lazy E e) { e(); } - // void test() { Foo a; lazyFunc(receiver(a)); } - // --- - case TOKdeclaration: - { DeclarationExp *de = (DeclarationExp *)e; - if (VarDeclaration *vd = de->declaration->isVarDeclaration()) - { - if (vd->init) - { - if (ExpInitializer* ei = vd->init->isExpInitializer()) - { - ei->exp->apply(&lambdaCheckForNestedRef, sc); - } - // TODO: Other classes of initializers? - } - } - break; - } -#endif case TOKsymoff: { SymOffExp *se = (SymOffExp *)e; VarDeclaration *v = se->var->isVarDeclaration(); if (v) - v->checkNestedReference(sc, 0); + v->checkNestedReference(sc, Loc()); break; } @@ -157,7 +128,7 @@ int lambdaCheckForNestedRef(Expression *e, void *param) { VarExp *ve = (VarExp *)e; VarDeclaration *v = ve->var->isVarDeclaration(); if (v) - v->checkNestedReference(sc, 0); + v->checkNestedReference(sc, Loc()); break; } @@ -166,7 +137,31 @@ int lambdaCheckForNestedRef(Expression *e, void *param) { ThisExp *te = (ThisExp *)e; VarDeclaration *v = te->var->isVarDeclaration(); if (v) - v->checkNestedReference(sc, 0); + v->checkNestedReference(sc, Loc()); + break; + } + + case TOKdeclaration: + { DeclarationExp *de = (DeclarationExp *)e; + VarDeclaration *v = de->declaration->isVarDeclaration(); + if (v) + { + v->checkNestedReference(sc, Loc()); + + /* Some expressions cause the frontend to create a temporary. + * For example, structs with cpctors replace the original + * expression e with: + * __cpcttmp = __cpcttmp.cpctor(e); + * + * In this instance, we need to ensure that the original + * expression e does not have any nested references by + * checking the declaration initializer too. + */ + if (v->init && v->init->isExpInitializer()) + { Expression *ie = v->init->toExpression(); + ie->apply (&lambdaCheckForNestedRef, param); + } + } break; } diff --git a/dmd2/doc.c b/dmd2/doc.c index 4ac4bc85a2..edaac79808 100644 --- a/dmd2/doc.c +++ b/dmd2/doc.c @@ -106,9 +106,10 @@ Parameter *isFunctionParameter(Dsymbol *s, unsigned char *p, size_t len); int isIdStart(unsigned char *p); int isIdTail(unsigned char *p); +int isIndentWS(unsigned char *p); int utfStride(unsigned char *p); -static unsigned char ddoc_default[] = "\ +static const char ddoc_default[] = "\ DDOC = \n\ \n\ $(TITLE)\n\ @@ -140,6 +141,7 @@ LINK2 = $+\n\ LPAREN= (\n\ RPAREN= )\n\ DOLLAR= $\n\ +DEPRECATED= $0\n\ \n\ RED = $0\n\ BLUE = $0\n\ @@ -199,11 +201,11 @@ ESCAPES = /isPackage() || s->isModule()) + return false; + + TemplateDeclaration *td; + bool dot; + + // Add parent names first + dot = emitAnchorName(buf, s->parent); + // Eponymous template members can share the parent anchor name + if (s->parent && (td = s->parent->isTemplateDeclaration()) != NULL && + td->onemember == s) + return dot; + if (dot) + buf->writeByte('.'); + // Use "this" not "__ctor" + if (s->isCtorDeclaration() || ((td = s->isTemplateDeclaration()) != NULL && + td->onemember && td->onemember->isCtorDeclaration())) + buf->writestring("this"); + else + { + /* We just want the identifier, not overloads like TemplateDeclaration::toChars. + * We don't want the template parameter list and constraints. */ + buf->writestring(s->Dsymbol::toChars()); + } + return true; +} + +static void emitAnchor(OutBuffer *buf, Dsymbol *s) +{ + buf->writestring("$(DDOC_ANCHOR "); + emitAnchorName(buf, s); + buf->writeByte(')'); +} + /******************************* emitComment **********************************/ +/** Get leading indentation from 'src' which represents lines of code. */ +static size_t getCodeIndent(const char *src) +{ + while (src && *src == '\n') + ++src; // skip until we find the first non-empty line + + size_t codeIndent = 0; + while (src && (*src == ' ' || *src == '\t')) + { + codeIndent++; + src++; + } + return codeIndent; +} + +void emitUnittestComment(Scope *sc, Dsymbol *s, size_t ofs) +{ + OutBuffer *buf = sc->docbuf; + + for (UnitTestDeclaration *utd = s->unittest; utd; utd = utd->unittest) + { + if (utd->protection == PROTprivate || !utd->comment || !utd->fbody) + continue; + + // Strip whitespaces to avoid showing empty summary + unsigned char *c = utd->comment; + while (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r') ++c; + + OutBuffer codebuf; + codebuf.writestring("$(DDOC_EXAMPLES \n"); + size_t o = codebuf.offset; + codebuf.writestring((char *)c); + + if (utd->codedoc) + { + size_t i = getCodeIndent(utd->codedoc); + while (i--) codebuf.writeByte(' '); + codebuf.writestring("----\n"); + codebuf.writestring(utd->codedoc); + codebuf.writestring("----\n"); + highlightText(sc, s, &codebuf, o); + } + + codebuf.writestring(")"); + buf->insert(buf->offset - ofs, codebuf.data, codebuf.offset); + } +} + /* * Emit doc comment to documentation file */ @@ -505,34 +591,12 @@ void Dsymbol::emitDitto(Scope *sc) buf->spread(sc->lastoffset, b.offset); memcpy(buf->data + sc->lastoffset, b.data, b.offset); sc->lastoffset += b.offset; -} -void emitUnittestComment(Scope *sc, Dsymbol *s, UnitTestDeclaration *test) -{ - static char pre[] = "$(D_CODE \n"; - OutBuffer *buf = sc->docbuf; - - buf->writestring("$(DDOC_SECTION "); - buf->writestring("$(B Example:)"); - for (UnitTestDeclaration *utd = test; utd; utd = utd->unittest) - { - if (utd->protection == PROTprivate || !utd->comment || !utd->fbody) - continue; - - OutBuffer codebuf; - const char *body = utd->fbody->toChars(); - if (strlen(body)) - { - codebuf.writestring(pre); - codebuf.writestring(body); - codebuf.writestring(")"); - codebuf.writeByte(0); - highlightCode2(sc, s, &codebuf, 0); - buf->writestring(codebuf.toChars()); - } - } - - buf->writestring(")"); + Dsymbol *s = this; + if (!s->unittest && parent) + s = parent->isTemplateDeclaration(); + if (s) + emitUnittestComment(sc, s, strlen(ddoc_decl_dd_e)); } void ScopeDsymbol::emitMemberComments(Scope *sc) @@ -586,6 +650,7 @@ void emitProtection(OutBuffer *buf, PROT prot) void Dsymbol::emitComment(Scope *sc) { } void InvariantDeclaration::emitComment(Scope *sc) { } +void UnitTestDeclaration::emitComment(Scope *sc) { } #if DMDV2 void PostBlitDeclaration::emitComment(Scope *sc) { } #endif @@ -650,8 +715,10 @@ void AggregateDeclaration::emitComment(Scope *sc) dc->pmacrotable = &sc->module->macrotable; buf->writestring(ddoc_decl_s); - toDocBuffer(buf, sc); - sc->lastoffset = buf->offset; + size_t o = buf->offset; + toDocBuffer(buf, sc); + highlightCode(sc, this, buf, o); + sc->lastoffset = buf->offset; buf->writestring(ddoc_decl_e); buf->writestring(ddoc_decl_dd_s); @@ -747,7 +814,9 @@ void EnumDeclaration::emitComment(Scope *sc) dc->pmacrotable = &sc->module->macrotable; buf->writestring(ddoc_decl_s); + size_t o = buf->offset; toDocBuffer(buf, sc); + highlightCode(sc, this, buf, o); sc->lastoffset = buf->offset; buf->writestring(ddoc_decl_e); @@ -767,7 +836,6 @@ void EnumMember::emitComment(Scope *sc) OutBuffer *buf = sc->docbuf; DocComment *dc = DocComment::parse(sc, this, comment); - size_t o; if (!dc) { @@ -777,7 +845,7 @@ void EnumMember::emitComment(Scope *sc) dc->pmacrotable = &sc->module->macrotable; buf->writestring(ddoc_decl_s); - o = buf->offset; + size_t o = buf->offset; toDocBuffer(buf, sc); highlightCode(sc, this, buf, o); sc->lastoffset = buf->offset; @@ -788,42 +856,6 @@ void EnumMember::emitComment(Scope *sc) buf->writestring(ddoc_decl_dd_e); } -static bool emitAnchorName(OutBuffer *buf, Dsymbol *s) -{ - if (!s || s->isPackage() || s->isModule()) - return false; - - TemplateDeclaration *td; - bool dot; - - // Add parent names first - dot = emitAnchorName(buf, s->parent); - // Eponymous template members can share the parent anchor name - if (s->parent && (td = s->parent->isTemplateDeclaration()) != NULL && - td->onemember == s) - return dot; - if (dot) - buf->writeByte('.'); - // Use "this" not "__ctor" - if (s->isCtorDeclaration() || ((td = s->isTemplateDeclaration()) != NULL && - td->onemember && td->onemember->isCtorDeclaration())) - buf->writestring("this"); - else - { - /* We just want the identifier, not overloads like TemplateDeclaration::toChars. - * We don't want the template parameter list and constraints. */ - buf->writestring(s->Dsymbol::toChars()); - } - return true; -} - -static void emitAnchor(OutBuffer *buf, Dsymbol *s) -{ - buf->writestring("$(DDOC_ANCHOR "); - emitAnchorName(buf, s); - buf->writeByte(')'); -} - /******************************* toDocBuffer **********************************/ void Dsymbol::toDocBuffer(OutBuffer *buf, Scope *sc) @@ -867,6 +899,9 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati //printf("declarationToDocBuffer() %s, originalType = %s, td = %s\n", decl->toChars(), decl->originalType ? decl->originalType->toChars() : "--", td ? td->toChars() : "--"); if (decl->ident) { + if (decl->isDeprecated()) + buf->writestring("$(DEPRECATED "); + prefix(buf, decl); if (decl->type) @@ -883,6 +918,10 @@ void declarationToDocBuffer(Declaration *decl, OutBuffer *buf, TemplateDeclarati } else buf->writestring(decl->ident->toChars()); + + if (decl->isDeprecated()) + buf->writestring(")"); + buf->writestring(";\n"); } } @@ -901,7 +940,7 @@ void AliasDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) buf->writestring("deprecated "); emitProtection(buf, protection); - buf->writestring("alias "); + buf->printf("alias %s = ", toChars()); if (Dsymbol *s = aliassym) // ident alias { @@ -923,8 +962,6 @@ void AliasDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) } } - buf->writestring(" "); - buf->writestring(toChars()); buf->writestring(";\n"); } } @@ -1033,11 +1070,10 @@ void AggregateDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) { if (ident) { - emitAnchor(buf, this); #if 0 emitProtection(buf, protection); #endif - buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); + buf->printf("%s %s", kind(), toChars()); buf->writestring(";\n"); } } @@ -1061,8 +1097,7 @@ void StructDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) } else { - emitAnchor(buf, this); - buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); + buf->printf("%s %s", kind(), toChars()); } buf->writestring(";\n"); } @@ -1087,10 +1122,9 @@ void ClassDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) } else { - emitAnchor(buf, this); if (isAbstract()) buf->writestring("abstract "); - buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); + buf->printf("%s %s", kind(), toChars()); } int any = 0; for (size_t i = 0; i < baseclasses->dim; i++) @@ -1127,8 +1161,7 @@ void EnumDeclaration::toDocBuffer(OutBuffer *buf, Scope *sc) { if (ident) { - emitAnchor(buf, this); - buf->printf("%s $(DDOC_PSYMBOL %s)", kind(), toChars()); + buf->printf("%s %s", kind(), toChars()); buf->writestring(";\n"); } } @@ -1195,6 +1228,7 @@ void DocComment::parseSections(unsigned char *comment) p = comment; while (*p) { + unsigned char *pstart0 = p; p = skipwhitespace(p); pstart = p; pend = p; @@ -1210,6 +1244,11 @@ void DocComment::parseSections(unsigned char *comment) // Check for start/end of a code section if (*p == '-') { + if (!inCode) + { // restore leading indentation + while (pstart0 < pstart && isIndentWS(pstart-1)) --pstart; + } + int numdash = 0; while (*p == '-') { @@ -1298,7 +1337,7 @@ void DocComment::parseSections(unsigned char *comment) void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf) { //printf("DocComment::writeSections()\n"); - if (sections.dim) + if (sections.dim || s->unittest) { buf->writestring("$(DDOC_SECTIONS \n"); for (size_t i = 0; i < sections.dim; i++) @@ -1320,7 +1359,7 @@ void DocComment::writeSections(Scope *sc, Dsymbol *s, OutBuffer *buf) } } if (s->unittest) - emitUnittestComment(sc, s, s->unittest); + emitUnittestComment(sc, s, 0); buf->writestring(")\n"); } else @@ -1911,6 +1950,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) int inCode = 0; //int inComment = 0; // in comment size_t iCodeStart; // start of code section + size_t codeIndent = 0; size_t iLineStart = offset; @@ -2083,6 +2123,30 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) codebuf.write(buf->data + iCodeStart, i - iCodeStart); codebuf.writeByte(0); + + // Remove leading indentations from all lines + bool lineStart = true; + unsigned char *endp = codebuf.data + codebuf.offset; + for (unsigned char *p = codebuf.data; p < endp; ) + { + if (lineStart) + { + size_t j = codeIndent; + unsigned char *q = p; + while (j-- > 0 && q < endp && isIndentWS(q)) + ++q; + codebuf.remove(p - codebuf.data, q - p); + assert(codebuf.data <= p); + assert(p < codebuf.data + codebuf.offset); + lineStart = false; + endp = codebuf.data + codebuf.offset; // update + continue; + } + if (*p == '\n') + lineStart = true; + ++p; + } + highlightCode2(sc, s, &codebuf, 0); buf->remove(iCodeStart, i - iCodeStart); i = buf->insert(iCodeStart, codebuf.data, codebuf.offset); @@ -2093,6 +2157,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) { static char pre[] = "$(D_CODE \n"; inCode = 1; + codeIndent = istart - iLineStart; // save indent count i = buf->insert(i, pre, sizeof(pre) - 1); iCodeStart = i; i--; // place i on > @@ -2238,6 +2303,9 @@ void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, size_t offset) unsigned char *lastp = buf->data; const char *highlight; + if (s->isModule() && ((Module *)s)->isDocFile) + sid = ""; + //printf("highlightCode2('%.*s')\n", buf->offset - 1, buf->data); res.reserve(buf->offset); while (1) @@ -2362,6 +2430,15 @@ int isIdTail(unsigned char *p) return 0; } +/**************************************** + * Determine if p points to the indentation space. + */ + +int isIndentWS(unsigned char *p) +{ + return (*p == ' ') || (*p == '\t'); +} + /***************************************** * Return number of bytes in UTF character. */ diff --git a/dmd2/dsymbol.c b/dmd2/dsymbol.c index f7c85a345e..20da3e69ae 100644 --- a/dmd2/dsymbol.c +++ b/dmd2/dsymbol.c @@ -37,22 +37,24 @@ #include "../gen/pragma.h" #endif +const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"}; + /****************************** Dsymbol ******************************/ Dsymbol::Dsymbol() { //printf("Dsymbol::Dsymbol(%p)\n", this); this->ident = NULL; - this->c_ident = NULL; this->parent = NULL; #if IN_DMD this->csym = NULL; this->isym = NULL; #endif - this->loc = 0; + this->loc = Loc(); this->comment = NULL; this->scope = NULL; this->errors = false; + this->depmsg = NULL; this->userAttributes = NULL; this->unittest = NULL; #if IN_LLVM @@ -64,13 +66,12 @@ Dsymbol::Dsymbol(Identifier *ident) { //printf("Dsymbol::Dsymbol(%p, ident)\n", this); this->ident = ident; - this->c_ident = NULL; this->parent = NULL; #if IN_DMD this->csym = NULL; this->isym = NULL; #endif - this->loc = 0; + this->loc = Loc(); this->comment = NULL; this->scope = NULL; this->errors = false; @@ -414,7 +415,7 @@ void *symbol_search_fp(void *arg, const char *seed) Dsymbol *s = (Dsymbol *)arg; Module::clearCache(); - return s->search(0, id, 4|2); + return s->search(Loc(), id, 4|2); } Dsymbol *Dsymbol::search_correct(Identifier *ident) @@ -432,7 +433,7 @@ Dsymbol *Dsymbol::search_correct(Identifier *ident) * symbol found, NULL if not */ -Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) +Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Object *id) { //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); Dsymbol *s = toAlias(); @@ -441,7 +442,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) switch (id->dyncast()) { case DYNCAST_IDENTIFIER: - sm = s->search(loc, id, 0); + sm = s->search(loc, (Identifier *)id, 0); break; case DYNCAST_DSYMBOL: @@ -449,7 +450,7 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) //printf("\ttemplate instance id\n"); Dsymbol *st = (Dsymbol *)id; TemplateInstance *ti = st->isTemplateInstance(); - id = ti->name; + Identifier *id = ti->name; sm = s->search(loc, id, 0); if (!sm) { @@ -546,9 +547,9 @@ int Dsymbol::isImportedSymbol() return FALSE; } -int Dsymbol::isDeprecated() +bool Dsymbol::isDeprecated() { - return FALSE; + return false; } #if DMDV2 @@ -606,7 +607,7 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) s2 = sd->symtab->lookup(ident); if (!s2->overloadInsert(this)) { - sd->multiplyDefined(0, this, s2); + sd->multiplyDefined(Loc(), this, s2); } } if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) @@ -741,7 +742,7 @@ Module *Dsymbol::getAccessModule() if (m) return m; TemplateInstance *ti = s->isTemplateInstance(); - if (ti && ti->isnested) + if (ti && ti->enclosing) /* Because of local template instantiation, the parent isn't where the access * rights come from - it's the template declaration */ @@ -807,8 +808,8 @@ void Dsymbol::addComment(unsigned char *comment) /********************************* OverloadSet ****************************/ #if DMDV2 -OverloadSet::OverloadSet() - : Dsymbol() +OverloadSet::OverloadSet(Identifier *ident) + : Dsymbol(ident) { } @@ -917,12 +918,20 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) ) ) { + /* Bugzilla 8668: + * Public selective import adds AliasDeclaration in module. + * To make an overload set, resolve aliases in here and + * get actual overload roots which accessible via s and s2. + */ + s = s->toAlias(); + s2 = s2->toAlias(); + /* If both s2 and s are overloadable (though we only * need to check s once) */ if (s2->isOverloadable() && (a || s->isOverloadable())) { if (!a) - a = new OverloadSet(); + a = new OverloadSet(s->ident); /* Don't add to a[] if s2 is alias of previous sym */ for (size_t j = 0; j < a->a.dim; j++) @@ -1067,7 +1076,7 @@ Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) return sprev; } } - multiplyDefined(0, s, sprev); + multiplyDefined(Loc(), s, sprev); return sprev; } @@ -1218,7 +1227,7 @@ FuncDeclaration *ScopeDsymbol::findGetMembers() Type *tret = NULL; tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd); - tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc); + tfgetmembers = (TypeFunction *)tfgetmembers->semantic(Loc(), &sc); } if (fdx) fdx = fdx->overloadExactMatch(tfgetmembers); @@ -1288,8 +1297,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) { /* $ gives the number of elements in the tuple */ VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); + Expression *e = new IntegerExp(Loc(), td->objects->dim, Type::tsize_t); + v->init = new ExpInitializer(Loc(), e); v->storage_class |= STCstatic | STCconst; v->semantic(sc); return v; @@ -1299,8 +1308,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) { /* $ gives the number of type entries in the type tuple */ VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); - Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); - v->init = new ExpInitializer(0, e); + Expression *e = new IntegerExp(Loc(), type->arguments->dim, Type::tsize_t); + v->init = new ExpInitializer(Loc(), e); v->storage_class |= STCstatic | STCconst; v->semantic(sc); return v; @@ -1364,8 +1373,8 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) { /* It is for an expression tuple, so the * length will be a const. */ - Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); - v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(0, e)); + Expression *e = new IntegerExp(Loc(), ((TupleExp *)ce)->exps->dim, Type::tsize_t); + v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, new ExpInitializer(Loc(), e)); v->storage_class |= STCstatic | STCconst; } else if (ce->type && (t = ce->type->toBasetype()) != NULL && @@ -1427,7 +1436,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) } Objects *tdargs = new Objects(); - Expression *edim = new IntegerExp(0, dim, Type::tsize_t); + Expression *edim = new IntegerExp(Loc(), dim, Type::tsize_t); edim = edim->semantic(sc); tdargs->push(edim); @@ -1457,7 +1466,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) t = e->type->toBasetype(); if (t && t->ty == Tfunction) e = new CallExp(e->loc, e); - v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(0, e)); + v = new VarDeclaration(loc, NULL, Id::dollar, new ExpInitializer(Loc(), e)); } else { /* For arrays, $ will either be a compile-time constant @@ -1465,7 +1474,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) * or a variable (in which case an expression is created in * toir.c). */ - VoidInitializer *e = new VoidInitializer(0); + VoidInitializer *e = new VoidInitializer(Loc()); e->type = Type::tsize_t; v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, e); v->storage_class |= STCctfe; // it's never a true static variable diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index c9f28003ee..54b56669af 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -76,7 +76,7 @@ struct EnumMember; struct ScopeDsymbol; struct WithScopeSymbol; struct ArrayScopeSymbol; -struct StaticStructInitDeclaration; +struct SymbolDeclaration; struct Expression; struct DeleteDeclaration; struct HdrGenState; @@ -118,7 +118,7 @@ enum PROT }; // this is used for printing the protection in json, traits, docs, etc. -static const char* Pprotectionnames[] = {NULL, "none", "private", "package", "protected", "public", "export"}; +extern const char* Pprotectionnames[]; /* State of symbol in winding its way through the passes of the compiler */ @@ -138,7 +138,6 @@ typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *); struct Dsymbol : Object { Identifier *ident; - Identifier *c_ident; Dsymbol *parent; #if IN_DMD Symbol *csym; // symbol for code generator @@ -190,9 +189,8 @@ struct Dsymbol : Object virtual void inlineScan(); virtual Dsymbol *search(Loc loc, Identifier *ident, int flags); Dsymbol *search_correct(Identifier *id); - Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id); + Dsymbol *searchX(Loc loc, Scope *sc, Object *id); virtual int overloadInsert(Dsymbol *s); - char *toHChars(); virtual void toHBuffer(OutBuffer *buf, HdrGenState *hgs); virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs); virtual void toDocBuffer(OutBuffer *buf, Scope *sc); @@ -207,7 +205,7 @@ struct Dsymbol : Object ClassDeclaration *isClassMember(); // are we a member of a class? virtual int isExport(); // is Dsymbol exported? virtual int isImportedSymbol(); // is Dsymbol imported? - virtual int isDeprecated(); // is Dsymbol deprecated? + virtual bool isDeprecated(); // is Dsymbol deprecated? #if DMDV2 virtual int isOverloadable(); virtual int hasOverloads(); @@ -215,7 +213,7 @@ struct Dsymbol : Object virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? virtual Type *getType(); // is this a type? - virtual char *mangle(bool isv = false); + virtual const char *mangle(bool isv = false); virtual int needThis(); // need a 'this' pointer? virtual enum PROT prot(); virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees @@ -281,7 +279,7 @@ struct Dsymbol : Object virtual Import *isImport() { return NULL; } virtual EnumDeclaration *isEnumDeclaration() { return NULL; } virtual DeleteDeclaration *isDeleteDeclaration() { return NULL; } - virtual StaticStructInitDeclaration *isStaticStructInitDeclaration() { return NULL; } + virtual SymbolDeclaration *isSymbolDeclaration() { return NULL; } virtual AttribDeclaration *isAttribDeclaration() { return NULL; } virtual OverloadSet *isOverloadSet() { return NULL; } #if IN_LLVM @@ -369,7 +367,7 @@ struct OverloadSet : Dsymbol { Dsymbols a; // array of Dsymbols - OverloadSet(); + OverloadSet(Identifier *ident); void push(Dsymbol *s); OverloadSet *isOverloadSet() { return this; } const char *kind(); diff --git a/dmd2/entity.c b/dmd2/entity.c index 8cb063dc70..53d253913e 100644 --- a/dmd2/entity.c +++ b/dmd2/entity.c @@ -25,2344 +25,2344 @@ struct NameId }; static NameId namesA[]={ - "Aacgr", 0x00386, // GREEK CAPITAL LETTER ALPHA WITH TONOS - "aacgr", 0x003AC, // GREEK SMALL LETTER ALPHA WITH TONOS - "Aacute", 0x000C1, // LATIN CAPITAL LETTER A WITH ACUTE - "aacute", 0x000E1, // LATIN SMALL LETTER A WITH ACUTE - "Abreve", 0x00102, // LATIN CAPITAL LETTER A WITH BREVE - "abreve", 0x00103, // LATIN SMALL LETTER A WITH BREVE - "ac", 0x0223E, // INVERTED LAZY S - "acd", 0x0223F, // SINE WAVE -// "acE", 0x0223E;0x00333, // INVERTED LAZY S with double underline - "Acirc", 0x000C2, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX - "acirc", 0x000E2, // LATIN SMALL LETTER A WITH CIRCUMFLEX - "acute", 0x000B4, // ACUTE ACCENT - "Acy", 0x00410, // CYRILLIC CAPITAL LETTER A - "acy", 0x00430, // CYRILLIC SMALL LETTER A - "AElig", 0x000C6, // LATIN CAPITAL LETTER AE - "aelig", 0x000E6, // LATIN SMALL LETTER AE - "af", 0x02061, // FUNCTION APPLICATION - "Afr", 0x1D504, // MATHEMATICAL FRAKTUR CAPITAL A - "afr", 0x1D51E, // MATHEMATICAL FRAKTUR SMALL A - "Agr", 0x00391, // GREEK CAPITAL LETTER ALPHA - "agr", 0x003B1, // GREEK SMALL LETTER ALPHA - "Agrave", 0x000C0, // LATIN CAPITAL LETTER A WITH GRAVE - "agrave", 0x000E0, // LATIN SMALL LETTER A WITH GRAVE - "alefsym", 0x02135, // ALEF SYMBOL - "aleph", 0x02135, // ALEF SYMBOL - "Alpha", 0x00391, // GREEK CAPITAL LETTER ALPHA - "alpha", 0x003B1, // GREEK SMALL LETTER ALPHA - "Amacr", 0x00100, // LATIN CAPITAL LETTER A WITH MACRON - "amacr", 0x00101, // LATIN SMALL LETTER A WITH MACRON - "amalg", 0x02A3F, // AMALGAMATION OR COPRODUCT - "amp", 0x00026, // AMPERSAND - "AMP", 0x00026, // AMPERSAND - "and", 0x02227, // LOGICAL AND - "And", 0x02A53, // DOUBLE LOGICAL AND - "andand", 0x02A55, // TWO INTERSECTING LOGICAL AND - "andd", 0x02A5C, // LOGICAL AND WITH HORIZONTAL DASH - "andslope", 0x02A58, // SLOPING LARGE AND - "andv", 0x02A5A, // LOGICAL AND WITH MIDDLE STEM - "ang", 0x02220, // ANGLE - "ange", 0x029A4, // ANGLE WITH UNDERBAR - "angle", 0x02220, // ANGLE - "angmsd", 0x02221, // MEASURED ANGLE - "angmsdaa", 0x029A8, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT - "angmsdab", 0x029A9, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT - "angmsdac", 0x029AA, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT - "angmsdad", 0x029AB, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT - "angmsdae", 0x029AC, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP - "angmsdaf", 0x029AD, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP - "angmsdag", 0x029AE, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN - "angmsdah", 0x029AF, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN - "angrt", 0x0221F, // RIGHT ANGLE - "angrtvb", 0x022BE, // RIGHT ANGLE WITH ARC - "angrtvbd", 0x0299D, // MEASURED RIGHT ANGLE WITH DOT - "angsph", 0x02222, // SPHERICAL ANGLE - "angst", 0x000C5, // LATIN CAPITAL LETTER A WITH RING ABOVE - "angzarr", 0x0237C, // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW - "Aogon", 0x00104, // LATIN CAPITAL LETTER A WITH OGONEK - "aogon", 0x00105, // LATIN SMALL LETTER A WITH OGONEK - "Aopf", 0x1D538, // MATHEMATICAL DOUBLE-STRUCK CAPITAL A - "aopf", 0x1D552, // MATHEMATICAL DOUBLE-STRUCK SMALL A - "ap", 0x02248, // ALMOST EQUAL TO - "apacir", 0x02A6F, // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT - "ape", 0x0224A, // ALMOST EQUAL OR EQUAL TO - "apE", 0x02A70, // APPROXIMATELY EQUAL OR EQUAL TO - "apid", 0x0224B, // TRIPLE TILDE - "apos", 0x00027, // APOSTROPHE - "ApplyFunction", 0x02061, // FUNCTION APPLICATION - "approx", 0x02248, // ALMOST EQUAL TO - "approxeq", 0x0224A, // ALMOST EQUAL OR EQUAL TO - "Aring", 0x000C5, // LATIN CAPITAL LETTER A WITH RING ABOVE - "aring", 0x000E5, // LATIN SMALL LETTER A WITH RING ABOVE - "Ascr", 0x1D49C, // MATHEMATICAL SCRIPT CAPITAL A - "ascr", 0x1D4B6, // MATHEMATICAL SCRIPT SMALL A - "Assign", 0x02254, // COLON EQUALS - "ast", 0x0002A, // ASTERISK - "asymp", 0x02248, // ALMOST EQUAL TO - "asympeq", 0x0224D, // EQUIVALENT TO - "Atilde", 0x000C3, // LATIN CAPITAL LETTER A WITH TILDE - "atilde", 0x000E3, // LATIN SMALL LETTER A WITH TILDE - "Auml", 0x000C4, // LATIN CAPITAL LETTER A WITH DIAERESIS - "auml", 0x000E4, // LATIN SMALL LETTER A WITH DIAERESIS - "awconint", 0x02233, // ANTICLOCKWISE CONTOUR INTEGRAL - "awint", 0x02A11, // ANTICLOCKWISE INTEGRATION - NULL, 0 + {"Aacgr", 0x00386}, // GREEK CAPITAL LETTER ALPHA WITH TONOS + {"aacgr", 0x003AC}, // GREEK SMALL LETTER ALPHA WITH TONOS + {"Aacute", 0x000C1}, // LATIN CAPITAL LETTER A WITH ACUTE + {"aacute", 0x000E1}, // LATIN SMALL LETTER A WITH ACUTE + {"Abreve", 0x00102}, // LATIN CAPITAL LETTER A WITH BREVE + {"abreve", 0x00103}, // LATIN SMALL LETTER A WITH BREVE + {"ac", 0x0223E}, // INVERTED LAZY S + {"acd", 0x0223F}, // SINE WAVE +// {"acE", 0x0223E;0x00333}, // INVERTED LAZY S with double underline + {"Acirc", 0x000C2}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX + {"acirc", 0x000E2}, // LATIN SMALL LETTER A WITH CIRCUMFLEX + {"acute", 0x000B4}, // ACUTE ACCENT + {"Acy", 0x00410}, // CYRILLIC CAPITAL LETTER A + {"acy", 0x00430}, // CYRILLIC SMALL LETTER A + {"AElig", 0x000C6}, // LATIN CAPITAL LETTER AE + {"aelig", 0x000E6}, // LATIN SMALL LETTER AE + {"af", 0x02061}, // FUNCTION APPLICATION + {"Afr", 0x1D504}, // MATHEMATICAL FRAKTUR CAPITAL A + {"afr", 0x1D51E}, // MATHEMATICAL FRAKTUR SMALL A + {"Agr", 0x00391}, // GREEK CAPITAL LETTER ALPHA + {"agr", 0x003B1}, // GREEK SMALL LETTER ALPHA + {"Agrave", 0x000C0}, // LATIN CAPITAL LETTER A WITH GRAVE + {"agrave", 0x000E0}, // LATIN SMALL LETTER A WITH GRAVE + {"alefsym", 0x02135}, // ALEF SYMBOL + {"aleph", 0x02135}, // ALEF SYMBOL + {"Alpha", 0x00391}, // GREEK CAPITAL LETTER ALPHA + {"alpha", 0x003B1}, // GREEK SMALL LETTER ALPHA + {"Amacr", 0x00100}, // LATIN CAPITAL LETTER A WITH MACRON + {"amacr", 0x00101}, // LATIN SMALL LETTER A WITH MACRON + {"amalg", 0x02A3F}, // AMALGAMATION OR COPRODUCT + {"amp", 0x00026}, // AMPERSAND + {"AMP", 0x00026}, // AMPERSAND + {"and", 0x02227}, // LOGICAL AND + {"And", 0x02A53}, // DOUBLE LOGICAL AND + {"andand", 0x02A55}, // TWO INTERSECTING LOGICAL AND + {"andd", 0x02A5C}, // LOGICAL AND WITH HORIZONTAL DASH + {"andslope", 0x02A58}, // SLOPING LARGE AND + {"andv", 0x02A5A}, // LOGICAL AND WITH MIDDLE STEM + {"ang", 0x02220}, // ANGLE + {"ange", 0x029A4}, // ANGLE WITH UNDERBAR + {"angle", 0x02220}, // ANGLE + {"angmsd", 0x02221}, // MEASURED ANGLE + {"angmsdaa", 0x029A8}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT + {"angmsdab", 0x029A9}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT + {"angmsdac", 0x029AA}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT + {"angmsdad", 0x029AB}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT + {"angmsdae", 0x029AC}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP + {"angmsdaf", 0x029AD}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP + {"angmsdag", 0x029AE}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN + {"angmsdah", 0x029AF}, // MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN + {"angrt", 0x0221F}, // RIGHT ANGLE + {"angrtvb", 0x022BE}, // RIGHT ANGLE WITH ARC + {"angrtvbd", 0x0299D}, // MEASURED RIGHT ANGLE WITH DOT + {"angsph", 0x02222}, // SPHERICAL ANGLE + {"angst", 0x000C5}, // LATIN CAPITAL LETTER A WITH RING ABOVE + {"angzarr", 0x0237C}, // RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW + {"Aogon", 0x00104}, // LATIN CAPITAL LETTER A WITH OGONEK + {"aogon", 0x00105}, // LATIN SMALL LETTER A WITH OGONEK + {"Aopf", 0x1D538}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL A + {"aopf", 0x1D552}, // MATHEMATICAL DOUBLE-STRUCK SMALL A + {"ap", 0x02248}, // ALMOST EQUAL TO + {"apacir", 0x02A6F}, // ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT + {"ape", 0x0224A}, // ALMOST EQUAL OR EQUAL TO + {"apE", 0x02A70}, // APPROXIMATELY EQUAL OR EQUAL TO + {"apid", 0x0224B}, // TRIPLE TILDE + {"apos", 0x00027}, // APOSTROPHE + {"ApplyFunction", 0x02061}, // FUNCTION APPLICATION + {"approx", 0x02248}, // ALMOST EQUAL TO + {"approxeq", 0x0224A}, // ALMOST EQUAL OR EQUAL TO + {"Aring", 0x000C5}, // LATIN CAPITAL LETTER A WITH RING ABOVE + {"aring", 0x000E5}, // LATIN SMALL LETTER A WITH RING ABOVE + {"Ascr", 0x1D49C}, // MATHEMATICAL SCRIPT CAPITAL A + {"ascr", 0x1D4B6}, // MATHEMATICAL SCRIPT SMALL A + {"Assign", 0x02254}, // COLON EQUALS + {"ast", 0x0002A}, // ASTERISK + {"asymp", 0x02248}, // ALMOST EQUAL TO + {"asympeq", 0x0224D}, // EQUIVALENT TO + {"Atilde", 0x000C3}, // LATIN CAPITAL LETTER A WITH TILDE + {"atilde", 0x000E3}, // LATIN SMALL LETTER A WITH TILDE + {"Auml", 0x000C4}, // LATIN CAPITAL LETTER A WITH DIAERESIS + {"auml", 0x000E4}, // LATIN SMALL LETTER A WITH DIAERESIS + {"awconint", 0x02233}, // ANTICLOCKWISE CONTOUR INTEGRAL + {"awint", 0x02A11}, // ANTICLOCKWISE INTEGRATION + {NULL, 0} }; static NameId namesB[]={ - "backcong", 0x0224C, // ALL EQUAL TO - "backepsilon", 0x003F6, // GREEK REVERSED LUNATE EPSILON SYMBOL - "backprime", 0x02035, // REVERSED PRIME - "backsim", 0x0223D, // REVERSED TILDE - "backsimeq", 0x022CD, // REVERSED TILDE EQUALS - "Backslash", 0x02216, // SET MINUS -// "b.alpha", 0x1D6C2, // MATHEMATICAL BOLD SMALL ALPHA - "Barv", 0x02AE7, // SHORT DOWN TACK WITH OVERBAR - "barvee", 0x022BD, // NOR - "barwed", 0x02305, // PROJECTIVE - "Barwed", 0x02306, // PERSPECTIVE - "barwedge", 0x02305, // PROJECTIVE -// "b.beta", 0x1D6C3, // MATHEMATICAL BOLD SMALL BETA - "bbrk", 0x023B5, // BOTTOM SQUARE BRACKET - "bbrktbrk", 0x023B6, // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET -// "b.chi", 0x1D6D8, // MATHEMATICAL BOLD SMALL CHI - "bcong", 0x0224C, // ALL EQUAL TO - "Bcy", 0x00411, // CYRILLIC CAPITAL LETTER BE - "bcy", 0x00431, // CYRILLIC SMALL LETTER BE -// "b.Delta", 0x1D6AB, // MATHEMATICAL BOLD CAPITAL DELTA -// "b.delta", 0x1D6C5, // MATHEMATICAL BOLD SMALL DELTA - "bdquo", 0x0201E, // DOUBLE LOW-9 QUOTATION MARK - "becaus", 0x02235, // BECAUSE - "because", 0x02235, // BECAUSE - "Because", 0x02235, // BECAUSE - "bemptyv", 0x029B0, // REVERSED EMPTY SET - "bepsi", 0x003F6, // GREEK REVERSED LUNATE EPSILON SYMBOL -// "b.epsi", 0x1D6C6, // MATHEMATICAL BOLD SMALL EPSILON -// "b.epsiv", 0x1D6DC, // MATHEMATICAL BOLD EPSILON SYMBOL - "bernou", 0x0212C, // SCRIPT CAPITAL B - "Bernoullis", 0x0212C, // SCRIPT CAPITAL B - "Beta", 0x00392, // GREEK CAPITAL LETTER BETA - "beta", 0x003B2, // GREEK SMALL LETTER BETA -// "b.eta", 0x1D6C8, // MATHEMATICAL BOLD SMALL ETA - "beth", 0x02136, // BET SYMBOL - "between", 0x0226C, // BETWEEN - "Bfr", 0x1D505, // MATHEMATICAL FRAKTUR CAPITAL B - "bfr", 0x1D51F, // MATHEMATICAL FRAKTUR SMALL B -// "b.Gamma", 0x1D6AA, // MATHEMATICAL BOLD CAPITAL GAMMA -// "b.gamma", 0x1D6C4, // MATHEMATICAL BOLD SMALL GAMMA -// "b.Gammad", 0x1D7CA, // MATHEMATICAL BOLD CAPITAL DIGAMMA -// "b.gammad", 0x1D7CB, // MATHEMATICAL BOLD SMALL DIGAMMA - "Bgr", 0x00392, // GREEK CAPITAL LETTER BETA - "bgr", 0x003B2, // GREEK SMALL LETTER BETA - "bigcap", 0x022C2, // N-ARY INTERSECTION - "bigcirc", 0x025EF, // LARGE CIRCLE - "bigcup", 0x022C3, // N-ARY UNION - "bigodot", 0x02A00, // N-ARY CIRCLED DOT OPERATOR - "bigoplus", 0x02A01, // N-ARY CIRCLED PLUS OPERATOR - "bigotimes", 0x02A02, // N-ARY CIRCLED TIMES OPERATOR - "bigsqcup", 0x02A06, // N-ARY SQUARE UNION OPERATOR - "bigstar", 0x02605, // BLACK STAR - "bigtriangledown", 0x025BD, // WHITE DOWN-POINTING TRIANGLE - "bigtriangleup", 0x025B3, // WHITE UP-POINTING TRIANGLE - "biguplus", 0x02A04, // N-ARY UNION OPERATOR WITH PLUS - "bigvee", 0x022C1, // N-ARY LOGICAL OR - "bigwedge", 0x022C0, // N-ARY LOGICAL AND -// "b.iota", 0x1D6CA, // MATHEMATICAL BOLD SMALL IOTA -// "b.kappa", 0x1D6CB, // MATHEMATICAL BOLD SMALL KAPPA -// "b.kappav", 0x1D6DE, // MATHEMATICAL BOLD KAPPA SYMBOL - "bkarow", 0x0290D, // RIGHTWARDS DOUBLE DASH ARROW - "blacklozenge", 0x029EB, // BLACK LOZENGE - "blacksquare", 0x025AA, // BLACK SMALL SQUARE - "blacktriangle", 0x025B4, // BLACK UP-POINTING SMALL TRIANGLE - "blacktriangledown", 0x025BE, // BLACK DOWN-POINTING SMALL TRIANGLE - "blacktriangleleft", 0x025C2, // BLACK LEFT-POINTING SMALL TRIANGLE - "blacktriangleright", 0x025B8, // BLACK RIGHT-POINTING SMALL TRIANGLE -// "b.Lambda", 0x1D6B2, // MATHEMATICAL BOLD CAPITAL LAMDA -// "b.lambda", 0x1D6CC, // MATHEMATICAL BOLD SMALL LAMDA - "blank", 0x02423, // OPEN BOX - "blk12", 0x02592, // MEDIUM SHADE - "blk14", 0x02591, // LIGHT SHADE - "blk34", 0x02593, // DARK SHADE - "block", 0x02588, // FULL BLOCK -// "b.mu", 0x1D6CD, // MATHEMATICAL BOLD SMALL MU -// "bne", 0x0003D;0x020E5, // EQUALS SIGN with reverse slash -// "bnequiv", 0x02261;0x020E5, // IDENTICAL TO with reverse slash - "bnot", 0x02310, // REVERSED NOT SIGN - "bNot", 0x02AED, // REVERSED DOUBLE STROKE NOT SIGN -// "b.nu", 0x1D6CE, // MATHEMATICAL BOLD SMALL NU -// "b.Omega", 0x1D6C0, // MATHEMATICAL BOLD CAPITAL OMEGA -// "b.omega", 0x1D6DA, // MATHEMATICAL BOLD SMALL OMEGA - "Bopf", 0x1D539, // MATHEMATICAL DOUBLE-STRUCK CAPITAL B - "bopf", 0x1D553, // MATHEMATICAL DOUBLE-STRUCK SMALL B - "bot", 0x022A5, // UP TACK - "bottom", 0x022A5, // UP TACK - "bowtie", 0x022C8, // BOWTIE - "boxbox", 0x029C9, // TWO JOINED SQUARES - "boxdl", 0x02510, // BOX DRAWINGS LIGHT DOWN AND LEFT - "boxdL", 0x02555, // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE - "boxDl", 0x02556, // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE - "boxDL", 0x02557, // BOX DRAWINGS DOUBLE DOWN AND LEFT - "boxdr", 0x0250C, // BOX DRAWINGS LIGHT DOWN AND RIGHT - "boxdR", 0x02552, // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE - "boxDr", 0x02553, // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE - "boxDR", 0x02554, // BOX DRAWINGS DOUBLE DOWN AND RIGHT - "boxh", 0x02500, // BOX DRAWINGS LIGHT HORIZONTAL - "boxH", 0x02550, // BOX DRAWINGS DOUBLE HORIZONTAL - "boxhd", 0x0252C, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL - "boxHd", 0x02564, // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE - "boxhD", 0x02565, // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE - "boxHD", 0x02566, // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL - "boxhu", 0x02534, // BOX DRAWINGS LIGHT UP AND HORIZONTAL - "boxHu", 0x02567, // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE - "boxhU", 0x02568, // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE - "boxHU", 0x02569, // BOX DRAWINGS DOUBLE UP AND HORIZONTAL - "boxminus", 0x0229F, // SQUARED MINUS - "boxplus", 0x0229E, // SQUARED PLUS - "boxtimes", 0x022A0, // SQUARED TIMES - "boxul", 0x02518, // BOX DRAWINGS LIGHT UP AND LEFT - "boxuL", 0x0255B, // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE - "boxUl", 0x0255C, // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE - "boxUL", 0x0255D, // BOX DRAWINGS DOUBLE UP AND LEFT - "boxur", 0x02514, // BOX DRAWINGS LIGHT UP AND RIGHT - "boxuR", 0x02558, // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE - "boxUr", 0x02559, // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE - "boxUR", 0x0255A, // BOX DRAWINGS DOUBLE UP AND RIGHT - "boxv", 0x02502, // BOX DRAWINGS LIGHT VERTICAL - "boxV", 0x02551, // BOX DRAWINGS DOUBLE VERTICAL - "boxvh", 0x0253C, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL - "boxvH", 0x0256A, // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE - "boxVh", 0x0256B, // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE - "boxVH", 0x0256C, // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL - "boxvl", 0x02524, // BOX DRAWINGS LIGHT VERTICAL AND LEFT - "boxvL", 0x02561, // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE - "boxVl", 0x02562, // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE - "boxVL", 0x02563, // BOX DRAWINGS DOUBLE VERTICAL AND LEFT - "boxvr", 0x0251C, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT - "boxvR", 0x0255E, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE - "boxVr", 0x0255F, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE - "boxVR", 0x02560, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT -// "b.Phi", 0x1D6BD, // MATHEMATICAL BOLD CAPITAL PHI -// "b.phi", 0x1D6D7, // MATHEMATICAL BOLD SMALL PHI -// "b.phiv", 0x1D6DF, // MATHEMATICAL BOLD PHI SYMBOL -// "b.Pi", 0x1D6B7, // MATHEMATICAL BOLD CAPITAL PI -// "b.pi", 0x1D6D1, // MATHEMATICAL BOLD SMALL PI -// "b.piv", 0x1D6E1, // MATHEMATICAL BOLD PI SYMBOL - "bprime", 0x02035, // REVERSED PRIME -// "b.Psi", 0x1D6BF, // MATHEMATICAL BOLD CAPITAL PSI -// "b.psi", 0x1D6D9, // MATHEMATICAL BOLD SMALL PSI - "breve", 0x002D8, // BREVE - "Breve", 0x002D8, // BREVE -// "b.rho", 0x1D6D2, // MATHEMATICAL BOLD SMALL RHO -// "b.rhov", 0x1D6E0, // MATHEMATICAL BOLD RHO SYMBOL - "brvbar", 0x000A6, // BROKEN BAR - "Bscr", 0x0212C, // SCRIPT CAPITAL B - "bscr", 0x1D4B7, // MATHEMATICAL SCRIPT SMALL B - "bsemi", 0x0204F, // REVERSED SEMICOLON -// "b.Sigma", 0x1D6BA, // MATHEMATICAL BOLD CAPITAL SIGMA -// "b.sigma", 0x1D6D4, // MATHEMATICAL BOLD SMALL SIGMA -// "b.sigmav", 0x1D6D3, // MATHEMATICAL BOLD SMALL FINAL SIGMA - "bsim", 0x0223D, // REVERSED TILDE - "bsime", 0x022CD, // REVERSED TILDE EQUALS - "bsol", 0x0005C, // REVERSE SOLIDUS - "bsolb", 0x029C5, // SQUARED FALLING DIAGONAL SLASH - "bsolhsub", 0x027C8, // REVERSE SOLIDUS PRECEDING SUBSET -// "b.tau", 0x1D6D5, // MATHEMATICAL BOLD SMALL TAU -// "b.Theta", 0x1D6AF, // MATHEMATICAL BOLD CAPITAL THETA -// "b.thetas", 0x1D6C9, // MATHEMATICAL BOLD SMALL THETA -// "b.thetav", 0x1D6DD, // MATHEMATICAL BOLD THETA SYMBOL - "bull", 0x02022, // BULLET - "bullet", 0x02022, // BULLET - "bump", 0x0224E, // GEOMETRICALLY EQUIVALENT TO - "bumpe", 0x0224F, // DIFFERENCE BETWEEN - "bumpE", 0x02AAE, // EQUALS SIGN WITH BUMPY ABOVE - "Bumpeq", 0x0224E, // GEOMETRICALLY EQUIVALENT TO - "bumpeq", 0x0224F, // DIFFERENCE BETWEEN -// "b.Upsi", 0x1D6BC, // MATHEMATICAL BOLD CAPITAL UPSILON -// "b.upsi", 0x1D6D6, // MATHEMATICAL BOLD SMALL UPSILON -// "b.Xi", 0x1D6B5, // MATHEMATICAL BOLD CAPITAL XI -// "b.xi", 0x1D6CF, // MATHEMATICAL BOLD SMALL XI -// "b.zeta", 0x1D6C7, // MATHEMATICAL BOLD SMALL ZETA - NULL, 0 + {"backcong", 0x0224C}, // ALL EQUAL TO + {"backepsilon", 0x003F6}, // GREEK REVERSED LUNATE EPSILON SYMBOL + {"backprime", 0x02035}, // REVERSED PRIME + {"backsim", 0x0223D}, // REVERSED TILDE + {"backsimeq", 0x022CD}, // REVERSED TILDE EQUALS + {"Backslash", 0x02216}, // SET MINUS +// "b.alpha", 0x1D6C2}, // MATHEMATICAL BOLD SMALL ALPHA + {"Barv", 0x02AE7}, // SHORT DOWN TACK WITH OVERBAR + {"barvee", 0x022BD}, // NOR + {"barwed", 0x02305}, // PROJECTIVE + {"Barwed", 0x02306}, // PERSPECTIVE + {"barwedge", 0x02305}, // PROJECTIVE +// "b.beta", 0x1D6C3}, // MATHEMATICAL BOLD SMALL BETA + {"bbrk", 0x023B5}, // BOTTOM SQUARE BRACKET + {"bbrktbrk", 0x023B6}, // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET +// "b.chi", 0x1D6D8}, // MATHEMATICAL BOLD SMALL CHI + {"bcong", 0x0224C}, // ALL EQUAL TO + {"Bcy", 0x00411}, // CYRILLIC CAPITAL LETTER BE + {"bcy", 0x00431}, // CYRILLIC SMALL LETTER BE +// "b.Delta", 0x1D6AB}, // MATHEMATICAL BOLD CAPITAL DELTA +// "b.delta", 0x1D6C5}, // MATHEMATICAL BOLD SMALL DELTA + {"bdquo", 0x0201E}, // DOUBLE LOW-9 QUOTATION MARK + {"becaus", 0x02235}, // BECAUSE + {"because", 0x02235}, // BECAUSE + {"Because", 0x02235}, // BECAUSE + {"bemptyv", 0x029B0}, // REVERSED EMPTY SET + {"bepsi", 0x003F6}, // GREEK REVERSED LUNATE EPSILON SYMBOL +// "b.epsi", 0x1D6C6}, // MATHEMATICAL BOLD SMALL EPSILON +// "b.epsiv", 0x1D6DC}, // MATHEMATICAL BOLD EPSILON SYMBOL + {"bernou", 0x0212C}, // SCRIPT CAPITAL B + {"Bernoullis", 0x0212C}, // SCRIPT CAPITAL B + {"Beta", 0x00392}, // GREEK CAPITAL LETTER BETA + {"beta", 0x003B2}, // GREEK SMALL LETTER BETA +// "b.eta", 0x1D6C8}, // MATHEMATICAL BOLD SMALL ETA + {"beth", 0x02136}, // BET SYMBOL + {"between", 0x0226C}, // BETWEEN + {"Bfr", 0x1D505}, // MATHEMATICAL FRAKTUR CAPITAL B + {"bfr", 0x1D51F}, // MATHEMATICAL FRAKTUR SMALL B +// "b.Gamma", 0x1D6AA}, // MATHEMATICAL BOLD CAPITAL GAMMA +// "b.gamma", 0x1D6C4}, // MATHEMATICAL BOLD SMALL GAMMA +// "b.Gammad", 0x1D7CA}, // MATHEMATICAL BOLD CAPITAL DIGAMMA +// "b.gammad", 0x1D7CB}, // MATHEMATICAL BOLD SMALL DIGAMMA + {"Bgr", 0x00392}, // GREEK CAPITAL LETTER BETA + {"bgr", 0x003B2}, // GREEK SMALL LETTER BETA + {"bigcap", 0x022C2}, // N-ARY INTERSECTION + {"bigcirc", 0x025EF}, // LARGE CIRCLE + {"bigcup", 0x022C3}, // N-ARY UNION + {"bigodot", 0x02A00}, // N-ARY CIRCLED DOT OPERATOR + {"bigoplus", 0x02A01}, // N-ARY CIRCLED PLUS OPERATOR + {"bigotimes", 0x02A02}, // N-ARY CIRCLED TIMES OPERATOR + {"bigsqcup", 0x02A06}, // N-ARY SQUARE UNION OPERATOR + {"bigstar", 0x02605}, // BLACK STAR + {"bigtriangledown", 0x025BD}, // WHITE DOWN-POINTING TRIANGLE + {"bigtriangleup", 0x025B3}, // WHITE UP-POINTING TRIANGLE + {"biguplus", 0x02A04}, // N-ARY UNION OPERATOR WITH PLUS + {"bigvee", 0x022C1}, // N-ARY LOGICAL OR + {"bigwedge", 0x022C0}, // N-ARY LOGICAL AND +// "b.iota", 0x1D6CA}, // MATHEMATICAL BOLD SMALL IOTA +// "b.kappa", 0x1D6CB}, // MATHEMATICAL BOLD SMALL KAPPA +// "b.kappav", 0x1D6DE}, // MATHEMATICAL BOLD KAPPA SYMBOL + {"bkarow", 0x0290D}, // RIGHTWARDS DOUBLE DASH ARROW + {"blacklozenge", 0x029EB}, // BLACK LOZENGE + {"blacksquare", 0x025AA}, // BLACK SMALL SQUARE + {"blacktriangle", 0x025B4}, // BLACK UP-POINTING SMALL TRIANGLE + {"blacktriangledown", 0x025BE}, // BLACK DOWN-POINTING SMALL TRIANGLE + {"blacktriangleleft", 0x025C2}, // BLACK LEFT-POINTING SMALL TRIANGLE + {"blacktriangleright", 0x025B8}, // BLACK RIGHT-POINTING SMALL TRIANGLE +// "b.Lambda", 0x1D6B2}, // MATHEMATICAL BOLD CAPITAL LAMDA +// "b.lambda", 0x1D6CC}, // MATHEMATICAL BOLD SMALL LAMDA + {"blank", 0x02423}, // OPEN BOX + {"blk12", 0x02592}, // MEDIUM SHADE + {"blk14", 0x02591}, // LIGHT SHADE + {"blk34", 0x02593}, // DARK SHADE + {"block", 0x02588}, // FULL BLOCK +// "b.mu", 0x1D6CD}, // MATHEMATICAL BOLD SMALL MU +// "bne", 0x0003D;0x020E5}, // EQUALS SIGN with reverse slash +// "bnequiv", 0x02261;0x020E5}, // IDENTICAL TO with reverse slash + {"bnot", 0x02310}, // REVERSED NOT SIGN + {"bNot", 0x02AED}, // REVERSED DOUBLE STROKE NOT SIGN +// "b.nu", 0x1D6CE}, // MATHEMATICAL BOLD SMALL NU +// "b.Omega", 0x1D6C0}, // MATHEMATICAL BOLD CAPITAL OMEGA +// "b.omega", 0x1D6DA}, // MATHEMATICAL BOLD SMALL OMEGA + {"Bopf", 0x1D539}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL B + {"bopf", 0x1D553}, // MATHEMATICAL DOUBLE-STRUCK SMALL B + {"bot", 0x022A5}, // UP TACK + {"bottom", 0x022A5}, // UP TACK + {"bowtie", 0x022C8}, // BOWTIE + {"boxbox", 0x029C9}, // TWO JOINED SQUARES + {"boxdl", 0x02510}, // BOX DRAWINGS LIGHT DOWN AND LEFT + {"boxdL", 0x02555}, // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + {"boxDl", 0x02556}, // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + {"boxDL", 0x02557}, // BOX DRAWINGS DOUBLE DOWN AND LEFT + {"boxdr", 0x0250C}, // BOX DRAWINGS LIGHT DOWN AND RIGHT + {"boxdR", 0x02552}, // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + {"boxDr", 0x02553}, // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + {"boxDR", 0x02554}, // BOX DRAWINGS DOUBLE DOWN AND RIGHT + {"boxh", 0x02500}, // BOX DRAWINGS LIGHT HORIZONTAL + {"boxH", 0x02550}, // BOX DRAWINGS DOUBLE HORIZONTAL + {"boxhd", 0x0252C}, // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + {"boxHd", 0x02564}, // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + {"boxhD", 0x02565}, // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + {"boxHD", 0x02566}, // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + {"boxhu", 0x02534}, // BOX DRAWINGS LIGHT UP AND HORIZONTAL + {"boxHu", 0x02567}, // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + {"boxhU", 0x02568}, // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + {"boxHU", 0x02569}, // BOX DRAWINGS DOUBLE UP AND HORIZONTAL + {"boxminus", 0x0229F}, // SQUARED MINUS + {"boxplus", 0x0229E}, // SQUARED PLUS + {"boxtimes", 0x022A0}, // SQUARED TIMES + {"boxul", 0x02518}, // BOX DRAWINGS LIGHT UP AND LEFT + {"boxuL", 0x0255B}, // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + {"boxUl", 0x0255C}, // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + {"boxUL", 0x0255D}, // BOX DRAWINGS DOUBLE UP AND LEFT + {"boxur", 0x02514}, // BOX DRAWINGS LIGHT UP AND RIGHT + {"boxuR", 0x02558}, // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + {"boxUr", 0x02559}, // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + {"boxUR", 0x0255A}, // BOX DRAWINGS DOUBLE UP AND RIGHT + {"boxv", 0x02502}, // BOX DRAWINGS LIGHT VERTICAL + {"boxV", 0x02551}, // BOX DRAWINGS DOUBLE VERTICAL + {"boxvh", 0x0253C}, // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + {"boxvH", 0x0256A}, // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + {"boxVh", 0x0256B}, // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + {"boxVH", 0x0256C}, // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + {"boxvl", 0x02524}, // BOX DRAWINGS LIGHT VERTICAL AND LEFT + {"boxvL", 0x02561}, // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + {"boxVl", 0x02562}, // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + {"boxVL", 0x02563}, // BOX DRAWINGS DOUBLE VERTICAL AND LEFT + {"boxvr", 0x0251C}, // BOX DRAWINGS LIGHT VERTICAL AND RIGHT + {"boxvR", 0x0255E}, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + {"boxVr", 0x0255F}, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + {"boxVR", 0x02560}, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT +// "b.Phi", 0x1D6BD}, // MATHEMATICAL BOLD CAPITAL PHI +// "b.phi", 0x1D6D7}, // MATHEMATICAL BOLD SMALL PHI +// "b.phiv", 0x1D6DF}, // MATHEMATICAL BOLD PHI SYMBOL +// "b.Pi", 0x1D6B7}, // MATHEMATICAL BOLD CAPITAL PI +// "b.pi", 0x1D6D1}, // MATHEMATICAL BOLD SMALL PI +// "b.piv", 0x1D6E1}, // MATHEMATICAL BOLD PI SYMBOL + {"bprime", 0x02035}, // REVERSED PRIME +// "b.Psi", 0x1D6BF}, // MATHEMATICAL BOLD CAPITAL PSI +// "b.psi", 0x1D6D9}, // MATHEMATICAL BOLD SMALL PSI + {"breve", 0x002D8}, // BREVE + {"Breve", 0x002D8}, // BREVE +// "b.rho", 0x1D6D2}, // MATHEMATICAL BOLD SMALL RHO +// "b.rhov", 0x1D6E0}, // MATHEMATICAL BOLD RHO SYMBOL + {"brvbar", 0x000A6}, // BROKEN BAR + {"Bscr", 0x0212C}, // SCRIPT CAPITAL B + {"bscr", 0x1D4B7}, // MATHEMATICAL SCRIPT SMALL B + {"bsemi", 0x0204F}, // REVERSED SEMICOLON +// "b.Sigma", 0x1D6BA}, // MATHEMATICAL BOLD CAPITAL SIGMA +// "b.sigma", 0x1D6D4}, // MATHEMATICAL BOLD SMALL SIGMA +// "b.sigmav", 0x1D6D3}, // MATHEMATICAL BOLD SMALL FINAL SIGMA + {"bsim", 0x0223D}, // REVERSED TILDE + {"bsime", 0x022CD}, // REVERSED TILDE EQUALS + {"bsol", 0x0005C}, // REVERSE SOLIDUS + {"bsolb", 0x029C5}, // SQUARED FALLING DIAGONAL SLASH + {"bsolhsub", 0x027C8}, // REVERSE SOLIDUS PRECEDING SUBSET +// "b.tau", 0x1D6D5}, // MATHEMATICAL BOLD SMALL TAU +// "b.Theta", 0x1D6AF}, // MATHEMATICAL BOLD CAPITAL THETA +// "b.thetas", 0x1D6C9}, // MATHEMATICAL BOLD SMALL THETA +// "b.thetav", 0x1D6DD}, // MATHEMATICAL BOLD THETA SYMBOL + {"bull", 0x02022}, // BULLET + {"bullet", 0x02022}, // BULLET + {"bump", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO + {"bumpe", 0x0224F}, // DIFFERENCE BETWEEN + {"bumpE", 0x02AAE}, // EQUALS SIGN WITH BUMPY ABOVE + {"Bumpeq", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO + {"bumpeq", 0x0224F}, // DIFFERENCE BETWEEN +// "b.Upsi", 0x1D6BC}, // MATHEMATICAL BOLD CAPITAL UPSILON +// "b.upsi", 0x1D6D6}, // MATHEMATICAL BOLD SMALL UPSILON +// "b.Xi", 0x1D6B5}, // MATHEMATICAL BOLD CAPITAL XI +// "b.xi", 0x1D6CF}, // MATHEMATICAL BOLD SMALL XI +// "b.zeta", 0x1D6C7}, // MATHEMATICAL BOLD SMALL ZETA + {NULL, 0} }; static NameId namesC[]={ - "Cacute", 0x00106, // LATIN CAPITAL LETTER C WITH ACUTE - "cacute", 0x00107, // LATIN SMALL LETTER C WITH ACUTE - "cap", 0x02229, // INTERSECTION - "Cap", 0x022D2, // DOUBLE INTERSECTION - "capand", 0x02A44, // INTERSECTION WITH LOGICAL AND - "capbrcup", 0x02A49, // INTERSECTION ABOVE BAR ABOVE UNION - "capcap", 0x02A4B, // INTERSECTION BESIDE AND JOINED WITH INTERSECTION - "capcup", 0x02A47, // INTERSECTION ABOVE UNION - "capdot", 0x02A40, // INTERSECTION WITH DOT - "CapitalDifferentialD", 0x02145, // DOUBLE-STRUCK ITALIC CAPITAL D -// "caps", 0x02229;0x0FE00, // INTERSECTION with serifs - "caret", 0x02041, // CARET INSERTION POINT - "caron", 0x002C7, // CARON - "Cayleys", 0x0212D, // BLACK-LETTER CAPITAL C - "ccaps", 0x02A4D, // CLOSED INTERSECTION WITH SERIFS - "Ccaron", 0x0010C, // LATIN CAPITAL LETTER C WITH CARON - "ccaron", 0x0010D, // LATIN SMALL LETTER C WITH CARON - "Ccedil", 0x000C7, // LATIN CAPITAL LETTER C WITH CEDILLA - "ccedil", 0x000E7, // LATIN SMALL LETTER C WITH CEDILLA - "Ccirc", 0x00108, // LATIN CAPITAL LETTER C WITH CIRCUMFLEX - "ccirc", 0x00109, // LATIN SMALL LETTER C WITH CIRCUMFLEX - "Cconint", 0x02230, // VOLUME INTEGRAL - "ccups", 0x02A4C, // CLOSED UNION WITH SERIFS - "ccupssm", 0x02A50, // CLOSED UNION WITH SERIFS AND SMASH PRODUCT - "Cdot", 0x0010A, // LATIN CAPITAL LETTER C WITH DOT ABOVE - "cdot", 0x0010B, // LATIN SMALL LETTER C WITH DOT ABOVE - "cedil", 0x000B8, // CEDILLA - "Cedilla", 0x000B8, // CEDILLA - "cemptyv", 0x029B2, // EMPTY SET WITH SMALL CIRCLE ABOVE - "cent", 0x000A2, // CENT SIGN - "centerdot", 0x000B7, // MIDDLE DOT - "CenterDot", 0x000B7, // MIDDLE DOT - "Cfr", 0x0212D, // BLACK-LETTER CAPITAL C - "cfr", 0x1D520, // MATHEMATICAL FRAKTUR SMALL C - "CHcy", 0x00427, // CYRILLIC CAPITAL LETTER CHE - "chcy", 0x00447, // CYRILLIC SMALL LETTER CHE - "check", 0x02713, // CHECK MARK - "checkmark", 0x02713, // CHECK MARK - "Chi", 0x003A7, // GREEK CAPITAL LETTER CHI - "chi", 0x003C7, // GREEK SMALL LETTER CHI - "cir", 0x025CB, // WHITE CIRCLE - "circ", 0x002C6, // MODIFIER LETTER CIRCUMFLEX ACCENT - "circeq", 0x02257, // RING EQUAL TO - "circlearrowleft", 0x021BA, // ANTICLOCKWISE OPEN CIRCLE ARROW - "circlearrowright", 0x021BB, // CLOCKWISE OPEN CIRCLE ARROW - "circledast", 0x0229B, // CIRCLED ASTERISK OPERATOR - "circledcirc", 0x0229A, // CIRCLED RING OPERATOR - "circleddash", 0x0229D, // CIRCLED DASH - "CircleDot", 0x02299, // CIRCLED DOT OPERATOR - "circledR", 0x000AE, // REGISTERED SIGN - "circledS", 0x024C8, // CIRCLED LATIN CAPITAL LETTER S - "CircleMinus", 0x02296, // CIRCLED MINUS - "CirclePlus", 0x02295, // CIRCLED PLUS - "CircleTimes", 0x02297, // CIRCLED TIMES - "cire", 0x02257, // RING EQUAL TO - "cirE", 0x029C3, // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT - "cirfnint", 0x02A10, // CIRCULATION FUNCTION - "cirmid", 0x02AEF, // VERTICAL LINE WITH CIRCLE ABOVE - "cirscir", 0x029C2, // CIRCLE WITH SMALL CIRCLE TO THE RIGHT - "ClockwiseContourIntegral", 0x02232, // CLOCKWISE CONTOUR INTEGRAL - "CloseCurlyDoubleQuote", 0x0201D, // RIGHT DOUBLE QUOTATION MARK - "CloseCurlyQuote", 0x02019, // RIGHT SINGLE QUOTATION MARK - "clubs", 0x02663, // BLACK CLUB SUIT - "clubsuit", 0x02663, // BLACK CLUB SUIT - "colon", 0x0003A, // COLON - "Colon", 0x02237, // PROPORTION - "colone", 0x02254, // COLON EQUALS - "Colone", 0x02A74, // DOUBLE COLON EQUAL - "coloneq", 0x02254, // COLON EQUALS - "comma", 0x0002C, // COMMA - "commat", 0x00040, // COMMERCIAL AT - "comp", 0x02201, // COMPLEMENT - "compfn", 0x02218, // RING OPERATOR - "complement", 0x02201, // COMPLEMENT - "complexes", 0x02102, // DOUBLE-STRUCK CAPITAL C - "cong", 0x02245, // APPROXIMATELY EQUAL TO - "congdot", 0x02A6D, // CONGRUENT WITH DOT ABOVE - "Congruent", 0x02261, // IDENTICAL TO - "conint", 0x0222E, // CONTOUR INTEGRAL - "Conint", 0x0222F, // SURFACE INTEGRAL - "ContourIntegral", 0x0222E, // CONTOUR INTEGRAL - "Copf", 0x02102, // DOUBLE-STRUCK CAPITAL C - "copf", 0x1D554, // MATHEMATICAL DOUBLE-STRUCK SMALL C - "coprod", 0x02210, // N-ARY COPRODUCT - "Coproduct", 0x02210, // N-ARY COPRODUCT - "copy", 0x000A9, // COPYRIGHT SIGN - "COPY", 0x000A9, // COPYRIGHT SIGN - "copysr", 0x02117, // SOUND RECORDING COPYRIGHT - "CounterClockwiseContourIntegral", 0x02233, // ANTICLOCKWISE CONTOUR INTEGRAL - "crarr", 0x021B5, // DOWNWARDS ARROW WITH CORNER LEFTWARDS - "cross", 0x02717, // BALLOT X - "Cross", 0x02A2F, // VECTOR OR CROSS PRODUCT - "Cscr", 0x1D49E, // MATHEMATICAL SCRIPT CAPITAL C - "cscr", 0x1D4B8, // MATHEMATICAL SCRIPT SMALL C - "csub", 0x02ACF, // CLOSED SUBSET - "csube", 0x02AD1, // CLOSED SUBSET OR EQUAL TO - "csup", 0x02AD0, // CLOSED SUPERSET - "csupe", 0x02AD2, // CLOSED SUPERSET OR EQUAL TO - "ctdot", 0x022EF, // MIDLINE HORIZONTAL ELLIPSIS - "cudarrl", 0x02938, // RIGHT-SIDE ARC CLOCKWISE ARROW - "cudarrr", 0x02935, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS - "cuepr", 0x022DE, // EQUAL TO OR PRECEDES - "cuesc", 0x022DF, // EQUAL TO OR SUCCEEDS - "cularr", 0x021B6, // ANTICLOCKWISE TOP SEMICIRCLE ARROW - "cularrp", 0x0293D, // TOP ARC ANTICLOCKWISE ARROW WITH PLUS - "cup", 0x0222A, // UNION - "Cup", 0x022D3, // DOUBLE UNION - "cupbrcap", 0x02A48, // UNION ABOVE BAR ABOVE INTERSECTION - "CupCap", 0x0224D, // EQUIVALENT TO - "cupcap", 0x02A46, // UNION ABOVE INTERSECTION - "cupcup", 0x02A4A, // UNION BESIDE AND JOINED WITH UNION - "cupdot", 0x0228D, // MULTISET MULTIPLICATION - "cupor", 0x02A45, // UNION WITH LOGICAL OR -// "cups", 0x0222A;0x0FE00, // UNION with serifs - "curarr", 0x021B7, // CLOCKWISE TOP SEMICIRCLE ARROW - "curarrm", 0x0293C, // TOP ARC CLOCKWISE ARROW WITH MINUS - "curlyeqprec", 0x022DE, // EQUAL TO OR PRECEDES - "curlyeqsucc", 0x022DF, // EQUAL TO OR SUCCEEDS - "curlyvee", 0x022CE, // CURLY LOGICAL OR - "curlywedge", 0x022CF, // CURLY LOGICAL AND - "curren", 0x000A4, // CURRENCY SIGN - "curvearrowleft", 0x021B6, // ANTICLOCKWISE TOP SEMICIRCLE ARROW - "curvearrowright", 0x021B7, // CLOCKWISE TOP SEMICIRCLE ARROW - "cuvee", 0x022CE, // CURLY LOGICAL OR - "cuwed", 0x022CF, // CURLY LOGICAL AND - "cwconint", 0x02232, // CLOCKWISE CONTOUR INTEGRAL - "cwint", 0x02231, // CLOCKWISE INTEGRAL - "cylcty", 0x0232D, // CYLINDRICITY - NULL, 0 + {"Cacute", 0x00106}, // LATIN CAPITAL LETTER C WITH ACUTE + {"cacute", 0x00107}, // LATIN SMALL LETTER C WITH ACUTE + {"cap", 0x02229}, // INTERSECTION + {"Cap", 0x022D2}, // DOUBLE INTERSECTION + {"capand", 0x02A44}, // INTERSECTION WITH LOGICAL AND + {"capbrcup", 0x02A49}, // INTERSECTION ABOVE BAR ABOVE UNION + {"capcap", 0x02A4B}, // INTERSECTION BESIDE AND JOINED WITH INTERSECTION + {"capcup", 0x02A47}, // INTERSECTION ABOVE UNION + {"capdot", 0x02A40}, // INTERSECTION WITH DOT + {"CapitalDifferentialD", 0x02145}, // DOUBLE-STRUCK ITALIC CAPITAL D +// "caps", 0x02229;0x0FE00}, // INTERSECTION with serifs + {"caret", 0x02041}, // CARET INSERTION POINT + {"caron", 0x002C7}, // CARON + {"Cayleys", 0x0212D}, // BLACK-LETTER CAPITAL C + {"ccaps", 0x02A4D}, // CLOSED INTERSECTION WITH SERIFS + {"Ccaron", 0x0010C}, // LATIN CAPITAL LETTER C WITH CARON + {"ccaron", 0x0010D}, // LATIN SMALL LETTER C WITH CARON + {"Ccedil", 0x000C7}, // LATIN CAPITAL LETTER C WITH CEDILLA + {"ccedil", 0x000E7}, // LATIN SMALL LETTER C WITH CEDILLA + {"Ccirc", 0x00108}, // LATIN CAPITAL LETTER C WITH CIRCUMFLEX + {"ccirc", 0x00109}, // LATIN SMALL LETTER C WITH CIRCUMFLEX + {"Cconint", 0x02230}, // VOLUME INTEGRAL + {"ccups", 0x02A4C}, // CLOSED UNION WITH SERIFS + {"ccupssm", 0x02A50}, // CLOSED UNION WITH SERIFS AND SMASH PRODUCT + {"Cdot", 0x0010A}, // LATIN CAPITAL LETTER C WITH DOT ABOVE + {"cdot", 0x0010B}, // LATIN SMALL LETTER C WITH DOT ABOVE + {"cedil", 0x000B8}, // CEDILLA + {"Cedilla", 0x000B8}, // CEDILLA + {"cemptyv", 0x029B2}, // EMPTY SET WITH SMALL CIRCLE ABOVE + {"cent", 0x000A2}, // CENT SIGN + {"centerdot", 0x000B7}, // MIDDLE DOT + {"CenterDot", 0x000B7}, // MIDDLE DOT + {"Cfr", 0x0212D}, // BLACK-LETTER CAPITAL C + {"cfr", 0x1D520}, // MATHEMATICAL FRAKTUR SMALL C + {"CHcy", 0x00427}, // CYRILLIC CAPITAL LETTER CHE + {"chcy", 0x00447}, // CYRILLIC SMALL LETTER CHE + {"check", 0x02713}, // CHECK MARK + {"checkmark", 0x02713}, // CHECK MARK + {"Chi", 0x003A7}, // GREEK CAPITAL LETTER CHI + {"chi", 0x003C7}, // GREEK SMALL LETTER CHI + {"cir", 0x025CB}, // WHITE CIRCLE + {"circ", 0x002C6}, // MODIFIER LETTER CIRCUMFLEX ACCENT + {"circeq", 0x02257}, // RING EQUAL TO + {"circlearrowleft", 0x021BA}, // ANTICLOCKWISE OPEN CIRCLE ARROW + {"circlearrowright", 0x021BB}, // CLOCKWISE OPEN CIRCLE ARROW + {"circledast", 0x0229B}, // CIRCLED ASTERISK OPERATOR + {"circledcirc", 0x0229A}, // CIRCLED RING OPERATOR + {"circleddash", 0x0229D}, // CIRCLED DASH + {"CircleDot", 0x02299}, // CIRCLED DOT OPERATOR + {"circledR", 0x000AE}, // REGISTERED SIGN + {"circledS", 0x024C8}, // CIRCLED LATIN CAPITAL LETTER S + {"CircleMinus", 0x02296}, // CIRCLED MINUS + {"CirclePlus", 0x02295}, // CIRCLED PLUS + {"CircleTimes", 0x02297}, // CIRCLED TIMES + {"cire", 0x02257}, // RING EQUAL TO + {"cirE", 0x029C3}, // CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT + {"cirfnint", 0x02A10}, // CIRCULATION FUNCTION + {"cirmid", 0x02AEF}, // VERTICAL LINE WITH CIRCLE ABOVE + {"cirscir", 0x029C2}, // CIRCLE WITH SMALL CIRCLE TO THE RIGHT + {"ClockwiseContourIntegral", 0x02232}, // CLOCKWISE CONTOUR INTEGRAL + {"CloseCurlyDoubleQuote", 0x0201D}, // RIGHT DOUBLE QUOTATION MARK + {"CloseCurlyQuote", 0x02019}, // RIGHT SINGLE QUOTATION MARK + {"clubs", 0x02663}, // BLACK CLUB SUIT + {"clubsuit", 0x02663}, // BLACK CLUB SUIT + {"colon", 0x0003A}, // COLON + {"Colon", 0x02237}, // PROPORTION + {"colone", 0x02254}, // COLON EQUALS + {"Colone", 0x02A74}, // DOUBLE COLON EQUAL + {"coloneq", 0x02254}, // COLON EQUALS + {"comma", 0x0002C}, // COMMA + {"commat", 0x00040}, // COMMERCIAL AT + {"comp", 0x02201}, // COMPLEMENT + {"compfn", 0x02218}, // RING OPERATOR + {"complement", 0x02201}, // COMPLEMENT + {"complexes", 0x02102}, // DOUBLE-STRUCK CAPITAL C + {"cong", 0x02245}, // APPROXIMATELY EQUAL TO + {"congdot", 0x02A6D}, // CONGRUENT WITH DOT ABOVE + {"Congruent", 0x02261}, // IDENTICAL TO + {"conint", 0x0222E}, // CONTOUR INTEGRAL + {"Conint", 0x0222F}, // SURFACE INTEGRAL + {"ContourIntegral", 0x0222E}, // CONTOUR INTEGRAL + {"Copf", 0x02102}, // DOUBLE-STRUCK CAPITAL C + {"copf", 0x1D554}, // MATHEMATICAL DOUBLE-STRUCK SMALL C + {"coprod", 0x02210}, // N-ARY COPRODUCT + {"Coproduct", 0x02210}, // N-ARY COPRODUCT + {"copy", 0x000A9}, // COPYRIGHT SIGN + {"COPY", 0x000A9}, // COPYRIGHT SIGN + {"copysr", 0x02117}, // SOUND RECORDING COPYRIGHT + {"CounterClockwiseContourIntegral", 0x02233}, // ANTICLOCKWISE CONTOUR INTEGRAL + {"crarr", 0x021B5}, // DOWNWARDS ARROW WITH CORNER LEFTWARDS + {"cross", 0x02717}, // BALLOT X + {"Cross", 0x02A2F}, // VECTOR OR CROSS PRODUCT + {"Cscr", 0x1D49E}, // MATHEMATICAL SCRIPT CAPITAL C + {"cscr", 0x1D4B8}, // MATHEMATICAL SCRIPT SMALL C + {"csub", 0x02ACF}, // CLOSED SUBSET + {"csube", 0x02AD1}, // CLOSED SUBSET OR EQUAL TO + {"csup", 0x02AD0}, // CLOSED SUPERSET + {"csupe", 0x02AD2}, // CLOSED SUPERSET OR EQUAL TO + {"ctdot", 0x022EF}, // MIDLINE HORIZONTAL ELLIPSIS + {"cudarrl", 0x02938}, // RIGHT-SIDE ARC CLOCKWISE ARROW + {"cudarrr", 0x02935}, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS + {"cuepr", 0x022DE}, // EQUAL TO OR PRECEDES + {"cuesc", 0x022DF}, // EQUAL TO OR SUCCEEDS + {"cularr", 0x021B6}, // ANTICLOCKWISE TOP SEMICIRCLE ARROW + {"cularrp", 0x0293D}, // TOP ARC ANTICLOCKWISE ARROW WITH PLUS + {"cup", 0x0222A}, // UNION + {"Cup", 0x022D3}, // DOUBLE UNION + {"cupbrcap", 0x02A48}, // UNION ABOVE BAR ABOVE INTERSECTION + {"CupCap", 0x0224D}, // EQUIVALENT TO + {"cupcap", 0x02A46}, // UNION ABOVE INTERSECTION + {"cupcup", 0x02A4A}, // UNION BESIDE AND JOINED WITH UNION + {"cupdot", 0x0228D}, // MULTISET MULTIPLICATION + {"cupor", 0x02A45}, // UNION WITH LOGICAL OR +// "cups", 0x0222A;0x0FE00}, // UNION with serifs + {"curarr", 0x021B7}, // CLOCKWISE TOP SEMICIRCLE ARROW + {"curarrm", 0x0293C}, // TOP ARC CLOCKWISE ARROW WITH MINUS + {"curlyeqprec", 0x022DE}, // EQUAL TO OR PRECEDES + {"curlyeqsucc", 0x022DF}, // EQUAL TO OR SUCCEEDS + {"curlyvee", 0x022CE}, // CURLY LOGICAL OR + {"curlywedge", 0x022CF}, // CURLY LOGICAL AND + {"curren", 0x000A4}, // CURRENCY SIGN + {"curvearrowleft", 0x021B6}, // ANTICLOCKWISE TOP SEMICIRCLE ARROW + {"curvearrowright", 0x021B7}, // CLOCKWISE TOP SEMICIRCLE ARROW + {"cuvee", 0x022CE}, // CURLY LOGICAL OR + {"cuwed", 0x022CF}, // CURLY LOGICAL AND + {"cwconint", 0x02232}, // CLOCKWISE CONTOUR INTEGRAL + {"cwint", 0x02231}, // CLOCKWISE INTEGRAL + {"cylcty", 0x0232D}, // CYLINDRICITY + {NULL, 0} }; static NameId namesD[]={ - "dagger", 0x02020, // DAGGER - "Dagger", 0x02021, // DOUBLE DAGGER - "daleth", 0x02138, // DALET SYMBOL - "darr", 0x02193, // DOWNWARDS ARROW - "Darr", 0x021A1, // DOWNWARDS TWO HEADED ARROW - "dArr", 0x021D3, // DOWNWARDS DOUBLE ARROW - "dash", 0x02010, // HYPHEN - "dashv", 0x022A3, // LEFT TACK - "Dashv", 0x02AE4, // VERTICAL BAR DOUBLE LEFT TURNSTILE - "dbkarow", 0x0290F, // RIGHTWARDS TRIPLE DASH ARROW - "dblac", 0x002DD, // DOUBLE ACUTE ACCENT - "Dcaron", 0x0010E, // LATIN CAPITAL LETTER D WITH CARON - "dcaron", 0x0010F, // LATIN SMALL LETTER D WITH CARON - "Dcy", 0x00414, // CYRILLIC CAPITAL LETTER DE - "dcy", 0x00434, // CYRILLIC SMALL LETTER DE - "DD", 0x02145, // DOUBLE-STRUCK ITALIC CAPITAL D - "dd", 0x02146, // DOUBLE-STRUCK ITALIC SMALL D - "ddagger", 0x02021, // DOUBLE DAGGER - "ddarr", 0x021CA, // DOWNWARDS PAIRED ARROWS - "DDotrahd", 0x02911, // RIGHTWARDS ARROW WITH DOTTED STEM - "ddotseq", 0x02A77, // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW - "deg", 0x000B0, // DEGREE SIGN - "Del", 0x02207, // NABLA - "Delta", 0x00394, // GREEK CAPITAL LETTER DELTA - "delta", 0x003B4, // GREEK SMALL LETTER DELTA - "demptyv", 0x029B1, // EMPTY SET WITH OVERBAR - "dfisht", 0x0297F, // DOWN FISH TAIL - "Dfr", 0x1D507, // MATHEMATICAL FRAKTUR CAPITAL D - "dfr", 0x1D521, // MATHEMATICAL FRAKTUR SMALL D - "Dgr", 0x00394, // GREEK CAPITAL LETTER DELTA - "dgr", 0x003B4, // GREEK SMALL LETTER DELTA - "dHar", 0x02965, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - "dharl", 0x021C3, // DOWNWARDS HARPOON WITH BARB LEFTWARDS - "dharr", 0x021C2, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - "DiacriticalAcute", 0x000B4, // ACUTE ACCENT - "DiacriticalDot", 0x002D9, // DOT ABOVE - "DiacriticalDoubleAcute", 0x002DD, // DOUBLE ACUTE ACCENT - "DiacriticalGrave", 0x00060, // GRAVE ACCENT - "DiacriticalTilde", 0x002DC, // SMALL TILDE - "diam", 0x022C4, // DIAMOND OPERATOR - "diamond", 0x022C4, // DIAMOND OPERATOR - "Diamond", 0x022C4, // DIAMOND OPERATOR - "diamondsuit", 0x02666, // BLACK DIAMOND SUIT - "diams", 0x02666, // BLACK DIAMOND SUIT - "die", 0x000A8, // DIAERESIS - "DifferentialD", 0x02146, // DOUBLE-STRUCK ITALIC SMALL D - "digamma", 0x003DD, // GREEK SMALL LETTER DIGAMMA - "disin", 0x022F2, // ELEMENT OF WITH LONG HORIZONTAL STROKE - "div", 0x000F7, // DIVISION SIGN - "divide", 0x000F7, // DIVISION SIGN - "divideontimes", 0x022C7, // DIVISION TIMES - "divonx", 0x022C7, // DIVISION TIMES - "DJcy", 0x00402, // CYRILLIC CAPITAL LETTER DJE - "djcy", 0x00452, // CYRILLIC SMALL LETTER DJE - "dlcorn", 0x0231E, // BOTTOM LEFT CORNER - "dlcrop", 0x0230D, // BOTTOM LEFT CROP - "dollar", 0x00024, // DOLLAR SIGN - "Dopf", 0x1D53B, // MATHEMATICAL DOUBLE-STRUCK CAPITAL D - "dopf", 0x1D555, // MATHEMATICAL DOUBLE-STRUCK SMALL D - "Dot", 0x000A8, // DIAERESIS - "dot", 0x002D9, // DOT ABOVE - "DotDot", 0x020DC, // COMBINING FOUR DOTS ABOVE - "doteq", 0x02250, // APPROACHES THE LIMIT - "doteqdot", 0x02251, // GEOMETRICALLY EQUAL TO - "DotEqual", 0x02250, // APPROACHES THE LIMIT - "dotminus", 0x02238, // DOT MINUS - "dotplus", 0x02214, // DOT PLUS - "dotsquare", 0x022A1, // SQUARED DOT OPERATOR - "doublebarwedge", 0x02306, // PERSPECTIVE - "DoubleContourIntegral", 0x0222F, // SURFACE INTEGRAL - "DoubleDot", 0x000A8, // DIAERESIS - "DoubleDownArrow", 0x021D3, // DOWNWARDS DOUBLE ARROW - "DoubleLeftArrow", 0x021D0, // LEFTWARDS DOUBLE ARROW - "DoubleLeftRightArrow", 0x021D4, // LEFT RIGHT DOUBLE ARROW - "DoubleLeftTee", 0x02AE4, // VERTICAL BAR DOUBLE LEFT TURNSTILE - "DoubleLongLeftArrow", 0x027F8, // LONG LEFTWARDS DOUBLE ARROW - "DoubleLongLeftRightArrow", 0x027FA, // LONG LEFT RIGHT DOUBLE ARROW - "DoubleLongRightArrow", 0x027F9, // LONG RIGHTWARDS DOUBLE ARROW - "DoubleRightArrow", 0x021D2, // RIGHTWARDS DOUBLE ARROW - "DoubleRightTee", 0x022A8, // TRUE - "DoubleUpArrow", 0x021D1, // UPWARDS DOUBLE ARROW - "DoubleUpDownArrow", 0x021D5, // UP DOWN DOUBLE ARROW - "DoubleVerticalBar", 0x02225, // PARALLEL TO - "downarrow", 0x02193, // DOWNWARDS ARROW - "DownArrow", 0x02193, // DOWNWARDS ARROW - "Downarrow", 0x021D3, // DOWNWARDS DOUBLE ARROW - "DownArrowBar", 0x02913, // DOWNWARDS ARROW TO BAR - "DownArrowUpArrow", 0x021F5, // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW - "DownBreve", 0x00311, // COMBINING INVERTED BREVE - "downdownarrows", 0x021CA, // DOWNWARDS PAIRED ARROWS - "downharpoonleft", 0x021C3, // DOWNWARDS HARPOON WITH BARB LEFTWARDS - "downharpoonright", 0x021C2, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - "DownLeftRightVector", 0x02950, // LEFT BARB DOWN RIGHT BARB DOWN HARPOON - "DownLeftTeeVector", 0x0295E, // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR - "DownLeftVector", 0x021BD, // LEFTWARDS HARPOON WITH BARB DOWNWARDS - "DownLeftVectorBar", 0x02956, // LEFTWARDS HARPOON WITH BARB DOWN TO BAR - "DownRightTeeVector", 0x0295F, // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR - "DownRightVector", 0x021C1, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - "DownRightVectorBar", 0x02957, // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR - "DownTee", 0x022A4, // DOWN TACK - "DownTeeArrow", 0x021A7, // DOWNWARDS ARROW FROM BAR - "drbkarow", 0x02910, // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW - "drcorn", 0x0231F, // BOTTOM RIGHT CORNER - "drcrop", 0x0230C, // BOTTOM RIGHT CROP - "Dscr", 0x1D49F, // MATHEMATICAL SCRIPT CAPITAL D - "dscr", 0x1D4B9, // MATHEMATICAL SCRIPT SMALL D - "DScy", 0x00405, // CYRILLIC CAPITAL LETTER DZE - "dscy", 0x00455, // CYRILLIC SMALL LETTER DZE - "dsol", 0x029F6, // SOLIDUS WITH OVERBAR - "Dstrok", 0x00110, // LATIN CAPITAL LETTER D WITH STROKE - "dstrok", 0x00111, // LATIN SMALL LETTER D WITH STROKE - "dtdot", 0x022F1, // DOWN RIGHT DIAGONAL ELLIPSIS - "dtri", 0x025BF, // WHITE DOWN-POINTING SMALL TRIANGLE - "dtrif", 0x025BE, // BLACK DOWN-POINTING SMALL TRIANGLE - "duarr", 0x021F5, // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW - "duhar", 0x0296F, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - "dwangle", 0x029A6, // OBLIQUE ANGLE OPENING UP - "DZcy", 0x0040F, // CYRILLIC CAPITAL LETTER DZHE - "dzcy", 0x0045F, // CYRILLIC SMALL LETTER DZHE - "dzigrarr", 0x027FF, // LONG RIGHTWARDS SQUIGGLE ARROW - NULL, 0 + {"dagger", 0x02020}, // DAGGER + {"Dagger", 0x02021}, // DOUBLE DAGGER + {"daleth", 0x02138}, // DALET SYMBOL + {"darr", 0x02193}, // DOWNWARDS ARROW + {"Darr", 0x021A1}, // DOWNWARDS TWO HEADED ARROW + {"dArr", 0x021D3}, // DOWNWARDS DOUBLE ARROW + {"dash", 0x02010}, // HYPHEN + {"dashv", 0x022A3}, // LEFT TACK + {"Dashv", 0x02AE4}, // VERTICAL BAR DOUBLE LEFT TURNSTILE + {"dbkarow", 0x0290F}, // RIGHTWARDS TRIPLE DASH ARROW + {"dblac", 0x002DD}, // DOUBLE ACUTE ACCENT + {"Dcaron", 0x0010E}, // LATIN CAPITAL LETTER D WITH CARON + {"dcaron", 0x0010F}, // LATIN SMALL LETTER D WITH CARON + {"Dcy", 0x00414}, // CYRILLIC CAPITAL LETTER DE + {"dcy", 0x00434}, // CYRILLIC SMALL LETTER DE + {"DD", 0x02145}, // DOUBLE-STRUCK ITALIC CAPITAL D + {"dd", 0x02146}, // DOUBLE-STRUCK ITALIC SMALL D + {"ddagger", 0x02021}, // DOUBLE DAGGER + {"ddarr", 0x021CA}, // DOWNWARDS PAIRED ARROWS + {"DDotrahd", 0x02911}, // RIGHTWARDS ARROW WITH DOTTED STEM + {"ddotseq", 0x02A77}, // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW + {"deg", 0x000B0}, // DEGREE SIGN + {"Del", 0x02207}, // NABLA + {"Delta", 0x00394}, // GREEK CAPITAL LETTER DELTA + {"delta", 0x003B4}, // GREEK SMALL LETTER DELTA + {"demptyv", 0x029B1}, // EMPTY SET WITH OVERBAR + {"dfisht", 0x0297F}, // DOWN FISH TAIL + {"Dfr", 0x1D507}, // MATHEMATICAL FRAKTUR CAPITAL D + {"dfr", 0x1D521}, // MATHEMATICAL FRAKTUR SMALL D + {"Dgr", 0x00394}, // GREEK CAPITAL LETTER DELTA + {"dgr", 0x003B4}, // GREEK SMALL LETTER DELTA + {"dHar", 0x02965}, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + {"dharl", 0x021C3}, // DOWNWARDS HARPOON WITH BARB LEFTWARDS + {"dharr", 0x021C2}, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + {"DiacriticalAcute", 0x000B4}, // ACUTE ACCENT + {"DiacriticalDot", 0x002D9}, // DOT ABOVE + {"DiacriticalDoubleAcute", 0x002DD}, // DOUBLE ACUTE ACCENT + {"DiacriticalGrave", 0x00060}, // GRAVE ACCENT + {"DiacriticalTilde", 0x002DC}, // SMALL TILDE + {"diam", 0x022C4}, // DIAMOND OPERATOR + {"diamond", 0x022C4}, // DIAMOND OPERATOR + {"Diamond", 0x022C4}, // DIAMOND OPERATOR + {"diamondsuit", 0x02666}, // BLACK DIAMOND SUIT + {"diams", 0x02666}, // BLACK DIAMOND SUIT + {"die", 0x000A8}, // DIAERESIS + {"DifferentialD", 0x02146}, // DOUBLE-STRUCK ITALIC SMALL D + {"digamma", 0x003DD}, // GREEK SMALL LETTER DIGAMMA + {"disin", 0x022F2}, // ELEMENT OF WITH LONG HORIZONTAL STROKE + {"div", 0x000F7}, // DIVISION SIGN + {"divide", 0x000F7}, // DIVISION SIGN + {"divideontimes", 0x022C7}, // DIVISION TIMES + {"divonx", 0x022C7}, // DIVISION TIMES + {"DJcy", 0x00402}, // CYRILLIC CAPITAL LETTER DJE + {"djcy", 0x00452}, // CYRILLIC SMALL LETTER DJE + {"dlcorn", 0x0231E}, // BOTTOM LEFT CORNER + {"dlcrop", 0x0230D}, // BOTTOM LEFT CROP + {"dollar", 0x00024}, // DOLLAR SIGN + {"Dopf", 0x1D53B}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL D + {"dopf", 0x1D555}, // MATHEMATICAL DOUBLE-STRUCK SMALL D + {"Dot", 0x000A8}, // DIAERESIS + {"dot", 0x002D9}, // DOT ABOVE + {"DotDot", 0x020DC}, // COMBINING FOUR DOTS ABOVE + {"doteq", 0x02250}, // APPROACHES THE LIMIT + {"doteqdot", 0x02251}, // GEOMETRICALLY EQUAL TO + {"DotEqual", 0x02250}, // APPROACHES THE LIMIT + {"dotminus", 0x02238}, // DOT MINUS + {"dotplus", 0x02214}, // DOT PLUS + {"dotsquare", 0x022A1}, // SQUARED DOT OPERATOR + {"doublebarwedge", 0x02306}, // PERSPECTIVE + {"DoubleContourIntegral", 0x0222F}, // SURFACE INTEGRAL + {"DoubleDot", 0x000A8}, // DIAERESIS + {"DoubleDownArrow", 0x021D3}, // DOWNWARDS DOUBLE ARROW + {"DoubleLeftArrow", 0x021D0}, // LEFTWARDS DOUBLE ARROW + {"DoubleLeftRightArrow", 0x021D4}, // LEFT RIGHT DOUBLE ARROW + {"DoubleLeftTee", 0x02AE4}, // VERTICAL BAR DOUBLE LEFT TURNSTILE + {"DoubleLongLeftArrow", 0x027F8}, // LONG LEFTWARDS DOUBLE ARROW + {"DoubleLongLeftRightArrow", 0x027FA}, // LONG LEFT RIGHT DOUBLE ARROW + {"DoubleLongRightArrow", 0x027F9}, // LONG RIGHTWARDS DOUBLE ARROW + {"DoubleRightArrow", 0x021D2}, // RIGHTWARDS DOUBLE ARROW + {"DoubleRightTee", 0x022A8}, // TRUE + {"DoubleUpArrow", 0x021D1}, // UPWARDS DOUBLE ARROW + {"DoubleUpDownArrow", 0x021D5}, // UP DOWN DOUBLE ARROW + {"DoubleVerticalBar", 0x02225}, // PARALLEL TO + {"downarrow", 0x02193}, // DOWNWARDS ARROW + {"DownArrow", 0x02193}, // DOWNWARDS ARROW + {"Downarrow", 0x021D3}, // DOWNWARDS DOUBLE ARROW + {"DownArrowBar", 0x02913}, // DOWNWARDS ARROW TO BAR + {"DownArrowUpArrow", 0x021F5}, // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW + {"DownBreve", 0x00311}, // COMBINING INVERTED BREVE + {"downdownarrows", 0x021CA}, // DOWNWARDS PAIRED ARROWS + {"downharpoonleft", 0x021C3}, // DOWNWARDS HARPOON WITH BARB LEFTWARDS + {"downharpoonright", 0x021C2}, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + {"DownLeftRightVector", 0x02950}, // LEFT BARB DOWN RIGHT BARB DOWN HARPOON + {"DownLeftTeeVector", 0x0295E}, // LEFTWARDS HARPOON WITH BARB DOWN FROM BAR + {"DownLeftVector", 0x021BD}, // LEFTWARDS HARPOON WITH BARB DOWNWARDS + {"DownLeftVectorBar", 0x02956}, // LEFTWARDS HARPOON WITH BARB DOWN TO BAR + {"DownRightTeeVector", 0x0295F}, // RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR + {"DownRightVector", 0x021C1}, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + {"DownRightVectorBar", 0x02957}, // RIGHTWARDS HARPOON WITH BARB DOWN TO BAR + {"DownTee", 0x022A4}, // DOWN TACK + {"DownTeeArrow", 0x021A7}, // DOWNWARDS ARROW FROM BAR + {"drbkarow", 0x02910}, // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW + {"drcorn", 0x0231F}, // BOTTOM RIGHT CORNER + {"drcrop", 0x0230C}, // BOTTOM RIGHT CROP + {"Dscr", 0x1D49F}, // MATHEMATICAL SCRIPT CAPITAL D + {"dscr", 0x1D4B9}, // MATHEMATICAL SCRIPT SMALL D + {"DScy", 0x00405}, // CYRILLIC CAPITAL LETTER DZE + {"dscy", 0x00455}, // CYRILLIC SMALL LETTER DZE + {"dsol", 0x029F6}, // SOLIDUS WITH OVERBAR + {"Dstrok", 0x00110}, // LATIN CAPITAL LETTER D WITH STROKE + {"dstrok", 0x00111}, // LATIN SMALL LETTER D WITH STROKE + {"dtdot", 0x022F1}, // DOWN RIGHT DIAGONAL ELLIPSIS + {"dtri", 0x025BF}, // WHITE DOWN-POINTING SMALL TRIANGLE + {"dtrif", 0x025BE}, // BLACK DOWN-POINTING SMALL TRIANGLE + {"duarr", 0x021F5}, // DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW + {"duhar", 0x0296F}, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + {"dwangle", 0x029A6}, // OBLIQUE ANGLE OPENING UP + {"DZcy", 0x0040F}, // CYRILLIC CAPITAL LETTER DZHE + {"dzcy", 0x0045F}, // CYRILLIC SMALL LETTER DZHE + {"dzigrarr", 0x027FF}, // LONG RIGHTWARDS SQUIGGLE ARROW + {NULL, 0} }; static NameId namesE[]={ - "Eacgr", 0x00388, // GREEK CAPITAL LETTER EPSILON WITH TONOS - "eacgr", 0x003AD, // GREEK SMALL LETTER EPSILON WITH TONOS - "Eacute", 0x000C9, // LATIN CAPITAL LETTER E WITH ACUTE - "eacute", 0x000E9, // LATIN SMALL LETTER E WITH ACUTE - "easter", 0x02A6E, // EQUALS WITH ASTERISK - "Ecaron", 0x0011A, // LATIN CAPITAL LETTER E WITH CARON - "ecaron", 0x0011B, // LATIN SMALL LETTER E WITH CARON - "ecir", 0x02256, // RING IN EQUAL TO - "Ecirc", 0x000CA, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX - "ecirc", 0x000EA, // LATIN SMALL LETTER E WITH CIRCUMFLEX - "ecolon", 0x02255, // EQUALS COLON - "Ecy", 0x0042D, // CYRILLIC CAPITAL LETTER E - "ecy", 0x0044D, // CYRILLIC SMALL LETTER E - "eDDot", 0x02A77, // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW - "Edot", 0x00116, // LATIN CAPITAL LETTER E WITH DOT ABOVE - "edot", 0x00117, // LATIN SMALL LETTER E WITH DOT ABOVE - "eDot", 0x02251, // GEOMETRICALLY EQUAL TO - "ee", 0x02147, // DOUBLE-STRUCK ITALIC SMALL E - "EEacgr", 0x00389, // GREEK CAPITAL LETTER ETA WITH TONOS - "eeacgr", 0x003AE, // GREEK SMALL LETTER ETA WITH TONOS - "EEgr", 0x00397, // GREEK CAPITAL LETTER ETA - "eegr", 0x003B7, // GREEK SMALL LETTER ETA - "efDot", 0x02252, // APPROXIMATELY EQUAL TO OR THE IMAGE OF - "Efr", 0x1D508, // MATHEMATICAL FRAKTUR CAPITAL E - "efr", 0x1D522, // MATHEMATICAL FRAKTUR SMALL E - "eg", 0x02A9A, // DOUBLE-LINE EQUAL TO OR GREATER-THAN - "Egr", 0x00395, // GREEK CAPITAL LETTER EPSILON - "egr", 0x003B5, // GREEK SMALL LETTER EPSILON - "Egrave", 0x000C8, // LATIN CAPITAL LETTER E WITH GRAVE - "egrave", 0x000E8, // LATIN SMALL LETTER E WITH GRAVE - "egs", 0x02A96, // SLANTED EQUAL TO OR GREATER-THAN - "egsdot", 0x02A98, // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE - "el", 0x02A99, // DOUBLE-LINE EQUAL TO OR LESS-THAN - "Element", 0x02208, // ELEMENT OF - "elinters", 0x023E7, // ELECTRICAL INTERSECTION - "ell", 0x02113, // SCRIPT SMALL L - "els", 0x02A95, // SLANTED EQUAL TO OR LESS-THAN - "elsdot", 0x02A97, // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE - "Emacr", 0x00112, // LATIN CAPITAL LETTER E WITH MACRON - "emacr", 0x00113, // LATIN SMALL LETTER E WITH MACRON - "empty", 0x02205, // EMPTY SET - "emptyset", 0x02205, // EMPTY SET - "EmptySmallSquare", 0x025FB, // WHITE MEDIUM SQUARE - "emptyv", 0x02205, // EMPTY SET - "EmptyVerySmallSquare", 0x025AB, // WHITE SMALL SQUARE - "emsp", 0x02003, // EM SPACE - "emsp13", 0x02004, // THREE-PER-EM SPACE - "emsp14", 0x02005, // FOUR-PER-EM SPACE - "ENG", 0x0014A, // LATIN CAPITAL LETTER ENG - "eng", 0x0014B, // LATIN SMALL LETTER ENG - "ensp", 0x02002, // EN SPACE - "Eogon", 0x00118, // LATIN CAPITAL LETTER E WITH OGONEK - "eogon", 0x00119, // LATIN SMALL LETTER E WITH OGONEK - "Eopf", 0x1D53C, // MATHEMATICAL DOUBLE-STRUCK CAPITAL E - "eopf", 0x1D556, // MATHEMATICAL DOUBLE-STRUCK SMALL E - "epar", 0x022D5, // EQUAL AND PARALLEL TO - "eparsl", 0x029E3, // EQUALS SIGN AND SLANTED PARALLEL - "eplus", 0x02A71, // EQUALS SIGN ABOVE PLUS SIGN - "epsi", 0x003B5, // GREEK SMALL LETTER EPSILON - "Epsilon", 0x00395, // GREEK CAPITAL LETTER EPSILON - "epsilon", 0x003B5, // GREEK SMALL LETTER EPSILON - "epsiv", 0x003F5, // GREEK LUNATE EPSILON SYMBOL - "eqcirc", 0x02256, // RING IN EQUAL TO - "eqcolon", 0x02255, // EQUALS COLON - "eqsim", 0x02242, // MINUS TILDE - "eqslantgtr", 0x02A96, // SLANTED EQUAL TO OR GREATER-THAN - "eqslantless", 0x02A95, // SLANTED EQUAL TO OR LESS-THAN - "Equal", 0x02A75, // TWO CONSECUTIVE EQUALS SIGNS - "equals", 0x0003D, // EQUALS SIGN - "EqualTilde", 0x02242, // MINUS TILDE - "equest", 0x0225F, // QUESTIONED EQUAL TO - "Equilibrium", 0x021CC, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - "equiv", 0x02261, // IDENTICAL TO - "equivDD", 0x02A78, // EQUIVALENT WITH FOUR DOTS ABOVE - "eqvparsl", 0x029E5, // IDENTICAL TO AND SLANTED PARALLEL - "erarr", 0x02971, // EQUALS SIGN ABOVE RIGHTWARDS ARROW - "erDot", 0x02253, // IMAGE OF OR APPROXIMATELY EQUAL TO - "escr", 0x0212F, // SCRIPT SMALL E - "Escr", 0x02130, // SCRIPT CAPITAL E - "esdot", 0x02250, // APPROACHES THE LIMIT - "esim", 0x02242, // MINUS TILDE - "Esim", 0x02A73, // EQUALS SIGN ABOVE TILDE OPERATOR - "Eta", 0x00397, // GREEK CAPITAL LETTER ETA - "eta", 0x003B7, // GREEK SMALL LETTER ETA - "ETH", 0x000D0, // LATIN CAPITAL LETTER ETH - "eth", 0x000F0, // LATIN SMALL LETTER ETH - "Euml", 0x000CB, // LATIN CAPITAL LETTER E WITH DIAERESIS - "euml", 0x000EB, // LATIN SMALL LETTER E WITH DIAERESIS - "euro", 0x020AC, // EURO SIGN - "excl", 0x00021, // EXCLAMATION MARK - "exist", 0x02203, // THERE EXISTS - "Exists", 0x02203, // THERE EXISTS - "expectation", 0x02130, // SCRIPT CAPITAL E - "exponentiale", 0x02147, // DOUBLE-STRUCK ITALIC SMALL E - "ExponentialE", 0x02147, // DOUBLE-STRUCK ITALIC SMALL E - NULL, 0 + {"Eacgr", 0x00388}, // GREEK CAPITAL LETTER EPSILON WITH TONOS + {"eacgr", 0x003AD}, // GREEK SMALL LETTER EPSILON WITH TONOS + {"Eacute", 0x000C9}, // LATIN CAPITAL LETTER E WITH ACUTE + {"eacute", 0x000E9}, // LATIN SMALL LETTER E WITH ACUTE + {"easter", 0x02A6E}, // EQUALS WITH ASTERISK + {"Ecaron", 0x0011A}, // LATIN CAPITAL LETTER E WITH CARON + {"ecaron", 0x0011B}, // LATIN SMALL LETTER E WITH CARON + {"ecir", 0x02256}, // RING IN EQUAL TO + {"Ecirc", 0x000CA}, // LATIN CAPITAL LETTER E WITH CIRCUMFLEX + {"ecirc", 0x000EA}, // LATIN SMALL LETTER E WITH CIRCUMFLEX + {"ecolon", 0x02255}, // EQUALS COLON + {"Ecy", 0x0042D}, // CYRILLIC CAPITAL LETTER E + {"ecy", 0x0044D}, // CYRILLIC SMALL LETTER E + {"eDDot", 0x02A77}, // EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW + {"Edot", 0x00116}, // LATIN CAPITAL LETTER E WITH DOT ABOVE + {"edot", 0x00117}, // LATIN SMALL LETTER E WITH DOT ABOVE + {"eDot", 0x02251}, // GEOMETRICALLY EQUAL TO + {"ee", 0x02147}, // DOUBLE-STRUCK ITALIC SMALL E + {"EEacgr", 0x00389}, // GREEK CAPITAL LETTER ETA WITH TONOS + {"eeacgr", 0x003AE}, // GREEK SMALL LETTER ETA WITH TONOS + {"EEgr", 0x00397}, // GREEK CAPITAL LETTER ETA + {"eegr", 0x003B7}, // GREEK SMALL LETTER ETA + {"efDot", 0x02252}, // APPROXIMATELY EQUAL TO OR THE IMAGE OF + {"Efr", 0x1D508}, // MATHEMATICAL FRAKTUR CAPITAL E + {"efr", 0x1D522}, // MATHEMATICAL FRAKTUR SMALL E + {"eg", 0x02A9A}, // DOUBLE-LINE EQUAL TO OR GREATER-THAN + {"Egr", 0x00395}, // GREEK CAPITAL LETTER EPSILON + {"egr", 0x003B5}, // GREEK SMALL LETTER EPSILON + {"Egrave", 0x000C8}, // LATIN CAPITAL LETTER E WITH GRAVE + {"egrave", 0x000E8}, // LATIN SMALL LETTER E WITH GRAVE + {"egs", 0x02A96}, // SLANTED EQUAL TO OR GREATER-THAN + {"egsdot", 0x02A98}, // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE + {"el", 0x02A99}, // DOUBLE-LINE EQUAL TO OR LESS-THAN + {"Element", 0x02208}, // ELEMENT OF + {"elinters", 0x023E7}, // ELECTRICAL INTERSECTION + {"ell", 0x02113}, // SCRIPT SMALL L + {"els", 0x02A95}, // SLANTED EQUAL TO OR LESS-THAN + {"elsdot", 0x02A97}, // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE + {"Emacr", 0x00112}, // LATIN CAPITAL LETTER E WITH MACRON + {"emacr", 0x00113}, // LATIN SMALL LETTER E WITH MACRON + {"empty", 0x02205}, // EMPTY SET + {"emptyset", 0x02205}, // EMPTY SET + {"EmptySmallSquare", 0x025FB}, // WHITE MEDIUM SQUARE + {"emptyv", 0x02205}, // EMPTY SET + {"EmptyVerySmallSquare", 0x025AB}, // WHITE SMALL SQUARE + {"emsp", 0x02003}, // EM SPACE + {"emsp13", 0x02004}, // THREE-PER-EM SPACE + {"emsp14", 0x02005}, // FOUR-PER-EM SPACE + {"ENG", 0x0014A}, // LATIN CAPITAL LETTER ENG + {"eng", 0x0014B}, // LATIN SMALL LETTER ENG + {"ensp", 0x02002}, // EN SPACE + {"Eogon", 0x00118}, // LATIN CAPITAL LETTER E WITH OGONEK + {"eogon", 0x00119}, // LATIN SMALL LETTER E WITH OGONEK + {"Eopf", 0x1D53C}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL E + {"eopf", 0x1D556}, // MATHEMATICAL DOUBLE-STRUCK SMALL E + {"epar", 0x022D5}, // EQUAL AND PARALLEL TO + {"eparsl", 0x029E3}, // EQUALS SIGN AND SLANTED PARALLEL + {"eplus", 0x02A71}, // EQUALS SIGN ABOVE PLUS SIGN + {"epsi", 0x003B5}, // GREEK SMALL LETTER EPSILON + {"Epsilon", 0x00395}, // GREEK CAPITAL LETTER EPSILON + {"epsilon", 0x003B5}, // GREEK SMALL LETTER EPSILON + {"epsiv", 0x003F5}, // GREEK LUNATE EPSILON SYMBOL + {"eqcirc", 0x02256}, // RING IN EQUAL TO + {"eqcolon", 0x02255}, // EQUALS COLON + {"eqsim", 0x02242}, // MINUS TILDE + {"eqslantgtr", 0x02A96}, // SLANTED EQUAL TO OR GREATER-THAN + {"eqslantless", 0x02A95}, // SLANTED EQUAL TO OR LESS-THAN + {"Equal", 0x02A75}, // TWO CONSECUTIVE EQUALS SIGNS + {"equals", 0x0003D}, // EQUALS SIGN + {"EqualTilde", 0x02242}, // MINUS TILDE + {"equest", 0x0225F}, // QUESTIONED EQUAL TO + {"Equilibrium", 0x021CC}, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + {"equiv", 0x02261}, // IDENTICAL TO + {"equivDD", 0x02A78}, // EQUIVALENT WITH FOUR DOTS ABOVE + {"eqvparsl", 0x029E5}, // IDENTICAL TO AND SLANTED PARALLEL + {"erarr", 0x02971}, // EQUALS SIGN ABOVE RIGHTWARDS ARROW + {"erDot", 0x02253}, // IMAGE OF OR APPROXIMATELY EQUAL TO + {"escr", 0x0212F}, // SCRIPT SMALL E + {"Escr", 0x02130}, // SCRIPT CAPITAL E + {"esdot", 0x02250}, // APPROACHES THE LIMIT + {"esim", 0x02242}, // MINUS TILDE + {"Esim", 0x02A73}, // EQUALS SIGN ABOVE TILDE OPERATOR + {"Eta", 0x00397}, // GREEK CAPITAL LETTER ETA + {"eta", 0x003B7}, // GREEK SMALL LETTER ETA + {"ETH", 0x000D0}, // LATIN CAPITAL LETTER ETH + {"eth", 0x000F0}, // LATIN SMALL LETTER ETH + {"Euml", 0x000CB}, // LATIN CAPITAL LETTER E WITH DIAERESIS + {"euml", 0x000EB}, // LATIN SMALL LETTER E WITH DIAERESIS + {"euro", 0x020AC}, // EURO SIGN + {"excl", 0x00021}, // EXCLAMATION MARK + {"exist", 0x02203}, // THERE EXISTS + {"Exists", 0x02203}, // THERE EXISTS + {"expectation", 0x02130}, // SCRIPT CAPITAL E + {"exponentiale", 0x02147}, // DOUBLE-STRUCK ITALIC SMALL E + {"ExponentialE", 0x02147}, // DOUBLE-STRUCK ITALIC SMALL E + {NULL, 0} }; static NameId namesF[]={ - "fallingdotseq", 0x02252, // APPROXIMATELY EQUAL TO OR THE IMAGE OF - "Fcy", 0x00424, // CYRILLIC CAPITAL LETTER EF - "fcy", 0x00444, // CYRILLIC SMALL LETTER EF - "female", 0x02640, // FEMALE SIGN - "ffilig", 0x0FB03, // LATIN SMALL LIGATURE FFI - "fflig", 0x0FB00, // LATIN SMALL LIGATURE FF - "ffllig", 0x0FB04, // LATIN SMALL LIGATURE FFL - "Ffr", 0x1D509, // MATHEMATICAL FRAKTUR CAPITAL F - "ffr", 0x1D523, // MATHEMATICAL FRAKTUR SMALL F - "filig", 0x0FB01, // LATIN SMALL LIGATURE FI - "FilledSmallSquare", 0x025FC, // BLACK MEDIUM SQUARE - "FilledVerySmallSquare", 0x025AA, // BLACK SMALL SQUARE -// "fjlig", 0x00066;0x0006A, // fj ligature - "flat", 0x0266D, // MUSIC FLAT SIGN - "fllig", 0x0FB02, // LATIN SMALL LIGATURE FL - "fltns", 0x025B1, // WHITE PARALLELOGRAM - "fnof", 0x00192, // LATIN SMALL LETTER F WITH HOOK - "Fopf", 0x1D53D, // MATHEMATICAL DOUBLE-STRUCK CAPITAL F - "fopf", 0x1D557, // MATHEMATICAL DOUBLE-STRUCK SMALL F - "forall", 0x02200, // FOR ALL - "ForAll", 0x02200, // FOR ALL - "fork", 0x022D4, // PITCHFORK - "forkv", 0x02AD9, // ELEMENT OF OPENING DOWNWARDS - "Fouriertrf", 0x02131, // SCRIPT CAPITAL F - "fpartint", 0x02A0D, // FINITE PART INTEGRAL - "frac12", 0x000BD, // VULGAR FRACTION ONE HALF - "frac13", 0x02153, // VULGAR FRACTION ONE THIRD - "frac14", 0x000BC, // VULGAR FRACTION ONE QUARTER - "frac15", 0x02155, // VULGAR FRACTION ONE FIFTH - "frac16", 0x02159, // VULGAR FRACTION ONE SIXTH - "frac18", 0x0215B, // VULGAR FRACTION ONE EIGHTH - "frac23", 0x02154, // VULGAR FRACTION TWO THIRDS - "frac25", 0x02156, // VULGAR FRACTION TWO FIFTHS - "frac34", 0x000BE, // VULGAR FRACTION THREE QUARTERS - "frac35", 0x02157, // VULGAR FRACTION THREE FIFTHS - "frac38", 0x0215C, // VULGAR FRACTION THREE EIGHTHS - "frac45", 0x02158, // VULGAR FRACTION FOUR FIFTHS - "frac56", 0x0215A, // VULGAR FRACTION FIVE SIXTHS - "frac58", 0x0215D, // VULGAR FRACTION FIVE EIGHTHS - "frac78", 0x0215E, // VULGAR FRACTION SEVEN EIGHTHS - "frasl", 0x02044, // FRACTION SLASH - "frown", 0x02322, // FROWN - "Fscr", 0x02131, // SCRIPT CAPITAL F - "fscr", 0x1D4BB, // MATHEMATICAL SCRIPT SMALL F - NULL, 0 + {"fallingdotseq", 0x02252}, // APPROXIMATELY EQUAL TO OR THE IMAGE OF + {"Fcy", 0x00424}, // CYRILLIC CAPITAL LETTER EF + {"fcy", 0x00444}, // CYRILLIC SMALL LETTER EF + {"female", 0x02640}, // FEMALE SIGN + {"ffilig", 0x0FB03}, // LATIN SMALL LIGATURE FFI + {"fflig", 0x0FB00}, // LATIN SMALL LIGATURE FF + {"ffllig", 0x0FB04}, // LATIN SMALL LIGATURE FFL + {"Ffr", 0x1D509}, // MATHEMATICAL FRAKTUR CAPITAL F + {"ffr", 0x1D523}, // MATHEMATICAL FRAKTUR SMALL F + {"filig", 0x0FB01}, // LATIN SMALL LIGATURE FI + {"FilledSmallSquare", 0x025FC}, // BLACK MEDIUM SQUARE + {"FilledVerySmallSquare", 0x025AA}, // BLACK SMALL SQUARE +// "fjlig", 0x00066;0x0006A}, // fj ligature + {"flat", 0x0266D}, // MUSIC FLAT SIGN + {"fllig", 0x0FB02}, // LATIN SMALL LIGATURE FL + {"fltns", 0x025B1}, // WHITE PARALLELOGRAM + {"fnof", 0x00192}, // LATIN SMALL LETTER F WITH HOOK + {"Fopf", 0x1D53D}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL F + {"fopf", 0x1D557}, // MATHEMATICAL DOUBLE-STRUCK SMALL F + {"forall", 0x02200}, // FOR ALL + {"ForAll", 0x02200}, // FOR ALL + {"fork", 0x022D4}, // PITCHFORK + {"forkv", 0x02AD9}, // ELEMENT OF OPENING DOWNWARDS + {"Fouriertrf", 0x02131}, // SCRIPT CAPITAL F + {"fpartint", 0x02A0D}, // FINITE PART INTEGRAL + {"frac12", 0x000BD}, // VULGAR FRACTION ONE HALF + {"frac13", 0x02153}, // VULGAR FRACTION ONE THIRD + {"frac14", 0x000BC}, // VULGAR FRACTION ONE QUARTER + {"frac15", 0x02155}, // VULGAR FRACTION ONE FIFTH + {"frac16", 0x02159}, // VULGAR FRACTION ONE SIXTH + {"frac18", 0x0215B}, // VULGAR FRACTION ONE EIGHTH + {"frac23", 0x02154}, // VULGAR FRACTION TWO THIRDS + {"frac25", 0x02156}, // VULGAR FRACTION TWO FIFTHS + {"frac34", 0x000BE}, // VULGAR FRACTION THREE QUARTERS + {"frac35", 0x02157}, // VULGAR FRACTION THREE FIFTHS + {"frac38", 0x0215C}, // VULGAR FRACTION THREE EIGHTHS + {"frac45", 0x02158}, // VULGAR FRACTION FOUR FIFTHS + {"frac56", 0x0215A}, // VULGAR FRACTION FIVE SIXTHS + {"frac58", 0x0215D}, // VULGAR FRACTION FIVE EIGHTHS + {"frac78", 0x0215E}, // VULGAR FRACTION SEVEN EIGHTHS + {"frasl", 0x02044}, // FRACTION SLASH + {"frown", 0x02322}, // FROWN + {"Fscr", 0x02131}, // SCRIPT CAPITAL F + {"fscr", 0x1D4BB}, // MATHEMATICAL SCRIPT SMALL F + {NULL, 0} }; static NameId namesG[]={ - "gacute", 0x001F5, // LATIN SMALL LETTER G WITH ACUTE - "Gamma", 0x00393, // GREEK CAPITAL LETTER GAMMA - "gamma", 0x003B3, // GREEK SMALL LETTER GAMMA - "Gammad", 0x003DC, // GREEK LETTER DIGAMMA - "gammad", 0x003DD, // GREEK SMALL LETTER DIGAMMA - "gap", 0x02A86, // GREATER-THAN OR APPROXIMATE - "Gbreve", 0x0011E, // LATIN CAPITAL LETTER G WITH BREVE - "gbreve", 0x0011F, // LATIN SMALL LETTER G WITH BREVE - "Gcedil", 0x00122, // LATIN CAPITAL LETTER G WITH CEDILLA - "Gcirc", 0x0011C, // LATIN CAPITAL LETTER G WITH CIRCUMFLEX - "gcirc", 0x0011D, // LATIN SMALL LETTER G WITH CIRCUMFLEX - "Gcy", 0x00413, // CYRILLIC CAPITAL LETTER GHE - "gcy", 0x00433, // CYRILLIC SMALL LETTER GHE - "Gdot", 0x00120, // LATIN CAPITAL LETTER G WITH DOT ABOVE - "gdot", 0x00121, // LATIN SMALL LETTER G WITH DOT ABOVE - "ge", 0x02265, // GREATER-THAN OR EQUAL TO - "gE", 0x02267, // GREATER-THAN OVER EQUAL TO - "gel", 0x022DB, // GREATER-THAN EQUAL TO OR LESS-THAN - "gEl", 0x02A8C, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN - "geq", 0x02265, // GREATER-THAN OR EQUAL TO - "geqq", 0x02267, // GREATER-THAN OVER EQUAL TO - "geqslant", 0x02A7E, // GREATER-THAN OR SLANTED EQUAL TO - "ges", 0x02A7E, // GREATER-THAN OR SLANTED EQUAL TO - "gescc", 0x02AA9, // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL - "gesdot", 0x02A80, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE - "gesdoto", 0x02A82, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE - "gesdotol", 0x02A84, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT -// "gesl", 0x022DB;0x0FE00, // GREATER-THAN slanted EQUAL TO OR LESS-THAN - "gesles", 0x02A94, // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL - "Gfr", 0x1D50A, // MATHEMATICAL FRAKTUR CAPITAL G - "gfr", 0x1D524, // MATHEMATICAL FRAKTUR SMALL G - "gg", 0x0226B, // MUCH GREATER-THAN - "Gg", 0x022D9, // VERY MUCH GREATER-THAN - "ggg", 0x022D9, // VERY MUCH GREATER-THAN - "Ggr", 0x00393, // GREEK CAPITAL LETTER GAMMA - "ggr", 0x003B3, // GREEK SMALL LETTER GAMMA - "gimel", 0x02137, // GIMEL SYMBOL - "GJcy", 0x00403, // CYRILLIC CAPITAL LETTER GJE - "gjcy", 0x00453, // CYRILLIC SMALL LETTER GJE - "gl", 0x02277, // GREATER-THAN OR LESS-THAN - "gla", 0x02AA5, // GREATER-THAN BESIDE LESS-THAN - "glE", 0x02A92, // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL - "glj", 0x02AA4, // GREATER-THAN OVERLAPPING LESS-THAN - "gnap", 0x02A8A, // GREATER-THAN AND NOT APPROXIMATE - "gnapprox", 0x02A8A, // GREATER-THAN AND NOT APPROXIMATE - "gnE", 0x02269, // GREATER-THAN BUT NOT EQUAL TO - "gne", 0x02A88, // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - "gneq", 0x02A88, // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO - "gneqq", 0x02269, // GREATER-THAN BUT NOT EQUAL TO - "gnsim", 0x022E7, // GREATER-THAN BUT NOT EQUIVALENT TO - "Gopf", 0x1D53E, // MATHEMATICAL DOUBLE-STRUCK CAPITAL G - "gopf", 0x1D558, // MATHEMATICAL DOUBLE-STRUCK SMALL G - "grave", 0x00060, // GRAVE ACCENT - "GreaterEqual", 0x02265, // GREATER-THAN OR EQUAL TO - "GreaterEqualLess", 0x022DB, // GREATER-THAN EQUAL TO OR LESS-THAN - "GreaterFullEqual", 0x02267, // GREATER-THAN OVER EQUAL TO - "GreaterGreater", 0x02AA2, // DOUBLE NESTED GREATER-THAN - "GreaterLess", 0x02277, // GREATER-THAN OR LESS-THAN - "GreaterSlantEqual", 0x02A7E, // GREATER-THAN OR SLANTED EQUAL TO - "GreaterTilde", 0x02273, // GREATER-THAN OR EQUIVALENT TO - "gscr", 0x0210A, // SCRIPT SMALL G - "Gscr", 0x1D4A2, // MATHEMATICAL SCRIPT CAPITAL G - "gsim", 0x02273, // GREATER-THAN OR EQUIVALENT TO - "gsime", 0x02A8E, // GREATER-THAN ABOVE SIMILAR OR EQUAL - "gsiml", 0x02A90, // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN - "gt", 0x0003E, // GREATER-THAN SIGN - "GT", 0x0003E, // GREATER-THAN SIGN - "Gt", 0x0226B, // MUCH GREATER-THAN - "gtcc", 0x02AA7, // GREATER-THAN CLOSED BY CURVE - "gtcir", 0x02A7A, // GREATER-THAN WITH CIRCLE INSIDE - "gtdot", 0x022D7, // GREATER-THAN WITH DOT - "gtlPar", 0x02995, // DOUBLE LEFT ARC GREATER-THAN BRACKET - "gtquest", 0x02A7C, // GREATER-THAN WITH QUESTION MARK ABOVE - "gtrapprox", 0x02A86, // GREATER-THAN OR APPROXIMATE - "gtrarr", 0x02978, // GREATER-THAN ABOVE RIGHTWARDS ARROW - "gtrdot", 0x022D7, // GREATER-THAN WITH DOT - "gtreqless", 0x022DB, // GREATER-THAN EQUAL TO OR LESS-THAN - "gtreqqless", 0x02A8C, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN - "gtrless", 0x02277, // GREATER-THAN OR LESS-THAN - "gtrsim", 0x02273, // GREATER-THAN OR EQUIVALENT TO -// "gvertneqq", 0x02269;0x0FE00, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke -// "gvnE", 0x02269;0x0FE00, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke - NULL, 0 + {"gacute", 0x001F5}, // LATIN SMALL LETTER G WITH ACUTE + {"Gamma", 0x00393}, // GREEK CAPITAL LETTER GAMMA + {"gamma", 0x003B3}, // GREEK SMALL LETTER GAMMA + {"Gammad", 0x003DC}, // GREEK LETTER DIGAMMA + {"gammad", 0x003DD}, // GREEK SMALL LETTER DIGAMMA + {"gap", 0x02A86}, // GREATER-THAN OR APPROXIMATE + {"Gbreve", 0x0011E}, // LATIN CAPITAL LETTER G WITH BREVE + {"gbreve", 0x0011F}, // LATIN SMALL LETTER G WITH BREVE + {"Gcedil", 0x00122}, // LATIN CAPITAL LETTER G WITH CEDILLA + {"Gcirc", 0x0011C}, // LATIN CAPITAL LETTER G WITH CIRCUMFLEX + {"gcirc", 0x0011D}, // LATIN SMALL LETTER G WITH CIRCUMFLEX + {"Gcy", 0x00413}, // CYRILLIC CAPITAL LETTER GHE + {"gcy", 0x00433}, // CYRILLIC SMALL LETTER GHE + {"Gdot", 0x00120}, // LATIN CAPITAL LETTER G WITH DOT ABOVE + {"gdot", 0x00121}, // LATIN SMALL LETTER G WITH DOT ABOVE + {"ge", 0x02265}, // GREATER-THAN OR EQUAL TO + {"gE", 0x02267}, // GREATER-THAN OVER EQUAL TO + {"gel", 0x022DB}, // GREATER-THAN EQUAL TO OR LESS-THAN + {"gEl", 0x02A8C}, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN + {"geq", 0x02265}, // GREATER-THAN OR EQUAL TO + {"geqq", 0x02267}, // GREATER-THAN OVER EQUAL TO + {"geqslant", 0x02A7E}, // GREATER-THAN OR SLANTED EQUAL TO + {"ges", 0x02A7E}, // GREATER-THAN OR SLANTED EQUAL TO + {"gescc", 0x02AA9}, // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL + {"gesdot", 0x02A80}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE + {"gesdoto", 0x02A82}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE + {"gesdotol", 0x02A84}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT +// "gesl", 0x022DB;0x0FE00}, // GREATER-THAN slanted EQUAL TO OR LESS-THAN + {"gesles", 0x02A94}, // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL + {"Gfr", 0x1D50A}, // MATHEMATICAL FRAKTUR CAPITAL G + {"gfr", 0x1D524}, // MATHEMATICAL FRAKTUR SMALL G + {"gg", 0x0226B}, // MUCH GREATER-THAN + {"Gg", 0x022D9}, // VERY MUCH GREATER-THAN + {"ggg", 0x022D9}, // VERY MUCH GREATER-THAN + {"Ggr", 0x00393}, // GREEK CAPITAL LETTER GAMMA + {"ggr", 0x003B3}, // GREEK SMALL LETTER GAMMA + {"gimel", 0x02137}, // GIMEL SYMBOL + {"GJcy", 0x00403}, // CYRILLIC CAPITAL LETTER GJE + {"gjcy", 0x00453}, // CYRILLIC SMALL LETTER GJE + {"gl", 0x02277}, // GREATER-THAN OR LESS-THAN + {"gla", 0x02AA5}, // GREATER-THAN BESIDE LESS-THAN + {"glE", 0x02A92}, // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL + {"glj", 0x02AA4}, // GREATER-THAN OVERLAPPING LESS-THAN + {"gnap", 0x02A8A}, // GREATER-THAN AND NOT APPROXIMATE + {"gnapprox", 0x02A8A}, // GREATER-THAN AND NOT APPROXIMATE + {"gnE", 0x02269}, // GREATER-THAN BUT NOT EQUAL TO + {"gne", 0x02A88}, // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO + {"gneq", 0x02A88}, // GREATER-THAN AND SINGLE-LINE NOT EQUAL TO + {"gneqq", 0x02269}, // GREATER-THAN BUT NOT EQUAL TO + {"gnsim", 0x022E7}, // GREATER-THAN BUT NOT EQUIVALENT TO + {"Gopf", 0x1D53E}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL G + {"gopf", 0x1D558}, // MATHEMATICAL DOUBLE-STRUCK SMALL G + {"grave", 0x00060}, // GRAVE ACCENT + {"GreaterEqual", 0x02265}, // GREATER-THAN OR EQUAL TO + {"GreaterEqualLess", 0x022DB}, // GREATER-THAN EQUAL TO OR LESS-THAN + {"GreaterFullEqual", 0x02267}, // GREATER-THAN OVER EQUAL TO + {"GreaterGreater", 0x02AA2}, // DOUBLE NESTED GREATER-THAN + {"GreaterLess", 0x02277}, // GREATER-THAN OR LESS-THAN + {"GreaterSlantEqual", 0x02A7E}, // GREATER-THAN OR SLANTED EQUAL TO + {"GreaterTilde", 0x02273}, // GREATER-THAN OR EQUIVALENT TO + {"gscr", 0x0210A}, // SCRIPT SMALL G + {"Gscr", 0x1D4A2}, // MATHEMATICAL SCRIPT CAPITAL G + {"gsim", 0x02273}, // GREATER-THAN OR EQUIVALENT TO + {"gsime", 0x02A8E}, // GREATER-THAN ABOVE SIMILAR OR EQUAL + {"gsiml", 0x02A90}, // GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN + {"gt", 0x0003E}, // GREATER-THAN SIGN + {"GT", 0x0003E}, // GREATER-THAN SIGN + {"Gt", 0x0226B}, // MUCH GREATER-THAN + {"gtcc", 0x02AA7}, // GREATER-THAN CLOSED BY CURVE + {"gtcir", 0x02A7A}, // GREATER-THAN WITH CIRCLE INSIDE + {"gtdot", 0x022D7}, // GREATER-THAN WITH DOT + {"gtlPar", 0x02995}, // DOUBLE LEFT ARC GREATER-THAN BRACKET + {"gtquest", 0x02A7C}, // GREATER-THAN WITH QUESTION MARK ABOVE + {"gtrapprox", 0x02A86}, // GREATER-THAN OR APPROXIMATE + {"gtrarr", 0x02978}, // GREATER-THAN ABOVE RIGHTWARDS ARROW + {"gtrdot", 0x022D7}, // GREATER-THAN WITH DOT + {"gtreqless", 0x022DB}, // GREATER-THAN EQUAL TO OR LESS-THAN + {"gtreqqless", 0x02A8C}, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN + {"gtrless", 0x02277}, // GREATER-THAN OR LESS-THAN + {"gtrsim", 0x02273}, // GREATER-THAN OR EQUIVALENT TO +// "gvertneqq", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke +// "gvnE", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke + {NULL, 0} }; static NameId namesH[]={ - "Hacek", 0x002C7, // CARON - "hairsp", 0x0200A, // HAIR SPACE - "half", 0x000BD, // VULGAR FRACTION ONE HALF - "hamilt", 0x0210B, // SCRIPT CAPITAL H - "HARDcy", 0x0042A, // CYRILLIC CAPITAL LETTER HARD SIGN - "hardcy", 0x0044A, // CYRILLIC SMALL LETTER HARD SIGN - "harr", 0x02194, // LEFT RIGHT ARROW - "hArr", 0x021D4, // LEFT RIGHT DOUBLE ARROW - "harrcir", 0x02948, // LEFT RIGHT ARROW THROUGH SMALL CIRCLE - "harrw", 0x021AD, // LEFT RIGHT WAVE ARROW - "Hat", 0x0005E, // CIRCUMFLEX ACCENT - "hbar", 0x0210F, // PLANCK CONSTANT OVER TWO PI - "Hcirc", 0x00124, // LATIN CAPITAL LETTER H WITH CIRCUMFLEX - "hcirc", 0x00125, // LATIN SMALL LETTER H WITH CIRCUMFLEX - "hearts", 0x02665, // BLACK HEART SUIT - "heartsuit", 0x02665, // BLACK HEART SUIT - "hellip", 0x02026, // HORIZONTAL ELLIPSIS - "hercon", 0x022B9, // HERMITIAN CONJUGATE MATRIX - "Hfr", 0x0210C, // BLACK-LETTER CAPITAL H - "hfr", 0x1D525, // MATHEMATICAL FRAKTUR SMALL H - "HilbertSpace", 0x0210B, // SCRIPT CAPITAL H - "hksearow", 0x02925, // SOUTH EAST ARROW WITH HOOK - "hkswarow", 0x02926, // SOUTH WEST ARROW WITH HOOK - "hoarr", 0x021FF, // LEFT RIGHT OPEN-HEADED ARROW - "homtht", 0x0223B, // HOMOTHETIC - "hookleftarrow", 0x021A9, // LEFTWARDS ARROW WITH HOOK - "hookrightarrow", 0x021AA, // RIGHTWARDS ARROW WITH HOOK - "Hopf", 0x0210D, // DOUBLE-STRUCK CAPITAL H - "hopf", 0x1D559, // MATHEMATICAL DOUBLE-STRUCK SMALL H - "horbar", 0x02015, // HORIZONTAL BAR - "HorizontalLine", 0x02500, // BOX DRAWINGS LIGHT HORIZONTAL - "Hscr", 0x0210B, // SCRIPT CAPITAL H - "hscr", 0x1D4BD, // MATHEMATICAL SCRIPT SMALL H - "hslash", 0x0210F, // PLANCK CONSTANT OVER TWO PI - "Hstrok", 0x00126, // LATIN CAPITAL LETTER H WITH STROKE - "hstrok", 0x00127, // LATIN SMALL LETTER H WITH STROKE - "HumpDownHump", 0x0224E, // GEOMETRICALLY EQUIVALENT TO - "HumpEqual", 0x0224F, // DIFFERENCE BETWEEN - "hybull", 0x02043, // HYPHEN BULLET - "hyphen", 0x02010, // HYPHEN - NULL, 0 + {"Hacek", 0x002C7}, // CARON + {"hairsp", 0x0200A}, // HAIR SPACE + {"half", 0x000BD}, // VULGAR FRACTION ONE HALF + {"hamilt", 0x0210B}, // SCRIPT CAPITAL H + {"HARDcy", 0x0042A}, // CYRILLIC CAPITAL LETTER HARD SIGN + {"hardcy", 0x0044A}, // CYRILLIC SMALL LETTER HARD SIGN + {"harr", 0x02194}, // LEFT RIGHT ARROW + {"hArr", 0x021D4}, // LEFT RIGHT DOUBLE ARROW + {"harrcir", 0x02948}, // LEFT RIGHT ARROW THROUGH SMALL CIRCLE + {"harrw", 0x021AD}, // LEFT RIGHT WAVE ARROW + {"Hat", 0x0005E}, // CIRCUMFLEX ACCENT + {"hbar", 0x0210F}, // PLANCK CONSTANT OVER TWO PI + {"Hcirc", 0x00124}, // LATIN CAPITAL LETTER H WITH CIRCUMFLEX + {"hcirc", 0x00125}, // LATIN SMALL LETTER H WITH CIRCUMFLEX + {"hearts", 0x02665}, // BLACK HEART SUIT + {"heartsuit", 0x02665}, // BLACK HEART SUIT + {"hellip", 0x02026}, // HORIZONTAL ELLIPSIS + {"hercon", 0x022B9}, // HERMITIAN CONJUGATE MATRIX + {"Hfr", 0x0210C}, // BLACK-LETTER CAPITAL H + {"hfr", 0x1D525}, // MATHEMATICAL FRAKTUR SMALL H + {"HilbertSpace", 0x0210B}, // SCRIPT CAPITAL H + {"hksearow", 0x02925}, // SOUTH EAST ARROW WITH HOOK + {"hkswarow", 0x02926}, // SOUTH WEST ARROW WITH HOOK + {"hoarr", 0x021FF}, // LEFT RIGHT OPEN-HEADED ARROW + {"homtht", 0x0223B}, // HOMOTHETIC + {"hookleftarrow", 0x021A9}, // LEFTWARDS ARROW WITH HOOK + {"hookrightarrow", 0x021AA}, // RIGHTWARDS ARROW WITH HOOK + {"Hopf", 0x0210D}, // DOUBLE-STRUCK CAPITAL H + {"hopf", 0x1D559}, // MATHEMATICAL DOUBLE-STRUCK SMALL H + {"horbar", 0x02015}, // HORIZONTAL BAR + {"HorizontalLine", 0x02500}, // BOX DRAWINGS LIGHT HORIZONTAL + {"Hscr", 0x0210B}, // SCRIPT CAPITAL H + {"hscr", 0x1D4BD}, // MATHEMATICAL SCRIPT SMALL H + {"hslash", 0x0210F}, // PLANCK CONSTANT OVER TWO PI + {"Hstrok", 0x00126}, // LATIN CAPITAL LETTER H WITH STROKE + {"hstrok", 0x00127}, // LATIN SMALL LETTER H WITH STROKE + {"HumpDownHump", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO + {"HumpEqual", 0x0224F}, // DIFFERENCE BETWEEN + {"hybull", 0x02043}, // HYPHEN BULLET + {"hyphen", 0x02010}, // HYPHEN + {NULL, 0} }; static NameId namesI[]={ - "Iacgr", 0x0038A, // GREEK CAPITAL LETTER IOTA WITH TONOS - "iacgr", 0x003AF, // GREEK SMALL LETTER IOTA WITH TONOS - "Iacute", 0x000CD, // LATIN CAPITAL LETTER I WITH ACUTE - "iacute", 0x000ED, // LATIN SMALL LETTER I WITH ACUTE - "ic", 0x02063, // INVISIBLE SEPARATOR - "Icirc", 0x000CE, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX - "icirc", 0x000EE, // LATIN SMALL LETTER I WITH CIRCUMFLEX - "Icy", 0x00418, // CYRILLIC CAPITAL LETTER I - "icy", 0x00438, // CYRILLIC SMALL LETTER I - "idiagr", 0x00390, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS - "Idigr", 0x003AA, // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA - "idigr", 0x003CA, // GREEK SMALL LETTER IOTA WITH DIALYTIKA - "Idot", 0x00130, // LATIN CAPITAL LETTER I WITH DOT ABOVE - "IEcy", 0x00415, // CYRILLIC CAPITAL LETTER IE - "iecy", 0x00435, // CYRILLIC SMALL LETTER IE - "iexcl", 0x000A1, // INVERTED EXCLAMATION MARK - "iff", 0x021D4, // LEFT RIGHT DOUBLE ARROW - "Ifr", 0x02111, // BLACK-LETTER CAPITAL I - "ifr", 0x1D526, // MATHEMATICAL FRAKTUR SMALL I - "Igr", 0x00399, // GREEK CAPITAL LETTER IOTA - "igr", 0x003B9, // GREEK SMALL LETTER IOTA - "Igrave", 0x000CC, // LATIN CAPITAL LETTER I WITH GRAVE - "igrave", 0x000EC, // LATIN SMALL LETTER I WITH GRAVE - "ii", 0x02148, // DOUBLE-STRUCK ITALIC SMALL I - "iiiint", 0x02A0C, // QUADRUPLE INTEGRAL OPERATOR - "iiint", 0x0222D, // TRIPLE INTEGRAL - "iinfin", 0x029DC, // INCOMPLETE INFINITY - "iiota", 0x02129, // TURNED GREEK SMALL LETTER IOTA - "IJlig", 0x00132, // LATIN CAPITAL LIGATURE IJ - "ijlig", 0x00133, // LATIN SMALL LIGATURE IJ - "Im", 0x02111, // BLACK-LETTER CAPITAL I - "Imacr", 0x0012A, // LATIN CAPITAL LETTER I WITH MACRON - "imacr", 0x0012B, // LATIN SMALL LETTER I WITH MACRON - "image", 0x02111, // BLACK-LETTER CAPITAL I - "ImaginaryI", 0x02148, // DOUBLE-STRUCK ITALIC SMALL I - "imagline", 0x02110, // SCRIPT CAPITAL I - "imagpart", 0x02111, // BLACK-LETTER CAPITAL I - "imath", 0x00131, // LATIN SMALL LETTER DOTLESS I - "imof", 0x022B7, // IMAGE OF - "imped", 0x001B5, // LATIN CAPITAL LETTER Z WITH STROKE - "Implies", 0x021D2, // RIGHTWARDS DOUBLE ARROW - "in", 0x02208, // ELEMENT OF - "incare", 0x02105, // CARE OF - "infin", 0x0221E, // INFINITY - "infintie", 0x029DD, // TIE OVER INFINITY - "inodot", 0x00131, // LATIN SMALL LETTER DOTLESS I - "int", 0x0222B, // INTEGRAL - "Int", 0x0222C, // DOUBLE INTEGRAL - "intcal", 0x022BA, // INTERCALATE - "integers", 0x02124, // DOUBLE-STRUCK CAPITAL Z - "Integral", 0x0222B, // INTEGRAL - "intercal", 0x022BA, // INTERCALATE - "Intersection", 0x022C2, // N-ARY INTERSECTION - "intlarhk", 0x02A17, // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK - "intprod", 0x02A3C, // INTERIOR PRODUCT - "InvisibleComma", 0x02063, // INVISIBLE SEPARATOR - "InvisibleTimes", 0x02062, // INVISIBLE TIMES - "IOcy", 0x00401, // CYRILLIC CAPITAL LETTER IO - "iocy", 0x00451, // CYRILLIC SMALL LETTER IO - "Iogon", 0x0012E, // LATIN CAPITAL LETTER I WITH OGONEK - "iogon", 0x0012F, // LATIN SMALL LETTER I WITH OGONEK - "Iopf", 0x1D540, // MATHEMATICAL DOUBLE-STRUCK CAPITAL I - "iopf", 0x1D55A, // MATHEMATICAL DOUBLE-STRUCK SMALL I - "Iota", 0x00399, // GREEK CAPITAL LETTER IOTA - "iota", 0x003B9, // GREEK SMALL LETTER IOTA - "iprod", 0x02A3C, // INTERIOR PRODUCT - "iquest", 0x000BF, // INVERTED QUESTION MARK - "Iscr", 0x02110, // SCRIPT CAPITAL I - "iscr", 0x1D4BE, // MATHEMATICAL SCRIPT SMALL I - "isin", 0x02208, // ELEMENT OF - "isindot", 0x022F5, // ELEMENT OF WITH DOT ABOVE - "isinE", 0x022F9, // ELEMENT OF WITH TWO HORIZONTAL STROKES - "isins", 0x022F4, // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - "isinsv", 0x022F3, // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - "isinv", 0x02208, // ELEMENT OF - "it", 0x02062, // INVISIBLE TIMES - "Itilde", 0x00128, // LATIN CAPITAL LETTER I WITH TILDE - "itilde", 0x00129, // LATIN SMALL LETTER I WITH TILDE - "Iukcy", 0x00406, // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I - "iukcy", 0x00456, // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I - "Iuml", 0x000CF, // LATIN CAPITAL LETTER I WITH DIAERESIS - "iuml", 0x000EF, // LATIN SMALL LETTER I WITH DIAERESIS - NULL, 0 + {"Iacgr", 0x0038A}, // GREEK CAPITAL LETTER IOTA WITH TONOS + {"iacgr", 0x003AF}, // GREEK SMALL LETTER IOTA WITH TONOS + {"Iacute", 0x000CD}, // LATIN CAPITAL LETTER I WITH ACUTE + {"iacute", 0x000ED}, // LATIN SMALL LETTER I WITH ACUTE + {"ic", 0x02063}, // INVISIBLE SEPARATOR + {"Icirc", 0x000CE}, // LATIN CAPITAL LETTER I WITH CIRCUMFLEX + {"icirc", 0x000EE}, // LATIN SMALL LETTER I WITH CIRCUMFLEX + {"Icy", 0x00418}, // CYRILLIC CAPITAL LETTER I + {"icy", 0x00438}, // CYRILLIC SMALL LETTER I + {"idiagr", 0x00390}, // GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + {"Idigr", 0x003AA}, // GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + {"idigr", 0x003CA}, // GREEK SMALL LETTER IOTA WITH DIALYTIKA + {"Idot", 0x00130}, // LATIN CAPITAL LETTER I WITH DOT ABOVE + {"IEcy", 0x00415}, // CYRILLIC CAPITAL LETTER IE + {"iecy", 0x00435}, // CYRILLIC SMALL LETTER IE + {"iexcl", 0x000A1}, // INVERTED EXCLAMATION MARK + {"iff", 0x021D4}, // LEFT RIGHT DOUBLE ARROW + {"Ifr", 0x02111}, // BLACK-LETTER CAPITAL I + {"ifr", 0x1D526}, // MATHEMATICAL FRAKTUR SMALL I + {"Igr", 0x00399}, // GREEK CAPITAL LETTER IOTA + {"igr", 0x003B9}, // GREEK SMALL LETTER IOTA + {"Igrave", 0x000CC}, // LATIN CAPITAL LETTER I WITH GRAVE + {"igrave", 0x000EC}, // LATIN SMALL LETTER I WITH GRAVE + {"ii", 0x02148}, // DOUBLE-STRUCK ITALIC SMALL I + {"iiiint", 0x02A0C}, // QUADRUPLE INTEGRAL OPERATOR + {"iiint", 0x0222D}, // TRIPLE INTEGRAL + {"iinfin", 0x029DC}, // INCOMPLETE INFINITY + {"iiota", 0x02129}, // TURNED GREEK SMALL LETTER IOTA + {"IJlig", 0x00132}, // LATIN CAPITAL LIGATURE IJ + {"ijlig", 0x00133}, // LATIN SMALL LIGATURE IJ + {"Im", 0x02111}, // BLACK-LETTER CAPITAL I + {"Imacr", 0x0012A}, // LATIN CAPITAL LETTER I WITH MACRON + {"imacr", 0x0012B}, // LATIN SMALL LETTER I WITH MACRON + {"image", 0x02111}, // BLACK-LETTER CAPITAL I + {"ImaginaryI", 0x02148}, // DOUBLE-STRUCK ITALIC SMALL I + {"imagline", 0x02110}, // SCRIPT CAPITAL I + {"imagpart", 0x02111}, // BLACK-LETTER CAPITAL I + {"imath", 0x00131}, // LATIN SMALL LETTER DOTLESS I + {"imof", 0x022B7}, // IMAGE OF + {"imped", 0x001B5}, // LATIN CAPITAL LETTER Z WITH STROKE + {"Implies", 0x021D2}, // RIGHTWARDS DOUBLE ARROW + {"in", 0x02208}, // ELEMENT OF + {"incare", 0x02105}, // CARE OF + {"infin", 0x0221E}, // INFINITY + {"infintie", 0x029DD}, // TIE OVER INFINITY + {"inodot", 0x00131}, // LATIN SMALL LETTER DOTLESS I + {"int", 0x0222B}, // INTEGRAL + {"Int", 0x0222C}, // DOUBLE INTEGRAL + {"intcal", 0x022BA}, // INTERCALATE + {"integers", 0x02124}, // DOUBLE-STRUCK CAPITAL Z + {"Integral", 0x0222B}, // INTEGRAL + {"intercal", 0x022BA}, // INTERCALATE + {"Intersection", 0x022C2}, // N-ARY INTERSECTION + {"intlarhk", 0x02A17}, // INTEGRAL WITH LEFTWARDS ARROW WITH HOOK + {"intprod", 0x02A3C}, // INTERIOR PRODUCT + {"InvisibleComma", 0x02063}, // INVISIBLE SEPARATOR + {"InvisibleTimes", 0x02062}, // INVISIBLE TIMES + {"IOcy", 0x00401}, // CYRILLIC CAPITAL LETTER IO + {"iocy", 0x00451}, // CYRILLIC SMALL LETTER IO + {"Iogon", 0x0012E}, // LATIN CAPITAL LETTER I WITH OGONEK + {"iogon", 0x0012F}, // LATIN SMALL LETTER I WITH OGONEK + {"Iopf", 0x1D540}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL I + {"iopf", 0x1D55A}, // MATHEMATICAL DOUBLE-STRUCK SMALL I + {"Iota", 0x00399}, // GREEK CAPITAL LETTER IOTA + {"iota", 0x003B9}, // GREEK SMALL LETTER IOTA + {"iprod", 0x02A3C}, // INTERIOR PRODUCT + {"iquest", 0x000BF}, // INVERTED QUESTION MARK + {"Iscr", 0x02110}, // SCRIPT CAPITAL I + {"iscr", 0x1D4BE}, // MATHEMATICAL SCRIPT SMALL I + {"isin", 0x02208}, // ELEMENT OF + {"isindot", 0x022F5}, // ELEMENT OF WITH DOT ABOVE + {"isinE", 0x022F9}, // ELEMENT OF WITH TWO HORIZONTAL STROKES + {"isins", 0x022F4}, // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + {"isinsv", 0x022F3}, // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + {"isinv", 0x02208}, // ELEMENT OF + {"it", 0x02062}, // INVISIBLE TIMES + {"Itilde", 0x00128}, // LATIN CAPITAL LETTER I WITH TILDE + {"itilde", 0x00129}, // LATIN SMALL LETTER I WITH TILDE + {"Iukcy", 0x00406}, // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + {"iukcy", 0x00456}, // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + {"Iuml", 0x000CF}, // LATIN CAPITAL LETTER I WITH DIAERESIS + {"iuml", 0x000EF}, // LATIN SMALL LETTER I WITH DIAERESIS + {NULL, 0} }; static NameId namesJ[]={ - "Jcirc", 0x00134, // LATIN CAPITAL LETTER J WITH CIRCUMFLEX - "jcirc", 0x00135, // LATIN SMALL LETTER J WITH CIRCUMFLEX - "Jcy", 0x00419, // CYRILLIC CAPITAL LETTER SHORT I - "jcy", 0x00439, // CYRILLIC SMALL LETTER SHORT I - "Jfr", 0x1D50D, // MATHEMATICAL FRAKTUR CAPITAL J - "jfr", 0x1D527, // MATHEMATICAL FRAKTUR SMALL J - "jmath", 0x00237, // LATIN SMALL LETTER DOTLESS J - "Jopf", 0x1D541, // MATHEMATICAL DOUBLE-STRUCK CAPITAL J - "jopf", 0x1D55B, // MATHEMATICAL DOUBLE-STRUCK SMALL J - "Jscr", 0x1D4A5, // MATHEMATICAL SCRIPT CAPITAL J - "jscr", 0x1D4BF, // MATHEMATICAL SCRIPT SMALL J - "Jsercy", 0x00408, // CYRILLIC CAPITAL LETTER JE - "jsercy", 0x00458, // CYRILLIC SMALL LETTER JE - "Jukcy", 0x00404, // CYRILLIC CAPITAL LETTER UKRAINIAN IE - "jukcy", 0x00454, // CYRILLIC SMALL LETTER UKRAINIAN IE - NULL, 0 + {"Jcirc", 0x00134}, // LATIN CAPITAL LETTER J WITH CIRCUMFLEX + {"jcirc", 0x00135}, // LATIN SMALL LETTER J WITH CIRCUMFLEX + {"Jcy", 0x00419}, // CYRILLIC CAPITAL LETTER SHORT I + {"jcy", 0x00439}, // CYRILLIC SMALL LETTER SHORT I + {"Jfr", 0x1D50D}, // MATHEMATICAL FRAKTUR CAPITAL J + {"jfr", 0x1D527}, // MATHEMATICAL FRAKTUR SMALL J + {"jmath", 0x00237}, // LATIN SMALL LETTER DOTLESS J + {"Jopf", 0x1D541}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL J + {"jopf", 0x1D55B}, // MATHEMATICAL DOUBLE-STRUCK SMALL J + {"Jscr", 0x1D4A5}, // MATHEMATICAL SCRIPT CAPITAL J + {"jscr", 0x1D4BF}, // MATHEMATICAL SCRIPT SMALL J + {"Jsercy", 0x00408}, // CYRILLIC CAPITAL LETTER JE + {"jsercy", 0x00458}, // CYRILLIC SMALL LETTER JE + {"Jukcy", 0x00404}, // CYRILLIC CAPITAL LETTER UKRAINIAN IE + {"jukcy", 0x00454}, // CYRILLIC SMALL LETTER UKRAINIAN IE + {NULL, 0} }; static NameId namesK[]={ - "Kappa", 0x0039A, // GREEK CAPITAL LETTER KAPPA - "kappa", 0x003BA, // GREEK SMALL LETTER KAPPA - "kappav", 0x003F0, // GREEK KAPPA SYMBOL - "Kcedil", 0x00136, // LATIN CAPITAL LETTER K WITH CEDILLA - "kcedil", 0x00137, // LATIN SMALL LETTER K WITH CEDILLA - "Kcy", 0x0041A, // CYRILLIC CAPITAL LETTER KA - "kcy", 0x0043A, // CYRILLIC SMALL LETTER KA - "Kfr", 0x1D50E, // MATHEMATICAL FRAKTUR CAPITAL K - "kfr", 0x1D528, // MATHEMATICAL FRAKTUR SMALL K - "Kgr", 0x0039A, // GREEK CAPITAL LETTER KAPPA - "kgr", 0x003BA, // GREEK SMALL LETTER KAPPA - "kgreen", 0x00138, // LATIN SMALL LETTER KRA - "KHcy", 0x00425, // CYRILLIC CAPITAL LETTER HA - "khcy", 0x00445, // CYRILLIC SMALL LETTER HA - "KHgr", 0x003A7, // GREEK CAPITAL LETTER CHI - "khgr", 0x003C7, // GREEK SMALL LETTER CHI - "KJcy", 0x0040C, // CYRILLIC CAPITAL LETTER KJE - "kjcy", 0x0045C, // CYRILLIC SMALL LETTER KJE - "Kopf", 0x1D542, // MATHEMATICAL DOUBLE-STRUCK CAPITAL K - "kopf", 0x1D55C, // MATHEMATICAL DOUBLE-STRUCK SMALL K - "Kscr", 0x1D4A6, // MATHEMATICAL SCRIPT CAPITAL K - "kscr", 0x1D4C0, // MATHEMATICAL SCRIPT SMALL K - NULL, 0 + {"Kappa", 0x0039A}, // GREEK CAPITAL LETTER KAPPA + {"kappa", 0x003BA}, // GREEK SMALL LETTER KAPPA + {"kappav", 0x003F0}, // GREEK KAPPA SYMBOL + {"Kcedil", 0x00136}, // LATIN CAPITAL LETTER K WITH CEDILLA + {"kcedil", 0x00137}, // LATIN SMALL LETTER K WITH CEDILLA + {"Kcy", 0x0041A}, // CYRILLIC CAPITAL LETTER KA + {"kcy", 0x0043A}, // CYRILLIC SMALL LETTER KA + {"Kfr", 0x1D50E}, // MATHEMATICAL FRAKTUR CAPITAL K + {"kfr", 0x1D528}, // MATHEMATICAL FRAKTUR SMALL K + {"Kgr", 0x0039A}, // GREEK CAPITAL LETTER KAPPA + {"kgr", 0x003BA}, // GREEK SMALL LETTER KAPPA + {"kgreen", 0x00138}, // LATIN SMALL LETTER KRA + {"KHcy", 0x00425}, // CYRILLIC CAPITAL LETTER HA + {"khcy", 0x00445}, // CYRILLIC SMALL LETTER HA + {"KHgr", 0x003A7}, // GREEK CAPITAL LETTER CHI + {"khgr", 0x003C7}, // GREEK SMALL LETTER CHI + {"KJcy", 0x0040C}, // CYRILLIC CAPITAL LETTER KJE + {"kjcy", 0x0045C}, // CYRILLIC SMALL LETTER KJE + {"Kopf", 0x1D542}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL K + {"kopf", 0x1D55C}, // MATHEMATICAL DOUBLE-STRUCK SMALL K + {"Kscr", 0x1D4A6}, // MATHEMATICAL SCRIPT CAPITAL K + {"kscr", 0x1D4C0}, // MATHEMATICAL SCRIPT SMALL K + {NULL, 0} }; static NameId namesL[]={ - "lAarr", 0x021DA, // LEFTWARDS TRIPLE ARROW - "Lacute", 0x00139, // LATIN CAPITAL LETTER L WITH ACUTE - "lacute", 0x0013A, // LATIN SMALL LETTER L WITH ACUTE - "laemptyv", 0x029B4, // EMPTY SET WITH LEFT ARROW ABOVE - "lagran", 0x02112, // SCRIPT CAPITAL L - "Lambda", 0x0039B, // GREEK CAPITAL LETTER LAMDA - "lambda", 0x003BB, // GREEK SMALL LETTER LAMDA - "lang", 0x027E8, // MATHEMATICAL LEFT ANGLE BRACKET - "Lang", 0x027EA, // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET - "langd", 0x02991, // LEFT ANGLE BRACKET WITH DOT - "langle", 0x027E8, // MATHEMATICAL LEFT ANGLE BRACKET - "lap", 0x02A85, // LESS-THAN OR APPROXIMATE - "Laplacetrf", 0x02112, // SCRIPT CAPITAL L - "laquo", 0x000AB, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK - "larr", 0x02190, // LEFTWARDS ARROW - "Larr", 0x0219E, // LEFTWARDS TWO HEADED ARROW - "lArr", 0x021D0, // LEFTWARDS DOUBLE ARROW - "larrb", 0x021E4, // LEFTWARDS ARROW TO BAR - "larrbfs", 0x0291F, // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND - "larrfs", 0x0291D, // LEFTWARDS ARROW TO BLACK DIAMOND - "larrhk", 0x021A9, // LEFTWARDS ARROW WITH HOOK - "larrlp", 0x021AB, // LEFTWARDS ARROW WITH LOOP - "larrpl", 0x02939, // LEFT-SIDE ARC ANTICLOCKWISE ARROW - "larrsim", 0x02973, // LEFTWARDS ARROW ABOVE TILDE OPERATOR - "larrtl", 0x021A2, // LEFTWARDS ARROW WITH TAIL - "lat", 0x02AAB, // LARGER THAN - "latail", 0x02919, // LEFTWARDS ARROW-TAIL - "lAtail", 0x0291B, // LEFTWARDS DOUBLE ARROW-TAIL - "late", 0x02AAD, // LARGER THAN OR EQUAL TO -// "lates", 0x02AAD;0x0FE00, // LARGER THAN OR slanted EQUAL - "lbarr", 0x0290C, // LEFTWARDS DOUBLE DASH ARROW - "lBarr", 0x0290E, // LEFTWARDS TRIPLE DASH ARROW - "lbbrk", 0x02772, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT - "lbrace", 0x0007B, // LEFT CURLY BRACKET - "lbrack", 0x0005B, // LEFT SQUARE BRACKET - "lbrke", 0x0298B, // LEFT SQUARE BRACKET WITH UNDERBAR - "lbrksld", 0x0298F, // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - "lbrkslu", 0x0298D, // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER - "Lcaron", 0x0013D, // LATIN CAPITAL LETTER L WITH CARON - "lcaron", 0x0013E, // LATIN SMALL LETTER L WITH CARON - "Lcedil", 0x0013B, // LATIN CAPITAL LETTER L WITH CEDILLA - "lcedil", 0x0013C, // LATIN SMALL LETTER L WITH CEDILLA - "lceil", 0x02308, // LEFT CEILING - "lcub", 0x0007B, // LEFT CURLY BRACKET - "Lcy", 0x0041B, // CYRILLIC CAPITAL LETTER EL - "lcy", 0x0043B, // CYRILLIC SMALL LETTER EL - "ldca", 0x02936, // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS - "ldquo", 0x0201C, // LEFT DOUBLE QUOTATION MARK - "ldquor", 0x0201E, // DOUBLE LOW-9 QUOTATION MARK - "ldrdhar", 0x02967, // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN - "ldrushar", 0x0294B, // LEFT BARB DOWN RIGHT BARB UP HARPOON - "ldsh", 0x021B2, // DOWNWARDS ARROW WITH TIP LEFTWARDS - "le", 0x02264, // LESS-THAN OR EQUAL TO - "lE", 0x02266, // LESS-THAN OVER EQUAL TO - "LeftAngleBracket", 0x027E8, // MATHEMATICAL LEFT ANGLE BRACKET - "leftarrow", 0x02190, // LEFTWARDS ARROW - "LeftArrow", 0x02190, // LEFTWARDS ARROW - "Leftarrow", 0x021D0, // LEFTWARDS DOUBLE ARROW - "LeftArrowBar", 0x021E4, // LEFTWARDS ARROW TO BAR - "LeftArrowRightArrow", 0x021C6, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - "leftarrowtail", 0x021A2, // LEFTWARDS ARROW WITH TAIL - "LeftCeiling", 0x02308, // LEFT CEILING - "LeftDoubleBracket", 0x027E6, // MATHEMATICAL LEFT WHITE SQUARE BRACKET - "LeftDownTeeVector", 0x02961, // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR - "LeftDownVector", 0x021C3, // DOWNWARDS HARPOON WITH BARB LEFTWARDS - "LeftDownVectorBar", 0x02959, // DOWNWARDS HARPOON WITH BARB LEFT TO BAR - "LeftFloor", 0x0230A, // LEFT FLOOR - "leftharpoondown", 0x021BD, // LEFTWARDS HARPOON WITH BARB DOWNWARDS - "leftharpoonup", 0x021BC, // LEFTWARDS HARPOON WITH BARB UPWARDS - "leftleftarrows", 0x021C7, // LEFTWARDS PAIRED ARROWS - "leftrightarrow", 0x02194, // LEFT RIGHT ARROW - "LeftRightArrow", 0x02194, // LEFT RIGHT ARROW - "Leftrightarrow", 0x021D4, // LEFT RIGHT DOUBLE ARROW - "leftrightarrows", 0x021C6, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - "leftrightharpoons", 0x021CB, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - "leftrightsquigarrow", 0x021AD, // LEFT RIGHT WAVE ARROW - "LeftRightVector", 0x0294E, // LEFT BARB UP RIGHT BARB UP HARPOON - "LeftTee", 0x022A3, // LEFT TACK - "LeftTeeArrow", 0x021A4, // LEFTWARDS ARROW FROM BAR - "LeftTeeVector", 0x0295A, // LEFTWARDS HARPOON WITH BARB UP FROM BAR - "leftthreetimes", 0x022CB, // LEFT SEMIDIRECT PRODUCT - "LeftTriangle", 0x022B2, // NORMAL SUBGROUP OF - "LeftTriangleBar", 0x029CF, // LEFT TRIANGLE BESIDE VERTICAL BAR - "LeftTriangleEqual", 0x022B4, // NORMAL SUBGROUP OF OR EQUAL TO - "LeftUpDownVector", 0x02951, // UP BARB LEFT DOWN BARB LEFT HARPOON - "LeftUpTeeVector", 0x02960, // UPWARDS HARPOON WITH BARB LEFT FROM BAR - "LeftUpVector", 0x021BF, // UPWARDS HARPOON WITH BARB LEFTWARDS - "LeftUpVectorBar", 0x02958, // UPWARDS HARPOON WITH BARB LEFT TO BAR - "LeftVector", 0x021BC, // LEFTWARDS HARPOON WITH BARB UPWARDS - "LeftVectorBar", 0x02952, // LEFTWARDS HARPOON WITH BARB UP TO BAR - "leg", 0x022DA, // LESS-THAN EQUAL TO OR GREATER-THAN - "lEg", 0x02A8B, // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN - "leq", 0x02264, // LESS-THAN OR EQUAL TO - "leqq", 0x02266, // LESS-THAN OVER EQUAL TO - "leqslant", 0x02A7D, // LESS-THAN OR SLANTED EQUAL TO - "les", 0x02A7D, // LESS-THAN OR SLANTED EQUAL TO - "lescc", 0x02AA8, // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL - "lesdot", 0x02A7F, // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE - "lesdoto", 0x02A81, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE - "lesdotor", 0x02A83, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT -// "lesg", 0x022DA;0x0FE00, // LESS-THAN slanted EQUAL TO OR GREATER-THAN - "lesges", 0x02A93, // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL - "lessapprox", 0x02A85, // LESS-THAN OR APPROXIMATE - "lessdot", 0x022D6, // LESS-THAN WITH DOT - "lesseqgtr", 0x022DA, // LESS-THAN EQUAL TO OR GREATER-THAN - "lesseqqgtr", 0x02A8B, // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN - "LessEqualGreater", 0x022DA, // LESS-THAN EQUAL TO OR GREATER-THAN - "LessFullEqual", 0x02266, // LESS-THAN OVER EQUAL TO - "LessGreater", 0x02276, // LESS-THAN OR GREATER-THAN - "lessgtr", 0x02276, // LESS-THAN OR GREATER-THAN - "LessLess", 0x02AA1, // DOUBLE NESTED LESS-THAN - "lesssim", 0x02272, // LESS-THAN OR EQUIVALENT TO - "LessSlantEqual", 0x02A7D, // LESS-THAN OR SLANTED EQUAL TO - "LessTilde", 0x02272, // LESS-THAN OR EQUIVALENT TO - "lfisht", 0x0297C, // LEFT FISH TAIL - "lfloor", 0x0230A, // LEFT FLOOR - "Lfr", 0x1D50F, // MATHEMATICAL FRAKTUR CAPITAL L - "lfr", 0x1D529, // MATHEMATICAL FRAKTUR SMALL L - "lg", 0x02276, // LESS-THAN OR GREATER-THAN - "lgE", 0x02A91, // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL - "Lgr", 0x0039B, // GREEK CAPITAL LETTER LAMDA - "lgr", 0x003BB, // GREEK SMALL LETTER LAMDA - "lHar", 0x02962, // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN - "lhard", 0x021BD, // LEFTWARDS HARPOON WITH BARB DOWNWARDS - "lharu", 0x021BC, // LEFTWARDS HARPOON WITH BARB UPWARDS - "lharul", 0x0296A, // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - "lhblk", 0x02584, // LOWER HALF BLOCK - "LJcy", 0x00409, // CYRILLIC CAPITAL LETTER LJE - "ljcy", 0x00459, // CYRILLIC SMALL LETTER LJE - "ll", 0x0226A, // MUCH LESS-THAN - "Ll", 0x022D8, // VERY MUCH LESS-THAN - "llarr", 0x021C7, // LEFTWARDS PAIRED ARROWS - "llcorner", 0x0231E, // BOTTOM LEFT CORNER - "Lleftarrow", 0x021DA, // LEFTWARDS TRIPLE ARROW - "llhard", 0x0296B, // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - "lltri", 0x025FA, // LOWER LEFT TRIANGLE - "Lmidot", 0x0013F, // LATIN CAPITAL LETTER L WITH MIDDLE DOT - "lmidot", 0x00140, // LATIN SMALL LETTER L WITH MIDDLE DOT - "lmoust", 0x023B0, // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - "lmoustache", 0x023B0, // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION - "lnap", 0x02A89, // LESS-THAN AND NOT APPROXIMATE - "lnapprox", 0x02A89, // LESS-THAN AND NOT APPROXIMATE - "lnE", 0x02268, // LESS-THAN BUT NOT EQUAL TO - "lne", 0x02A87, // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - "lneq", 0x02A87, // LESS-THAN AND SINGLE-LINE NOT EQUAL TO - "lneqq", 0x02268, // LESS-THAN BUT NOT EQUAL TO - "lnsim", 0x022E6, // LESS-THAN BUT NOT EQUIVALENT TO - "loang", 0x027EC, // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET - "loarr", 0x021FD, // LEFTWARDS OPEN-HEADED ARROW - "lobrk", 0x027E6, // MATHEMATICAL LEFT WHITE SQUARE BRACKET - "longleftarrow", 0x027F5, // LONG LEFTWARDS ARROW - "LongLeftArrow", 0x027F5, // LONG LEFTWARDS ARROW - "Longleftarrow", 0x027F8, // LONG LEFTWARDS DOUBLE ARROW - "longleftrightarrow", 0x027F7, // LONG LEFT RIGHT ARROW - "LongLeftRightArrow", 0x027F7, // LONG LEFT RIGHT ARROW - "Longleftrightarrow", 0x027FA, // LONG LEFT RIGHT DOUBLE ARROW - "longmapsto", 0x027FC, // LONG RIGHTWARDS ARROW FROM BAR - "longrightarrow", 0x027F6, // LONG RIGHTWARDS ARROW - "LongRightArrow", 0x027F6, // LONG RIGHTWARDS ARROW - "Longrightarrow", 0x027F9, // LONG RIGHTWARDS DOUBLE ARROW - "looparrowleft", 0x021AB, // LEFTWARDS ARROW WITH LOOP - "looparrowright", 0x021AC, // RIGHTWARDS ARROW WITH LOOP - "lopar", 0x02985, // LEFT WHITE PARENTHESIS - "Lopf", 0x1D543, // MATHEMATICAL DOUBLE-STRUCK CAPITAL L - "lopf", 0x1D55D, // MATHEMATICAL DOUBLE-STRUCK SMALL L - "loplus", 0x02A2D, // PLUS SIGN IN LEFT HALF CIRCLE - "lotimes", 0x02A34, // MULTIPLICATION SIGN IN LEFT HALF CIRCLE - "lowast", 0x02217, // ASTERISK OPERATOR - "lowbar", 0x0005F, // LOW LINE - "LowerLeftArrow", 0x02199, // SOUTH WEST ARROW - "LowerRightArrow", 0x02198, // SOUTH EAST ARROW - "loz", 0x025CA, // LOZENGE - "lozenge", 0x025CA, // LOZENGE - "lozf", 0x029EB, // BLACK LOZENGE - "lpar", 0x00028, // LEFT PARENTHESIS - "lparlt", 0x02993, // LEFT ARC LESS-THAN BRACKET - "lrarr", 0x021C6, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW - "lrcorner", 0x0231F, // BOTTOM RIGHT CORNER - "lrhar", 0x021CB, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - "lrhard", 0x0296D, // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH - "lrm", 0x0200E, // LEFT-TO-RIGHT MARK - "lrtri", 0x022BF, // RIGHT TRIANGLE - "lsaquo", 0x02039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - "Lscr", 0x02112, // SCRIPT CAPITAL L - "lscr", 0x1D4C1, // MATHEMATICAL SCRIPT SMALL L - "lsh", 0x021B0, // UPWARDS ARROW WITH TIP LEFTWARDS - "Lsh", 0x021B0, // UPWARDS ARROW WITH TIP LEFTWARDS - "lsim", 0x02272, // LESS-THAN OR EQUIVALENT TO - "lsime", 0x02A8D, // LESS-THAN ABOVE SIMILAR OR EQUAL - "lsimg", 0x02A8F, // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN - "lsqb", 0x0005B, // LEFT SQUARE BRACKET - "lsquo", 0x02018, // LEFT SINGLE QUOTATION MARK - "lsquor", 0x0201A, // SINGLE LOW-9 QUOTATION MARK - "Lstrok", 0x00141, // LATIN CAPITAL LETTER L WITH STROKE - "lstrok", 0x00142, // LATIN SMALL LETTER L WITH STROKE - "lt", 0x0003C, // LESS-THAN SIGN - "LT", 0x0003C, // LESS-THAN SIGN - "Lt", 0x0226A, // MUCH LESS-THAN - "ltcc", 0x02AA6, // LESS-THAN CLOSED BY CURVE - "ltcir", 0x02A79, // LESS-THAN WITH CIRCLE INSIDE - "ltdot", 0x022D6, // LESS-THAN WITH DOT - "lthree", 0x022CB, // LEFT SEMIDIRECT PRODUCT - "ltimes", 0x022C9, // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT - "ltlarr", 0x02976, // LESS-THAN ABOVE LEFTWARDS ARROW - "ltquest", 0x02A7B, // LESS-THAN WITH QUESTION MARK ABOVE - "ltri", 0x025C3, // WHITE LEFT-POINTING SMALL TRIANGLE - "ltrie", 0x022B4, // NORMAL SUBGROUP OF OR EQUAL TO - "ltrif", 0x025C2, // BLACK LEFT-POINTING SMALL TRIANGLE - "ltrPar", 0x02996, // DOUBLE RIGHT ARC LESS-THAN BRACKET - "lurdshar", 0x0294A, // LEFT BARB UP RIGHT BARB DOWN HARPOON - "luruhar", 0x02966, // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP -// "lvertneqq", 0x02268;0x0FE00, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke -// "lvnE", 0x02268;0x0FE00, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke - NULL, 0 + {"lAarr", 0x021DA}, // LEFTWARDS TRIPLE ARROW + {"Lacute", 0x00139}, // LATIN CAPITAL LETTER L WITH ACUTE + {"lacute", 0x0013A}, // LATIN SMALL LETTER L WITH ACUTE + {"laemptyv", 0x029B4}, // EMPTY SET WITH LEFT ARROW ABOVE + {"lagran", 0x02112}, // SCRIPT CAPITAL L + {"Lambda", 0x0039B}, // GREEK CAPITAL LETTER LAMDA + {"lambda", 0x003BB}, // GREEK SMALL LETTER LAMDA + {"lang", 0x027E8}, // MATHEMATICAL LEFT ANGLE BRACKET + {"Lang", 0x027EA}, // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET + {"langd", 0x02991}, // LEFT ANGLE BRACKET WITH DOT + {"langle", 0x027E8}, // MATHEMATICAL LEFT ANGLE BRACKET + {"lap", 0x02A85}, // LESS-THAN OR APPROXIMATE + {"Laplacetrf", 0x02112}, // SCRIPT CAPITAL L + {"laquo", 0x000AB}, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + {"larr", 0x02190}, // LEFTWARDS ARROW + {"Larr", 0x0219E}, // LEFTWARDS TWO HEADED ARROW + {"lArr", 0x021D0}, // LEFTWARDS DOUBLE ARROW + {"larrb", 0x021E4}, // LEFTWARDS ARROW TO BAR + {"larrbfs", 0x0291F}, // LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND + {"larrfs", 0x0291D}, // LEFTWARDS ARROW TO BLACK DIAMOND + {"larrhk", 0x021A9}, // LEFTWARDS ARROW WITH HOOK + {"larrlp", 0x021AB}, // LEFTWARDS ARROW WITH LOOP + {"larrpl", 0x02939}, // LEFT-SIDE ARC ANTICLOCKWISE ARROW + {"larrsim", 0x02973}, // LEFTWARDS ARROW ABOVE TILDE OPERATOR + {"larrtl", 0x021A2}, // LEFTWARDS ARROW WITH TAIL + {"lat", 0x02AAB}, // LARGER THAN + {"latail", 0x02919}, // LEFTWARDS ARROW-TAIL + {"lAtail", 0x0291B}, // LEFTWARDS DOUBLE ARROW-TAIL + {"late", 0x02AAD}, // LARGER THAN OR EQUAL TO +// "lates", 0x02AAD;0x0FE00}, // LARGER THAN OR slanted EQUAL + {"lbarr", 0x0290C}, // LEFTWARDS DOUBLE DASH ARROW + {"lBarr", 0x0290E}, // LEFTWARDS TRIPLE DASH ARROW + {"lbbrk", 0x02772}, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT + {"lbrace", 0x0007B}, // LEFT CURLY BRACKET + {"lbrack", 0x0005B}, // LEFT SQUARE BRACKET + {"lbrke", 0x0298B}, // LEFT SQUARE BRACKET WITH UNDERBAR + {"lbrksld", 0x0298F}, // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {"lbrkslu", 0x0298D}, // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER + {"Lcaron", 0x0013D}, // LATIN CAPITAL LETTER L WITH CARON + {"lcaron", 0x0013E}, // LATIN SMALL LETTER L WITH CARON + {"Lcedil", 0x0013B}, // LATIN CAPITAL LETTER L WITH CEDILLA + {"lcedil", 0x0013C}, // LATIN SMALL LETTER L WITH CEDILLA + {"lceil", 0x02308}, // LEFT CEILING + {"lcub", 0x0007B}, // LEFT CURLY BRACKET + {"Lcy", 0x0041B}, // CYRILLIC CAPITAL LETTER EL + {"lcy", 0x0043B}, // CYRILLIC SMALL LETTER EL + {"ldca", 0x02936}, // ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS + {"ldquo", 0x0201C}, // LEFT DOUBLE QUOTATION MARK + {"ldquor", 0x0201E}, // DOUBLE LOW-9 QUOTATION MARK + {"ldrdhar", 0x02967}, // LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN + {"ldrushar", 0x0294B}, // LEFT BARB DOWN RIGHT BARB UP HARPOON + {"ldsh", 0x021B2}, // DOWNWARDS ARROW WITH TIP LEFTWARDS + {"le", 0x02264}, // LESS-THAN OR EQUAL TO + {"lE", 0x02266}, // LESS-THAN OVER EQUAL TO + {"LeftAngleBracket", 0x027E8}, // MATHEMATICAL LEFT ANGLE BRACKET + {"leftarrow", 0x02190}, // LEFTWARDS ARROW + {"LeftArrow", 0x02190}, // LEFTWARDS ARROW + {"Leftarrow", 0x021D0}, // LEFTWARDS DOUBLE ARROW + {"LeftArrowBar", 0x021E4}, // LEFTWARDS ARROW TO BAR + {"LeftArrowRightArrow", 0x021C6}, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + {"leftarrowtail", 0x021A2}, // LEFTWARDS ARROW WITH TAIL + {"LeftCeiling", 0x02308}, // LEFT CEILING + {"LeftDoubleBracket", 0x027E6}, // MATHEMATICAL LEFT WHITE SQUARE BRACKET + {"LeftDownTeeVector", 0x02961}, // DOWNWARDS HARPOON WITH BARB LEFT FROM BAR + {"LeftDownVector", 0x021C3}, // DOWNWARDS HARPOON WITH BARB LEFTWARDS + {"LeftDownVectorBar", 0x02959}, // DOWNWARDS HARPOON WITH BARB LEFT TO BAR + {"LeftFloor", 0x0230A}, // LEFT FLOOR + {"leftharpoondown", 0x021BD}, // LEFTWARDS HARPOON WITH BARB DOWNWARDS + {"leftharpoonup", 0x021BC}, // LEFTWARDS HARPOON WITH BARB UPWARDS + {"leftleftarrows", 0x021C7}, // LEFTWARDS PAIRED ARROWS + {"leftrightarrow", 0x02194}, // LEFT RIGHT ARROW + {"LeftRightArrow", 0x02194}, // LEFT RIGHT ARROW + {"Leftrightarrow", 0x021D4}, // LEFT RIGHT DOUBLE ARROW + {"leftrightarrows", 0x021C6}, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + {"leftrightharpoons", 0x021CB}, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + {"leftrightsquigarrow", 0x021AD}, // LEFT RIGHT WAVE ARROW + {"LeftRightVector", 0x0294E}, // LEFT BARB UP RIGHT BARB UP HARPOON + {"LeftTee", 0x022A3}, // LEFT TACK + {"LeftTeeArrow", 0x021A4}, // LEFTWARDS ARROW FROM BAR + {"LeftTeeVector", 0x0295A}, // LEFTWARDS HARPOON WITH BARB UP FROM BAR + {"leftthreetimes", 0x022CB}, // LEFT SEMIDIRECT PRODUCT + {"LeftTriangle", 0x022B2}, // NORMAL SUBGROUP OF + {"LeftTriangleBar", 0x029CF}, // LEFT TRIANGLE BESIDE VERTICAL BAR + {"LeftTriangleEqual", 0x022B4}, // NORMAL SUBGROUP OF OR EQUAL TO + {"LeftUpDownVector", 0x02951}, // UP BARB LEFT DOWN BARB LEFT HARPOON + {"LeftUpTeeVector", 0x02960}, // UPWARDS HARPOON WITH BARB LEFT FROM BAR + {"LeftUpVector", 0x021BF}, // UPWARDS HARPOON WITH BARB LEFTWARDS + {"LeftUpVectorBar", 0x02958}, // UPWARDS HARPOON WITH BARB LEFT TO BAR + {"LeftVector", 0x021BC}, // LEFTWARDS HARPOON WITH BARB UPWARDS + {"LeftVectorBar", 0x02952}, // LEFTWARDS HARPOON WITH BARB UP TO BAR + {"leg", 0x022DA}, // LESS-THAN EQUAL TO OR GREATER-THAN + {"lEg", 0x02A8B}, // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN + {"leq", 0x02264}, // LESS-THAN OR EQUAL TO + {"leqq", 0x02266}, // LESS-THAN OVER EQUAL TO + {"leqslant", 0x02A7D}, // LESS-THAN OR SLANTED EQUAL TO + {"les", 0x02A7D}, // LESS-THAN OR SLANTED EQUAL TO + {"lescc", 0x02AA8}, // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL + {"lesdot", 0x02A7F}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE + {"lesdoto", 0x02A81}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE + {"lesdotor", 0x02A83}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT +// "lesg", 0x022DA;0x0FE00}, // LESS-THAN slanted EQUAL TO OR GREATER-THAN + {"lesges", 0x02A93}, // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL + {"lessapprox", 0x02A85}, // LESS-THAN OR APPROXIMATE + {"lessdot", 0x022D6}, // LESS-THAN WITH DOT + {"lesseqgtr", 0x022DA}, // LESS-THAN EQUAL TO OR GREATER-THAN + {"lesseqqgtr", 0x02A8B}, // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN + {"LessEqualGreater", 0x022DA}, // LESS-THAN EQUAL TO OR GREATER-THAN + {"LessFullEqual", 0x02266}, // LESS-THAN OVER EQUAL TO + {"LessGreater", 0x02276}, // LESS-THAN OR GREATER-THAN + {"lessgtr", 0x02276}, // LESS-THAN OR GREATER-THAN + {"LessLess", 0x02AA1}, // DOUBLE NESTED LESS-THAN + {"lesssim", 0x02272}, // LESS-THAN OR EQUIVALENT TO + {"LessSlantEqual", 0x02A7D}, // LESS-THAN OR SLANTED EQUAL TO + {"LessTilde", 0x02272}, // LESS-THAN OR EQUIVALENT TO + {"lfisht", 0x0297C}, // LEFT FISH TAIL + {"lfloor", 0x0230A}, // LEFT FLOOR + {"Lfr", 0x1D50F}, // MATHEMATICAL FRAKTUR CAPITAL L + {"lfr", 0x1D529}, // MATHEMATICAL FRAKTUR SMALL L + {"lg", 0x02276}, // LESS-THAN OR GREATER-THAN + {"lgE", 0x02A91}, // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL + {"Lgr", 0x0039B}, // GREEK CAPITAL LETTER LAMDA + {"lgr", 0x003BB}, // GREEK SMALL LETTER LAMDA + {"lHar", 0x02962}, // LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN + {"lhard", 0x021BD}, // LEFTWARDS HARPOON WITH BARB DOWNWARDS + {"lharu", 0x021BC}, // LEFTWARDS HARPOON WITH BARB UPWARDS + {"lharul", 0x0296A}, // LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH + {"lhblk", 0x02584}, // LOWER HALF BLOCK + {"LJcy", 0x00409}, // CYRILLIC CAPITAL LETTER LJE + {"ljcy", 0x00459}, // CYRILLIC SMALL LETTER LJE + {"ll", 0x0226A}, // MUCH LESS-THAN + {"Ll", 0x022D8}, // VERY MUCH LESS-THAN + {"llarr", 0x021C7}, // LEFTWARDS PAIRED ARROWS + {"llcorner", 0x0231E}, // BOTTOM LEFT CORNER + {"Lleftarrow", 0x021DA}, // LEFTWARDS TRIPLE ARROW + {"llhard", 0x0296B}, // LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH + {"lltri", 0x025FA}, // LOWER LEFT TRIANGLE + {"Lmidot", 0x0013F}, // LATIN CAPITAL LETTER L WITH MIDDLE DOT + {"lmidot", 0x00140}, // LATIN SMALL LETTER L WITH MIDDLE DOT + {"lmoust", 0x023B0}, // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION + {"lmoustache", 0x023B0}, // UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION + {"lnap", 0x02A89}, // LESS-THAN AND NOT APPROXIMATE + {"lnapprox", 0x02A89}, // LESS-THAN AND NOT APPROXIMATE + {"lnE", 0x02268}, // LESS-THAN BUT NOT EQUAL TO + {"lne", 0x02A87}, // LESS-THAN AND SINGLE-LINE NOT EQUAL TO + {"lneq", 0x02A87}, // LESS-THAN AND SINGLE-LINE NOT EQUAL TO + {"lneqq", 0x02268}, // LESS-THAN BUT NOT EQUAL TO + {"lnsim", 0x022E6}, // LESS-THAN BUT NOT EQUIVALENT TO + {"loang", 0x027EC}, // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET + {"loarr", 0x021FD}, // LEFTWARDS OPEN-HEADED ARROW + {"lobrk", 0x027E6}, // MATHEMATICAL LEFT WHITE SQUARE BRACKET + {"longleftarrow", 0x027F5}, // LONG LEFTWARDS ARROW + {"LongLeftArrow", 0x027F5}, // LONG LEFTWARDS ARROW + {"Longleftarrow", 0x027F8}, // LONG LEFTWARDS DOUBLE ARROW + {"longleftrightarrow", 0x027F7}, // LONG LEFT RIGHT ARROW + {"LongLeftRightArrow", 0x027F7}, // LONG LEFT RIGHT ARROW + {"Longleftrightarrow", 0x027FA}, // LONG LEFT RIGHT DOUBLE ARROW + {"longmapsto", 0x027FC}, // LONG RIGHTWARDS ARROW FROM BAR + {"longrightarrow", 0x027F6}, // LONG RIGHTWARDS ARROW + {"LongRightArrow", 0x027F6}, // LONG RIGHTWARDS ARROW + {"Longrightarrow", 0x027F9}, // LONG RIGHTWARDS DOUBLE ARROW + {"looparrowleft", 0x021AB}, // LEFTWARDS ARROW WITH LOOP + {"looparrowright", 0x021AC}, // RIGHTWARDS ARROW WITH LOOP + {"lopar", 0x02985}, // LEFT WHITE PARENTHESIS + {"Lopf", 0x1D543}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL L + {"lopf", 0x1D55D}, // MATHEMATICAL DOUBLE-STRUCK SMALL L + {"loplus", 0x02A2D}, // PLUS SIGN IN LEFT HALF CIRCLE + {"lotimes", 0x02A34}, // MULTIPLICATION SIGN IN LEFT HALF CIRCLE + {"lowast", 0x02217}, // ASTERISK OPERATOR + {"lowbar", 0x0005F}, // LOW LINE + {"LowerLeftArrow", 0x02199}, // SOUTH WEST ARROW + {"LowerRightArrow", 0x02198}, // SOUTH EAST ARROW + {"loz", 0x025CA}, // LOZENGE + {"lozenge", 0x025CA}, // LOZENGE + {"lozf", 0x029EB}, // BLACK LOZENGE + {"lpar", 0x00028}, // LEFT PARENTHESIS + {"lparlt", 0x02993}, // LEFT ARC LESS-THAN BRACKET + {"lrarr", 0x021C6}, // LEFTWARDS ARROW OVER RIGHTWARDS ARROW + {"lrcorner", 0x0231F}, // BOTTOM RIGHT CORNER + {"lrhar", 0x021CB}, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + {"lrhard", 0x0296D}, // RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH + {"lrm", 0x0200E}, // LEFT-TO-RIGHT MARK + {"lrtri", 0x022BF}, // RIGHT TRIANGLE + {"lsaquo", 0x02039}, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + {"Lscr", 0x02112}, // SCRIPT CAPITAL L + {"lscr", 0x1D4C1}, // MATHEMATICAL SCRIPT SMALL L + {"lsh", 0x021B0}, // UPWARDS ARROW WITH TIP LEFTWARDS + {"Lsh", 0x021B0}, // UPWARDS ARROW WITH TIP LEFTWARDS + {"lsim", 0x02272}, // LESS-THAN OR EQUIVALENT TO + {"lsime", 0x02A8D}, // LESS-THAN ABOVE SIMILAR OR EQUAL + {"lsimg", 0x02A8F}, // LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN + {"lsqb", 0x0005B}, // LEFT SQUARE BRACKET + {"lsquo", 0x02018}, // LEFT SINGLE QUOTATION MARK + {"lsquor", 0x0201A}, // SINGLE LOW-9 QUOTATION MARK + {"Lstrok", 0x00141}, // LATIN CAPITAL LETTER L WITH STROKE + {"lstrok", 0x00142}, // LATIN SMALL LETTER L WITH STROKE + {"lt", 0x0003C}, // LESS-THAN SIGN + {"LT", 0x0003C}, // LESS-THAN SIGN + {"Lt", 0x0226A}, // MUCH LESS-THAN + {"ltcc", 0x02AA6}, // LESS-THAN CLOSED BY CURVE + {"ltcir", 0x02A79}, // LESS-THAN WITH CIRCLE INSIDE + {"ltdot", 0x022D6}, // LESS-THAN WITH DOT + {"lthree", 0x022CB}, // LEFT SEMIDIRECT PRODUCT + {"ltimes", 0x022C9}, // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT + {"ltlarr", 0x02976}, // LESS-THAN ABOVE LEFTWARDS ARROW + {"ltquest", 0x02A7B}, // LESS-THAN WITH QUESTION MARK ABOVE + {"ltri", 0x025C3}, // WHITE LEFT-POINTING SMALL TRIANGLE + {"ltrie", 0x022B4}, // NORMAL SUBGROUP OF OR EQUAL TO + {"ltrif", 0x025C2}, // BLACK LEFT-POINTING SMALL TRIANGLE + {"ltrPar", 0x02996}, // DOUBLE RIGHT ARC LESS-THAN BRACKET + {"lurdshar", 0x0294A}, // LEFT BARB UP RIGHT BARB DOWN HARPOON + {"luruhar", 0x02966}, // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP +// "lvertneqq", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke +// "lvnE", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke + {NULL, 0} }; static NameId namesM[]={ - "macr", 0x000AF, // MACRON - "male", 0x02642, // MALE SIGN - "malt", 0x02720, // MALTESE CROSS - "maltese", 0x02720, // MALTESE CROSS - "map", 0x021A6, // RIGHTWARDS ARROW FROM BAR - "Map", 0x02905, // RIGHTWARDS TWO-HEADED ARROW FROM BAR - "mapsto", 0x021A6, // RIGHTWARDS ARROW FROM BAR - "mapstodown", 0x021A7, // DOWNWARDS ARROW FROM BAR - "mapstoleft", 0x021A4, // LEFTWARDS ARROW FROM BAR - "mapstoup", 0x021A5, // UPWARDS ARROW FROM BAR - "marker", 0x025AE, // BLACK VERTICAL RECTANGLE - "mcomma", 0x02A29, // MINUS SIGN WITH COMMA ABOVE - "Mcy", 0x0041C, // CYRILLIC CAPITAL LETTER EM - "mcy", 0x0043C, // CYRILLIC SMALL LETTER EM - "mdash", 0x02014, // EM DASH - "mDDot", 0x0223A, // GEOMETRIC PROPORTION - "measuredangle", 0x02221, // MEASURED ANGLE - "MediumSpace", 0x0205F, // MEDIUM MATHEMATICAL SPACE - "Mellintrf", 0x02133, // SCRIPT CAPITAL M - "Mfr", 0x1D510, // MATHEMATICAL FRAKTUR CAPITAL M - "mfr", 0x1D52A, // MATHEMATICAL FRAKTUR SMALL M - "Mgr", 0x0039C, // GREEK CAPITAL LETTER MU - "mgr", 0x003BC, // GREEK SMALL LETTER MU - "mho", 0x02127, // INVERTED OHM SIGN - "micro", 0x000B5, // MICRO SIGN - "mid", 0x02223, // DIVIDES - "midast", 0x0002A, // ASTERISK - "midcir", 0x02AF0, // VERTICAL LINE WITH CIRCLE BELOW - "middot", 0x000B7, // MIDDLE DOT - "minus", 0x02212, // MINUS SIGN - "minusb", 0x0229F, // SQUARED MINUS - "minusd", 0x02238, // DOT MINUS - "minusdu", 0x02A2A, // MINUS SIGN WITH DOT BELOW - "MinusPlus", 0x02213, // MINUS-OR-PLUS SIGN - "mlcp", 0x02ADB, // TRANSVERSAL INTERSECTION - "mldr", 0x02026, // HORIZONTAL ELLIPSIS - "mnplus", 0x02213, // MINUS-OR-PLUS SIGN - "models", 0x022A7, // MODELS - "Mopf", 0x1D544, // MATHEMATICAL DOUBLE-STRUCK CAPITAL M - "mopf", 0x1D55E, // MATHEMATICAL DOUBLE-STRUCK SMALL M - "mp", 0x02213, // MINUS-OR-PLUS SIGN - "Mscr", 0x02133, // SCRIPT CAPITAL M - "mscr", 0x1D4C2, // MATHEMATICAL SCRIPT SMALL M - "mstpos", 0x0223E, // INVERTED LAZY S - "Mu", 0x0039C, // GREEK CAPITAL LETTER MU - "mu", 0x003BC, // GREEK SMALL LETTER MU - "multimap", 0x022B8, // MULTIMAP - "mumap", 0x022B8, // MULTIMAP - NULL, 0 + {"macr", 0x000AF}, // MACRON + {"male", 0x02642}, // MALE SIGN + {"malt", 0x02720}, // MALTESE CROSS + {"maltese", 0x02720}, // MALTESE CROSS + {"map", 0x021A6}, // RIGHTWARDS ARROW FROM BAR + {"Map", 0x02905}, // RIGHTWARDS TWO-HEADED ARROW FROM BAR + {"mapsto", 0x021A6}, // RIGHTWARDS ARROW FROM BAR + {"mapstodown", 0x021A7}, // DOWNWARDS ARROW FROM BAR + {"mapstoleft", 0x021A4}, // LEFTWARDS ARROW FROM BAR + {"mapstoup", 0x021A5}, // UPWARDS ARROW FROM BAR + {"marker", 0x025AE}, // BLACK VERTICAL RECTANGLE + {"mcomma", 0x02A29}, // MINUS SIGN WITH COMMA ABOVE + {"Mcy", 0x0041C}, // CYRILLIC CAPITAL LETTER EM + {"mcy", 0x0043C}, // CYRILLIC SMALL LETTER EM + {"mdash", 0x02014}, // EM DASH + {"mDDot", 0x0223A}, // GEOMETRIC PROPORTION + {"measuredangle", 0x02221}, // MEASURED ANGLE + {"MediumSpace", 0x0205F}, // MEDIUM MATHEMATICAL SPACE + {"Mellintrf", 0x02133}, // SCRIPT CAPITAL M + {"Mfr", 0x1D510}, // MATHEMATICAL FRAKTUR CAPITAL M + {"mfr", 0x1D52A}, // MATHEMATICAL FRAKTUR SMALL M + {"Mgr", 0x0039C}, // GREEK CAPITAL LETTER MU + {"mgr", 0x003BC}, // GREEK SMALL LETTER MU + {"mho", 0x02127}, // INVERTED OHM SIGN + {"micro", 0x000B5}, // MICRO SIGN + {"mid", 0x02223}, // DIVIDES + {"midast", 0x0002A}, // ASTERISK + {"midcir", 0x02AF0}, // VERTICAL LINE WITH CIRCLE BELOW + {"middot", 0x000B7}, // MIDDLE DOT + {"minus", 0x02212}, // MINUS SIGN + {"minusb", 0x0229F}, // SQUARED MINUS + {"minusd", 0x02238}, // DOT MINUS + {"minusdu", 0x02A2A}, // MINUS SIGN WITH DOT BELOW + {"MinusPlus", 0x02213}, // MINUS-OR-PLUS SIGN + {"mlcp", 0x02ADB}, // TRANSVERSAL INTERSECTION + {"mldr", 0x02026}, // HORIZONTAL ELLIPSIS + {"mnplus", 0x02213}, // MINUS-OR-PLUS SIGN + {"models", 0x022A7}, // MODELS + {"Mopf", 0x1D544}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL M + {"mopf", 0x1D55E}, // MATHEMATICAL DOUBLE-STRUCK SMALL M + {"mp", 0x02213}, // MINUS-OR-PLUS SIGN + {"Mscr", 0x02133}, // SCRIPT CAPITAL M + {"mscr", 0x1D4C2}, // MATHEMATICAL SCRIPT SMALL M + {"mstpos", 0x0223E}, // INVERTED LAZY S + {"Mu", 0x0039C}, // GREEK CAPITAL LETTER MU + {"mu", 0x003BC}, // GREEK SMALL LETTER MU + {"multimap", 0x022B8}, // MULTIMAP + {"mumap", 0x022B8}, // MULTIMAP + {NULL, 0} }; static NameId namesN[]={ - "nabla", 0x02207, // NABLA - "Nacute", 0x00143, // LATIN CAPITAL LETTER N WITH ACUTE - "nacute", 0x00144, // LATIN SMALL LETTER N WITH ACUTE -// "nang", 0x02220;0x020D2, // ANGLE with vertical line - "nap", 0x02249, // NOT ALMOST EQUAL TO -// "napE", 0x02A70;0x00338, // APPROXIMATELY EQUAL OR EQUAL TO with slash -// "napid", 0x0224B;0x00338, // TRIPLE TILDE with slash - "napos", 0x00149, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE - "napprox", 0x02249, // NOT ALMOST EQUAL TO - "natur", 0x0266E, // MUSIC NATURAL SIGN - "natural", 0x0266E, // MUSIC NATURAL SIGN - "naturals", 0x02115, // DOUBLE-STRUCK CAPITAL N - "nbsp", 0x000A0, // NO-BREAK SPACE -// "nbump", 0x0224E;0x00338, // GEOMETRICALLY EQUIVALENT TO with slash -// "nbumpe", 0x0224F;0x00338, // DIFFERENCE BETWEEN with slash - "ncap", 0x02A43, // INTERSECTION WITH OVERBAR - "Ncaron", 0x00147, // LATIN CAPITAL LETTER N WITH CARON - "ncaron", 0x00148, // LATIN SMALL LETTER N WITH CARON - "Ncedil", 0x00145, // LATIN CAPITAL LETTER N WITH CEDILLA - "ncedil", 0x00146, // LATIN SMALL LETTER N WITH CEDILLA - "ncong", 0x02247, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO -// "ncongdot", 0x02A6D;0x00338, // CONGRUENT WITH DOT ABOVE with slash - "ncup", 0x02A42, // UNION WITH OVERBAR - "Ncy", 0x0041D, // CYRILLIC CAPITAL LETTER EN - "ncy", 0x0043D, // CYRILLIC SMALL LETTER EN - "ndash", 0x02013, // EN DASH - "ne", 0x02260, // NOT EQUAL TO - "nearhk", 0x02924, // NORTH EAST ARROW WITH HOOK - "nearr", 0x02197, // NORTH EAST ARROW - "neArr", 0x021D7, // NORTH EAST DOUBLE ARROW - "nearrow", 0x02197, // NORTH EAST ARROW -// "nedot", 0x02250;0x00338, // APPROACHES THE LIMIT with slash - "NegativeMediumSpace", 0x0200B, // ZERO WIDTH SPACE - "NegativeThickSpace", 0x0200B, // ZERO WIDTH SPACE - "NegativeThinSpace", 0x0200B, // ZERO WIDTH SPACE - "NegativeVeryThinSpace", 0x0200B, // ZERO WIDTH SPACE - "nequiv", 0x02262, // NOT IDENTICAL TO - "nesear", 0x02928, // NORTH EAST ARROW AND SOUTH EAST ARROW -// "nesim", 0x02242;0x00338, // MINUS TILDE with slash - "NestedGreaterGreater", 0x0226B, // MUCH GREATER-THAN - "NestedLessLess", 0x0226A, // MUCH LESS-THAN - "NewLine", 0x0000A, // LINE FEED (LF) - "nexist", 0x02204, // THERE DOES NOT EXIST - "nexists", 0x02204, // THERE DOES NOT EXIST - "Nfr", 0x1D511, // MATHEMATICAL FRAKTUR CAPITAL N - "nfr", 0x1D52B, // MATHEMATICAL FRAKTUR SMALL N -// "ngE", 0x02267;0x00338, // GREATER-THAN OVER EQUAL TO with slash - "nge", 0x02271, // NEITHER GREATER-THAN NOR EQUAL TO - "ngeq", 0x02271, // NEITHER GREATER-THAN NOR EQUAL TO -// "ngeqq", 0x02267;0x00338, // GREATER-THAN OVER EQUAL TO with slash -// "ngeqslant", 0x02A7E;0x00338, // GREATER-THAN OR SLANTED EQUAL TO with slash -// "nges", 0x02A7E;0x00338, // GREATER-THAN OR SLANTED EQUAL TO with slash -// "nGg", 0x022D9;0x00338, // VERY MUCH GREATER-THAN with slash - "Ngr", 0x0039D, // GREEK CAPITAL LETTER NU - "ngr", 0x003BD, // GREEK SMALL LETTER NU - "ngsim", 0x02275, // NEITHER GREATER-THAN NOR EQUIVALENT TO -// "nGt", 0x0226B;0x020D2, // MUCH GREATER THAN with vertical line - "ngt", 0x0226F, // NOT GREATER-THAN - "ngtr", 0x0226F, // NOT GREATER-THAN -// "nGtv", 0x0226B;0x00338, // MUCH GREATER THAN with slash - "nharr", 0x021AE, // LEFT RIGHT ARROW WITH STROKE - "nhArr", 0x021CE, // LEFT RIGHT DOUBLE ARROW WITH STROKE - "nhpar", 0x02AF2, // PARALLEL WITH HORIZONTAL STROKE - "ni", 0x0220B, // CONTAINS AS MEMBER - "nis", 0x022FC, // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - "nisd", 0x022FA, // CONTAINS WITH LONG HORIZONTAL STROKE - "niv", 0x0220B, // CONTAINS AS MEMBER - "NJcy", 0x0040A, // CYRILLIC CAPITAL LETTER NJE - "njcy", 0x0045A, // CYRILLIC SMALL LETTER NJE - "nlarr", 0x0219A, // LEFTWARDS ARROW WITH STROKE - "nlArr", 0x021CD, // LEFTWARDS DOUBLE ARROW WITH STROKE - "nldr", 0x02025, // TWO DOT LEADER -// "nlE", 0x02266;0x00338, // LESS-THAN OVER EQUAL TO with slash - "nle", 0x02270, // NEITHER LESS-THAN NOR EQUAL TO - "nleftarrow", 0x0219A, // LEFTWARDS ARROW WITH STROKE - "nLeftarrow", 0x021CD, // LEFTWARDS DOUBLE ARROW WITH STROKE - "nleftrightarrow", 0x021AE, // LEFT RIGHT ARROW WITH STROKE - "nLeftrightarrow", 0x021CE, // LEFT RIGHT DOUBLE ARROW WITH STROKE - "nleq", 0x02270, // NEITHER LESS-THAN NOR EQUAL TO -// "nleqq", 0x02266;0x00338, // LESS-THAN OVER EQUAL TO with slash -// "nleqslant", 0x02A7D;0x00338, // LESS-THAN OR SLANTED EQUAL TO with slash -// "nles", 0x02A7D;0x00338, // LESS-THAN OR SLANTED EQUAL TO with slash - "nless", 0x0226E, // NOT LESS-THAN -// "nLl", 0x022D8;0x00338, // VERY MUCH LESS-THAN with slash - "nlsim", 0x02274, // NEITHER LESS-THAN NOR EQUIVALENT TO -// "nLt", 0x0226A;0x020D2, // MUCH LESS THAN with vertical line - "nlt", 0x0226E, // NOT LESS-THAN - "nltri", 0x022EA, // NOT NORMAL SUBGROUP OF - "nltrie", 0x022EC, // NOT NORMAL SUBGROUP OF OR EQUAL TO -// "nLtv", 0x0226A;0x00338, // MUCH LESS THAN with slash - "nmid", 0x02224, // DOES NOT DIVIDE - "NoBreak", 0x02060, // WORD JOINER - "NonBreakingSpace", 0x000A0, // NO-BREAK SPACE - "Nopf", 0x02115, // DOUBLE-STRUCK CAPITAL N - "nopf", 0x1D55F, // MATHEMATICAL DOUBLE-STRUCK SMALL N - "not", 0x000AC, // NOT SIGN - "Not", 0x02AEC, // DOUBLE STROKE NOT SIGN - "NotCongruent", 0x02262, // NOT IDENTICAL TO - "NotCupCap", 0x0226D, // NOT EQUIVALENT TO - "NotDoubleVerticalBar", 0x02226, // NOT PARALLEL TO - "NotElement", 0x02209, // NOT AN ELEMENT OF - "NotEqual", 0x02260, // NOT EQUAL TO -// "NotEqualTilde", 0x02242;0x00338, // MINUS TILDE with slash - "NotExists", 0x02204, // THERE DOES NOT EXIST - "NotGreater", 0x0226F, // NOT GREATER-THAN - "NotGreaterEqual", 0x02271, // NEITHER GREATER-THAN NOR EQUAL TO -// "NotGreaterFullEqual", 0x02267;0x00338, // GREATER-THAN OVER EQUAL TO with slash -// "NotGreaterGreater", 0x0226B;0x00338, // MUCH GREATER THAN with slash - "NotGreaterLess", 0x02279, // NEITHER GREATER-THAN NOR LESS-THAN -// "NotGreaterSlantEqual", 0x02A7E;0x00338, // GREATER-THAN OR SLANTED EQUAL TO with slash - "NotGreaterTilde", 0x02275, // NEITHER GREATER-THAN NOR EQUIVALENT TO -// "NotHumpDownHump", 0x0224E;0x00338, // GEOMETRICALLY EQUIVALENT TO with slash -// "NotHumpEqual", 0x0224F;0x00338, // DIFFERENCE BETWEEN with slash - "notin", 0x02209, // NOT AN ELEMENT OF -// "notindot", 0x022F5;0x00338, // ELEMENT OF WITH DOT ABOVE with slash -// "notinE", 0x022F9;0x00338, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash - "notinva", 0x02209, // NOT AN ELEMENT OF - "notinvb", 0x022F7, // SMALL ELEMENT OF WITH OVERBAR - "notinvc", 0x022F6, // ELEMENT OF WITH OVERBAR - "NotLeftTriangle", 0x022EA, // NOT NORMAL SUBGROUP OF -// "NotLeftTriangleBar", 0x029CF;0x00338, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash - "NotLeftTriangleEqual", 0x022EC, // NOT NORMAL SUBGROUP OF OR EQUAL TO - "NotLess", 0x0226E, // NOT LESS-THAN - "NotLessEqual", 0x02270, // NEITHER LESS-THAN NOR EQUAL TO - "NotLessGreater", 0x02278, // NEITHER LESS-THAN NOR GREATER-THAN -// "NotLessLess", 0x0226A;0x00338, // MUCH LESS THAN with slash -// "NotLessSlantEqual", 0x02A7D;0x00338, // LESS-THAN OR SLANTED EQUAL TO with slash - "NotLessTilde", 0x02274, // NEITHER LESS-THAN NOR EQUIVALENT TO -// "NotNestedGreaterGreater", 0x02AA2;0x00338, // DOUBLE NESTED GREATER-THAN with slash -// "NotNestedLessLess", 0x02AA1;0x00338, // DOUBLE NESTED LESS-THAN with slash - "notni", 0x0220C, // DOES NOT CONTAIN AS MEMBER - "notniva", 0x0220C, // DOES NOT CONTAIN AS MEMBER - "notnivb", 0x022FE, // SMALL CONTAINS WITH OVERBAR - "notnivc", 0x022FD, // CONTAINS WITH OVERBAR - "NotPrecedes", 0x02280, // DOES NOT PRECEDE -// "NotPrecedesEqual", 0x02AAF;0x00338, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - "NotPrecedesSlantEqual", 0x022E0, // DOES NOT PRECEDE OR EQUAL - "NotReverseElement", 0x0220C, // DOES NOT CONTAIN AS MEMBER - "NotRightTriangle", 0x022EB, // DOES NOT CONTAIN AS NORMAL SUBGROUP -// "NotRightTriangleBar", 0x029D0;0x00338, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash - "NotRightTriangleEqual", 0x022ED, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL -// "NotSquareSubset", 0x0228F;0x00338, // SQUARE IMAGE OF with slash - "NotSquareSubsetEqual", 0x022E2, // NOT SQUARE IMAGE OF OR EQUAL TO -// "NotSquareSuperset", 0x02290;0x00338, // SQUARE ORIGINAL OF with slash - "NotSquareSupersetEqual", 0x022E3, // NOT SQUARE ORIGINAL OF OR EQUAL TO -// "NotSubset", 0x02282;0x020D2, // SUBSET OF with vertical line - "NotSubsetEqual", 0x02288, // NEITHER A SUBSET OF NOR EQUAL TO - "NotSucceeds", 0x02281, // DOES NOT SUCCEED -// "NotSucceedsEqual", 0x02AB0;0x00338, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - "NotSucceedsSlantEqual", 0x022E1, // DOES NOT SUCCEED OR EQUAL -// "NotSucceedsTilde", 0x0227F;0x00338, // SUCCEEDS OR EQUIVALENT TO with slash -// "NotSuperset", 0x02283;0x020D2, // SUPERSET OF with vertical line - "NotSupersetEqual", 0x02289, // NEITHER A SUPERSET OF NOR EQUAL TO - "NotTilde", 0x02241, // NOT TILDE - "NotTildeEqual", 0x02244, // NOT ASYMPTOTICALLY EQUAL TO - "NotTildeFullEqual", 0x02247, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO - "NotTildeTilde", 0x02249, // NOT ALMOST EQUAL TO - "NotVerticalBar", 0x02224, // DOES NOT DIVIDE - "npar", 0x02226, // NOT PARALLEL TO - "nparallel", 0x02226, // NOT PARALLEL TO -// "nparsl", 0x02AFD;0x020E5, // DOUBLE SOLIDUS OPERATOR with reverse slash -// "npart", 0x02202;0x00338, // PARTIAL DIFFERENTIAL with slash - "npolint", 0x02A14, // LINE INTEGRATION NOT INCLUDING THE POLE - "npr", 0x02280, // DOES NOT PRECEDE - "nprcue", 0x022E0, // DOES NOT PRECEDE OR EQUAL -// "npre", 0x02AAF;0x00338, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - "nprec", 0x02280, // DOES NOT PRECEDE -// "npreceq", 0x02AAF;0x00338, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash - "nrarr", 0x0219B, // RIGHTWARDS ARROW WITH STROKE - "nrArr", 0x021CF, // RIGHTWARDS DOUBLE ARROW WITH STROKE -// "nrarrc", 0x02933;0x00338, // WAVE ARROW POINTING DIRECTLY RIGHT with slash -// "nrarrw", 0x0219D;0x00338, // RIGHTWARDS WAVE ARROW with slash - "nrightarrow", 0x0219B, // RIGHTWARDS ARROW WITH STROKE - "nRightarrow", 0x021CF, // RIGHTWARDS DOUBLE ARROW WITH STROKE - "nrtri", 0x022EB, // DOES NOT CONTAIN AS NORMAL SUBGROUP - "nrtrie", 0x022ED, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL - "nsc", 0x02281, // DOES NOT SUCCEED - "nsccue", 0x022E1, // DOES NOT SUCCEED OR EQUAL -// "nsce", 0x02AB0;0x00338, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - "Nscr", 0x1D4A9, // MATHEMATICAL SCRIPT CAPITAL N - "nscr", 0x1D4C3, // MATHEMATICAL SCRIPT SMALL N - "nshortmid", 0x02224, // DOES NOT DIVIDE - "nshortparallel", 0x02226, // NOT PARALLEL TO - "nsim", 0x02241, // NOT TILDE - "nsime", 0x02244, // NOT ASYMPTOTICALLY EQUAL TO - "nsimeq", 0x02244, // NOT ASYMPTOTICALLY EQUAL TO - "nsmid", 0x02224, // DOES NOT DIVIDE - "nspar", 0x02226, // NOT PARALLEL TO - "nsqsube", 0x022E2, // NOT SQUARE IMAGE OF OR EQUAL TO - "nsqsupe", 0x022E3, // NOT SQUARE ORIGINAL OF OR EQUAL TO - "nsub", 0x02284, // NOT A SUBSET OF - "nsube", 0x02288, // NEITHER A SUBSET OF NOR EQUAL TO -// "nsubE", 0x02AC5;0x00338, // SUBSET OF ABOVE EQUALS SIGN with slash -// "nsubset", 0x02282;0x020D2, // SUBSET OF with vertical line - "nsubseteq", 0x02288, // NEITHER A SUBSET OF NOR EQUAL TO -// "nsubseteqq", 0x02AC5;0x00338, // SUBSET OF ABOVE EQUALS SIGN with slash - "nsucc", 0x02281, // DOES NOT SUCCEED -// "nsucceq", 0x02AB0;0x00338, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash - "nsup", 0x02285, // NOT A SUPERSET OF - "nsupe", 0x02289, // NEITHER A SUPERSET OF NOR EQUAL TO -// "nsupE", 0x02AC6;0x00338, // SUPERSET OF ABOVE EQUALS SIGN with slash -// "nsupset", 0x02283;0x020D2, // SUPERSET OF with vertical line - "nsupseteq", 0x02289, // NEITHER A SUPERSET OF NOR EQUAL TO -// "nsupseteqq", 0x02AC6;0x00338, // SUPERSET OF ABOVE EQUALS SIGN with slash - "ntgl", 0x02279, // NEITHER GREATER-THAN NOR LESS-THAN - "Ntilde", 0x000D1, // LATIN CAPITAL LETTER N WITH TILDE - "ntilde", 0x000F1, // LATIN SMALL LETTER N WITH TILDE - "ntlg", 0x02278, // NEITHER LESS-THAN NOR GREATER-THAN - "ntriangleleft", 0x022EA, // NOT NORMAL SUBGROUP OF - "ntrianglelefteq", 0x022EC, // NOT NORMAL SUBGROUP OF OR EQUAL TO - "ntriangleright", 0x022EB, // DOES NOT CONTAIN AS NORMAL SUBGROUP - "ntrianglerighteq", 0x022ED, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL - "Nu", 0x0039D, // GREEK CAPITAL LETTER NU - "nu", 0x003BD, // GREEK SMALL LETTER NU - "num", 0x00023, // NUMBER SIGN - "numero", 0x02116, // NUMERO SIGN - "numsp", 0x02007, // FIGURE SPACE -// "nvap", 0x0224D;0x020D2, // EQUIVALENT TO with vertical line - "nvdash", 0x022AC, // DOES NOT PROVE - "nvDash", 0x022AD, // NOT TRUE - "nVdash", 0x022AE, // DOES NOT FORCE - "nVDash", 0x022AF, // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE -// "nvge", 0x02265;0x020D2, // GREATER-THAN OR EQUAL TO with vertical line -// "nvgt", 0x0003E;0x020D2, // GREATER-THAN SIGN with vertical line - "nvHarr", 0x02904, // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE - "nvinfin", 0x029DE, // INFINITY NEGATED WITH VERTICAL BAR - "nvlArr", 0x02902, // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE -// "nvle", 0x02264;0x020D2, // LESS-THAN OR EQUAL TO with vertical line -// "nvlt", 0x0003C;0x020D2, // LESS-THAN SIGN with vertical line -// "nvltrie", 0x022B4;0x020D2, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line - "nvrArr", 0x02903, // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE -// "nvrtrie", 0x022B5;0x020D2, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line -// "nvsim", 0x0223C;0x020D2, // TILDE OPERATOR with vertical line - "nwarhk", 0x02923, // NORTH WEST ARROW WITH HOOK - "nwarr", 0x02196, // NORTH WEST ARROW - "nwArr", 0x021D6, // NORTH WEST DOUBLE ARROW - "nwarrow", 0x02196, // NORTH WEST ARROW - "nwnear", 0x02927, // NORTH WEST ARROW AND NORTH EAST ARROW - NULL, 0 + {"nabla", 0x02207}, // NABLA + {"Nacute", 0x00143}, // LATIN CAPITAL LETTER N WITH ACUTE + {"nacute", 0x00144}, // LATIN SMALL LETTER N WITH ACUTE +// "nang", 0x02220;0x020D2}, // ANGLE with vertical line + {"nap", 0x02249}, // NOT ALMOST EQUAL TO +// "napE", 0x02A70;0x00338}, // APPROXIMATELY EQUAL OR EQUAL TO with slash +// "napid", 0x0224B;0x00338}, // TRIPLE TILDE with slash + {"napos", 0x00149}, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + {"napprox", 0x02249}, // NOT ALMOST EQUAL TO + {"natur", 0x0266E}, // MUSIC NATURAL SIGN + {"natural", 0x0266E}, // MUSIC NATURAL SIGN + {"naturals", 0x02115}, // DOUBLE-STRUCK CAPITAL N + {"nbsp", 0x000A0}, // NO-BREAK SPACE +// "nbump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash +// "nbumpe", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash + {"ncap", 0x02A43}, // INTERSECTION WITH OVERBAR + {"Ncaron", 0x00147}, // LATIN CAPITAL LETTER N WITH CARON + {"ncaron", 0x00148}, // LATIN SMALL LETTER N WITH CARON + {"Ncedil", 0x00145}, // LATIN CAPITAL LETTER N WITH CEDILLA + {"ncedil", 0x00146}, // LATIN SMALL LETTER N WITH CEDILLA + {"ncong", 0x02247}, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO +// "ncongdot", 0x02A6D;0x00338}, // CONGRUENT WITH DOT ABOVE with slash + {"ncup", 0x02A42}, // UNION WITH OVERBAR + {"Ncy", 0x0041D}, // CYRILLIC CAPITAL LETTER EN + {"ncy", 0x0043D}, // CYRILLIC SMALL LETTER EN + {"ndash", 0x02013}, // EN DASH + {"ne", 0x02260}, // NOT EQUAL TO + {"nearhk", 0x02924}, // NORTH EAST ARROW WITH HOOK + {"nearr", 0x02197}, // NORTH EAST ARROW + {"neArr", 0x021D7}, // NORTH EAST DOUBLE ARROW + {"nearrow", 0x02197}, // NORTH EAST ARROW +// "nedot", 0x02250;0x00338}, // APPROACHES THE LIMIT with slash + {"NegativeMediumSpace", 0x0200B}, // ZERO WIDTH SPACE + {"NegativeThickSpace", 0x0200B}, // ZERO WIDTH SPACE + {"NegativeThinSpace", 0x0200B}, // ZERO WIDTH SPACE + {"NegativeVeryThinSpace", 0x0200B}, // ZERO WIDTH SPACE + {"nequiv", 0x02262}, // NOT IDENTICAL TO + {"nesear", 0x02928}, // NORTH EAST ARROW AND SOUTH EAST ARROW +// "nesim", 0x02242;0x00338}, // MINUS TILDE with slash + {"NestedGreaterGreater", 0x0226B}, // MUCH GREATER-THAN + {"NestedLessLess", 0x0226A}, // MUCH LESS-THAN + {"NewLine", 0x0000A}, // LINE FEED (LF) + {"nexist", 0x02204}, // THERE DOES NOT EXIST + {"nexists", 0x02204}, // THERE DOES NOT EXIST + {"Nfr", 0x1D511}, // MATHEMATICAL FRAKTUR CAPITAL N + {"nfr", 0x1D52B}, // MATHEMATICAL FRAKTUR SMALL N +// "ngE", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash + {"nge", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO + {"ngeq", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO +// "ngeqq", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash +// "ngeqslant", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash +// "nges", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash +// "nGg", 0x022D9;0x00338}, // VERY MUCH GREATER-THAN with slash + {"Ngr", 0x0039D}, // GREEK CAPITAL LETTER NU + {"ngr", 0x003BD}, // GREEK SMALL LETTER NU + {"ngsim", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO +// "nGt", 0x0226B;0x020D2}, // MUCH GREATER THAN with vertical line + {"ngt", 0x0226F}, // NOT GREATER-THAN + {"ngtr", 0x0226F}, // NOT GREATER-THAN +// "nGtv", 0x0226B;0x00338}, // MUCH GREATER THAN with slash + {"nharr", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE + {"nhArr", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE + {"nhpar", 0x02AF2}, // PARALLEL WITH HORIZONTAL STROKE + {"ni", 0x0220B}, // CONTAINS AS MEMBER + {"nis", 0x022FC}, // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + {"nisd", 0x022FA}, // CONTAINS WITH LONG HORIZONTAL STROKE + {"niv", 0x0220B}, // CONTAINS AS MEMBER + {"NJcy", 0x0040A}, // CYRILLIC CAPITAL LETTER NJE + {"njcy", 0x0045A}, // CYRILLIC SMALL LETTER NJE + {"nlarr", 0x0219A}, // LEFTWARDS ARROW WITH STROKE + {"nlArr", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE + {"nldr", 0x02025}, // TWO DOT LEADER +// "nlE", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash + {"nle", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO + {"nleftarrow", 0x0219A}, // LEFTWARDS ARROW WITH STROKE + {"nLeftarrow", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE + {"nleftrightarrow", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE + {"nLeftrightarrow", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE + {"nleq", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO +// "nleqq", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash +// "nleqslant", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash +// "nles", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash + {"nless", 0x0226E}, // NOT LESS-THAN +// "nLl", 0x022D8;0x00338}, // VERY MUCH LESS-THAN with slash + {"nlsim", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO +// "nLt", 0x0226A;0x020D2}, // MUCH LESS THAN with vertical line + {"nlt", 0x0226E}, // NOT LESS-THAN + {"nltri", 0x022EA}, // NOT NORMAL SUBGROUP OF + {"nltrie", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO +// "nLtv", 0x0226A;0x00338}, // MUCH LESS THAN with slash + {"nmid", 0x02224}, // DOES NOT DIVIDE + {"NoBreak", 0x02060}, // WORD JOINER + {"NonBreakingSpace", 0x000A0}, // NO-BREAK SPACE + {"Nopf", 0x02115}, // DOUBLE-STRUCK CAPITAL N + {"nopf", 0x1D55F}, // MATHEMATICAL DOUBLE-STRUCK SMALL N + {"not", 0x000AC}, // NOT SIGN + {"Not", 0x02AEC}, // DOUBLE STROKE NOT SIGN + {"NotCongruent", 0x02262}, // NOT IDENTICAL TO + {"NotCupCap", 0x0226D}, // NOT EQUIVALENT TO + {"NotDoubleVerticalBar", 0x02226}, // NOT PARALLEL TO + {"NotElement", 0x02209}, // NOT AN ELEMENT OF + {"NotEqual", 0x02260}, // NOT EQUAL TO +// "NotEqualTilde", 0x02242;0x00338}, // MINUS TILDE with slash + {"NotExists", 0x02204}, // THERE DOES NOT EXIST + {"NotGreater", 0x0226F}, // NOT GREATER-THAN + {"NotGreaterEqual", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO +// "NotGreaterFullEqual", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash +// "NotGreaterGreater", 0x0226B;0x00338}, // MUCH GREATER THAN with slash + {"NotGreaterLess", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN +// "NotGreaterSlantEqual", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash + {"NotGreaterTilde", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO +// "NotHumpDownHump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash +// "NotHumpEqual", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash + {"notin", 0x02209}, // NOT AN ELEMENT OF +// "notindot", 0x022F5;0x00338}, // ELEMENT OF WITH DOT ABOVE with slash +// "notinE", 0x022F9;0x00338}, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash + {"notinva", 0x02209}, // NOT AN ELEMENT OF + {"notinvb", 0x022F7}, // SMALL ELEMENT OF WITH OVERBAR + {"notinvc", 0x022F6}, // ELEMENT OF WITH OVERBAR + {"NotLeftTriangle", 0x022EA}, // NOT NORMAL SUBGROUP OF +// "NotLeftTriangleBar", 0x029CF;0x00338}, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash + {"NotLeftTriangleEqual", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO + {"NotLess", 0x0226E}, // NOT LESS-THAN + {"NotLessEqual", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO + {"NotLessGreater", 0x02278}, // NEITHER LESS-THAN NOR GREATER-THAN +// "NotLessLess", 0x0226A;0x00338}, // MUCH LESS THAN with slash +// "NotLessSlantEqual", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash + {"NotLessTilde", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO +// "NotNestedGreaterGreater", 0x02AA2;0x00338}, // DOUBLE NESTED GREATER-THAN with slash +// "NotNestedLessLess", 0x02AA1;0x00338}, // DOUBLE NESTED LESS-THAN with slash + {"notni", 0x0220C}, // DOES NOT CONTAIN AS MEMBER + {"notniva", 0x0220C}, // DOES NOT CONTAIN AS MEMBER + {"notnivb", 0x022FE}, // SMALL CONTAINS WITH OVERBAR + {"notnivc", 0x022FD}, // CONTAINS WITH OVERBAR + {"NotPrecedes", 0x02280}, // DOES NOT PRECEDE +// "NotPrecedesEqual", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"NotPrecedesSlantEqual", 0x022E0}, // DOES NOT PRECEDE OR EQUAL + {"NotReverseElement", 0x0220C}, // DOES NOT CONTAIN AS MEMBER + {"NotRightTriangle", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP +// "NotRightTriangleBar", 0x029D0;0x00338}, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash + {"NotRightTriangleEqual", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL +// "NotSquareSubset", 0x0228F;0x00338}, // SQUARE IMAGE OF with slash + {"NotSquareSubsetEqual", 0x022E2}, // NOT SQUARE IMAGE OF OR EQUAL TO +// "NotSquareSuperset", 0x02290;0x00338}, // SQUARE ORIGINAL OF with slash + {"NotSquareSupersetEqual", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO +// "NotSubset", 0x02282;0x020D2}, // SUBSET OF with vertical line + {"NotSubsetEqual", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO + {"NotSucceeds", 0x02281}, // DOES NOT SUCCEED +// "NotSucceedsEqual", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"NotSucceedsSlantEqual", 0x022E1}, // DOES NOT SUCCEED OR EQUAL +// "NotSucceedsTilde", 0x0227F;0x00338}, // SUCCEEDS OR EQUIVALENT TO with slash +// "NotSuperset", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"NotSupersetEqual", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO + {"NotTilde", 0x02241}, // NOT TILDE + {"NotTildeEqual", 0x02244}, // NOT ASYMPTOTICALLY EQUAL TO + {"NotTildeFullEqual", 0x02247}, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO + {"NotTildeTilde", 0x02249}, // NOT ALMOST EQUAL TO + {"NotVerticalBar", 0x02224}, // DOES NOT DIVIDE + {"npar", 0x02226}, // NOT PARALLEL TO + {"nparallel", 0x02226}, // NOT PARALLEL TO +// "nparsl", 0x02AFD;0x020E5}, // DOUBLE SOLIDUS OPERATOR with reverse slash +// "npart", 0x02202;0x00338}, // PARTIAL DIFFERENTIAL with slash + {"npolint", 0x02A14}, // LINE INTEGRATION NOT INCLUDING THE POLE + {"npr", 0x02280}, // DOES NOT PRECEDE + {"nprcue", 0x022E0}, // DOES NOT PRECEDE OR EQUAL +// "npre", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"nprec", 0x02280}, // DOES NOT PRECEDE +// "npreceq", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash + {"nrarr", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE + {"nrArr", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE +// "nrarrc", 0x02933;0x00338}, // WAVE ARROW POINTING DIRECTLY RIGHT with slash +// "nrarrw", 0x0219D;0x00338}, // RIGHTWARDS WAVE ARROW with slash + {"nrightarrow", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE + {"nRightarrow", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE + {"nrtri", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP + {"nrtrie", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL + {"nsc", 0x02281}, // DOES NOT SUCCEED + {"nsccue", 0x022E1}, // DOES NOT SUCCEED OR EQUAL +// "nsce", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"Nscr", 0x1D4A9}, // MATHEMATICAL SCRIPT CAPITAL N + {"nscr", 0x1D4C3}, // MATHEMATICAL SCRIPT SMALL N + {"nshortmid", 0x02224}, // DOES NOT DIVIDE + {"nshortparallel", 0x02226}, // NOT PARALLEL TO + {"nsim", 0x02241}, // NOT TILDE + {"nsime", 0x02244}, // NOT ASYMPTOTICALLY EQUAL TO + {"nsimeq", 0x02244}, // NOT ASYMPTOTICALLY EQUAL TO + {"nsmid", 0x02224}, // DOES NOT DIVIDE + {"nspar", 0x02226}, // NOT PARALLEL TO + {"nsqsube", 0x022E2}, // NOT SQUARE IMAGE OF OR EQUAL TO + {"nsqsupe", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO + {"nsub", 0x02284}, // NOT A SUBSET OF + {"nsube", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO +// "nsubE", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash +// "nsubset", 0x02282;0x020D2}, // SUBSET OF with vertical line + {"nsubseteq", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO +// "nsubseteqq", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash + {"nsucc", 0x02281}, // DOES NOT SUCCEED +// "nsucceq", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash + {"nsup", 0x02285}, // NOT A SUPERSET OF + {"nsupe", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO +// "nsupE", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash +// "nsupset", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"nsupseteq", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO +// "nsupseteqq", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash + {"ntgl", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN + {"Ntilde", 0x000D1}, // LATIN CAPITAL LETTER N WITH TILDE + {"ntilde", 0x000F1}, // LATIN SMALL LETTER N WITH TILDE + {"ntlg", 0x02278}, // NEITHER LESS-THAN NOR GREATER-THAN + {"ntriangleleft", 0x022EA}, // NOT NORMAL SUBGROUP OF + {"ntrianglelefteq", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO + {"ntriangleright", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP + {"ntrianglerighteq", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL + {"Nu", 0x0039D}, // GREEK CAPITAL LETTER NU + {"nu", 0x003BD}, // GREEK SMALL LETTER NU + {"num", 0x00023}, // NUMBER SIGN + {"numero", 0x02116}, // NUMERO SIGN + {"numsp", 0x02007}, // FIGURE SPACE +// "nvap", 0x0224D;0x020D2}, // EQUIVALENT TO with vertical line + {"nvdash", 0x022AC}, // DOES NOT PROVE + {"nvDash", 0x022AD}, // NOT TRUE + {"nVdash", 0x022AE}, // DOES NOT FORCE + {"nVDash", 0x022AF}, // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE +// "nvge", 0x02265;0x020D2}, // GREATER-THAN OR EQUAL TO with vertical line +// "nvgt", 0x0003E;0x020D2}, // GREATER-THAN SIGN with vertical line + {"nvHarr", 0x02904}, // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE + {"nvinfin", 0x029DE}, // INFINITY NEGATED WITH VERTICAL BAR + {"nvlArr", 0x02902}, // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE +// "nvle", 0x02264;0x020D2}, // LESS-THAN OR EQUAL TO with vertical line +// "nvlt", 0x0003C;0x020D2}, // LESS-THAN SIGN with vertical line +// "nvltrie", 0x022B4;0x020D2}, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line + {"nvrArr", 0x02903}, // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE +// "nvrtrie", 0x022B5;0x020D2}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line +// "nvsim", 0x0223C;0x020D2}, // TILDE OPERATOR with vertical line + {"nwarhk", 0x02923}, // NORTH WEST ARROW WITH HOOK + {"nwarr", 0x02196}, // NORTH WEST ARROW + {"nwArr", 0x021D6}, // NORTH WEST DOUBLE ARROW + {"nwarrow", 0x02196}, // NORTH WEST ARROW + {"nwnear", 0x02927}, // NORTH WEST ARROW AND NORTH EAST ARROW + {NULL, 0} }; static NameId namesO[]={ - "Oacgr", 0x0038C, // GREEK CAPITAL LETTER OMICRON WITH TONOS - "oacgr", 0x003CC, // GREEK SMALL LETTER OMICRON WITH TONOS - "Oacute", 0x000D3, // LATIN CAPITAL LETTER O WITH ACUTE - "oacute", 0x000F3, // LATIN SMALL LETTER O WITH ACUTE - "oast", 0x0229B, // CIRCLED ASTERISK OPERATOR - "ocir", 0x0229A, // CIRCLED RING OPERATOR - "Ocirc", 0x000D4, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX - "ocirc", 0x000F4, // LATIN SMALL LETTER O WITH CIRCUMFLEX - "Ocy", 0x0041E, // CYRILLIC CAPITAL LETTER O - "ocy", 0x0043E, // CYRILLIC SMALL LETTER O - "odash", 0x0229D, // CIRCLED DASH - "Odblac", 0x00150, // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE - "odblac", 0x00151, // LATIN SMALL LETTER O WITH DOUBLE ACUTE - "odiv", 0x02A38, // CIRCLED DIVISION SIGN - "odot", 0x02299, // CIRCLED DOT OPERATOR - "odsold", 0x029BC, // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN - "OElig", 0x00152, // LATIN CAPITAL LIGATURE OE - "oelig", 0x00153, // LATIN SMALL LIGATURE OE - "ofcir", 0x029BF, // CIRCLED BULLET - "Ofr", 0x1D512, // MATHEMATICAL FRAKTUR CAPITAL O - "ofr", 0x1D52C, // MATHEMATICAL FRAKTUR SMALL O - "ogon", 0x002DB, // OGONEK - "Ogr", 0x0039F, // GREEK CAPITAL LETTER OMICRON - "ogr", 0x003BF, // GREEK SMALL LETTER OMICRON - "Ograve", 0x000D2, // LATIN CAPITAL LETTER O WITH GRAVE - "ograve", 0x000F2, // LATIN SMALL LETTER O WITH GRAVE - "ogt", 0x029C1, // CIRCLED GREATER-THAN - "OHacgr", 0x0038F, // GREEK CAPITAL LETTER OMEGA WITH TONOS - "ohacgr", 0x003CE, // GREEK SMALL LETTER OMEGA WITH TONOS - "ohbar", 0x029B5, // CIRCLE WITH HORIZONTAL BAR - "OHgr", 0x003A9, // GREEK CAPITAL LETTER OMEGA - "ohgr", 0x003C9, // GREEK SMALL LETTER OMEGA - "ohm", 0x003A9, // GREEK CAPITAL LETTER OMEGA - "oint", 0x0222E, // CONTOUR INTEGRAL - "olarr", 0x021BA, // ANTICLOCKWISE OPEN CIRCLE ARROW - "olcir", 0x029BE, // CIRCLED WHITE BULLET - "olcross", 0x029BB, // CIRCLE WITH SUPERIMPOSED X - "oline", 0x0203E, // OVERLINE - "olt", 0x029C0, // CIRCLED LESS-THAN - "Omacr", 0x0014C, // LATIN CAPITAL LETTER O WITH MACRON - "omacr", 0x0014D, // LATIN SMALL LETTER O WITH MACRON - "Omega", 0x003A9, // GREEK CAPITAL LETTER OMEGA - "omega", 0x003C9, // GREEK SMALL LETTER OMEGA - "Omicron", 0x0039F, // GREEK CAPITAL LETTER OMICRON - "omicron", 0x003BF, // GREEK SMALL LETTER OMICRON - "omid", 0x029B6, // CIRCLED VERTICAL BAR - "ominus", 0x02296, // CIRCLED MINUS - "Oopf", 0x1D546, // MATHEMATICAL DOUBLE-STRUCK CAPITAL O - "oopf", 0x1D560, // MATHEMATICAL DOUBLE-STRUCK SMALL O - "opar", 0x029B7, // CIRCLED PARALLEL - "OpenCurlyDoubleQuote", 0x0201C, // LEFT DOUBLE QUOTATION MARK - "OpenCurlyQuote", 0x02018, // LEFT SINGLE QUOTATION MARK - "operp", 0x029B9, // CIRCLED PERPENDICULAR - "oplus", 0x02295, // CIRCLED PLUS - "or", 0x02228, // LOGICAL OR - "Or", 0x02A54, // DOUBLE LOGICAL OR - "orarr", 0x021BB, // CLOCKWISE OPEN CIRCLE ARROW - "ord", 0x02A5D, // LOGICAL OR WITH HORIZONTAL DASH - "order", 0x02134, // SCRIPT SMALL O - "orderof", 0x02134, // SCRIPT SMALL O - "ordf", 0x000AA, // FEMININE ORDINAL INDICATOR - "ordm", 0x000BA, // MASCULINE ORDINAL INDICATOR - "origof", 0x022B6, // ORIGINAL OF - "oror", 0x02A56, // TWO INTERSECTING LOGICAL OR - "orslope", 0x02A57, // SLOPING LARGE OR - "orv", 0x02A5B, // LOGICAL OR WITH MIDDLE STEM - "oS", 0x024C8, // CIRCLED LATIN CAPITAL LETTER S - "oscr", 0x02134, // SCRIPT SMALL O - "Oscr", 0x1D4AA, // MATHEMATICAL SCRIPT CAPITAL O - "Oslash", 0x000D8, // LATIN CAPITAL LETTER O WITH STROKE - "oslash", 0x000F8, // LATIN SMALL LETTER O WITH STROKE - "osol", 0x02298, // CIRCLED DIVISION SLASH - "Otilde", 0x000D5, // LATIN CAPITAL LETTER O WITH TILDE - "otilde", 0x000F5, // LATIN SMALL LETTER O WITH TILDE - "otimes", 0x02297, // CIRCLED TIMES - "Otimes", 0x02A37, // MULTIPLICATION SIGN IN DOUBLE CIRCLE - "otimesas", 0x02A36, // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT - "Ouml", 0x000D6, // LATIN CAPITAL LETTER O WITH DIAERESIS - "ouml", 0x000F6, // LATIN SMALL LETTER O WITH DIAERESIS - "ovbar", 0x0233D, // APL FUNCTIONAL SYMBOL CIRCLE STILE - "OverBar", 0x0203E, // OVERLINE - "OverBrace", 0x023DE, // TOP CURLY BRACKET - "OverBracket", 0x023B4, // TOP SQUARE BRACKET - "OverParenthesis", 0x023DC, // TOP PARENTHESIS - NULL, 0 + {"Oacgr", 0x0038C}, // GREEK CAPITAL LETTER OMICRON WITH TONOS + {"oacgr", 0x003CC}, // GREEK SMALL LETTER OMICRON WITH TONOS + {"Oacute", 0x000D3}, // LATIN CAPITAL LETTER O WITH ACUTE + {"oacute", 0x000F3}, // LATIN SMALL LETTER O WITH ACUTE + {"oast", 0x0229B}, // CIRCLED ASTERISK OPERATOR + {"ocir", 0x0229A}, // CIRCLED RING OPERATOR + {"Ocirc", 0x000D4}, // LATIN CAPITAL LETTER O WITH CIRCUMFLEX + {"ocirc", 0x000F4}, // LATIN SMALL LETTER O WITH CIRCUMFLEX + {"Ocy", 0x0041E}, // CYRILLIC CAPITAL LETTER O + {"ocy", 0x0043E}, // CYRILLIC SMALL LETTER O + {"odash", 0x0229D}, // CIRCLED DASH + {"Odblac", 0x00150}, // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + {"odblac", 0x00151}, // LATIN SMALL LETTER O WITH DOUBLE ACUTE + {"odiv", 0x02A38}, // CIRCLED DIVISION SIGN + {"odot", 0x02299}, // CIRCLED DOT OPERATOR + {"odsold", 0x029BC}, // CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN + {"OElig", 0x00152}, // LATIN CAPITAL LIGATURE OE + {"oelig", 0x00153}, // LATIN SMALL LIGATURE OE + {"ofcir", 0x029BF}, // CIRCLED BULLET + {"Ofr", 0x1D512}, // MATHEMATICAL FRAKTUR CAPITAL O + {"ofr", 0x1D52C}, // MATHEMATICAL FRAKTUR SMALL O + {"ogon", 0x002DB}, // OGONEK + {"Ogr", 0x0039F}, // GREEK CAPITAL LETTER OMICRON + {"ogr", 0x003BF}, // GREEK SMALL LETTER OMICRON + {"Ograve", 0x000D2}, // LATIN CAPITAL LETTER O WITH GRAVE + {"ograve", 0x000F2}, // LATIN SMALL LETTER O WITH GRAVE + {"ogt", 0x029C1}, // CIRCLED GREATER-THAN + {"OHacgr", 0x0038F}, // GREEK CAPITAL LETTER OMEGA WITH TONOS + {"ohacgr", 0x003CE}, // GREEK SMALL LETTER OMEGA WITH TONOS + {"ohbar", 0x029B5}, // CIRCLE WITH HORIZONTAL BAR + {"OHgr", 0x003A9}, // GREEK CAPITAL LETTER OMEGA + {"ohgr", 0x003C9}, // GREEK SMALL LETTER OMEGA + {"ohm", 0x003A9}, // GREEK CAPITAL LETTER OMEGA + {"oint", 0x0222E}, // CONTOUR INTEGRAL + {"olarr", 0x021BA}, // ANTICLOCKWISE OPEN CIRCLE ARROW + {"olcir", 0x029BE}, // CIRCLED WHITE BULLET + {"olcross", 0x029BB}, // CIRCLE WITH SUPERIMPOSED X + {"oline", 0x0203E}, // OVERLINE + {"olt", 0x029C0}, // CIRCLED LESS-THAN + {"Omacr", 0x0014C}, // LATIN CAPITAL LETTER O WITH MACRON + {"omacr", 0x0014D}, // LATIN SMALL LETTER O WITH MACRON + {"Omega", 0x003A9}, // GREEK CAPITAL LETTER OMEGA + {"omega", 0x003C9}, // GREEK SMALL LETTER OMEGA + {"Omicron", 0x0039F}, // GREEK CAPITAL LETTER OMICRON + {"omicron", 0x003BF}, // GREEK SMALL LETTER OMICRON + {"omid", 0x029B6}, // CIRCLED VERTICAL BAR + {"ominus", 0x02296}, // CIRCLED MINUS + {"Oopf", 0x1D546}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL O + {"oopf", 0x1D560}, // MATHEMATICAL DOUBLE-STRUCK SMALL O + {"opar", 0x029B7}, // CIRCLED PARALLEL + {"OpenCurlyDoubleQuote", 0x0201C}, // LEFT DOUBLE QUOTATION MARK + {"OpenCurlyQuote", 0x02018}, // LEFT SINGLE QUOTATION MARK + {"operp", 0x029B9}, // CIRCLED PERPENDICULAR + {"oplus", 0x02295}, // CIRCLED PLUS + {"or", 0x02228}, // LOGICAL OR + {"Or", 0x02A54}, // DOUBLE LOGICAL OR + {"orarr", 0x021BB}, // CLOCKWISE OPEN CIRCLE ARROW + {"ord", 0x02A5D}, // LOGICAL OR WITH HORIZONTAL DASH + {"order", 0x02134}, // SCRIPT SMALL O + {"orderof", 0x02134}, // SCRIPT SMALL O + {"ordf", 0x000AA}, // FEMININE ORDINAL INDICATOR + {"ordm", 0x000BA}, // MASCULINE ORDINAL INDICATOR + {"origof", 0x022B6}, // ORIGINAL OF + {"oror", 0x02A56}, // TWO INTERSECTING LOGICAL OR + {"orslope", 0x02A57}, // SLOPING LARGE OR + {"orv", 0x02A5B}, // LOGICAL OR WITH MIDDLE STEM + {"oS", 0x024C8}, // CIRCLED LATIN CAPITAL LETTER S + {"oscr", 0x02134}, // SCRIPT SMALL O + {"Oscr", 0x1D4AA}, // MATHEMATICAL SCRIPT CAPITAL O + {"Oslash", 0x000D8}, // LATIN CAPITAL LETTER O WITH STROKE + {"oslash", 0x000F8}, // LATIN SMALL LETTER O WITH STROKE + {"osol", 0x02298}, // CIRCLED DIVISION SLASH + {"Otilde", 0x000D5}, // LATIN CAPITAL LETTER O WITH TILDE + {"otilde", 0x000F5}, // LATIN SMALL LETTER O WITH TILDE + {"otimes", 0x02297}, // CIRCLED TIMES + {"Otimes", 0x02A37}, // MULTIPLICATION SIGN IN DOUBLE CIRCLE + {"otimesas", 0x02A36}, // CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT + {"Ouml", 0x000D6}, // LATIN CAPITAL LETTER O WITH DIAERESIS + {"ouml", 0x000F6}, // LATIN SMALL LETTER O WITH DIAERESIS + {"ovbar", 0x0233D}, // APL FUNCTIONAL SYMBOL CIRCLE STILE + {"OverBar", 0x0203E}, // OVERLINE + {"OverBrace", 0x023DE}, // TOP CURLY BRACKET + {"OverBracket", 0x023B4}, // TOP SQUARE BRACKET + {"OverParenthesis", 0x023DC}, // TOP PARENTHESIS + {NULL, 0} }; static NameId namesP[]={ - "par", 0x02225, // PARALLEL TO - "para", 0x000B6, // PILCROW SIGN - "parallel", 0x02225, // PARALLEL TO - "parsim", 0x02AF3, // PARALLEL WITH TILDE OPERATOR - "parsl", 0x02AFD, // DOUBLE SOLIDUS OPERATOR - "part", 0x02202, // PARTIAL DIFFERENTIAL - "PartialD", 0x02202, // PARTIAL DIFFERENTIAL - "Pcy", 0x0041F, // CYRILLIC CAPITAL LETTER PE - "pcy", 0x0043F, // CYRILLIC SMALL LETTER PE - "percnt", 0x00025, // PERCENT SIGN - "period", 0x0002E, // FULL STOP - "permil", 0x02030, // PER MILLE SIGN - "perp", 0x022A5, // UP TACK - "pertenk", 0x02031, // PER TEN THOUSAND SIGN - "Pfr", 0x1D513, // MATHEMATICAL FRAKTUR CAPITAL P - "pfr", 0x1D52D, // MATHEMATICAL FRAKTUR SMALL P - "Pgr", 0x003A0, // GREEK CAPITAL LETTER PI - "pgr", 0x003C0, // GREEK SMALL LETTER PI - "PHgr", 0x003A6, // GREEK CAPITAL LETTER PHI - "phgr", 0x003C6, // GREEK SMALL LETTER PHI - "Phi", 0x003A6, // GREEK CAPITAL LETTER PHI - "phi", 0x003C6, // GREEK SMALL LETTER PHI - "phiv", 0x003D5, // GREEK PHI SYMBOL - "phmmat", 0x02133, // SCRIPT CAPITAL M - "phone", 0x0260E, // BLACK TELEPHONE - "Pi", 0x003A0, // GREEK CAPITAL LETTER PI - "pi", 0x003C0, // GREEK SMALL LETTER PI - "pitchfork", 0x022D4, // PITCHFORK - "piv", 0x003D6, // GREEK PI SYMBOL - "planck", 0x0210F, // PLANCK CONSTANT OVER TWO PI - "planckh", 0x0210E, // PLANCK CONSTANT - "plankv", 0x0210F, // PLANCK CONSTANT OVER TWO PI - "plus", 0x0002B, // PLUS SIGN - "plusacir", 0x02A23, // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE - "plusb", 0x0229E, // SQUARED PLUS - "pluscir", 0x02A22, // PLUS SIGN WITH SMALL CIRCLE ABOVE - "plusdo", 0x02214, // DOT PLUS - "plusdu", 0x02A25, // PLUS SIGN WITH DOT BELOW - "pluse", 0x02A72, // PLUS SIGN ABOVE EQUALS SIGN - "PlusMinus", 0x000B1, // PLUS-MINUS SIGN - "plusmn", 0x000B1, // PLUS-MINUS SIGN - "plussim", 0x02A26, // PLUS SIGN WITH TILDE BELOW - "plustwo", 0x02A27, // PLUS SIGN WITH SUBSCRIPT TWO - "pm", 0x000B1, // PLUS-MINUS SIGN - "Poincareplane", 0x0210C, // BLACK-LETTER CAPITAL H - "pointint", 0x02A15, // INTEGRAL AROUND A POINT OPERATOR - "Popf", 0x02119, // DOUBLE-STRUCK CAPITAL P - "popf", 0x1D561, // MATHEMATICAL DOUBLE-STRUCK SMALL P - "pound", 0x000A3, // POUND SIGN - "pr", 0x0227A, // PRECEDES - "Pr", 0x02ABB, // DOUBLE PRECEDES - "prap", 0x02AB7, // PRECEDES ABOVE ALMOST EQUAL TO - "prcue", 0x0227C, // PRECEDES OR EQUAL TO - "pre", 0x02AAF, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - "prE", 0x02AB3, // PRECEDES ABOVE EQUALS SIGN - "prec", 0x0227A, // PRECEDES - "precapprox", 0x02AB7, // PRECEDES ABOVE ALMOST EQUAL TO - "preccurlyeq", 0x0227C, // PRECEDES OR EQUAL TO - "Precedes", 0x0227A, // PRECEDES - "PrecedesEqual", 0x02AAF, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - "PrecedesSlantEqual", 0x0227C, // PRECEDES OR EQUAL TO - "PrecedesTilde", 0x0227E, // PRECEDES OR EQUIVALENT TO - "preceq", 0x02AAF, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN - "precnapprox", 0x02AB9, // PRECEDES ABOVE NOT ALMOST EQUAL TO - "precneqq", 0x02AB5, // PRECEDES ABOVE NOT EQUAL TO - "precnsim", 0x022E8, // PRECEDES BUT NOT EQUIVALENT TO - "precsim", 0x0227E, // PRECEDES OR EQUIVALENT TO - "prime", 0x02032, // PRIME - "Prime", 0x02033, // DOUBLE PRIME - "primes", 0x02119, // DOUBLE-STRUCK CAPITAL P - "prnap", 0x02AB9, // PRECEDES ABOVE NOT ALMOST EQUAL TO - "prnE", 0x02AB5, // PRECEDES ABOVE NOT EQUAL TO - "prnsim", 0x022E8, // PRECEDES BUT NOT EQUIVALENT TO - "prod", 0x0220F, // N-ARY PRODUCT - "Product", 0x0220F, // N-ARY PRODUCT - "profalar", 0x0232E, // ALL AROUND-PROFILE - "profline", 0x02312, // ARC - "profsurf", 0x02313, // SEGMENT - "prop", 0x0221D, // PROPORTIONAL TO - "Proportion", 0x02237, // PROPORTION - "Proportional", 0x0221D, // PROPORTIONAL TO - "propto", 0x0221D, // PROPORTIONAL TO - "prsim", 0x0227E, // PRECEDES OR EQUIVALENT TO - "prurel", 0x022B0, // PRECEDES UNDER RELATION - "Pscr", 0x1D4AB, // MATHEMATICAL SCRIPT CAPITAL P - "pscr", 0x1D4C5, // MATHEMATICAL SCRIPT SMALL P - "PSgr", 0x003A8, // GREEK CAPITAL LETTER PSI - "psgr", 0x003C8, // GREEK SMALL LETTER PSI - "Psi", 0x003A8, // GREEK CAPITAL LETTER PSI - "psi", 0x003C8, // GREEK SMALL LETTER PSI - "puncsp", 0x02008, // PUNCTUATION SPACE - NULL, 0 + {"par", 0x02225}, // PARALLEL TO + {"para", 0x000B6}, // PILCROW SIGN + {"parallel", 0x02225}, // PARALLEL TO + {"parsim", 0x02AF3}, // PARALLEL WITH TILDE OPERATOR + {"parsl", 0x02AFD}, // DOUBLE SOLIDUS OPERATOR + {"part", 0x02202}, // PARTIAL DIFFERENTIAL + {"PartialD", 0x02202}, // PARTIAL DIFFERENTIAL + {"Pcy", 0x0041F}, // CYRILLIC CAPITAL LETTER PE + {"pcy", 0x0043F}, // CYRILLIC SMALL LETTER PE + {"percnt", 0x00025}, // PERCENT SIGN + {"period", 0x0002E}, // FULL STOP + {"permil", 0x02030}, // PER MILLE SIGN + {"perp", 0x022A5}, // UP TACK + {"pertenk", 0x02031}, // PER TEN THOUSAND SIGN + {"Pfr", 0x1D513}, // MATHEMATICAL FRAKTUR CAPITAL P + {"pfr", 0x1D52D}, // MATHEMATICAL FRAKTUR SMALL P + {"Pgr", 0x003A0}, // GREEK CAPITAL LETTER PI + {"pgr", 0x003C0}, // GREEK SMALL LETTER PI + {"PHgr", 0x003A6}, // GREEK CAPITAL LETTER PHI + {"phgr", 0x003C6}, // GREEK SMALL LETTER PHI + {"Phi", 0x003A6}, // GREEK CAPITAL LETTER PHI + {"phi", 0x003C6}, // GREEK SMALL LETTER PHI + {"phiv", 0x003D5}, // GREEK PHI SYMBOL + {"phmmat", 0x02133}, // SCRIPT CAPITAL M + {"phone", 0x0260E}, // BLACK TELEPHONE + {"Pi", 0x003A0}, // GREEK CAPITAL LETTER PI + {"pi", 0x003C0}, // GREEK SMALL LETTER PI + {"pitchfork", 0x022D4}, // PITCHFORK + {"piv", 0x003D6}, // GREEK PI SYMBOL + {"planck", 0x0210F}, // PLANCK CONSTANT OVER TWO PI + {"planckh", 0x0210E}, // PLANCK CONSTANT + {"plankv", 0x0210F}, // PLANCK CONSTANT OVER TWO PI + {"plus", 0x0002B}, // PLUS SIGN + {"plusacir", 0x02A23}, // PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE + {"plusb", 0x0229E}, // SQUARED PLUS + {"pluscir", 0x02A22}, // PLUS SIGN WITH SMALL CIRCLE ABOVE + {"plusdo", 0x02214}, // DOT PLUS + {"plusdu", 0x02A25}, // PLUS SIGN WITH DOT BELOW + {"pluse", 0x02A72}, // PLUS SIGN ABOVE EQUALS SIGN + {"PlusMinus", 0x000B1}, // PLUS-MINUS SIGN + {"plusmn", 0x000B1}, // PLUS-MINUS SIGN + {"plussim", 0x02A26}, // PLUS SIGN WITH TILDE BELOW + {"plustwo", 0x02A27}, // PLUS SIGN WITH SUBSCRIPT TWO + {"pm", 0x000B1}, // PLUS-MINUS SIGN + {"Poincareplane", 0x0210C}, // BLACK-LETTER CAPITAL H + {"pointint", 0x02A15}, // INTEGRAL AROUND A POINT OPERATOR + {"Popf", 0x02119}, // DOUBLE-STRUCK CAPITAL P + {"popf", 0x1D561}, // MATHEMATICAL DOUBLE-STRUCK SMALL P + {"pound", 0x000A3}, // POUND SIGN + {"pr", 0x0227A}, // PRECEDES + {"Pr", 0x02ABB}, // DOUBLE PRECEDES + {"prap", 0x02AB7}, // PRECEDES ABOVE ALMOST EQUAL TO + {"prcue", 0x0227C}, // PRECEDES OR EQUAL TO + {"pre", 0x02AAF}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + {"prE", 0x02AB3}, // PRECEDES ABOVE EQUALS SIGN + {"prec", 0x0227A}, // PRECEDES + {"precapprox", 0x02AB7}, // PRECEDES ABOVE ALMOST EQUAL TO + {"preccurlyeq", 0x0227C}, // PRECEDES OR EQUAL TO + {"Precedes", 0x0227A}, // PRECEDES + {"PrecedesEqual", 0x02AAF}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + {"PrecedesSlantEqual", 0x0227C}, // PRECEDES OR EQUAL TO + {"PrecedesTilde", 0x0227E}, // PRECEDES OR EQUIVALENT TO + {"preceq", 0x02AAF}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN + {"precnapprox", 0x02AB9}, // PRECEDES ABOVE NOT ALMOST EQUAL TO + {"precneqq", 0x02AB5}, // PRECEDES ABOVE NOT EQUAL TO + {"precnsim", 0x022E8}, // PRECEDES BUT NOT EQUIVALENT TO + {"precsim", 0x0227E}, // PRECEDES OR EQUIVALENT TO + {"prime", 0x02032}, // PRIME + {"Prime", 0x02033}, // DOUBLE PRIME + {"primes", 0x02119}, // DOUBLE-STRUCK CAPITAL P + {"prnap", 0x02AB9}, // PRECEDES ABOVE NOT ALMOST EQUAL TO + {"prnE", 0x02AB5}, // PRECEDES ABOVE NOT EQUAL TO + {"prnsim", 0x022E8}, // PRECEDES BUT NOT EQUIVALENT TO + {"prod", 0x0220F}, // N-ARY PRODUCT + {"Product", 0x0220F}, // N-ARY PRODUCT + {"profalar", 0x0232E}, // ALL AROUND-PROFILE + {"profline", 0x02312}, // ARC + {"profsurf", 0x02313}, // SEGMENT + {"prop", 0x0221D}, // PROPORTIONAL TO + {"Proportion", 0x02237}, // PROPORTION + {"Proportional", 0x0221D}, // PROPORTIONAL TO + {"propto", 0x0221D}, // PROPORTIONAL TO + {"prsim", 0x0227E}, // PRECEDES OR EQUIVALENT TO + {"prurel", 0x022B0}, // PRECEDES UNDER RELATION + {"Pscr", 0x1D4AB}, // MATHEMATICAL SCRIPT CAPITAL P + {"pscr", 0x1D4C5}, // MATHEMATICAL SCRIPT SMALL P + {"PSgr", 0x003A8}, // GREEK CAPITAL LETTER PSI + {"psgr", 0x003C8}, // GREEK SMALL LETTER PSI + {"Psi", 0x003A8}, // GREEK CAPITAL LETTER PSI + {"psi", 0x003C8}, // GREEK SMALL LETTER PSI + {"puncsp", 0x02008}, // PUNCTUATION SPACE + {NULL, 0} }; static NameId namesQ[]={ - "Qfr", 0x1D514, // MATHEMATICAL FRAKTUR CAPITAL Q - "qfr", 0x1D52E, // MATHEMATICAL FRAKTUR SMALL Q - "qint", 0x02A0C, // QUADRUPLE INTEGRAL OPERATOR - "Qopf", 0x0211A, // DOUBLE-STRUCK CAPITAL Q - "qopf", 0x1D562, // MATHEMATICAL DOUBLE-STRUCK SMALL Q - "qprime", 0x02057, // QUADRUPLE PRIME - "Qscr", 0x1D4AC, // MATHEMATICAL SCRIPT CAPITAL Q - "qscr", 0x1D4C6, // MATHEMATICAL SCRIPT SMALL Q - "quaternions", 0x0210D, // DOUBLE-STRUCK CAPITAL H - "quatint", 0x02A16, // QUATERNION INTEGRAL OPERATOR - "quest", 0x0003F, // QUESTION MARK - "questeq", 0x0225F, // QUESTIONED EQUAL TO - "quot", 0x00022, // QUOTATION MARK - "QUOT", 0x00022, // QUOTATION MARK - NULL, 0 + {"Qfr", 0x1D514}, // MATHEMATICAL FRAKTUR CAPITAL Q + {"qfr", 0x1D52E}, // MATHEMATICAL FRAKTUR SMALL Q + {"qint", 0x02A0C}, // QUADRUPLE INTEGRAL OPERATOR + {"Qopf", 0x0211A}, // DOUBLE-STRUCK CAPITAL Q + {"qopf", 0x1D562}, // MATHEMATICAL DOUBLE-STRUCK SMALL Q + {"qprime", 0x02057}, // QUADRUPLE PRIME + {"Qscr", 0x1D4AC}, // MATHEMATICAL SCRIPT CAPITAL Q + {"qscr", 0x1D4C6}, // MATHEMATICAL SCRIPT SMALL Q + {"quaternions", 0x0210D}, // DOUBLE-STRUCK CAPITAL H + {"quatint", 0x02A16}, // QUATERNION INTEGRAL OPERATOR + {"quest", 0x0003F}, // QUESTION MARK + {"questeq", 0x0225F}, // QUESTIONED EQUAL TO + {"quot", 0x00022}, // QUOTATION MARK + {"QUOT", 0x00022}, // QUOTATION MARK + {NULL, 0} }; static NameId namesR[]={ - "rAarr", 0x021DB, // RIGHTWARDS TRIPLE ARROW -// "race", 0x0223D;0x00331, // REVERSED TILDE with underline - "Racute", 0x00154, // LATIN CAPITAL LETTER R WITH ACUTE - "racute", 0x00155, // LATIN SMALL LETTER R WITH ACUTE - "radic", 0x0221A, // SQUARE ROOT - "raemptyv", 0x029B3, // EMPTY SET WITH RIGHT ARROW ABOVE - "rang", 0x027E9, // MATHEMATICAL RIGHT ANGLE BRACKET - "Rang", 0x027EB, // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET - "rangd", 0x02992, // RIGHT ANGLE BRACKET WITH DOT - "range", 0x029A5, // REVERSED ANGLE WITH UNDERBAR - "rangle", 0x027E9, // MATHEMATICAL RIGHT ANGLE BRACKET - "raquo", 0x000BB, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK - "rarr", 0x02192, // RIGHTWARDS ARROW - "Rarr", 0x021A0, // RIGHTWARDS TWO HEADED ARROW - "rArr", 0x021D2, // RIGHTWARDS DOUBLE ARROW - "rarrap", 0x02975, // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO - "rarrb", 0x021E5, // RIGHTWARDS ARROW TO BAR - "rarrbfs", 0x02920, // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND - "rarrc", 0x02933, // WAVE ARROW POINTING DIRECTLY RIGHT - "rarrfs", 0x0291E, // RIGHTWARDS ARROW TO BLACK DIAMOND - "rarrhk", 0x021AA, // RIGHTWARDS ARROW WITH HOOK - "rarrlp", 0x021AC, // RIGHTWARDS ARROW WITH LOOP - "rarrpl", 0x02945, // RIGHTWARDS ARROW WITH PLUS BELOW - "rarrsim", 0x02974, // RIGHTWARDS ARROW ABOVE TILDE OPERATOR - "rarrtl", 0x021A3, // RIGHTWARDS ARROW WITH TAIL - "Rarrtl", 0x02916, // RIGHTWARDS TWO-HEADED ARROW WITH TAIL - "rarrw", 0x0219D, // RIGHTWARDS WAVE ARROW - "ratail", 0x0291A, // RIGHTWARDS ARROW-TAIL - "rAtail", 0x0291C, // RIGHTWARDS DOUBLE ARROW-TAIL - "ratio", 0x02236, // RATIO - "rationals", 0x0211A, // DOUBLE-STRUCK CAPITAL Q - "rbarr", 0x0290D, // RIGHTWARDS DOUBLE DASH ARROW - "rBarr", 0x0290F, // RIGHTWARDS TRIPLE DASH ARROW - "RBarr", 0x02910, // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW - "rbbrk", 0x02773, // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT - "rbrace", 0x0007D, // RIGHT CURLY BRACKET - "rbrack", 0x0005D, // RIGHT SQUARE BRACKET - "rbrke", 0x0298C, // RIGHT SQUARE BRACKET WITH UNDERBAR - "rbrksld", 0x0298E, // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER - "rbrkslu", 0x02990, // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER - "Rcaron", 0x00158, // LATIN CAPITAL LETTER R WITH CARON - "rcaron", 0x00159, // LATIN SMALL LETTER R WITH CARON - "Rcedil", 0x00156, // LATIN CAPITAL LETTER R WITH CEDILLA - "rcedil", 0x00157, // LATIN SMALL LETTER R WITH CEDILLA - "rceil", 0x02309, // RIGHT CEILING - "rcub", 0x0007D, // RIGHT CURLY BRACKET - "Rcy", 0x00420, // CYRILLIC CAPITAL LETTER ER - "rcy", 0x00440, // CYRILLIC SMALL LETTER ER - "rdca", 0x02937, // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS - "rdldhar", 0x02969, // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN - "rdquo", 0x0201D, // RIGHT DOUBLE QUOTATION MARK - "rdquor", 0x0201D, // RIGHT DOUBLE QUOTATION MARK - "rdsh", 0x021B3, // DOWNWARDS ARROW WITH TIP RIGHTWARDS - "Re", 0x0211C, // BLACK-LETTER CAPITAL R - "real", 0x0211C, // BLACK-LETTER CAPITAL R - "realine", 0x0211B, // SCRIPT CAPITAL R - "realpart", 0x0211C, // BLACK-LETTER CAPITAL R - "reals", 0x0211D, // DOUBLE-STRUCK CAPITAL R - "rect", 0x025AD, // WHITE RECTANGLE - "reg", 0x000AE, // REGISTERED SIGN - "REG", 0x000AE, // REGISTERED SIGN - "ReverseElement", 0x0220B, // CONTAINS AS MEMBER - "ReverseEquilibrium", 0x021CB, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON - "ReverseUpEquilibrium", 0x0296F, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - "rfisht", 0x0297D, // RIGHT FISH TAIL - "rfloor", 0x0230B, // RIGHT FLOOR - "Rfr", 0x0211C, // BLACK-LETTER CAPITAL R - "rfr", 0x1D52F, // MATHEMATICAL FRAKTUR SMALL R - "Rgr", 0x003A1, // GREEK CAPITAL LETTER RHO - "rgr", 0x003C1, // GREEK SMALL LETTER RHO - "rHar", 0x02964, // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN - "rhard", 0x021C1, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - "rharu", 0x021C0, // RIGHTWARDS HARPOON WITH BARB UPWARDS - "rharul", 0x0296C, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH - "Rho", 0x003A1, // GREEK CAPITAL LETTER RHO - "rho", 0x003C1, // GREEK SMALL LETTER RHO - "rhov", 0x003F1, // GREEK RHO SYMBOL - "RightAngleBracket", 0x027E9, // MATHEMATICAL RIGHT ANGLE BRACKET - "rightarrow", 0x02192, // RIGHTWARDS ARROW - "RightArrow", 0x02192, // RIGHTWARDS ARROW - "Rightarrow", 0x021D2, // RIGHTWARDS DOUBLE ARROW - "RightArrowBar", 0x021E5, // RIGHTWARDS ARROW TO BAR - "RightArrowLeftArrow", 0x021C4, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - "rightarrowtail", 0x021A3, // RIGHTWARDS ARROW WITH TAIL - "RightCeiling", 0x02309, // RIGHT CEILING - "RightDoubleBracket", 0x027E7, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET - "RightDownTeeVector", 0x0295D, // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR - "RightDownVector", 0x021C2, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS - "RightDownVectorBar", 0x02955, // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR - "RightFloor", 0x0230B, // RIGHT FLOOR - "rightharpoondown", 0x021C1, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS - "rightharpoonup", 0x021C0, // RIGHTWARDS HARPOON WITH BARB UPWARDS - "rightleftarrows", 0x021C4, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - "rightleftharpoons", 0x021CC, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - "rightrightarrows", 0x021C9, // RIGHTWARDS PAIRED ARROWS - "rightsquigarrow", 0x0219D, // RIGHTWARDS WAVE ARROW - "RightTee", 0x022A2, // RIGHT TACK - "RightTeeArrow", 0x021A6, // RIGHTWARDS ARROW FROM BAR - "RightTeeVector", 0x0295B, // RIGHTWARDS HARPOON WITH BARB UP FROM BAR - "rightthreetimes", 0x022CC, // RIGHT SEMIDIRECT PRODUCT - "RightTriangle", 0x022B3, // CONTAINS AS NORMAL SUBGROUP - "RightTriangleBar", 0x029D0, // VERTICAL BAR BESIDE RIGHT TRIANGLE - "RightTriangleEqual", 0x022B5, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - "RightUpDownVector", 0x0294F, // UP BARB RIGHT DOWN BARB RIGHT HARPOON - "RightUpTeeVector", 0x0295C, // UPWARDS HARPOON WITH BARB RIGHT FROM BAR - "RightUpVector", 0x021BE, // UPWARDS HARPOON WITH BARB RIGHTWARDS - "RightUpVectorBar", 0x02954, // UPWARDS HARPOON WITH BARB RIGHT TO BAR - "RightVector", 0x021C0, // RIGHTWARDS HARPOON WITH BARB UPWARDS - "RightVectorBar", 0x02953, // RIGHTWARDS HARPOON WITH BARB UP TO BAR - "ring", 0x002DA, // RING ABOVE - "risingdotseq", 0x02253, // IMAGE OF OR APPROXIMATELY EQUAL TO - "rlarr", 0x021C4, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW - "rlhar", 0x021CC, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON - "rlm", 0x0200F, // RIGHT-TO-LEFT MARK - "rmoust", 0x023B1, // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - "rmoustache", 0x023B1, // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION - "rnmid", 0x02AEE, // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH - "roang", 0x027ED, // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET - "roarr", 0x021FE, // RIGHTWARDS OPEN-HEADED ARROW - "robrk", 0x027E7, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET - "ropar", 0x02986, // RIGHT WHITE PARENTHESIS - "Ropf", 0x0211D, // DOUBLE-STRUCK CAPITAL R - "ropf", 0x1D563, // MATHEMATICAL DOUBLE-STRUCK SMALL R - "roplus", 0x02A2E, // PLUS SIGN IN RIGHT HALF CIRCLE - "rotimes", 0x02A35, // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE - "RoundImplies", 0x02970, // RIGHT DOUBLE ARROW WITH ROUNDED HEAD - "rpar", 0x00029, // RIGHT PARENTHESIS - "rpargt", 0x02994, // RIGHT ARC GREATER-THAN BRACKET - "rppolint", 0x02A12, // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE - "rrarr", 0x021C9, // RIGHTWARDS PAIRED ARROWS - "Rrightarrow", 0x021DB, // RIGHTWARDS TRIPLE ARROW - "rsaquo", 0x0203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - "Rscr", 0x0211B, // SCRIPT CAPITAL R - "rscr", 0x1D4C7, // MATHEMATICAL SCRIPT SMALL R - "rsh", 0x021B1, // UPWARDS ARROW WITH TIP RIGHTWARDS - "Rsh", 0x021B1, // UPWARDS ARROW WITH TIP RIGHTWARDS - "rsqb", 0x0005D, // RIGHT SQUARE BRACKET - "rsquo", 0x02019, // RIGHT SINGLE QUOTATION MARK - "rsquor", 0x02019, // RIGHT SINGLE QUOTATION MARK - "rthree", 0x022CC, // RIGHT SEMIDIRECT PRODUCT - "rtimes", 0x022CA, // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT - "rtri", 0x025B9, // WHITE RIGHT-POINTING SMALL TRIANGLE - "rtrie", 0x022B5, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - "rtrif", 0x025B8, // BLACK RIGHT-POINTING SMALL TRIANGLE - "rtriltri", 0x029CE, // RIGHT TRIANGLE ABOVE LEFT TRIANGLE - "RuleDelayed", 0x029F4, // RULE-DELAYED - "ruluhar", 0x02968, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP - "rx", 0x0211E, // PRESCRIPTION TAKE - NULL, 0 + {"rAarr", 0x021DB}, // RIGHTWARDS TRIPLE ARROW +// "race", 0x0223D;0x00331}, // REVERSED TILDE with underline + {"Racute", 0x00154}, // LATIN CAPITAL LETTER R WITH ACUTE + {"racute", 0x00155}, // LATIN SMALL LETTER R WITH ACUTE + {"radic", 0x0221A}, // SQUARE ROOT + {"raemptyv", 0x029B3}, // EMPTY SET WITH RIGHT ARROW ABOVE + {"rang", 0x027E9}, // MATHEMATICAL RIGHT ANGLE BRACKET + {"Rang", 0x027EB}, // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET + {"rangd", 0x02992}, // RIGHT ANGLE BRACKET WITH DOT + {"range", 0x029A5}, // REVERSED ANGLE WITH UNDERBAR + {"rangle", 0x027E9}, // MATHEMATICAL RIGHT ANGLE BRACKET + {"raquo", 0x000BB}, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + {"rarr", 0x02192}, // RIGHTWARDS ARROW + {"Rarr", 0x021A0}, // RIGHTWARDS TWO HEADED ARROW + {"rArr", 0x021D2}, // RIGHTWARDS DOUBLE ARROW + {"rarrap", 0x02975}, // RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO + {"rarrb", 0x021E5}, // RIGHTWARDS ARROW TO BAR + {"rarrbfs", 0x02920}, // RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND + {"rarrc", 0x02933}, // WAVE ARROW POINTING DIRECTLY RIGHT + {"rarrfs", 0x0291E}, // RIGHTWARDS ARROW TO BLACK DIAMOND + {"rarrhk", 0x021AA}, // RIGHTWARDS ARROW WITH HOOK + {"rarrlp", 0x021AC}, // RIGHTWARDS ARROW WITH LOOP + {"rarrpl", 0x02945}, // RIGHTWARDS ARROW WITH PLUS BELOW + {"rarrsim", 0x02974}, // RIGHTWARDS ARROW ABOVE TILDE OPERATOR + {"rarrtl", 0x021A3}, // RIGHTWARDS ARROW WITH TAIL + {"Rarrtl", 0x02916}, // RIGHTWARDS TWO-HEADED ARROW WITH TAIL + {"rarrw", 0x0219D}, // RIGHTWARDS WAVE ARROW + {"ratail", 0x0291A}, // RIGHTWARDS ARROW-TAIL + {"rAtail", 0x0291C}, // RIGHTWARDS DOUBLE ARROW-TAIL + {"ratio", 0x02236}, // RATIO + {"rationals", 0x0211A}, // DOUBLE-STRUCK CAPITAL Q + {"rbarr", 0x0290D}, // RIGHTWARDS DOUBLE DASH ARROW + {"rBarr", 0x0290F}, // RIGHTWARDS TRIPLE DASH ARROW + {"RBarr", 0x02910}, // RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW + {"rbbrk", 0x02773}, // LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT + {"rbrace", 0x0007D}, // RIGHT CURLY BRACKET + {"rbrack", 0x0005D}, // RIGHT SQUARE BRACKET + {"rbrke", 0x0298C}, // RIGHT SQUARE BRACKET WITH UNDERBAR + {"rbrksld", 0x0298E}, // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER + {"rbrkslu", 0x02990}, // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER + {"Rcaron", 0x00158}, // LATIN CAPITAL LETTER R WITH CARON + {"rcaron", 0x00159}, // LATIN SMALL LETTER R WITH CARON + {"Rcedil", 0x00156}, // LATIN CAPITAL LETTER R WITH CEDILLA + {"rcedil", 0x00157}, // LATIN SMALL LETTER R WITH CEDILLA + {"rceil", 0x02309}, // RIGHT CEILING + {"rcub", 0x0007D}, // RIGHT CURLY BRACKET + {"Rcy", 0x00420}, // CYRILLIC CAPITAL LETTER ER + {"rcy", 0x00440}, // CYRILLIC SMALL LETTER ER + {"rdca", 0x02937}, // ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS + {"rdldhar", 0x02969}, // RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN + {"rdquo", 0x0201D}, // RIGHT DOUBLE QUOTATION MARK + {"rdquor", 0x0201D}, // RIGHT DOUBLE QUOTATION MARK + {"rdsh", 0x021B3}, // DOWNWARDS ARROW WITH TIP RIGHTWARDS + {"Re", 0x0211C}, // BLACK-LETTER CAPITAL R + {"real", 0x0211C}, // BLACK-LETTER CAPITAL R + {"realine", 0x0211B}, // SCRIPT CAPITAL R + {"realpart", 0x0211C}, // BLACK-LETTER CAPITAL R + {"reals", 0x0211D}, // DOUBLE-STRUCK CAPITAL R + {"rect", 0x025AD}, // WHITE RECTANGLE + {"reg", 0x000AE}, // REGISTERED SIGN + {"REG", 0x000AE}, // REGISTERED SIGN + {"ReverseElement", 0x0220B}, // CONTAINS AS MEMBER + {"ReverseEquilibrium", 0x021CB}, // LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON + {"ReverseUpEquilibrium", 0x0296F}, // DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + {"rfisht", 0x0297D}, // RIGHT FISH TAIL + {"rfloor", 0x0230B}, // RIGHT FLOOR + {"Rfr", 0x0211C}, // BLACK-LETTER CAPITAL R + {"rfr", 0x1D52F}, // MATHEMATICAL FRAKTUR SMALL R + {"Rgr", 0x003A1}, // GREEK CAPITAL LETTER RHO + {"rgr", 0x003C1}, // GREEK SMALL LETTER RHO + {"rHar", 0x02964}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN + {"rhard", 0x021C1}, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + {"rharu", 0x021C0}, // RIGHTWARDS HARPOON WITH BARB UPWARDS + {"rharul", 0x0296C}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH + {"Rho", 0x003A1}, // GREEK CAPITAL LETTER RHO + {"rho", 0x003C1}, // GREEK SMALL LETTER RHO + {"rhov", 0x003F1}, // GREEK RHO SYMBOL + {"RightAngleBracket", 0x027E9}, // MATHEMATICAL RIGHT ANGLE BRACKET + {"rightarrow", 0x02192}, // RIGHTWARDS ARROW + {"RightArrow", 0x02192}, // RIGHTWARDS ARROW + {"Rightarrow", 0x021D2}, // RIGHTWARDS DOUBLE ARROW + {"RightArrowBar", 0x021E5}, // RIGHTWARDS ARROW TO BAR + {"RightArrowLeftArrow", 0x021C4}, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + {"rightarrowtail", 0x021A3}, // RIGHTWARDS ARROW WITH TAIL + {"RightCeiling", 0x02309}, // RIGHT CEILING + {"RightDoubleBracket", 0x027E7}, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET + {"RightDownTeeVector", 0x0295D}, // DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR + {"RightDownVector", 0x021C2}, // DOWNWARDS HARPOON WITH BARB RIGHTWARDS + {"RightDownVectorBar", 0x02955}, // DOWNWARDS HARPOON WITH BARB RIGHT TO BAR + {"RightFloor", 0x0230B}, // RIGHT FLOOR + {"rightharpoondown", 0x021C1}, // RIGHTWARDS HARPOON WITH BARB DOWNWARDS + {"rightharpoonup", 0x021C0}, // RIGHTWARDS HARPOON WITH BARB UPWARDS + {"rightleftarrows", 0x021C4}, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + {"rightleftharpoons", 0x021CC}, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + {"rightrightarrows", 0x021C9}, // RIGHTWARDS PAIRED ARROWS + {"rightsquigarrow", 0x0219D}, // RIGHTWARDS WAVE ARROW + {"RightTee", 0x022A2}, // RIGHT TACK + {"RightTeeArrow", 0x021A6}, // RIGHTWARDS ARROW FROM BAR + {"RightTeeVector", 0x0295B}, // RIGHTWARDS HARPOON WITH BARB UP FROM BAR + {"rightthreetimes", 0x022CC}, // RIGHT SEMIDIRECT PRODUCT + {"RightTriangle", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP + {"RightTriangleBar", 0x029D0}, // VERTICAL BAR BESIDE RIGHT TRIANGLE + {"RightTriangleEqual", 0x022B5}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + {"RightUpDownVector", 0x0294F}, // UP BARB RIGHT DOWN BARB RIGHT HARPOON + {"RightUpTeeVector", 0x0295C}, // UPWARDS HARPOON WITH BARB RIGHT FROM BAR + {"RightUpVector", 0x021BE}, // UPWARDS HARPOON WITH BARB RIGHTWARDS + {"RightUpVectorBar", 0x02954}, // UPWARDS HARPOON WITH BARB RIGHT TO BAR + {"RightVector", 0x021C0}, // RIGHTWARDS HARPOON WITH BARB UPWARDS + {"RightVectorBar", 0x02953}, // RIGHTWARDS HARPOON WITH BARB UP TO BAR + {"ring", 0x002DA}, // RING ABOVE + {"risingdotseq", 0x02253}, // IMAGE OF OR APPROXIMATELY EQUAL TO + {"rlarr", 0x021C4}, // RIGHTWARDS ARROW OVER LEFTWARDS ARROW + {"rlhar", 0x021CC}, // RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON + {"rlm", 0x0200F}, // RIGHT-TO-LEFT MARK + {"rmoust", 0x023B1}, // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION + {"rmoustache", 0x023B1}, // UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION + {"rnmid", 0x02AEE}, // DOES NOT DIVIDE WITH REVERSED NEGATION SLASH + {"roang", 0x027ED}, // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET + {"roarr", 0x021FE}, // RIGHTWARDS OPEN-HEADED ARROW + {"robrk", 0x027E7}, // MATHEMATICAL RIGHT WHITE SQUARE BRACKET + {"ropar", 0x02986}, // RIGHT WHITE PARENTHESIS + {"Ropf", 0x0211D}, // DOUBLE-STRUCK CAPITAL R + {"ropf", 0x1D563}, // MATHEMATICAL DOUBLE-STRUCK SMALL R + {"roplus", 0x02A2E}, // PLUS SIGN IN RIGHT HALF CIRCLE + {"rotimes", 0x02A35}, // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE + {"RoundImplies", 0x02970}, // RIGHT DOUBLE ARROW WITH ROUNDED HEAD + {"rpar", 0x00029}, // RIGHT PARENTHESIS + {"rpargt", 0x02994}, // RIGHT ARC GREATER-THAN BRACKET + {"rppolint", 0x02A12}, // LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE + {"rrarr", 0x021C9}, // RIGHTWARDS PAIRED ARROWS + {"Rrightarrow", 0x021DB}, // RIGHTWARDS TRIPLE ARROW + {"rsaquo", 0x0203A}, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + {"Rscr", 0x0211B}, // SCRIPT CAPITAL R + {"rscr", 0x1D4C7}, // MATHEMATICAL SCRIPT SMALL R + {"rsh", 0x021B1}, // UPWARDS ARROW WITH TIP RIGHTWARDS + {"Rsh", 0x021B1}, // UPWARDS ARROW WITH TIP RIGHTWARDS + {"rsqb", 0x0005D}, // RIGHT SQUARE BRACKET + {"rsquo", 0x02019}, // RIGHT SINGLE QUOTATION MARK + {"rsquor", 0x02019}, // RIGHT SINGLE QUOTATION MARK + {"rthree", 0x022CC}, // RIGHT SEMIDIRECT PRODUCT + {"rtimes", 0x022CA}, // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT + {"rtri", 0x025B9}, // WHITE RIGHT-POINTING SMALL TRIANGLE + {"rtrie", 0x022B5}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + {"rtrif", 0x025B8}, // BLACK RIGHT-POINTING SMALL TRIANGLE + {"rtriltri", 0x029CE}, // RIGHT TRIANGLE ABOVE LEFT TRIANGLE + {"RuleDelayed", 0x029F4}, // RULE-DELAYED + {"ruluhar", 0x02968}, // RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP + {"rx", 0x0211E}, // PRESCRIPTION TAKE + {NULL, 0} }; static NameId namesS[]={ - "Sacute", 0x0015A, // LATIN CAPITAL LETTER S WITH ACUTE - "sacute", 0x0015B, // LATIN SMALL LETTER S WITH ACUTE - "sbquo", 0x0201A, // SINGLE LOW-9 QUOTATION MARK - "sc", 0x0227B, // SUCCEEDS - "Sc", 0x02ABC, // DOUBLE SUCCEEDS - "scap", 0x02AB8, // SUCCEEDS ABOVE ALMOST EQUAL TO - "Scaron", 0x00160, // LATIN CAPITAL LETTER S WITH CARON - "scaron", 0x00161, // LATIN SMALL LETTER S WITH CARON - "sccue", 0x0227D, // SUCCEEDS OR EQUAL TO - "sce", 0x02AB0, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - "scE", 0x02AB4, // SUCCEEDS ABOVE EQUALS SIGN - "Scedil", 0x0015E, // LATIN CAPITAL LETTER S WITH CEDILLA - "scedil", 0x0015F, // LATIN SMALL LETTER S WITH CEDILLA - "Scirc", 0x0015C, // LATIN CAPITAL LETTER S WITH CIRCUMFLEX - "scirc", 0x0015D, // LATIN SMALL LETTER S WITH CIRCUMFLEX - "scnap", 0x02ABA, // SUCCEEDS ABOVE NOT ALMOST EQUAL TO - "scnE", 0x02AB6, // SUCCEEDS ABOVE NOT EQUAL TO - "scnsim", 0x022E9, // SUCCEEDS BUT NOT EQUIVALENT TO - "scpolint", 0x02A13, // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE - "scsim", 0x0227F, // SUCCEEDS OR EQUIVALENT TO - "Scy", 0x00421, // CYRILLIC CAPITAL LETTER ES - "scy", 0x00441, // CYRILLIC SMALL LETTER ES - "sdot", 0x022C5, // DOT OPERATOR - "sdotb", 0x022A1, // SQUARED DOT OPERATOR - "sdote", 0x02A66, // EQUALS SIGN WITH DOT BELOW - "searhk", 0x02925, // SOUTH EAST ARROW WITH HOOK - "searr", 0x02198, // SOUTH EAST ARROW - "seArr", 0x021D8, // SOUTH EAST DOUBLE ARROW - "searrow", 0x02198, // SOUTH EAST ARROW - "sect", 0x000A7, // SECTION SIGN - "semi", 0x0003B, // SEMICOLON - "seswar", 0x02929, // SOUTH EAST ARROW AND SOUTH WEST ARROW - "setminus", 0x02216, // SET MINUS - "setmn", 0x02216, // SET MINUS - "sext", 0x02736, // SIX POINTED BLACK STAR - "sfgr", 0x003C2, // GREEK SMALL LETTER FINAL SIGMA - "Sfr", 0x1D516, // MATHEMATICAL FRAKTUR CAPITAL S - "sfr", 0x1D530, // MATHEMATICAL FRAKTUR SMALL S - "sfrown", 0x02322, // FROWN - "Sgr", 0x003A3, // GREEK CAPITAL LETTER SIGMA - "sgr", 0x003C3, // GREEK SMALL LETTER SIGMA - "sharp", 0x0266F, // MUSIC SHARP SIGN - "SHCHcy", 0x00429, // CYRILLIC CAPITAL LETTER SHCHA - "shchcy", 0x00449, // CYRILLIC SMALL LETTER SHCHA - "SHcy", 0x00428, // CYRILLIC CAPITAL LETTER SHA - "shcy", 0x00448, // CYRILLIC SMALL LETTER SHA - "ShortDownArrow", 0x02193, // DOWNWARDS ARROW - "ShortLeftArrow", 0x02190, // LEFTWARDS ARROW - "shortmid", 0x02223, // DIVIDES - "shortparallel", 0x02225, // PARALLEL TO - "ShortRightArrow", 0x02192, // RIGHTWARDS ARROW - "ShortUpArrow", 0x02191, // UPWARDS ARROW - "shy", 0x000AD, // SOFT HYPHEN - "Sigma", 0x003A3, // GREEK CAPITAL LETTER SIGMA - "sigma", 0x003C3, // GREEK SMALL LETTER SIGMA - "sigmaf", 0x003C2, // GREEK SMALL LETTER FINAL SIGMA - "sigmav", 0x003C2, // GREEK SMALL LETTER FINAL SIGMA - "sim", 0x0223C, // TILDE OPERATOR - "simdot", 0x02A6A, // TILDE OPERATOR WITH DOT ABOVE - "sime", 0x02243, // ASYMPTOTICALLY EQUAL TO - "simeq", 0x02243, // ASYMPTOTICALLY EQUAL TO - "simg", 0x02A9E, // SIMILAR OR GREATER-THAN - "simgE", 0x02AA0, // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN - "siml", 0x02A9D, // SIMILAR OR LESS-THAN - "simlE", 0x02A9F, // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN - "simne", 0x02246, // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO - "simplus", 0x02A24, // PLUS SIGN WITH TILDE ABOVE - "simrarr", 0x02972, // TILDE OPERATOR ABOVE RIGHTWARDS ARROW - "slarr", 0x02190, // LEFTWARDS ARROW - "SmallCircle", 0x02218, // RING OPERATOR - "smallsetminus", 0x02216, // SET MINUS - "smashp", 0x02A33, // SMASH PRODUCT - "smeparsl", 0x029E4, // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE - "smid", 0x02223, // DIVIDES - "smile", 0x02323, // SMILE - "smt", 0x02AAA, // SMALLER THAN - "smte", 0x02AAC, // SMALLER THAN OR EQUAL TO -// "smtes", 0x02AAC;0x0FE00, // SMALLER THAN OR slanted EQUAL - "SOFTcy", 0x0042C, // CYRILLIC CAPITAL LETTER SOFT SIGN - "softcy", 0x0044C, // CYRILLIC SMALL LETTER SOFT SIGN - "sol", 0x0002F, // SOLIDUS - "solb", 0x029C4, // SQUARED RISING DIAGONAL SLASH - "solbar", 0x0233F, // APL FUNCTIONAL SYMBOL SLASH BAR - "Sopf", 0x1D54A, // MATHEMATICAL DOUBLE-STRUCK CAPITAL S - "sopf", 0x1D564, // MATHEMATICAL DOUBLE-STRUCK SMALL S - "spades", 0x02660, // BLACK SPADE SUIT - "spadesuit", 0x02660, // BLACK SPADE SUIT - "spar", 0x02225, // PARALLEL TO - "sqcap", 0x02293, // SQUARE CAP -// "sqcaps", 0x02293;0x0FE00, // SQUARE CAP with serifs - "sqcup", 0x02294, // SQUARE CUP -// "sqcups", 0x02294;0x0FE00, // SQUARE CUP with serifs - "Sqrt", 0x0221A, // SQUARE ROOT - "sqsub", 0x0228F, // SQUARE IMAGE OF - "sqsube", 0x02291, // SQUARE IMAGE OF OR EQUAL TO - "sqsubset", 0x0228F, // SQUARE IMAGE OF - "sqsubseteq", 0x02291, // SQUARE IMAGE OF OR EQUAL TO - "sqsup", 0x02290, // SQUARE ORIGINAL OF - "sqsupe", 0x02292, // SQUARE ORIGINAL OF OR EQUAL TO - "sqsupset", 0x02290, // SQUARE ORIGINAL OF - "sqsupseteq", 0x02292, // SQUARE ORIGINAL OF OR EQUAL TO - "squ", 0x025A1, // WHITE SQUARE - "square", 0x025A1, // WHITE SQUARE - "Square", 0x025A1, // WHITE SQUARE - "SquareIntersection", 0x02293, // SQUARE CAP - "SquareSubset", 0x0228F, // SQUARE IMAGE OF - "SquareSubsetEqual", 0x02291, // SQUARE IMAGE OF OR EQUAL TO - "SquareSuperset", 0x02290, // SQUARE ORIGINAL OF - "SquareSupersetEqual", 0x02292, // SQUARE ORIGINAL OF OR EQUAL TO - "SquareUnion", 0x02294, // SQUARE CUP - "squarf", 0x025AA, // BLACK SMALL SQUARE - "squf", 0x025AA, // BLACK SMALL SQUARE - "srarr", 0x02192, // RIGHTWARDS ARROW - "Sscr", 0x1D4AE, // MATHEMATICAL SCRIPT CAPITAL S - "sscr", 0x1D4C8, // MATHEMATICAL SCRIPT SMALL S - "ssetmn", 0x02216, // SET MINUS - "ssmile", 0x02323, // SMILE - "sstarf", 0x022C6, // STAR OPERATOR - "Star", 0x022C6, // STAR OPERATOR - "star", 0x02606, // WHITE STAR - "starf", 0x02605, // BLACK STAR - "straightepsilon", 0x003F5, // GREEK LUNATE EPSILON SYMBOL - "straightphi", 0x003D5, // GREEK PHI SYMBOL - "strns", 0x000AF, // MACRON - "sub", 0x02282, // SUBSET OF - "Sub", 0x022D0, // DOUBLE SUBSET - "subdot", 0x02ABD, // SUBSET WITH DOT - "sube", 0x02286, // SUBSET OF OR EQUAL TO - "subE", 0x02AC5, // SUBSET OF ABOVE EQUALS SIGN - "subedot", 0x02AC3, // SUBSET OF OR EQUAL TO WITH DOT ABOVE - "submult", 0x02AC1, // SUBSET WITH MULTIPLICATION SIGN BELOW - "subne", 0x0228A, // SUBSET OF WITH NOT EQUAL TO - "subnE", 0x02ACB, // SUBSET OF ABOVE NOT EQUAL TO - "subplus", 0x02ABF, // SUBSET WITH PLUS SIGN BELOW - "subrarr", 0x02979, // SUBSET ABOVE RIGHTWARDS ARROW - "subset", 0x02282, // SUBSET OF - "Subset", 0x022D0, // DOUBLE SUBSET - "subseteq", 0x02286, // SUBSET OF OR EQUAL TO - "subseteqq", 0x02AC5, // SUBSET OF ABOVE EQUALS SIGN - "SubsetEqual", 0x02286, // SUBSET OF OR EQUAL TO - "subsetneq", 0x0228A, // SUBSET OF WITH NOT EQUAL TO - "subsetneqq", 0x02ACB, // SUBSET OF ABOVE NOT EQUAL TO - "subsim", 0x02AC7, // SUBSET OF ABOVE TILDE OPERATOR - "subsub", 0x02AD5, // SUBSET ABOVE SUBSET - "subsup", 0x02AD3, // SUBSET ABOVE SUPERSET - "succ", 0x0227B, // SUCCEEDS - "succapprox", 0x02AB8, // SUCCEEDS ABOVE ALMOST EQUAL TO - "succcurlyeq", 0x0227D, // SUCCEEDS OR EQUAL TO - "Succeeds", 0x0227B, // SUCCEEDS - "SucceedsEqual", 0x02AB0, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - "SucceedsSlantEqual", 0x0227D, // SUCCEEDS OR EQUAL TO - "SucceedsTilde", 0x0227F, // SUCCEEDS OR EQUIVALENT TO - "succeq", 0x02AB0, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN - "succnapprox", 0x02ABA, // SUCCEEDS ABOVE NOT ALMOST EQUAL TO - "succneqq", 0x02AB6, // SUCCEEDS ABOVE NOT EQUAL TO - "succnsim", 0x022E9, // SUCCEEDS BUT NOT EQUIVALENT TO - "succsim", 0x0227F, // SUCCEEDS OR EQUIVALENT TO - "SuchThat", 0x0220B, // CONTAINS AS MEMBER - "sum", 0x02211, // N-ARY SUMMATION - "Sum", 0x02211, // N-ARY SUMMATION - "sung", 0x0266A, // EIGHTH NOTE - "sup", 0x02283, // SUPERSET OF - "Sup", 0x022D1, // DOUBLE SUPERSET - "sup1", 0x000B9, // SUPERSCRIPT ONE - "sup2", 0x000B2, // SUPERSCRIPT TWO - "sup3", 0x000B3, // SUPERSCRIPT THREE - "supdot", 0x02ABE, // SUPERSET WITH DOT - "supdsub", 0x02AD8, // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET - "supe", 0x02287, // SUPERSET OF OR EQUAL TO - "supE", 0x02AC6, // SUPERSET OF ABOVE EQUALS SIGN - "supedot", 0x02AC4, // SUPERSET OF OR EQUAL TO WITH DOT ABOVE - "Superset", 0x02283, // SUPERSET OF - "SupersetEqual", 0x02287, // SUPERSET OF OR EQUAL TO - "suphsol", 0x027C9, // SUPERSET PRECEDING SOLIDUS - "suphsub", 0x02AD7, // SUPERSET BESIDE SUBSET - "suplarr", 0x0297B, // SUPERSET ABOVE LEFTWARDS ARROW - "supmult", 0x02AC2, // SUPERSET WITH MULTIPLICATION SIGN BELOW - "supne", 0x0228B, // SUPERSET OF WITH NOT EQUAL TO - "supnE", 0x02ACC, // SUPERSET OF ABOVE NOT EQUAL TO - "supplus", 0x02AC0, // SUPERSET WITH PLUS SIGN BELOW - "supset", 0x02283, // SUPERSET OF - "Supset", 0x022D1, // DOUBLE SUPERSET - "supseteq", 0x02287, // SUPERSET OF OR EQUAL TO - "supseteqq", 0x02AC6, // SUPERSET OF ABOVE EQUALS SIGN - "supsetneq", 0x0228B, // SUPERSET OF WITH NOT EQUAL TO - "supsetneqq", 0x02ACC, // SUPERSET OF ABOVE NOT EQUAL TO - "supsim", 0x02AC8, // SUPERSET OF ABOVE TILDE OPERATOR - "supsub", 0x02AD4, // SUPERSET ABOVE SUBSET - "supsup", 0x02AD6, // SUPERSET ABOVE SUPERSET - "swarhk", 0x02926, // SOUTH WEST ARROW WITH HOOK - "swarr", 0x02199, // SOUTH WEST ARROW - "swArr", 0x021D9, // SOUTH WEST DOUBLE ARROW - "swarrow", 0x02199, // SOUTH WEST ARROW - "swnwar", 0x0292A, // SOUTH WEST ARROW AND NORTH WEST ARROW - "szlig", 0x000DF, // LATIN SMALL LETTER SHARP S - NULL, 0 + {"Sacute", 0x0015A}, // LATIN CAPITAL LETTER S WITH ACUTE + {"sacute", 0x0015B}, // LATIN SMALL LETTER S WITH ACUTE + {"sbquo", 0x0201A}, // SINGLE LOW-9 QUOTATION MARK + {"sc", 0x0227B}, // SUCCEEDS + {"Sc", 0x02ABC}, // DOUBLE SUCCEEDS + {"scap", 0x02AB8}, // SUCCEEDS ABOVE ALMOST EQUAL TO + {"Scaron", 0x00160}, // LATIN CAPITAL LETTER S WITH CARON + {"scaron", 0x00161}, // LATIN SMALL LETTER S WITH CARON + {"sccue", 0x0227D}, // SUCCEEDS OR EQUAL TO + {"sce", 0x02AB0}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + {"scE", 0x02AB4}, // SUCCEEDS ABOVE EQUALS SIGN + {"Scedil", 0x0015E}, // LATIN CAPITAL LETTER S WITH CEDILLA + {"scedil", 0x0015F}, // LATIN SMALL LETTER S WITH CEDILLA + {"Scirc", 0x0015C}, // LATIN CAPITAL LETTER S WITH CIRCUMFLEX + {"scirc", 0x0015D}, // LATIN SMALL LETTER S WITH CIRCUMFLEX + {"scnap", 0x02ABA}, // SUCCEEDS ABOVE NOT ALMOST EQUAL TO + {"scnE", 0x02AB6}, // SUCCEEDS ABOVE NOT EQUAL TO + {"scnsim", 0x022E9}, // SUCCEEDS BUT NOT EQUIVALENT TO + {"scpolint", 0x02A13}, // LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE + {"scsim", 0x0227F}, // SUCCEEDS OR EQUIVALENT TO + {"Scy", 0x00421}, // CYRILLIC CAPITAL LETTER ES + {"scy", 0x00441}, // CYRILLIC SMALL LETTER ES + {"sdot", 0x022C5}, // DOT OPERATOR + {"sdotb", 0x022A1}, // SQUARED DOT OPERATOR + {"sdote", 0x02A66}, // EQUALS SIGN WITH DOT BELOW + {"searhk", 0x02925}, // SOUTH EAST ARROW WITH HOOK + {"searr", 0x02198}, // SOUTH EAST ARROW + {"seArr", 0x021D8}, // SOUTH EAST DOUBLE ARROW + {"searrow", 0x02198}, // SOUTH EAST ARROW + {"sect", 0x000A7}, // SECTION SIGN + {"semi", 0x0003B}, // SEMICOLON + {"seswar", 0x02929}, // SOUTH EAST ARROW AND SOUTH WEST ARROW + {"setminus", 0x02216}, // SET MINUS + {"setmn", 0x02216}, // SET MINUS + {"sext", 0x02736}, // SIX POINTED BLACK STAR + {"sfgr", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA + {"Sfr", 0x1D516}, // MATHEMATICAL FRAKTUR CAPITAL S + {"sfr", 0x1D530}, // MATHEMATICAL FRAKTUR SMALL S + {"sfrown", 0x02322}, // FROWN + {"Sgr", 0x003A3}, // GREEK CAPITAL LETTER SIGMA + {"sgr", 0x003C3}, // GREEK SMALL LETTER SIGMA + {"sharp", 0x0266F}, // MUSIC SHARP SIGN + {"SHCHcy", 0x00429}, // CYRILLIC CAPITAL LETTER SHCHA + {"shchcy", 0x00449}, // CYRILLIC SMALL LETTER SHCHA + {"SHcy", 0x00428}, // CYRILLIC CAPITAL LETTER SHA + {"shcy", 0x00448}, // CYRILLIC SMALL LETTER SHA + {"ShortDownArrow", 0x02193}, // DOWNWARDS ARROW + {"ShortLeftArrow", 0x02190}, // LEFTWARDS ARROW + {"shortmid", 0x02223}, // DIVIDES + {"shortparallel", 0x02225}, // PARALLEL TO + {"ShortRightArrow", 0x02192}, // RIGHTWARDS ARROW + {"ShortUpArrow", 0x02191}, // UPWARDS ARROW + {"shy", 0x000AD}, // SOFT HYPHEN + {"Sigma", 0x003A3}, // GREEK CAPITAL LETTER SIGMA + {"sigma", 0x003C3}, // GREEK SMALL LETTER SIGMA + {"sigmaf", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA + {"sigmav", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA + {"sim", 0x0223C}, // TILDE OPERATOR + {"simdot", 0x02A6A}, // TILDE OPERATOR WITH DOT ABOVE + {"sime", 0x02243}, // ASYMPTOTICALLY EQUAL TO + {"simeq", 0x02243}, // ASYMPTOTICALLY EQUAL TO + {"simg", 0x02A9E}, // SIMILAR OR GREATER-THAN + {"simgE", 0x02AA0}, // SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN + {"siml", 0x02A9D}, // SIMILAR OR LESS-THAN + {"simlE", 0x02A9F}, // SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN + {"simne", 0x02246}, // APPROXIMATELY BUT NOT ACTUALLY EQUAL TO + {"simplus", 0x02A24}, // PLUS SIGN WITH TILDE ABOVE + {"simrarr", 0x02972}, // TILDE OPERATOR ABOVE RIGHTWARDS ARROW + {"slarr", 0x02190}, // LEFTWARDS ARROW + {"SmallCircle", 0x02218}, // RING OPERATOR + {"smallsetminus", 0x02216}, // SET MINUS + {"smashp", 0x02A33}, // SMASH PRODUCT + {"smeparsl", 0x029E4}, // EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE + {"smid", 0x02223}, // DIVIDES + {"smile", 0x02323}, // SMILE + {"smt", 0x02AAA}, // SMALLER THAN + {"smte", 0x02AAC}, // SMALLER THAN OR EQUAL TO +// "smtes", 0x02AAC;0x0FE00}, // SMALLER THAN OR slanted EQUAL + {"SOFTcy", 0x0042C}, // CYRILLIC CAPITAL LETTER SOFT SIGN + {"softcy", 0x0044C}, // CYRILLIC SMALL LETTER SOFT SIGN + {"sol", 0x0002F}, // SOLIDUS + {"solb", 0x029C4}, // SQUARED RISING DIAGONAL SLASH + {"solbar", 0x0233F}, // APL FUNCTIONAL SYMBOL SLASH BAR + {"Sopf", 0x1D54A}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL S + {"sopf", 0x1D564}, // MATHEMATICAL DOUBLE-STRUCK SMALL S + {"spades", 0x02660}, // BLACK SPADE SUIT + {"spadesuit", 0x02660}, // BLACK SPADE SUIT + {"spar", 0x02225}, // PARALLEL TO + {"sqcap", 0x02293}, // SQUARE CAP +// "sqcaps", 0x02293;0x0FE00}, // SQUARE CAP with serifs + {"sqcup", 0x02294}, // SQUARE CUP +// "sqcups", 0x02294;0x0FE00}, // SQUARE CUP with serifs + {"Sqrt", 0x0221A}, // SQUARE ROOT + {"sqsub", 0x0228F}, // SQUARE IMAGE OF + {"sqsube", 0x02291}, // SQUARE IMAGE OF OR EQUAL TO + {"sqsubset", 0x0228F}, // SQUARE IMAGE OF + {"sqsubseteq", 0x02291}, // SQUARE IMAGE OF OR EQUAL TO + {"sqsup", 0x02290}, // SQUARE ORIGINAL OF + {"sqsupe", 0x02292}, // SQUARE ORIGINAL OF OR EQUAL TO + {"sqsupset", 0x02290}, // SQUARE ORIGINAL OF + {"sqsupseteq", 0x02292}, // SQUARE ORIGINAL OF OR EQUAL TO + {"squ", 0x025A1}, // WHITE SQUARE + {"square", 0x025A1}, // WHITE SQUARE + {"Square", 0x025A1}, // WHITE SQUARE + {"SquareIntersection", 0x02293}, // SQUARE CAP + {"SquareSubset", 0x0228F}, // SQUARE IMAGE OF + {"SquareSubsetEqual", 0x02291}, // SQUARE IMAGE OF OR EQUAL TO + {"SquareSuperset", 0x02290}, // SQUARE ORIGINAL OF + {"SquareSupersetEqual", 0x02292}, // SQUARE ORIGINAL OF OR EQUAL TO + {"SquareUnion", 0x02294}, // SQUARE CUP + {"squarf", 0x025AA}, // BLACK SMALL SQUARE + {"squf", 0x025AA}, // BLACK SMALL SQUARE + {"srarr", 0x02192}, // RIGHTWARDS ARROW + {"Sscr", 0x1D4AE}, // MATHEMATICAL SCRIPT CAPITAL S + {"sscr", 0x1D4C8}, // MATHEMATICAL SCRIPT SMALL S + {"ssetmn", 0x02216}, // SET MINUS + {"ssmile", 0x02323}, // SMILE + {"sstarf", 0x022C6}, // STAR OPERATOR + {"Star", 0x022C6}, // STAR OPERATOR + {"star", 0x02606}, // WHITE STAR + {"starf", 0x02605}, // BLACK STAR + {"straightepsilon", 0x003F5}, // GREEK LUNATE EPSILON SYMBOL + {"straightphi", 0x003D5}, // GREEK PHI SYMBOL + {"strns", 0x000AF}, // MACRON + {"sub", 0x02282}, // SUBSET OF + {"Sub", 0x022D0}, // DOUBLE SUBSET + {"subdot", 0x02ABD}, // SUBSET WITH DOT + {"sube", 0x02286}, // SUBSET OF OR EQUAL TO + {"subE", 0x02AC5}, // SUBSET OF ABOVE EQUALS SIGN + {"subedot", 0x02AC3}, // SUBSET OF OR EQUAL TO WITH DOT ABOVE + {"submult", 0x02AC1}, // SUBSET WITH MULTIPLICATION SIGN BELOW + {"subne", 0x0228A}, // SUBSET OF WITH NOT EQUAL TO + {"subnE", 0x02ACB}, // SUBSET OF ABOVE NOT EQUAL TO + {"subplus", 0x02ABF}, // SUBSET WITH PLUS SIGN BELOW + {"subrarr", 0x02979}, // SUBSET ABOVE RIGHTWARDS ARROW + {"subset", 0x02282}, // SUBSET OF + {"Subset", 0x022D0}, // DOUBLE SUBSET + {"subseteq", 0x02286}, // SUBSET OF OR EQUAL TO + {"subseteqq", 0x02AC5}, // SUBSET OF ABOVE EQUALS SIGN + {"SubsetEqual", 0x02286}, // SUBSET OF OR EQUAL TO + {"subsetneq", 0x0228A}, // SUBSET OF WITH NOT EQUAL TO + {"subsetneqq", 0x02ACB}, // SUBSET OF ABOVE NOT EQUAL TO + {"subsim", 0x02AC7}, // SUBSET OF ABOVE TILDE OPERATOR + {"subsub", 0x02AD5}, // SUBSET ABOVE SUBSET + {"subsup", 0x02AD3}, // SUBSET ABOVE SUPERSET + {"succ", 0x0227B}, // SUCCEEDS + {"succapprox", 0x02AB8}, // SUCCEEDS ABOVE ALMOST EQUAL TO + {"succcurlyeq", 0x0227D}, // SUCCEEDS OR EQUAL TO + {"Succeeds", 0x0227B}, // SUCCEEDS + {"SucceedsEqual", 0x02AB0}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + {"SucceedsSlantEqual", 0x0227D}, // SUCCEEDS OR EQUAL TO + {"SucceedsTilde", 0x0227F}, // SUCCEEDS OR EQUIVALENT TO + {"succeq", 0x02AB0}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN + {"succnapprox", 0x02ABA}, // SUCCEEDS ABOVE NOT ALMOST EQUAL TO + {"succneqq", 0x02AB6}, // SUCCEEDS ABOVE NOT EQUAL TO + {"succnsim", 0x022E9}, // SUCCEEDS BUT NOT EQUIVALENT TO + {"succsim", 0x0227F}, // SUCCEEDS OR EQUIVALENT TO + {"SuchThat", 0x0220B}, // CONTAINS AS MEMBER + {"sum", 0x02211}, // N-ARY SUMMATION + {"Sum", 0x02211}, // N-ARY SUMMATION + {"sung", 0x0266A}, // EIGHTH NOTE + {"sup", 0x02283}, // SUPERSET OF + {"Sup", 0x022D1}, // DOUBLE SUPERSET + {"sup1", 0x000B9}, // SUPERSCRIPT ONE + {"sup2", 0x000B2}, // SUPERSCRIPT TWO + {"sup3", 0x000B3}, // SUPERSCRIPT THREE + {"supdot", 0x02ABE}, // SUPERSET WITH DOT + {"supdsub", 0x02AD8}, // SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET + {"supe", 0x02287}, // SUPERSET OF OR EQUAL TO + {"supE", 0x02AC6}, // SUPERSET OF ABOVE EQUALS SIGN + {"supedot", 0x02AC4}, // SUPERSET OF OR EQUAL TO WITH DOT ABOVE + {"Superset", 0x02283}, // SUPERSET OF + {"SupersetEqual", 0x02287}, // SUPERSET OF OR EQUAL TO + {"suphsol", 0x027C9}, // SUPERSET PRECEDING SOLIDUS + {"suphsub", 0x02AD7}, // SUPERSET BESIDE SUBSET + {"suplarr", 0x0297B}, // SUPERSET ABOVE LEFTWARDS ARROW + {"supmult", 0x02AC2}, // SUPERSET WITH MULTIPLICATION SIGN BELOW + {"supne", 0x0228B}, // SUPERSET OF WITH NOT EQUAL TO + {"supnE", 0x02ACC}, // SUPERSET OF ABOVE NOT EQUAL TO + {"supplus", 0x02AC0}, // SUPERSET WITH PLUS SIGN BELOW + {"supset", 0x02283}, // SUPERSET OF + {"Supset", 0x022D1}, // DOUBLE SUPERSET + {"supseteq", 0x02287}, // SUPERSET OF OR EQUAL TO + {"supseteqq", 0x02AC6}, // SUPERSET OF ABOVE EQUALS SIGN + {"supsetneq", 0x0228B}, // SUPERSET OF WITH NOT EQUAL TO + {"supsetneqq", 0x02ACC}, // SUPERSET OF ABOVE NOT EQUAL TO + {"supsim", 0x02AC8}, // SUPERSET OF ABOVE TILDE OPERATOR + {"supsub", 0x02AD4}, // SUPERSET ABOVE SUBSET + {"supsup", 0x02AD6}, // SUPERSET ABOVE SUPERSET + {"swarhk", 0x02926}, // SOUTH WEST ARROW WITH HOOK + {"swarr", 0x02199}, // SOUTH WEST ARROW + {"swArr", 0x021D9}, // SOUTH WEST DOUBLE ARROW + {"swarrow", 0x02199}, // SOUTH WEST ARROW + {"swnwar", 0x0292A}, // SOUTH WEST ARROW AND NORTH WEST ARROW + {"szlig", 0x000DF}, // LATIN SMALL LETTER SHARP S + {NULL, 0} }; static NameId namesT[]={ - "Tab", 0x00009, // CHARACTER TABULATION - "target", 0x02316, // POSITION INDICATOR - "Tau", 0x003A4, // GREEK CAPITAL LETTER TAU - "tau", 0x003C4, // GREEK SMALL LETTER TAU - "tbrk", 0x023B4, // TOP SQUARE BRACKET - "Tcaron", 0x00164, // LATIN CAPITAL LETTER T WITH CARON - "tcaron", 0x00165, // LATIN SMALL LETTER T WITH CARON - "Tcedil", 0x00162, // LATIN CAPITAL LETTER T WITH CEDILLA - "tcedil", 0x00163, // LATIN SMALL LETTER T WITH CEDILLA - "Tcy", 0x00422, // CYRILLIC CAPITAL LETTER TE - "tcy", 0x00442, // CYRILLIC SMALL LETTER TE - "tdot", 0x020DB, // COMBINING THREE DOTS ABOVE - "telrec", 0x02315, // TELEPHONE RECORDER - "Tfr", 0x1D517, // MATHEMATICAL FRAKTUR CAPITAL T - "tfr", 0x1D531, // MATHEMATICAL FRAKTUR SMALL T - "Tgr", 0x003A4, // GREEK CAPITAL LETTER TAU - "tgr", 0x003C4, // GREEK SMALL LETTER TAU - "there4", 0x02234, // THEREFORE - "therefore", 0x02234, // THEREFORE - "Therefore", 0x02234, // THEREFORE - "Theta", 0x00398, // GREEK CAPITAL LETTER THETA - "theta", 0x003B8, // GREEK SMALL LETTER THETA - "thetasym", 0x003D1, // GREEK THETA SYMBOL - "thetav", 0x003D1, // GREEK THETA SYMBOL - "THgr", 0x00398, // GREEK CAPITAL LETTER THETA - "thgr", 0x003B8, // GREEK SMALL LETTER THETA - "thickapprox", 0x02248, // ALMOST EQUAL TO - "thicksim", 0x0223C, // TILDE OPERATOR -// "ThickSpace", 0x0205F;0x0200A, // space of width 5/18 em - "thinsp", 0x02009, // THIN SPACE - "ThinSpace", 0x02009, // THIN SPACE - "thkap", 0x02248, // ALMOST EQUAL TO - "thksim", 0x0223C, // TILDE OPERATOR - "THORN", 0x000DE, // LATIN CAPITAL LETTER THORN - "thorn", 0x000FE, // LATIN SMALL LETTER THORN - "tilde", 0x002DC, // SMALL TILDE - "Tilde", 0x0223C, // TILDE OPERATOR - "TildeEqual", 0x02243, // ASYMPTOTICALLY EQUAL TO - "TildeFullEqual", 0x02245, // APPROXIMATELY EQUAL TO - "TildeTilde", 0x02248, // ALMOST EQUAL TO - "times", 0x000D7, // MULTIPLICATION SIGN - "timesb", 0x022A0, // SQUARED TIMES - "timesbar", 0x02A31, // MULTIPLICATION SIGN WITH UNDERBAR - "timesd", 0x02A30, // MULTIPLICATION SIGN WITH DOT ABOVE - "tint", 0x0222D, // TRIPLE INTEGRAL - "toea", 0x02928, // NORTH EAST ARROW AND SOUTH EAST ARROW - "top", 0x022A4, // DOWN TACK - "topbot", 0x02336, // APL FUNCTIONAL SYMBOL I-BEAM - "topcir", 0x02AF1, // DOWN TACK WITH CIRCLE BELOW - "Topf", 0x1D54B, // MATHEMATICAL DOUBLE-STRUCK CAPITAL T - "topf", 0x1D565, // MATHEMATICAL DOUBLE-STRUCK SMALL T - "topfork", 0x02ADA, // PITCHFORK WITH TEE TOP - "tosa", 0x02929, // SOUTH EAST ARROW AND SOUTH WEST ARROW - "tprime", 0x02034, // TRIPLE PRIME - "trade", 0x02122, // TRADE MARK SIGN - "TRADE", 0x02122, // TRADE MARK SIGN - "triangle", 0x025B5, // WHITE UP-POINTING SMALL TRIANGLE - "triangledown", 0x025BF, // WHITE DOWN-POINTING SMALL TRIANGLE - "triangleleft", 0x025C3, // WHITE LEFT-POINTING SMALL TRIANGLE - "trianglelefteq", 0x022B4, // NORMAL SUBGROUP OF OR EQUAL TO - "triangleq", 0x0225C, // DELTA EQUAL TO - "triangleright", 0x025B9, // WHITE RIGHT-POINTING SMALL TRIANGLE - "trianglerighteq", 0x022B5, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO - "tridot", 0x025EC, // WHITE UP-POINTING TRIANGLE WITH DOT - "trie", 0x0225C, // DELTA EQUAL TO - "triminus", 0x02A3A, // MINUS SIGN IN TRIANGLE - "TripleDot", 0x020DB, // COMBINING THREE DOTS ABOVE - "triplus", 0x02A39, // PLUS SIGN IN TRIANGLE - "trisb", 0x029CD, // TRIANGLE WITH SERIFS AT BOTTOM - "tritime", 0x02A3B, // MULTIPLICATION SIGN IN TRIANGLE - "trpezium", 0x023E2, // WHITE TRAPEZIUM - "Tscr", 0x1D4AF, // MATHEMATICAL SCRIPT CAPITAL T - "tscr", 0x1D4C9, // MATHEMATICAL SCRIPT SMALL T - "TScy", 0x00426, // CYRILLIC CAPITAL LETTER TSE - "tscy", 0x00446, // CYRILLIC SMALL LETTER TSE - "TSHcy", 0x0040B, // CYRILLIC CAPITAL LETTER TSHE - "tshcy", 0x0045B, // CYRILLIC SMALL LETTER TSHE - "Tstrok", 0x00166, // LATIN CAPITAL LETTER T WITH STROKE - "tstrok", 0x00167, // LATIN SMALL LETTER T WITH STROKE - "twixt", 0x0226C, // BETWEEN - "twoheadleftarrow", 0x0219E, // LEFTWARDS TWO HEADED ARROW - "twoheadrightarrow", 0x021A0, // RIGHTWARDS TWO HEADED ARROW - NULL, 0 + {"Tab", 0x00009}, // CHARACTER TABULATION + {"target", 0x02316}, // POSITION INDICATOR + {"Tau", 0x003A4}, // GREEK CAPITAL LETTER TAU + {"tau", 0x003C4}, // GREEK SMALL LETTER TAU + {"tbrk", 0x023B4}, // TOP SQUARE BRACKET + {"Tcaron", 0x00164}, // LATIN CAPITAL LETTER T WITH CARON + {"tcaron", 0x00165}, // LATIN SMALL LETTER T WITH CARON + {"Tcedil", 0x00162}, // LATIN CAPITAL LETTER T WITH CEDILLA + {"tcedil", 0x00163}, // LATIN SMALL LETTER T WITH CEDILLA + {"Tcy", 0x00422}, // CYRILLIC CAPITAL LETTER TE + {"tcy", 0x00442}, // CYRILLIC SMALL LETTER TE + {"tdot", 0x020DB}, // COMBINING THREE DOTS ABOVE + {"telrec", 0x02315}, // TELEPHONE RECORDER + {"Tfr", 0x1D517}, // MATHEMATICAL FRAKTUR CAPITAL T + {"tfr", 0x1D531}, // MATHEMATICAL FRAKTUR SMALL T + {"Tgr", 0x003A4}, // GREEK CAPITAL LETTER TAU + {"tgr", 0x003C4}, // GREEK SMALL LETTER TAU + {"there4", 0x02234}, // THEREFORE + {"therefore", 0x02234}, // THEREFORE + {"Therefore", 0x02234}, // THEREFORE + {"Theta", 0x00398}, // GREEK CAPITAL LETTER THETA + {"theta", 0x003B8}, // GREEK SMALL LETTER THETA + {"thetasym", 0x003D1}, // GREEK THETA SYMBOL + {"thetav", 0x003D1}, // GREEK THETA SYMBOL + {"THgr", 0x00398}, // GREEK CAPITAL LETTER THETA + {"thgr", 0x003B8}, // GREEK SMALL LETTER THETA + {"thickapprox", 0x02248}, // ALMOST EQUAL TO + {"thicksim", 0x0223C}, // TILDE OPERATOR +// "ThickSpace", 0x0205F;0x0200A}, // space of width 5/18 em + {"thinsp", 0x02009}, // THIN SPACE + {"ThinSpace", 0x02009}, // THIN SPACE + {"thkap", 0x02248}, // ALMOST EQUAL TO + {"thksim", 0x0223C}, // TILDE OPERATOR + {"THORN", 0x000DE}, // LATIN CAPITAL LETTER THORN + {"thorn", 0x000FE}, // LATIN SMALL LETTER THORN + {"tilde", 0x002DC}, // SMALL TILDE + {"Tilde", 0x0223C}, // TILDE OPERATOR + {"TildeEqual", 0x02243}, // ASYMPTOTICALLY EQUAL TO + {"TildeFullEqual", 0x02245}, // APPROXIMATELY EQUAL TO + {"TildeTilde", 0x02248}, // ALMOST EQUAL TO + {"times", 0x000D7}, // MULTIPLICATION SIGN + {"timesb", 0x022A0}, // SQUARED TIMES + {"timesbar", 0x02A31}, // MULTIPLICATION SIGN WITH UNDERBAR + {"timesd", 0x02A30}, // MULTIPLICATION SIGN WITH DOT ABOVE + {"tint", 0x0222D}, // TRIPLE INTEGRAL + {"toea", 0x02928}, // NORTH EAST ARROW AND SOUTH EAST ARROW + {"top", 0x022A4}, // DOWN TACK + {"topbot", 0x02336}, // APL FUNCTIONAL SYMBOL I-BEAM + {"topcir", 0x02AF1}, // DOWN TACK WITH CIRCLE BELOW + {"Topf", 0x1D54B}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL T + {"topf", 0x1D565}, // MATHEMATICAL DOUBLE-STRUCK SMALL T + {"topfork", 0x02ADA}, // PITCHFORK WITH TEE TOP + {"tosa", 0x02929}, // SOUTH EAST ARROW AND SOUTH WEST ARROW + {"tprime", 0x02034}, // TRIPLE PRIME + {"trade", 0x02122}, // TRADE MARK SIGN + {"TRADE", 0x02122}, // TRADE MARK SIGN + {"triangle", 0x025B5}, // WHITE UP-POINTING SMALL TRIANGLE + {"triangledown", 0x025BF}, // WHITE DOWN-POINTING SMALL TRIANGLE + {"triangleleft", 0x025C3}, // WHITE LEFT-POINTING SMALL TRIANGLE + {"trianglelefteq", 0x022B4}, // NORMAL SUBGROUP OF OR EQUAL TO + {"triangleq", 0x0225C}, // DELTA EQUAL TO + {"triangleright", 0x025B9}, // WHITE RIGHT-POINTING SMALL TRIANGLE + {"trianglerighteq", 0x022B5}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO + {"tridot", 0x025EC}, // WHITE UP-POINTING TRIANGLE WITH DOT + {"trie", 0x0225C}, // DELTA EQUAL TO + {"triminus", 0x02A3A}, // MINUS SIGN IN TRIANGLE + {"TripleDot", 0x020DB}, // COMBINING THREE DOTS ABOVE + {"triplus", 0x02A39}, // PLUS SIGN IN TRIANGLE + {"trisb", 0x029CD}, // TRIANGLE WITH SERIFS AT BOTTOM + {"tritime", 0x02A3B}, // MULTIPLICATION SIGN IN TRIANGLE + {"trpezium", 0x023E2}, // WHITE TRAPEZIUM + {"Tscr", 0x1D4AF}, // MATHEMATICAL SCRIPT CAPITAL T + {"tscr", 0x1D4C9}, // MATHEMATICAL SCRIPT SMALL T + {"TScy", 0x00426}, // CYRILLIC CAPITAL LETTER TSE + {"tscy", 0x00446}, // CYRILLIC SMALL LETTER TSE + {"TSHcy", 0x0040B}, // CYRILLIC CAPITAL LETTER TSHE + {"tshcy", 0x0045B}, // CYRILLIC SMALL LETTER TSHE + {"Tstrok", 0x00166}, // LATIN CAPITAL LETTER T WITH STROKE + {"tstrok", 0x00167}, // LATIN SMALL LETTER T WITH STROKE + {"twixt", 0x0226C}, // BETWEEN + {"twoheadleftarrow", 0x0219E}, // LEFTWARDS TWO HEADED ARROW + {"twoheadrightarrow", 0x021A0}, // RIGHTWARDS TWO HEADED ARROW + {NULL, 0} }; static NameId namesU[]={ - "Uacgr", 0x0038E, // GREEK CAPITAL LETTER UPSILON WITH TONOS - "uacgr", 0x003CD, // GREEK SMALL LETTER UPSILON WITH TONOS - "Uacute", 0x000DA, // LATIN CAPITAL LETTER U WITH ACUTE - "uacute", 0x000FA, // LATIN SMALL LETTER U WITH ACUTE - "uarr", 0x02191, // UPWARDS ARROW - "Uarr", 0x0219F, // UPWARDS TWO HEADED ARROW - "uArr", 0x021D1, // UPWARDS DOUBLE ARROW - "Uarrocir", 0x02949, // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE - "Ubrcy", 0x0040E, // CYRILLIC CAPITAL LETTER SHORT U - "ubrcy", 0x0045E, // CYRILLIC SMALL LETTER SHORT U - "Ubreve", 0x0016C, // LATIN CAPITAL LETTER U WITH BREVE - "ubreve", 0x0016D, // LATIN SMALL LETTER U WITH BREVE - "Ucirc", 0x000DB, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX - "ucirc", 0x000FB, // LATIN SMALL LETTER U WITH CIRCUMFLEX - "Ucy", 0x00423, // CYRILLIC CAPITAL LETTER U - "ucy", 0x00443, // CYRILLIC SMALL LETTER U - "udarr", 0x021C5, // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW - "Udblac", 0x00170, // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE - "udblac", 0x00171, // LATIN SMALL LETTER U WITH DOUBLE ACUTE - "udhar", 0x0296E, // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - "udiagr", 0x003B0, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS - "Udigr", 0x003AB, // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA - "udigr", 0x003CB, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA - "ufisht", 0x0297E, // UP FISH TAIL - "Ufr", 0x1D518, // MATHEMATICAL FRAKTUR CAPITAL U - "ufr", 0x1D532, // MATHEMATICAL FRAKTUR SMALL U - "Ugr", 0x003A5, // GREEK CAPITAL LETTER UPSILON - "ugr", 0x003C5, // GREEK SMALL LETTER UPSILON - "Ugrave", 0x000D9, // LATIN CAPITAL LETTER U WITH GRAVE - "ugrave", 0x000F9, // LATIN SMALL LETTER U WITH GRAVE - "uHar", 0x02963, // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT - "uharl", 0x021BF, // UPWARDS HARPOON WITH BARB LEFTWARDS - "uharr", 0x021BE, // UPWARDS HARPOON WITH BARB RIGHTWARDS - "uhblk", 0x02580, // UPPER HALF BLOCK - "ulcorn", 0x0231C, // TOP LEFT CORNER - "ulcorner", 0x0231C, // TOP LEFT CORNER - "ulcrop", 0x0230F, // TOP LEFT CROP - "ultri", 0x025F8, // UPPER LEFT TRIANGLE - "Umacr", 0x0016A, // LATIN CAPITAL LETTER U WITH MACRON - "umacr", 0x0016B, // LATIN SMALL LETTER U WITH MACRON - "uml", 0x000A8, // DIAERESIS - "UnderBar", 0x0005F, // LOW LINE - "UnderBrace", 0x023DF, // BOTTOM CURLY BRACKET - "UnderBracket", 0x023B5, // BOTTOM SQUARE BRACKET - "UnderParenthesis", 0x023DD, // BOTTOM PARENTHESIS - "Union", 0x022C3, // N-ARY UNION - "UnionPlus", 0x0228E, // MULTISET UNION - "Uogon", 0x00172, // LATIN CAPITAL LETTER U WITH OGONEK - "uogon", 0x00173, // LATIN SMALL LETTER U WITH OGONEK - "Uopf", 0x1D54C, // MATHEMATICAL DOUBLE-STRUCK CAPITAL U - "uopf", 0x1D566, // MATHEMATICAL DOUBLE-STRUCK SMALL U - "uparrow", 0x02191, // UPWARDS ARROW - "UpArrow", 0x02191, // UPWARDS ARROW - "Uparrow", 0x021D1, // UPWARDS DOUBLE ARROW - "UpArrowBar", 0x02912, // UPWARDS ARROW TO BAR - "UpArrowDownArrow", 0x021C5, // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW - "updownarrow", 0x02195, // UP DOWN ARROW - "UpDownArrow", 0x02195, // UP DOWN ARROW - "Updownarrow", 0x021D5, // UP DOWN DOUBLE ARROW - "UpEquilibrium", 0x0296E, // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT - "upharpoonleft", 0x021BF, // UPWARDS HARPOON WITH BARB LEFTWARDS - "upharpoonright", 0x021BE, // UPWARDS HARPOON WITH BARB RIGHTWARDS - "uplus", 0x0228E, // MULTISET UNION - "UpperLeftArrow", 0x02196, // NORTH WEST ARROW - "UpperRightArrow", 0x02197, // NORTH EAST ARROW - "upsi", 0x003C5, // GREEK SMALL LETTER UPSILON - "Upsi", 0x003D2, // GREEK UPSILON WITH HOOK SYMBOL - "upsih", 0x003D2, // GREEK UPSILON WITH HOOK SYMBOL - "Upsilon", 0x003A5, // GREEK CAPITAL LETTER UPSILON - "upsilon", 0x003C5, // GREEK SMALL LETTER UPSILON - "UpTee", 0x022A5, // UP TACK - "UpTeeArrow", 0x021A5, // UPWARDS ARROW FROM BAR - "upuparrows", 0x021C8, // UPWARDS PAIRED ARROWS - "urcorn", 0x0231D, // TOP RIGHT CORNER - "urcorner", 0x0231D, // TOP RIGHT CORNER - "urcrop", 0x0230E, // TOP RIGHT CROP - "Uring", 0x0016E, // LATIN CAPITAL LETTER U WITH RING ABOVE - "uring", 0x0016F, // LATIN SMALL LETTER U WITH RING ABOVE - "urtri", 0x025F9, // UPPER RIGHT TRIANGLE - "Uscr", 0x1D4B0, // MATHEMATICAL SCRIPT CAPITAL U - "uscr", 0x1D4CA, // MATHEMATICAL SCRIPT SMALL U - "utdot", 0x022F0, // UP RIGHT DIAGONAL ELLIPSIS - "Utilde", 0x00168, // LATIN CAPITAL LETTER U WITH TILDE - "utilde", 0x00169, // LATIN SMALL LETTER U WITH TILDE - "utri", 0x025B5, // WHITE UP-POINTING SMALL TRIANGLE - "utrif", 0x025B4, // BLACK UP-POINTING SMALL TRIANGLE - "uuarr", 0x021C8, // UPWARDS PAIRED ARROWS - "Uuml", 0x000DC, // LATIN CAPITAL LETTER U WITH DIAERESIS - "uuml", 0x000FC, // LATIN SMALL LETTER U WITH DIAERESIS - "uwangle", 0x029A7, // OBLIQUE ANGLE OPENING DOWN - NULL, 0 + {"Uacgr", 0x0038E}, // GREEK CAPITAL LETTER UPSILON WITH TONOS + {"uacgr", 0x003CD}, // GREEK SMALL LETTER UPSILON WITH TONOS + {"Uacute", 0x000DA}, // LATIN CAPITAL LETTER U WITH ACUTE + {"uacute", 0x000FA}, // LATIN SMALL LETTER U WITH ACUTE + {"uarr", 0x02191}, // UPWARDS ARROW + {"Uarr", 0x0219F}, // UPWARDS TWO HEADED ARROW + {"uArr", 0x021D1}, // UPWARDS DOUBLE ARROW + {"Uarrocir", 0x02949}, // UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE + {"Ubrcy", 0x0040E}, // CYRILLIC CAPITAL LETTER SHORT U + {"ubrcy", 0x0045E}, // CYRILLIC SMALL LETTER SHORT U + {"Ubreve", 0x0016C}, // LATIN CAPITAL LETTER U WITH BREVE + {"ubreve", 0x0016D}, // LATIN SMALL LETTER U WITH BREVE + {"Ucirc", 0x000DB}, // LATIN CAPITAL LETTER U WITH CIRCUMFLEX + {"ucirc", 0x000FB}, // LATIN SMALL LETTER U WITH CIRCUMFLEX + {"Ucy", 0x00423}, // CYRILLIC CAPITAL LETTER U + {"ucy", 0x00443}, // CYRILLIC SMALL LETTER U + {"udarr", 0x021C5}, // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW + {"Udblac", 0x00170}, // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + {"udblac", 0x00171}, // LATIN SMALL LETTER U WITH DOUBLE ACUTE + {"udhar", 0x0296E}, // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + {"udiagr", 0x003B0}, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + {"Udigr", 0x003AB}, // GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + {"udigr", 0x003CB}, // GREEK SMALL LETTER UPSILON WITH DIALYTIKA + {"ufisht", 0x0297E}, // UP FISH TAIL + {"Ufr", 0x1D518}, // MATHEMATICAL FRAKTUR CAPITAL U + {"ufr", 0x1D532}, // MATHEMATICAL FRAKTUR SMALL U + {"Ugr", 0x003A5}, // GREEK CAPITAL LETTER UPSILON + {"ugr", 0x003C5}, // GREEK SMALL LETTER UPSILON + {"Ugrave", 0x000D9}, // LATIN CAPITAL LETTER U WITH GRAVE + {"ugrave", 0x000F9}, // LATIN SMALL LETTER U WITH GRAVE + {"uHar", 0x02963}, // UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT + {"uharl", 0x021BF}, // UPWARDS HARPOON WITH BARB LEFTWARDS + {"uharr", 0x021BE}, // UPWARDS HARPOON WITH BARB RIGHTWARDS + {"uhblk", 0x02580}, // UPPER HALF BLOCK + {"ulcorn", 0x0231C}, // TOP LEFT CORNER + {"ulcorner", 0x0231C}, // TOP LEFT CORNER + {"ulcrop", 0x0230F}, // TOP LEFT CROP + {"ultri", 0x025F8}, // UPPER LEFT TRIANGLE + {"Umacr", 0x0016A}, // LATIN CAPITAL LETTER U WITH MACRON + {"umacr", 0x0016B}, // LATIN SMALL LETTER U WITH MACRON + {"uml", 0x000A8}, // DIAERESIS + {"UnderBar", 0x0005F}, // LOW LINE + {"UnderBrace", 0x023DF}, // BOTTOM CURLY BRACKET + {"UnderBracket", 0x023B5}, // BOTTOM SQUARE BRACKET + {"UnderParenthesis", 0x023DD}, // BOTTOM PARENTHESIS + {"Union", 0x022C3}, // N-ARY UNION + {"UnionPlus", 0x0228E}, // MULTISET UNION + {"Uogon", 0x00172}, // LATIN CAPITAL LETTER U WITH OGONEK + {"uogon", 0x00173}, // LATIN SMALL LETTER U WITH OGONEK + {"Uopf", 0x1D54C}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL U + {"uopf", 0x1D566}, // MATHEMATICAL DOUBLE-STRUCK SMALL U + {"uparrow", 0x02191}, // UPWARDS ARROW + {"UpArrow", 0x02191}, // UPWARDS ARROW + {"Uparrow", 0x021D1}, // UPWARDS DOUBLE ARROW + {"UpArrowBar", 0x02912}, // UPWARDS ARROW TO BAR + {"UpArrowDownArrow", 0x021C5}, // UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW + {"updownarrow", 0x02195}, // UP DOWN ARROW + {"UpDownArrow", 0x02195}, // UP DOWN ARROW + {"Updownarrow", 0x021D5}, // UP DOWN DOUBLE ARROW + {"UpEquilibrium", 0x0296E}, // UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT + {"upharpoonleft", 0x021BF}, // UPWARDS HARPOON WITH BARB LEFTWARDS + {"upharpoonright", 0x021BE}, // UPWARDS HARPOON WITH BARB RIGHTWARDS + {"uplus", 0x0228E}, // MULTISET UNION + {"UpperLeftArrow", 0x02196}, // NORTH WEST ARROW + {"UpperRightArrow", 0x02197}, // NORTH EAST ARROW + {"upsi", 0x003C5}, // GREEK SMALL LETTER UPSILON + {"Upsi", 0x003D2}, // GREEK UPSILON WITH HOOK SYMBOL + {"upsih", 0x003D2}, // GREEK UPSILON WITH HOOK SYMBOL + {"Upsilon", 0x003A5}, // GREEK CAPITAL LETTER UPSILON + {"upsilon", 0x003C5}, // GREEK SMALL LETTER UPSILON + {"UpTee", 0x022A5}, // UP TACK + {"UpTeeArrow", 0x021A5}, // UPWARDS ARROW FROM BAR + {"upuparrows", 0x021C8}, // UPWARDS PAIRED ARROWS + {"urcorn", 0x0231D}, // TOP RIGHT CORNER + {"urcorner", 0x0231D}, // TOP RIGHT CORNER + {"urcrop", 0x0230E}, // TOP RIGHT CROP + {"Uring", 0x0016E}, // LATIN CAPITAL LETTER U WITH RING ABOVE + {"uring", 0x0016F}, // LATIN SMALL LETTER U WITH RING ABOVE + {"urtri", 0x025F9}, // UPPER RIGHT TRIANGLE + {"Uscr", 0x1D4B0}, // MATHEMATICAL SCRIPT CAPITAL U + {"uscr", 0x1D4CA}, // MATHEMATICAL SCRIPT SMALL U + {"utdot", 0x022F0}, // UP RIGHT DIAGONAL ELLIPSIS + {"Utilde", 0x00168}, // LATIN CAPITAL LETTER U WITH TILDE + {"utilde", 0x00169}, // LATIN SMALL LETTER U WITH TILDE + {"utri", 0x025B5}, // WHITE UP-POINTING SMALL TRIANGLE + {"utrif", 0x025B4}, // BLACK UP-POINTING SMALL TRIANGLE + {"uuarr", 0x021C8}, // UPWARDS PAIRED ARROWS + {"Uuml", 0x000DC}, // LATIN CAPITAL LETTER U WITH DIAERESIS + {"uuml", 0x000FC}, // LATIN SMALL LETTER U WITH DIAERESIS + {"uwangle", 0x029A7}, // OBLIQUE ANGLE OPENING DOWN + {NULL, 0} }; static NameId namesV[]={ - "vangrt", 0x0299C, // RIGHT ANGLE VARIANT WITH SQUARE - "varepsilon", 0x003F5, // GREEK LUNATE EPSILON SYMBOL - "varkappa", 0x003F0, // GREEK KAPPA SYMBOL - "varnothing", 0x02205, // EMPTY SET - "varphi", 0x003D5, // GREEK PHI SYMBOL - "varpi", 0x003D6, // GREEK PI SYMBOL - "varpropto", 0x0221D, // PROPORTIONAL TO - "varr", 0x02195, // UP DOWN ARROW - "vArr", 0x021D5, // UP DOWN DOUBLE ARROW - "varrho", 0x003F1, // GREEK RHO SYMBOL - "varsigma", 0x003C2, // GREEK SMALL LETTER FINAL SIGMA -// "varsubsetneq", 0x0228A;0x0FE00, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "varsubsetneqq", 0x02ACB;0x0FE00, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -// "varsupsetneq", 0x0228B;0x0FE00, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "varsupsetneqq", 0x02ACC;0x0FE00, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - "vartheta", 0x003D1, // GREEK THETA SYMBOL - "vartriangleleft", 0x022B2, // NORMAL SUBGROUP OF - "vartriangleright", 0x022B3, // CONTAINS AS NORMAL SUBGROUP - "vBar", 0x02AE8, // SHORT UP TACK WITH UNDERBAR - "Vbar", 0x02AEB, // DOUBLE UP TACK - "vBarv", 0x02AE9, // SHORT UP TACK ABOVE SHORT DOWN TACK - "Vcy", 0x00412, // CYRILLIC CAPITAL LETTER VE - "vcy", 0x00432, // CYRILLIC SMALL LETTER VE - "vdash", 0x022A2, // RIGHT TACK - "vDash", 0x022A8, // TRUE - "Vdash", 0x022A9, // FORCES - "VDash", 0x022AB, // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE - "Vdashl", 0x02AE6, // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL - "vee", 0x02228, // LOGICAL OR - "Vee", 0x022C1, // N-ARY LOGICAL OR - "veebar", 0x022BB, // XOR - "veeeq", 0x0225A, // EQUIANGULAR TO - "vellip", 0x022EE, // VERTICAL ELLIPSIS - "verbar", 0x0007C, // VERTICAL LINE - "Verbar", 0x02016, // DOUBLE VERTICAL LINE - "vert", 0x0007C, // VERTICAL LINE - "Vert", 0x02016, // DOUBLE VERTICAL LINE - "VerticalBar", 0x02223, // DIVIDES - "VerticalLine", 0x0007C, // VERTICAL LINE - "VerticalSeparator", 0x02758, // LIGHT VERTICAL BAR - "VerticalTilde", 0x02240, // WREATH PRODUCT - "VeryThinSpace", 0x0200A, // HAIR SPACE - "Vfr", 0x1D519, // MATHEMATICAL FRAKTUR CAPITAL V - "vfr", 0x1D533, // MATHEMATICAL FRAKTUR SMALL V - "vltri", 0x022B2, // NORMAL SUBGROUP OF -// "vnsub", 0x02282;0x020D2, // SUBSET OF with vertical line -// "vnsup", 0x02283;0x020D2, // SUPERSET OF with vertical line - "Vopf", 0x1D54D, // MATHEMATICAL DOUBLE-STRUCK CAPITAL V - "vopf", 0x1D567, // MATHEMATICAL DOUBLE-STRUCK SMALL V - "vprop", 0x0221D, // PROPORTIONAL TO - "vrtri", 0x022B3, // CONTAINS AS NORMAL SUBGROUP - "Vscr", 0x1D4B1, // MATHEMATICAL SCRIPT CAPITAL V - "vscr", 0x1D4CB, // MATHEMATICAL SCRIPT SMALL V -// "vsubne", 0x0228A;0x0FE00, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "vsubnE", 0x02ACB;0x0FE00, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members -// "vsupne", 0x0228B;0x0FE00, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members -// "vsupnE", 0x02ACC;0x0FE00, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members - "Vvdash", 0x022AA, // TRIPLE VERTICAL BAR RIGHT TURNSTILE - "vzigzag", 0x0299A, // VERTICAL ZIGZAG LINE - NULL, 0 + {"vangrt", 0x0299C}, // RIGHT ANGLE VARIANT WITH SQUARE + {"varepsilon", 0x003F5}, // GREEK LUNATE EPSILON SYMBOL + {"varkappa", 0x003F0}, // GREEK KAPPA SYMBOL + {"varnothing", 0x02205}, // EMPTY SET + {"varphi", 0x003D5}, // GREEK PHI SYMBOL + {"varpi", 0x003D6}, // GREEK PI SYMBOL + {"varpropto", 0x0221D}, // PROPORTIONAL TO + {"varr", 0x02195}, // UP DOWN ARROW + {"vArr", 0x021D5}, // UP DOWN DOUBLE ARROW + {"varrho", 0x003F1}, // GREEK RHO SYMBOL + {"varsigma", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA +// "varsubsetneq", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members +// "varsubsetneqq", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members +// "varsupsetneq", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members +// "varsupsetneqq", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"vartheta", 0x003D1}, // GREEK THETA SYMBOL + {"vartriangleleft", 0x022B2}, // NORMAL SUBGROUP OF + {"vartriangleright", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP + {"vBar", 0x02AE8}, // SHORT UP TACK WITH UNDERBAR + {"Vbar", 0x02AEB}, // DOUBLE UP TACK + {"vBarv", 0x02AE9}, // SHORT UP TACK ABOVE SHORT DOWN TACK + {"Vcy", 0x00412}, // CYRILLIC CAPITAL LETTER VE + {"vcy", 0x00432}, // CYRILLIC SMALL LETTER VE + {"vdash", 0x022A2}, // RIGHT TACK + {"vDash", 0x022A8}, // TRUE + {"Vdash", 0x022A9}, // FORCES + {"VDash", 0x022AB}, // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE + {"Vdashl", 0x02AE6}, // LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL + {"vee", 0x02228}, // LOGICAL OR + {"Vee", 0x022C1}, // N-ARY LOGICAL OR + {"veebar", 0x022BB}, // XOR + {"veeeq", 0x0225A}, // EQUIANGULAR TO + {"vellip", 0x022EE}, // VERTICAL ELLIPSIS + {"verbar", 0x0007C}, // VERTICAL LINE + {"Verbar", 0x02016}, // DOUBLE VERTICAL LINE + {"vert", 0x0007C}, // VERTICAL LINE + {"Vert", 0x02016}, // DOUBLE VERTICAL LINE + {"VerticalBar", 0x02223}, // DIVIDES + {"VerticalLine", 0x0007C}, // VERTICAL LINE + {"VerticalSeparator", 0x02758}, // LIGHT VERTICAL BAR + {"VerticalTilde", 0x02240}, // WREATH PRODUCT + {"VeryThinSpace", 0x0200A}, // HAIR SPACE + {"Vfr", 0x1D519}, // MATHEMATICAL FRAKTUR CAPITAL V + {"vfr", 0x1D533}, // MATHEMATICAL FRAKTUR SMALL V + {"vltri", 0x022B2}, // NORMAL SUBGROUP OF +// "vnsub", 0x02282;0x020D2}, // SUBSET OF with vertical line +// "vnsup", 0x02283;0x020D2}, // SUPERSET OF with vertical line + {"Vopf", 0x1D54D}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL V + {"vopf", 0x1D567}, // MATHEMATICAL DOUBLE-STRUCK SMALL V + {"vprop", 0x0221D}, // PROPORTIONAL TO + {"vrtri", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP + {"Vscr", 0x1D4B1}, // MATHEMATICAL SCRIPT CAPITAL V + {"vscr", 0x1D4CB}, // MATHEMATICAL SCRIPT SMALL V +// "vsubne", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members +// "vsubnE", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members +// "vsupne", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members +// "vsupnE", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members + {"Vvdash", 0x022AA}, // TRIPLE VERTICAL BAR RIGHT TURNSTILE + {"vzigzag", 0x0299A}, // VERTICAL ZIGZAG LINE + {NULL, 0} }; static NameId namesW[]={ - "Wcirc", 0x00174, // LATIN CAPITAL LETTER W WITH CIRCUMFLEX - "wcirc", 0x00175, // LATIN SMALL LETTER W WITH CIRCUMFLEX - "wedbar", 0x02A5F, // LOGICAL AND WITH UNDERBAR - "wedge", 0x02227, // LOGICAL AND - "Wedge", 0x022C0, // N-ARY LOGICAL AND - "wedgeq", 0x02259, // ESTIMATES - "weierp", 0x02118, // SCRIPT CAPITAL P - "Wfr", 0x1D51A, // MATHEMATICAL FRAKTUR CAPITAL W - "wfr", 0x1D534, // MATHEMATICAL FRAKTUR SMALL W - "Wopf", 0x1D54E, // MATHEMATICAL DOUBLE-STRUCK CAPITAL W - "wopf", 0x1D568, // MATHEMATICAL DOUBLE-STRUCK SMALL W - "wp", 0x02118, // SCRIPT CAPITAL P - "wr", 0x02240, // WREATH PRODUCT - "wreath", 0x02240, // WREATH PRODUCT - "Wscr", 0x1D4B2, // MATHEMATICAL SCRIPT CAPITAL W - "wscr", 0x1D4CC, // MATHEMATICAL SCRIPT SMALL W - NULL, 0 + {"Wcirc", 0x00174}, // LATIN CAPITAL LETTER W WITH CIRCUMFLEX + {"wcirc", 0x00175}, // LATIN SMALL LETTER W WITH CIRCUMFLEX + {"wedbar", 0x02A5F}, // LOGICAL AND WITH UNDERBAR + {"wedge", 0x02227}, // LOGICAL AND + {"Wedge", 0x022C0}, // N-ARY LOGICAL AND + {"wedgeq", 0x02259}, // ESTIMATES + {"weierp", 0x02118}, // SCRIPT CAPITAL P + {"Wfr", 0x1D51A}, // MATHEMATICAL FRAKTUR CAPITAL W + {"wfr", 0x1D534}, // MATHEMATICAL FRAKTUR SMALL W + {"Wopf", 0x1D54E}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL W + {"wopf", 0x1D568}, // MATHEMATICAL DOUBLE-STRUCK SMALL W + {"wp", 0x02118}, // SCRIPT CAPITAL P + {"wr", 0x02240}, // WREATH PRODUCT + {"wreath", 0x02240}, // WREATH PRODUCT + {"Wscr", 0x1D4B2}, // MATHEMATICAL SCRIPT CAPITAL W + {"wscr", 0x1D4CC}, // MATHEMATICAL SCRIPT SMALL W + {NULL, 0} }; static NameId namesX[]={ - "xcap", 0x022C2, // N-ARY INTERSECTION - "xcirc", 0x025EF, // LARGE CIRCLE - "xcup", 0x022C3, // N-ARY UNION - "xdtri", 0x025BD, // WHITE DOWN-POINTING TRIANGLE - "Xfr", 0x1D51B, // MATHEMATICAL FRAKTUR CAPITAL X - "xfr", 0x1D535, // MATHEMATICAL FRAKTUR SMALL X - "Xgr", 0x0039E, // GREEK CAPITAL LETTER XI - "xgr", 0x003BE, // GREEK SMALL LETTER XI - "xharr", 0x027F7, // LONG LEFT RIGHT ARROW - "xhArr", 0x027FA, // LONG LEFT RIGHT DOUBLE ARROW - "Xi", 0x0039E, // GREEK CAPITAL LETTER XI - "xi", 0x003BE, // GREEK SMALL LETTER XI - "xlarr", 0x027F5, // LONG LEFTWARDS ARROW - "xlArr", 0x027F8, // LONG LEFTWARDS DOUBLE ARROW - "xmap", 0x027FC, // LONG RIGHTWARDS ARROW FROM BAR - "xnis", 0x022FB, // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE - "xodot", 0x02A00, // N-ARY CIRCLED DOT OPERATOR - "Xopf", 0x1D54F, // MATHEMATICAL DOUBLE-STRUCK CAPITAL X - "xopf", 0x1D569, // MATHEMATICAL DOUBLE-STRUCK SMALL X - "xoplus", 0x02A01, // N-ARY CIRCLED PLUS OPERATOR - "xotime", 0x02A02, // N-ARY CIRCLED TIMES OPERATOR - "xrarr", 0x027F6, // LONG RIGHTWARDS ARROW - "xrArr", 0x027F9, // LONG RIGHTWARDS DOUBLE ARROW - "Xscr", 0x1D4B3, // MATHEMATICAL SCRIPT CAPITAL X - "xscr", 0x1D4CD, // MATHEMATICAL SCRIPT SMALL X - "xsqcup", 0x02A06, // N-ARY SQUARE UNION OPERATOR - "xuplus", 0x02A04, // N-ARY UNION OPERATOR WITH PLUS - "xutri", 0x025B3, // WHITE UP-POINTING TRIANGLE - "xvee", 0x022C1, // N-ARY LOGICAL OR - "xwedge", 0x022C0, // N-ARY LOGICAL AND - NULL, 0 + {"xcap", 0x022C2}, // N-ARY INTERSECTION + {"xcirc", 0x025EF}, // LARGE CIRCLE + {"xcup", 0x022C3}, // N-ARY UNION + {"xdtri", 0x025BD}, // WHITE DOWN-POINTING TRIANGLE + {"Xfr", 0x1D51B}, // MATHEMATICAL FRAKTUR CAPITAL X + {"xfr", 0x1D535}, // MATHEMATICAL FRAKTUR SMALL X + {"Xgr", 0x0039E}, // GREEK CAPITAL LETTER XI + {"xgr", 0x003BE}, // GREEK SMALL LETTER XI + {"xharr", 0x027F7}, // LONG LEFT RIGHT ARROW + {"xhArr", 0x027FA}, // LONG LEFT RIGHT DOUBLE ARROW + {"Xi", 0x0039E}, // GREEK CAPITAL LETTER XI + {"xi", 0x003BE}, // GREEK SMALL LETTER XI + {"xlarr", 0x027F5}, // LONG LEFTWARDS ARROW + {"xlArr", 0x027F8}, // LONG LEFTWARDS DOUBLE ARROW + {"xmap", 0x027FC}, // LONG RIGHTWARDS ARROW FROM BAR + {"xnis", 0x022FB}, // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE + {"xodot", 0x02A00}, // N-ARY CIRCLED DOT OPERATOR + {"Xopf", 0x1D54F}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL X + {"xopf", 0x1D569}, // MATHEMATICAL DOUBLE-STRUCK SMALL X + {"xoplus", 0x02A01}, // N-ARY CIRCLED PLUS OPERATOR + {"xotime", 0x02A02}, // N-ARY CIRCLED TIMES OPERATOR + {"xrarr", 0x027F6}, // LONG RIGHTWARDS ARROW + {"xrArr", 0x027F9}, // LONG RIGHTWARDS DOUBLE ARROW + {"Xscr", 0x1D4B3}, // MATHEMATICAL SCRIPT CAPITAL X + {"xscr", 0x1D4CD}, // MATHEMATICAL SCRIPT SMALL X + {"xsqcup", 0x02A06}, // N-ARY SQUARE UNION OPERATOR + {"xuplus", 0x02A04}, // N-ARY UNION OPERATOR WITH PLUS + {"xutri", 0x025B3}, // WHITE UP-POINTING TRIANGLE + {"xvee", 0x022C1}, // N-ARY LOGICAL OR + {"xwedge", 0x022C0}, // N-ARY LOGICAL AND + {NULL, 0} }; static NameId namesY[]={ - "Yacute", 0x000DD, // LATIN CAPITAL LETTER Y WITH ACUTE - "yacute", 0x000FD, // LATIN SMALL LETTER Y WITH ACUTE - "YAcy", 0x0042F, // CYRILLIC CAPITAL LETTER YA - "yacy", 0x0044F, // CYRILLIC SMALL LETTER YA - "Ycirc", 0x00176, // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX - "ycirc", 0x00177, // LATIN SMALL LETTER Y WITH CIRCUMFLEX - "Ycy", 0x0042B, // CYRILLIC CAPITAL LETTER YERU - "ycy", 0x0044B, // CYRILLIC SMALL LETTER YERU - "yen", 0x000A5, // YEN SIGN - "Yfr", 0x1D51C, // MATHEMATICAL FRAKTUR CAPITAL Y - "yfr", 0x1D536, // MATHEMATICAL FRAKTUR SMALL Y - "YIcy", 0x00407, // CYRILLIC CAPITAL LETTER YI - "yicy", 0x00457, // CYRILLIC SMALL LETTER YI - "Yopf", 0x1D550, // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y - "yopf", 0x1D56A, // MATHEMATICAL DOUBLE-STRUCK SMALL Y - "Yscr", 0x1D4B4, // MATHEMATICAL SCRIPT CAPITAL Y - "yscr", 0x1D4CE, // MATHEMATICAL SCRIPT SMALL Y - "YUcy", 0x0042E, // CYRILLIC CAPITAL LETTER YU - "yucy", 0x0044E, // CYRILLIC SMALL LETTER YU - "yuml", 0x000FF, // LATIN SMALL LETTER Y WITH DIAERESIS - "Yuml", 0x00178, // LATIN CAPITAL LETTER Y WITH DIAERESIS - NULL, 0 + {"Yacute", 0x000DD}, // LATIN CAPITAL LETTER Y WITH ACUTE + {"yacute", 0x000FD}, // LATIN SMALL LETTER Y WITH ACUTE + {"YAcy", 0x0042F}, // CYRILLIC CAPITAL LETTER YA + {"yacy", 0x0044F}, // CYRILLIC SMALL LETTER YA + {"Ycirc", 0x00176}, // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + {"ycirc", 0x00177}, // LATIN SMALL LETTER Y WITH CIRCUMFLEX + {"Ycy", 0x0042B}, // CYRILLIC CAPITAL LETTER YERU + {"ycy", 0x0044B}, // CYRILLIC SMALL LETTER YERU + {"yen", 0x000A5}, // YEN SIGN + {"Yfr", 0x1D51C}, // MATHEMATICAL FRAKTUR CAPITAL Y + {"yfr", 0x1D536}, // MATHEMATICAL FRAKTUR SMALL Y + {"YIcy", 0x00407}, // CYRILLIC CAPITAL LETTER YI + {"yicy", 0x00457}, // CYRILLIC SMALL LETTER YI + {"Yopf", 0x1D550}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL Y + {"yopf", 0x1D56A}, // MATHEMATICAL DOUBLE-STRUCK SMALL Y + {"Yscr", 0x1D4B4}, // MATHEMATICAL SCRIPT CAPITAL Y + {"yscr", 0x1D4CE}, // MATHEMATICAL SCRIPT SMALL Y + {"YUcy", 0x0042E}, // CYRILLIC CAPITAL LETTER YU + {"yucy", 0x0044E}, // CYRILLIC SMALL LETTER YU + {"yuml", 0x000FF}, // LATIN SMALL LETTER Y WITH DIAERESIS + {"Yuml", 0x00178}, // LATIN CAPITAL LETTER Y WITH DIAERESIS + {NULL, 0} }; static NameId namesZ[]={ - "Zacute", 0x00179, // LATIN CAPITAL LETTER Z WITH ACUTE - "zacute", 0x0017A, // LATIN SMALL LETTER Z WITH ACUTE - "Zcaron", 0x0017D, // LATIN CAPITAL LETTER Z WITH CARON - "zcaron", 0x0017E, // LATIN SMALL LETTER Z WITH CARON - "Zcy", 0x00417, // CYRILLIC CAPITAL LETTER ZE - "zcy", 0x00437, // CYRILLIC SMALL LETTER ZE - "Zdot", 0x0017B, // LATIN CAPITAL LETTER Z WITH DOT ABOVE - "zdot", 0x0017C, // LATIN SMALL LETTER Z WITH DOT ABOVE - "zeetrf", 0x02128, // BLACK-LETTER CAPITAL Z - "ZeroWidthSpace", 0x0200B, // ZERO WIDTH SPACE - "Zeta", 0x00396, // GREEK CAPITAL LETTER ZETA - "zeta", 0x003B6, // GREEK SMALL LETTER ZETA - "Zfr", 0x02128, // BLACK-LETTER CAPITAL Z - "zfr", 0x1D537, // MATHEMATICAL FRAKTUR SMALL Z - "Zgr", 0x00396, // GREEK CAPITAL LETTER ZETA - "zgr", 0x003B6, // GREEK SMALL LETTER ZETA - "ZHcy", 0x00416, // CYRILLIC CAPITAL LETTER ZHE - "zhcy", 0x00436, // CYRILLIC SMALL LETTER ZHE - "zigrarr", 0x021DD, // RIGHTWARDS SQUIGGLE ARROW - "Zopf", 0x02124, // DOUBLE-STRUCK CAPITAL Z - "zopf", 0x1D56B, // MATHEMATICAL DOUBLE-STRUCK SMALL Z - "Zscr", 0x1D4B5, // MATHEMATICAL SCRIPT CAPITAL Z - "zscr", 0x1D4CF, // MATHEMATICAL SCRIPT SMALL Z - "zwj", 0x0200D, // ZERO WIDTH JOINER - "zwnj", 0x0200C, // ZERO WIDTH NON-JOINER - NULL, 0 + {"Zacute", 0x00179}, // LATIN CAPITAL LETTER Z WITH ACUTE + {"zacute", 0x0017A}, // LATIN SMALL LETTER Z WITH ACUTE + {"Zcaron", 0x0017D}, // LATIN CAPITAL LETTER Z WITH CARON + {"zcaron", 0x0017E}, // LATIN SMALL LETTER Z WITH CARON + {"Zcy", 0x00417}, // CYRILLIC CAPITAL LETTER ZE + {"zcy", 0x00437}, // CYRILLIC SMALL LETTER ZE + {"Zdot", 0x0017B}, // LATIN CAPITAL LETTER Z WITH DOT ABOVE + {"zdot", 0x0017C}, // LATIN SMALL LETTER Z WITH DOT ABOVE + {"zeetrf", 0x02128}, // BLACK-LETTER CAPITAL Z + {"ZeroWidthSpace", 0x0200B}, // ZERO WIDTH SPACE + {"Zeta", 0x00396}, // GREEK CAPITAL LETTER ZETA + {"zeta", 0x003B6}, // GREEK SMALL LETTER ZETA + {"Zfr", 0x02128}, // BLACK-LETTER CAPITAL Z + {"zfr", 0x1D537}, // MATHEMATICAL FRAKTUR SMALL Z + {"Zgr", 0x00396}, // GREEK CAPITAL LETTER ZETA + {"zgr", 0x003B6}, // GREEK SMALL LETTER ZETA + {"ZHcy", 0x00416}, // CYRILLIC CAPITAL LETTER ZHE + {"zhcy", 0x00436}, // CYRILLIC SMALL LETTER ZHE + {"zigrarr", 0x021DD}, // RIGHTWARDS SQUIGGLE ARROW + {"Zopf", 0x02124}, // DOUBLE-STRUCK CAPITAL Z + {"zopf", 0x1D56B}, // MATHEMATICAL DOUBLE-STRUCK SMALL Z + {"Zscr", 0x1D4B5}, // MATHEMATICAL SCRIPT CAPITAL Z + {"zscr", 0x1D4CF}, // MATHEMATICAL SCRIPT SMALL Z + {"zwj", 0x0200D}, // ZERO WIDTH JOINER + {"zwnj", 0x0200C}, // ZERO WIDTH NON-JOINER + {NULL, 0} }; // @todo@ order namesTable and names? by frequency diff --git a/dmd2/enum.c b/dmd2/enum.c index 1addb84459..9b665c712f 100644 --- a/dmd2/enum.c +++ b/dmd2/enum.c @@ -18,6 +18,7 @@ #include "expression.h" #include "module.h" #include "declaration.h" +#include "init.h" /********************************* EnumDeclaration ****************************/ @@ -33,7 +34,7 @@ EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype) #if IN_DMD sinit = NULL; #endif - isdeprecated = 0; + isdeprecated = false; isdone = 0; #if IN_DMD objFileDone = 0; @@ -56,6 +57,14 @@ Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s) else ed = new EnumDeclaration(loc, ident, t); ScopeDsymbol::syntaxCopy(ed); + if (isAnonymous()) + { + for (size_t i = 0; i < members->dim; i++) + { + EnumMember *em = (*members)[i]->isEnumMember(); + em->ed = ed; + } + } return ed; } @@ -66,6 +75,23 @@ void EnumDeclaration::setScope(Scope *sc) ScopeDsymbol::setScope(sc); } +int EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) +{ + if (!isAnonymous()) + return ScopeDsymbol::addMember(sc, sd, memnum); + + /* Anonymous enum members get added to enclosing scope. + */ + for (size_t i = 0; i < members->dim; i++) + { + EnumMember *em = (*members)[i]->isEnumMember(); + em->ed = this; + //printf("add %s\n", em->toChars()); + em->addMember(sc, sd, 1); + } + return 1; +} + void EnumDeclaration::semantic0(Scope *sc) { /* This function is a hack to get around a significant problem. @@ -105,7 +131,7 @@ void EnumDeclaration::semantic(Scope *sc) //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars()); //printf("EnumDeclaration::semantic() %s\n", toChars()); - if (!members) // enum ident; + if (!members && !memtype) // enum ident; return; if (!memtype && !isAnonymous()) @@ -130,7 +156,7 @@ void EnumDeclaration::semantic(Scope *sc) unsigned dprogress_save = Module::dprogress; if (sc->stc & STCdeprecated) - isdeprecated = 1; + isdeprecated = true; userAttributes = sc->userAttributes; parent = sc->parent; @@ -161,6 +187,11 @@ void EnumDeclaration::semantic(Scope *sc) return; } } + if (memtype->ty == Tvoid) + { + error("base type must not be void"); + memtype = Type::terror; + } #if 0 // Decided to abandon this restriction for D 2.0 if (!memtype->isintegral()) { error("base type must be of integral type, not %s", memtype->toChars()); @@ -170,6 +201,10 @@ void EnumDeclaration::semantic(Scope *sc) } isdone = 1; + + if (!members) // enum ident : memtype; + return; + Module::dprogress++; type = type->semantic(loc, sc); @@ -181,6 +216,26 @@ void EnumDeclaration::semantic(Scope *sc) } if (members->dim == 0) error("enum %s must have at least one member", toChars()); + + ScopeDsymbol *scopesym; + if (isAnonymous()) + { + /* Anonymous enum members get added to enclosing scope. + */ + for (Scope *sct = sce; sct; sct = sct->enclosing) + { + if (sct->scopesym) + { + scopesym = sct->scopesym; + if (!sct->scopesym->symtab) + sct->scopesym->symtab = new DsymbolTable(); + break; + } + } + } + else + scopesym = this; + int first = 1; Expression *elast = NULL; for (size_t i = 0; i < members->dim; i++) @@ -202,7 +257,7 @@ void EnumDeclaration::semantic(Scope *sc) if (e) { assert(e->dyncast() == DYNCAST_EXPRESSION); - e = e->semantic(sce); + e = e->ctfeSemantic(sce); e = e->ctfeInterpret(); if (memtype) { @@ -236,13 +291,20 @@ void EnumDeclaration::semantic(Scope *sc) if (!isAnonymous()) e = e->castTo(sce, type); } + else if (memtype && memtype == Type::terror) + { + e = new ErrorExp(); + minval = e; + maxval = e; + defaultval = e; + } else { // Lazily evaluate enum.max if (!emax) { - emax = t->getProperty(0, Id::max); - emax = emax->semantic(sce); + emax = t->getProperty(Loc(), Id::max, 0); + emax = emax->ctfeSemantic(sce); emax = emax->ctfeInterpret(); } @@ -250,14 +312,14 @@ void EnumDeclaration::semantic(Scope *sc) // But first check that (elast != t.max) assert(elast); e = new EqualExp(TOKequal, em->loc, elast, emax); - e = e->semantic(sce); + e = e->ctfeSemantic(sce); e = e->ctfeInterpret(); if (e->toInteger()) error("overflow of enum value %s", elast->toChars()); // Now set e to (elast + 1) e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32)); - e = e->semantic(sce); + e = e->ctfeSemantic(sce); e = e->castTo(sce, elast->type); e = e->ctfeInterpret(); @@ -265,7 +327,7 @@ void EnumDeclaration::semantic(Scope *sc) { // Check that e != elast (not always true for floats) Expression *etest = new EqualExp(TOKequal, em->loc, e, elast); - etest = etest->semantic(sce); + etest = etest->ctfeSemantic(sce); etest = etest->ctfeInterpret(); if (etest->toInteger()) error("enum member %s has inexact value, due to loss of precision", em->toChars()); @@ -275,29 +337,22 @@ void EnumDeclaration::semantic(Scope *sc) em->value = e; // Add to symbol table only after evaluating 'value' - if (isAnonymous()) + if (isAnonymous() && !sc->func) { - /* Anonymous enum members get added to enclosing scope. - */ - for (Scope *sct = sce; sct; sct = sct->enclosing) - { - if (sct->scopesym) - { - if (!sct->scopesym->symtab) - sct->scopesym->symtab = new DsymbolTable(); - em->addMember(sce, sct->scopesym, 1); - break; - } - } + // already inserted to enclosing scope in addMember + assert(em->ed); } else - em->addMember(sc, this, 1); + { + em->ed = this; + em->addMember(sc, scopesym, 1); + } /* Compute .min, .max and .default values. * If enum doesn't have a name, we can never identify the enum type, * so there is no purpose for a .min, .max or .default */ - if (!isAnonymous()) + if (!isAnonymous() && memtype != Type::terror) { if (first) { defaultval = e; @@ -315,13 +370,13 @@ void EnumDeclaration::semantic(Scope *sc) // Compute if(e < minval) ec = new CmpExp(TOKlt, em->loc, e, minval); - ec = ec->semantic(sce); + ec = ec->ctfeSemantic(sce); ec = ec->ctfeInterpret(); if (ec->toInteger()) minval = e; ec = new CmpExp(TOKgt, em->loc, e, maxval); - ec = ec->semantic(sce); + ec = ec->ctfeSemantic(sce); ec = ec->ctfeInterpret(); if (ec->toInteger()) maxval = e; @@ -390,7 +445,7 @@ const char *EnumDeclaration::kind() return "enum"; } -int EnumDeclaration::isDeprecated() +bool EnumDeclaration::isDeprecated() { return isdeprecated; } @@ -417,9 +472,11 @@ Dsymbol *EnumDeclaration::search(Loc loc, Identifier *ident, int flags) EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *type) : Dsymbol(id) { + this->ed = NULL; this->value = value; this->type = type; this->loc = loc; + this->vd = NULL; } Dsymbol *EnumMember::syntaxCopy(Dsymbol *s) @@ -462,4 +519,26 @@ const char *EnumMember::kind() return "enum member"; } +void EnumMember::semantic(Scope *sc) +{ + assert(ed); + if (this->vd) return; + ed->semantic(sc); + assert(value); + vd = new VarDeclaration(loc, type, ident, new ExpInitializer(loc, value->copy())); + vd->storage_class = STCmanifest; + vd->semantic(sc); + + vd->protection = ed->isAnonymous() ? ed->protection : PROTpublic; + vd->parent = ed->isAnonymous() ? ed->parent : ed; + vd->userAttributes = ed->isAnonymous() ? ed->userAttributes : NULL; +} + +Expression *EnumMember::getVarExp(Loc loc, Scope *sc) +{ + semantic(sc); + assert(vd); + Expression *e = new VarExp(loc, vd); + return e->semantic(sc); +} diff --git a/dmd2/enum.h b/dmd2/enum.h index 165f535699..b9e2255c5a 100644 --- a/dmd2/enum.h +++ b/dmd2/enum.h @@ -22,7 +22,7 @@ struct Identifier; struct Type; struct Expression; struct HdrGenState; - +struct VarDeclaration; struct EnumDeclaration : ScopeDsymbol { /* enum ident : memtype { ... } @@ -40,15 +40,13 @@ struct EnumDeclaration : ScopeDsymbol Expression *minval; Expression *defaultval; // default initializer #endif - int isdeprecated; + bool isdeprecated; int isdone; // 0: not done // 1: semantic() successfully completed -#ifdef IN_GCC - Expressions *attributes; // GCC decl/type attributes -#endif EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); + int addMember(Scope *sc, ScopeDsymbol *sd, int memnum); void setScope(Scope *sc); void semantic0(Scope *sc); void semantic(Scope *sc); @@ -59,7 +57,7 @@ struct EnumDeclaration : ScopeDsymbol #if DMDV2 Dsymbol *search(Loc, Identifier *ident, int flags); #endif - int isDeprecated(); // is Dsymbol deprecated? + bool isDeprecated(); // is Dsymbol deprecated? void emitComment(Scope *sc); void toJson(JsonOut *json); @@ -85,13 +83,17 @@ struct EnumDeclaration : ScopeDsymbol struct EnumMember : Dsymbol { + EnumDeclaration *ed; Expression *value; Type *type; + VarDeclaration *vd; EnumMember(Loc loc, Identifier *id, Expression *value, Type *type); Dsymbol *syntaxCopy(Dsymbol *s); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); const char *kind(); + void semantic(Scope *sc); + Expression *getVarExp(Loc loc, Scope *sc); void emitComment(Scope *sc); void toJson(JsonOut *json); diff --git a/dmd2/expression.c b/dmd2/expression.c index c60814d12b..18406d87a3 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -21,14 +21,13 @@ #endif #if _WIN32 && __DMC__ -extern "C" char * __cdecl __locale_decpoint; +extern "C" const char * __cdecl __locale_decpoint; #endif #include "rmem.h" #include "port.h" -#if IN_DMD #include "root.h" -#endif +#include "target.h" #include "mtype.h" #include "init.h" @@ -53,6 +52,7 @@ extern "C" char * __cdecl __locale_decpoint; Expression *createTypeInfoArray(Scope *sc, Expression *args[], size_t dim); #endif Expression *expandVar(int result, VarDeclaration *v); +void functionToCBuffer2(TypeFunction *t, OutBuffer *buf, HdrGenState *hgs, int mod, const char *kind); #define LOGSEMANTIC 0 @@ -163,11 +163,12 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, */ FuncDeclaration *hasThis(Scope *sc) -{ FuncDeclaration *fd; - FuncDeclaration *fdthis; - +{ //printf("hasThis()\n"); - fdthis = sc->parent->isFuncDeclaration(); + Dsymbol *p = sc->parent; + while (p && p->isTemplateMixin()) + p = p->parent; + FuncDeclaration *fdthis = p ? p->isFuncDeclaration() : NULL; //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); /* Special case for inside template constraint @@ -180,7 +181,7 @@ FuncDeclaration *hasThis(Scope *sc) } // Go upwards until we find the enclosing member function - fd = fdthis; + FuncDeclaration *fd = fdthis; while (1) { if (!fd) @@ -216,33 +217,86 @@ Lno: return NULL; // don't have 'this' available } +bool isNeedThisScope(Scope *sc, Declaration *d) +{ + if (sc->intypeof == 1) + return false; + + AggregateDeclaration *ad = d->isThis(); + if (!ad) + return false; + //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars()); + + for (Dsymbol *s = sc->parent; s; s = s->toParent2()) + { + //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2()); + if (AggregateDeclaration *ad2 = s->isAggregateDeclaration()) + { + //printf("\t ad2 = %s\n", ad2->toChars()); + if (ad2 == ad) + return false; + else if (ad2->isNested()) + continue; + else + return true; + } + if (FuncDeclaration *f = s->isFuncDeclaration()) + { + if (f->isFuncLiteralDeclaration()) + continue; + if (f->isMember2()) + break; + if (TemplateDeclaration *td = f->parent->isTemplateDeclaration()) + { + if ((td->scope->stc & STCstatic) && td->isMember()) + break; // no valid 'this' + } + } + } + return true; +} + +Expression *checkRightThis(Scope *sc, Expression *e) +{ + if (e->op == TOKvar && e->type->ty != Terror) + { + VarExp *ve = (VarExp *)e; + if (isNeedThisScope(sc, ve->var)) + { + //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n", + // sc->intypeof, sc->getStructClassScope(), func, fdthis); + e->error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars()); + e = new ErrorExp(); + } + } + return e; +} + /*************************************** * Pull out any properties. */ -Expression *resolveProperties(Scope *sc, Expression *e) +Expression *resolvePropertiesX(Scope *sc, Expression *e) { - //printf("resolveProperties(%s)\n", e->toChars()); - TemplateDeclaration *td; - Objects *targsi; - Expression *ethis; + Objects *tiargs; + Type *tthis; if (e->op == TOKdotti) { DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e; td = dti->getTempdecl(sc); dti->ti->semanticTiargs(sc); - targsi = dti->ti->tiargs; - ethis = dti->e1; + tiargs = dti->ti->tiargs; + tthis = dti->e1->type; goto L1; } else if (e->op == TOKdottd) { DotTemplateExp *dte = (DotTemplateExp *)e; td = dte->td; - targsi = NULL; - ethis = dte->e1; + tiargs = NULL; + tthis = dte->e1->type; goto L1; } else if (e->op == TOKimport) @@ -251,20 +305,30 @@ Expression *resolveProperties(Scope *sc, Expression *e) td = s->isTemplateDeclaration(); if (td) { - targsi = NULL; - ethis = NULL; + tiargs = NULL; + tthis = NULL; + goto L1; + } + TemplateInstance *ti = s->isTemplateInstance(); + if (ti && !ti->semanticRun) + { + //assert(ti->needsTypeInference(sc)); + td = ti->tempdecl; + ti->semanticTiargs(sc); + tiargs = ti->tiargs; + tthis = NULL; goto L1; } } else if (e->op == TOKtemplate) { td = ((TemplateExp *)e)->td; - targsi = NULL; - ethis = NULL; + tiargs = NULL; + tthis = NULL; L1: assert(td); unsigned errors = global.startGagging(); - FuncDeclaration *fd = td->deduceFunctionTemplate(sc, e->loc, targsi, ethis, NULL, 1); + FuncDeclaration *fd = resolveFuncCall(e->loc, sc, td, tiargs, tthis, NULL, 1); if (global.endGagging(errors)) fd = NULL; // eat "is not a function template" error if (fd && fd->type) @@ -300,7 +364,8 @@ Expression *resolveProperties(Scope *sc, Expression *e) /* Look for e being a lazy parameter; rewrite as delegate call */ else if (e->op == TOKvar) - { VarExp *ve = (VarExp *)e; + { + VarExp *ve = (VarExp *)e; if (ve->var->storage_class & STClazy) { @@ -326,6 +391,15 @@ return_expr: return e; } +Expression *resolveProperties(Scope *sc, Expression *e) +{ + //printf("resolveProperties(%s)\n", e->toChars()); + + e = resolvePropertiesX(sc, e); + e = checkRightThis(sc, e); + return e; +} + /****************************** * Check the tail CallExp is really property function call. */ @@ -362,136 +436,251 @@ void checkPropertyCall(Expression *e, Expression *emsg) } } + +/****************************** + * Find symbol in accordance with the UFCS name look up rule + */ + +Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident) +{ + Loc loc = ue->loc; + Dsymbol *s = NULL; + + for (Scope *scx = sc; scx; scx = scx->enclosing) + { + if (!scx->scopesym) + continue; + s = scx->scopesym->search(loc, ident, 0); + if (s) + { + // overload set contains only module scope symbols. + if (s->isOverloadSet()) + break; + // selective/renamed imports also be picked up + if (AliasDeclaration *ad = s->isAliasDeclaration()) + { + if (ad->import) + break; + } + // See only module scope symbols for UFCS target. + Dsymbol *p = s->toParent2(); + if (p && p->isModule()) + break; + } + s = NULL; + } + if (!s) + return ue->e1->type->Type::getProperty(loc, ident, 0); + + FuncDeclaration *f = s->isFuncDeclaration(); + if (f) + { TemplateDeclaration *tempdecl = getFuncTemplateDecl(f); + if (tempdecl) + { + if (tempdecl->overroot) + tempdecl = tempdecl->overroot; + s = tempdecl; + } + } + + if (ue->op == TOKdotti) + { + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue; + TemplateDeclaration *td = s->toAlias()->isTemplateDeclaration(); + if (!td) + { s->error(loc, "is not a template"); + return new ErrorExp(); + } + if (!dti->ti->semanticTiargs(sc)) + return new ErrorExp(); + return new ScopeExp(loc, new TemplateInstance(loc, td, dti->ti->tiargs)); + } + else + { + return new DsymbolExp(loc, s, 1); + } +} + +/****************************** + * Pull out callable entity with UFCS. + */ + +Expression *resolveUFCS(Scope *sc, CallExp *ce) +{ + Loc loc = ce->loc; + Expression *eleft; + Expression *e; + + if (ce->e1->op == TOKdot) + { + DotIdExp *die = (DotIdExp *)ce->e1; + Identifier *ident = die->ident; + + Expression *ex = die->semanticX(sc); + if (ex != die) + { ce->e1 = ex; + return NULL; + } + eleft = die->e1; + + Type *t = eleft->type->toBasetype(); + if (t->ty == Tarray || t->ty == Tsarray || + t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid)) + { + /* Built-in types and arrays have no callable properties, so do shortcut. + * It is necessary in: e.init() + */ + } +#if 1 + else if (t->ty == Taarray) + { + if (ident == Id::remove) + { + /* Transform: + * aa.remove(arg) into delete aa[arg] + */ + if (!ce->arguments || ce->arguments->dim != 1) + { ce->error("expected key as argument to aa.remove()"); + return new ErrorExp(); + } + if (!eleft->type->isMutable()) + { ce->error("cannot remove key from %s associative array %s", + MODtoChars(t->mod), eleft->toChars()); + return new ErrorExp(); + } + Expression *key = (*ce->arguments)[0]; + key = key->semantic(sc); + key = resolveProperties(sc, key); + + TypeAArray *taa = (TypeAArray *)t; + key = key->implicitCastTo(sc, taa->index); + + if (!key->rvalue()) + return new ErrorExp(); + + return new RemoveExp(loc, eleft, key); + } + else if (ident == Id::apply || ident == Id::applyReverse) + { + return NULL; + } + else + { TypeAArray *taa = (TypeAArray *)t; + assert(taa->ty == Taarray); + StructDeclaration *sd = taa->getImpl(); + Dsymbol *s = sd->search(Loc(), ident, 2); + if (s) + return NULL; + } + } +#endif + else + { + if (Expression *ey = die->semanticY(sc, 1)) + { ce->e1 = ey; + return NULL; + } + } + e = searchUFCS(sc, die, ident); + } + else if (ce->e1->op == TOKdotti) + { + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1; + if (Expression *ey = dti->semanticY(sc, 1)) + { ce->e1 = ey; + return NULL; + } + eleft = dti->e1; + e = searchUFCS(sc, dti, dti->ti->name); + } + else + return NULL; + + // Rewrite + ce->e1 = e; + if (!ce->arguments) + ce->arguments = new Expressions(); + ce->arguments->shift(eleft); + + return NULL; +} + /****************************** * Pull out property with UFCS. */ Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL) { - Expression *e = NULL; - Expression *eleft; - Identifier *ident; - Objects* tiargs; Loc loc = e1->loc; + Expression *eleft; + Expression *e; if (e1->op == TOKdot) { DotIdExp *die = (DotIdExp *)e1; - eleft = die->e1; - ident = die->ident; - tiargs = NULL; - goto L1; + eleft = die->e1; + e = searchUFCS(sc, die, die->ident); } else if (e1->op == TOKdotti) { DotTemplateInstanceExp *dti; dti = (DotTemplateInstanceExp *)e1; - eleft = dti->e1; - ident = dti->ti->name; - tiargs = dti->ti->tiargs; - L1: - /* .ident - * .ident!tiargs - */ - e = new IdentifierExp(loc, Id::empty); - if (tiargs) - e = new DotTemplateInstanceExp(loc, e, ident, tiargs); - else - e = new DotIdExp(loc, e, ident); - - if (e2) - { - // run semantic without gagging - e2 = e2->semantic(sc); - - /* .f(e1) = e2 - */ - Expression *ex = e->syntaxCopy(); - Expressions *a1 = new Expressions(); - a1->setDim(1); - (*a1)[0] = eleft; - ex = new CallExp(loc, ex, a1); - ex = ex->trySemantic(sc); - - /* .f(e1, e2) - */ - Expressions *a2 = new Expressions(); - a2->setDim(2); - (*a2)[0] = eleft; - (*a2)[1] = e2; - e = new CallExp(loc, e, a2); - if (ex) - { // if fallback setter exists, gag errors - e = e->trySemantic(sc); - if (!e) - { checkPropertyCall(ex, e1); - ex = new AssignExp(loc, ex, e2); - return ex->semantic(sc); - } - } - else - { // strict setter prints errors if fails - e = e->semantic(sc); - } - checkPropertyCall(e, e1); - return e; - } - else - { - /* .f(e1) - */ - Expressions *arguments = new Expressions(); - arguments->setDim(1); - (*arguments)[0] = eleft; - e = new CallExp(loc, e, arguments); - e = e->semantic(sc); - checkPropertyCall(e, e1); - return e->semantic(sc); - } + eleft = dti->e1; + e = searchUFCS(sc, dti, dti->ti->name); } - return e; -} + else + return NULL; -/********************************* - * Attempt to find a type property. If failed, attempt to find - * UFCS property. If UFCS found, return expression. Otherwise - * show type property error message. - * Returns non-NULL only if UFCS property found. - */ -Expression * resolveProperty(Scope *sc, Expression **e1, Expression *e2) -{ - enum TOK op = (*e1)->op; - UnaExp *una = (UnaExp *)(*e1); - Type *t = una->e1->type; - int olderrors = global.errors; - una->e1 = una->e1->semantic(sc); - if (global.errors == olderrors && una->e1->type) + // Rewrite + if (e2) { - unsigned errors = global.startGagging(); - // try property gagged - if (op == TOKdotti) - *e1 = ((DotTemplateInstanceExp *)una)->semantic(sc, 1); - else if (op == TOKdot) - *e1 = ((DotIdExp *)una)->semantic(sc, 1); + // run semantic without gagging + e2 = e2->semantic(sc); - if (global.endGagging(errors) || (*e1)->op == TOKerror) - { - (*e1)->op = op; - errors = global.startGagging(); // try UFCS gagged - Expression *e = resolveUFCSProperties(sc, una, e2); - if (!global.endGagging(errors) && (*e1)->op != TOKerror) - return e; // found UFCS + /* f(e1) = e2 + */ + Expression *ex = e->copy(); + Expressions *a1 = new Expressions(); + a1->setDim(1); + (*a1)[0] = eleft; + ex = new CallExp(loc, ex, a1); + ex = ex->trySemantic(sc); - // try property non-gagged - una->type = t; // restore type - if (op == TOKdotti) - *e1 = ((DotTemplateInstanceExp *)una)->semantic(sc, 1); - else if (op == TOKdot) - *e1 = ((DotIdExp *)una)->semantic(sc, 1); + /* f(e1, e2) + */ + Expressions *a2 = new Expressions(); + a2->setDim(2); + (*a2)[0] = eleft; + (*a2)[1] = e2; + e = new CallExp(loc, e, a2); + if (ex) + { // if fallback setter exists, gag errors + e = e->trySemantic(sc); + if (!e) + { checkPropertyCall(ex, e1); + ex = new AssignExp(loc, ex, e2); + return ex->semantic(sc); + } } + else + { // strict setter prints errors if fails + e = e->semantic(sc); + } + checkPropertyCall(e, e1); + return e; + } + else + { + /* f(e1) + */ + Expressions *arguments = new Expressions(); + arguments->setDim(1); + (*arguments)[0] = eleft; + e = new CallExp(loc, e, arguments); + e = e->semantic(sc); + checkPropertyCall(e, e1); + return e->semantic(sc); } - - return NULL; } /****************************** @@ -566,12 +755,13 @@ void expandTuples(Expressions *exps) // Inline expand all the tuples while (arg->op == TOKtuple) - { TupleExp *te = (TupleExp *)arg; - + { + TupleExp *te = (TupleExp *)arg; exps->remove(i); // remove arg exps->insert(i, te->exps); // replace with tuple contents if (i == exps->dim) return; // empty tuple, no more arguments + (*exps)[i] = Expression::combine(te->e0, (*exps)[i]); arg = (*exps)[i]; } } @@ -689,21 +879,46 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt */ //printf("arrayExpressionToCommonType()\n"); IntegerExp integerexp(0); - CondExp condexp(0, &integerexp, NULL, NULL); + CondExp condexp(Loc(), &integerexp, NULL, NULL); Type *t0 = NULL; Expression *e0; size_t j0; for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; - + { + Expression *e = (*exps)[i]; e = resolveProperties(sc, e); if (!e->type) { e->error("%s has no value", e->toChars()); e = new ErrorExp(); } - e = callCpCtor(e->loc, sc, e, 1); + if (Expression *ex = e->isTemp()) + e = ex; + if (e->isLvalue()) + { + e = callCpCtor(e->loc, sc, e, 1); + } + else + { + Type *tb = e->type->toBasetype(); + if (tb->ty == Tsarray) + { + e = callCpCtor(e->loc, sc, e, 1); + } + else if (tb->ty == Tstruct) + { + if (e->op == TOKcall && !e->isLvalue()) + { + valueNoDtor(e); + } + else + { /* Not transferring it, so call the copy constructor + */ + e = callCpCtor(e->loc, sc, e, 1); + } + } + } if (t0) { if (t0 != e->type) @@ -788,6 +1003,9 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) arg = resolveProperties(sc, arg); (*exps)[i] = arg; + if (arg->op == TOKtype) + arg->error("%s is not an expression", arg->toChars()); + //arg->rvalue(); } } @@ -829,23 +1047,47 @@ void valueNoDtor(Expression *e) } /******************************************** - * Determine if t is an array of structs that need a postblit. + * Determine if t is an array of structs that need a default construction. */ #if DMDV2 -int checkPostblit(Loc loc, Type *t) +bool checkDefCtor(Loc loc, Type *t) { t = t->toBasetype(); while (t->ty == Tsarray) t = t->nextOf()->toBasetype(); if (t->ty == Tstruct) - { FuncDeclaration *fd = ((TypeStruct *)t)->sym->postblit; - if (fd) - { if (fd->storage_class & STCdisable) - fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); - return 1; + { + StructDeclaration *sd = ((TypeStruct *)t)->sym; + if (sd->noDefaultCtor) + { + sd->error(loc, "default construction is disabled"); + return true; } } - return 0; + return false; +} +#endif + +/******************************************** + * Determine if t is an array of structs that need a postblit. + */ +#if DMDV2 +bool checkPostblit(Loc loc, Type *t) +{ + t = t->toBasetype(); + while (t->ty == Tsarray) + t = t->nextOf()->toBasetype(); + if (t->ty == Tstruct) + { + StructDeclaration *sd = ((TypeStruct *)t)->sym; + if (sd->postblit) + { + if (sd->postblit->storage_class & STCdisable) + sd->error(loc, "is not copyable because it is annotated with @disable"); + return true; + } + } + return false; } #endif @@ -883,7 +1125,7 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) * directly onto the stack. */ Identifier *idtmp = Lexer::uniqueId("__cpcttmp"); - VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); + VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(Loc(), e)); tmp->storage_class |= STCctfe; tmp->noscope = noscope; Expression *ae = new DeclarationExp(loc, tmp); @@ -910,7 +1152,7 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) */ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, - Expression *ethis, Expressions *arguments, FuncDeclaration *fd) + Type *tthis, Expressions *arguments, FuncDeclaration *fd) { //printf("functionParameters()\n"); assert(arguments); @@ -936,13 +1178,14 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, fd->functionSemantic3(); } } + bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration(); size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) unsigned wildmatch = 0; - if (ethis && tf->isWild()) + if (tthis && tf->isWild() && !isCtorCall) { - Type *t = ethis->type; + Type *t = tthis; if (t->isWild()) wildmatch |= MODwild; else if (t->isConst()) @@ -979,7 +1222,8 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arg = p->defaultArg; arg = arg->inlineCopy(sc); #if DMDV2 - arg = arg->resolveLoc(loc, sc); // __FILE__ and __LINE__ + // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ + arg = arg->resolveLoc(loc, sc); #endif arguments->push(arg); nargs++; @@ -1036,7 +1280,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, v->parent = sc->parent; //sc->insert(v); - Expression *c = new DeclarationExp(0, v); + Expression *c = new DeclarationExp(Loc(), v); c->type = v->type; for (size_t u = i; u < nargs; u++) @@ -1156,6 +1400,8 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Type *t = arg->type; if (!t->isMutable() || !t->isAssignable()) // check blit assignable arg->error("cannot modify struct %s with immutable members", arg->toChars()); + else + checkDefCtor(arg->loc, t); arg = arg->toLvalue(sc, arg); } else if (p->storageClass & STClazy) @@ -1164,6 +1410,8 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } else { + if (Expression *e = arg->isTemp()) + arg = e; Type *tb = arg->type->toBasetype(); if (tb->ty == Tsarray) { @@ -1307,7 +1555,29 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } #endif Type *tret = tf->next; - if (wildmatch) + if (isCtorCall) + { + //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(), + // wildmatch, tf->isWild(), fd->isolateReturn()); + if (!tthis) + { assert(sc->intypeof || global.errors); + tthis = fd->isThis()->type->addMod(fd->type->mod); + } + if (tf->isWild() && !fd->isolateReturn()) + { + if (wildmatch) + tret = tret->substWildTo(wildmatch); + if (!tret->implicitConvTo(tthis)) + { + const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars(); + const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars(); + ::error(loc, "inout constructor %s creates%s object, not%s", + fd->toPrettyChars(), s1, s2); + } + } + tret = tthis; + } + else if (wildmatch) { /* Adjust function return type based on wildmatch */ //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars()); @@ -1379,7 +1649,7 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h { Expression *e = (*arguments)[i]; if (i) - buf->writeByte(','); + buf->writestring(", "); argbuf.reset(); e->type->toCBuffer2(&argbuf, hgs, 0); buf->write(&argbuf); @@ -1390,7 +1660,6 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h /******************************** Expression **************************/ Expression::Expression(Loc loc, enum TOK op, int size) - : loc(loc) { //printf("Expression::Expression(op = %d) this = %p\n", op, this); this->loc = loc; @@ -1404,6 +1673,21 @@ Expression::Expression(Loc loc, enum TOK op, int size) #endif } +Expression *EXP_CANT_INTERPRET; +Expression *EXP_CONTINUE_INTERPRET; +Expression *EXP_BREAK_INTERPRET; +Expression *EXP_GOTO_INTERPRET; +Expression *EXP_VOID_INTERPRET; + +void Expression::init() +{ + EXP_CANT_INTERPRET = new ErrorExp(); + EXP_CONTINUE_INTERPRET = new ErrorExp(); + EXP_BREAK_INTERPRET = new ErrorExp(); + EXP_GOTO_INTERPRET = new ErrorExp(); + EXP_VOID_INTERPRET = new ErrorExp(); +} + Expression *Expression::syntaxCopy() { //printf("Expression::syntaxCopy()\n"); @@ -1421,7 +1705,7 @@ Expression *Expression::copy() if (!size) { #ifdef DEBUG - fprintf(stdmsg, "No expression copy for: %s\n", toChars()); + fprintf(stderr, "No expression copy for: %s\n", toChars()); printf("op = %d\n", op); dump(0); #endif @@ -1467,10 +1751,33 @@ Expression *Expression::trySemantic(Scope *sc) return e; } +/********************************** + * Shortcut to run semantic with purity and + * safety checking disabled for the immediate + * expressions + */ + +Expression *Expression::ctfeSemantic(Scope *sc) +{ + if (sc) + { + assert(sc->needctfe >= 0); + sc->needctfe++; + Expression *e = semantic(sc); + sc->needctfe--; + assert(sc->needctfe >= 0); + return e; + } + else + { + return semantic(sc); + } +} + void Expression::print() { - fprintf(stdmsg, "%s\n", toChars()); - fflush(stdmsg); + fprintf(stderr, "%s\n", toChars()); + fflush(stderr); } char *Expression::toChars() @@ -1764,8 +2071,9 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f) } // Find the closest pure parent of the called function - if (getFuncTemplateDecl(f)) - { // The closest pure parent of instantiated template function is + if (getFuncTemplateDecl(f) && + f->parent->isTemplateInstance()->enclosing == NULL) + { // The closest pure parent of instantiated non-nested template function is // always itself. if (!f->isPure() && outerfunc->setImpure()) error("pure function '%s' cannot call impure function '%s'", @@ -1806,7 +2114,8 @@ void Expression::checkPurity(Scope *sc, FuncDeclaration *f) // If the caller has a pure parent, then either the called func must be pure, // OR, they must have the same pure parent. if (/*outerfunc->isPure() &&*/ // comment out because we deduce purity now - !f->isPure() && calledparent != outerfunc) + !f->isPure() && calledparent != outerfunc && + !sc->needctfe) { if (outerfunc->setImpure()) error("pure function '%s' cannot call impure function '%s'", @@ -1907,6 +2216,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis) void Expression::checkSafety(Scope *sc, FuncDeclaration *f) { if (sc->func && !sc->intypeof && + !(sc->needctfe) && !f->isSafe() && !f->isTrusted()) { if (sc->func->setUnsafe()) @@ -1935,8 +2245,12 @@ Expression *Expression::checkToBoolean(Scope *sc) assert(type); #endif - // Structs can be converted to bool using opCast(bool)() + Expression *e = this; + Type *t = type; Type *tb = type->toBasetype(); + Type *att = NULL; +Lagain: + // Structs can be converted to bool using opCast(bool)() if (tb->ty == Tstruct) { AggregateDeclaration *ad = ((TypeStruct *)tb)->sym; /* Don't really need to check for opCast first, but by doing so we @@ -1945,26 +2259,29 @@ Expression *Expression::checkToBoolean(Scope *sc) Dsymbol *fd = search_function(ad, Id::cast); if (fd) { - Expression *e = new CastExp(loc, this, Type::tbool); + e = new CastExp(loc, e, Type::tbool); e = e->semantic(sc); return e; } // Forward to aliasthis. - if (ad->aliasthis) + if (ad->aliasthis && tb != att) { - Expression *e = resolveAliasThis(sc, this); - e = e->checkToBoolean(sc); - return e; + if (!att && tb->checkAliasThisRec()) + att = tb; + e = resolveAliasThis(sc, e); + t = e->type; + tb = e->type->toBasetype(); + goto Lagain; } } - if (!type->checkBoolean()) - { if (type->toBasetype() != Type::terror) - error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); + if (!t->checkBoolean()) + { if (tb != Type::terror) + error("expression %s of type %s does not have a boolean value", toChars(), t->toChars()); return new ErrorExp(); } - return this; + return e; } /**************************** @@ -2030,7 +2347,7 @@ int Expression::isBit() } /**************************************** - * Resolve __LINE__ and __FILE__ to loc. + * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc. */ Expression *Expression::resolveLoc(Loc loc, Scope *sc) @@ -2123,7 +2440,7 @@ IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type) } IntegerExp::IntegerExp(dinteger_t value) - : Expression(0, TOKint64, sizeof(IntegerExp)) + : Expression(Loc(), TOKint64, sizeof(IntegerExp)) { this->type = Type::tint32; this->value = value; @@ -2166,9 +2483,9 @@ dinteger_t IntegerExp::toInteger() case Tint64: value = (d_int64) value; break; case Tuns64: value = (d_uns64) value; break; case Tpointer: - if (PTRSIZE == 4) + if (Target::ptrsize == 4) value = (d_uns32) value; - else if (PTRSIZE == 8) + else if (Target::ptrsize == 8) value = (d_uns64) value; else assert(0); @@ -2352,9 +2669,9 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("cast("); buf->writestring(t->toChars()); buf->writeByte(')'); - if (PTRSIZE == 4) + if (Target::ptrsize == 4) goto L3; - else if (PTRSIZE == 8) + else if (Target::ptrsize == 8) goto L4; else assert(0); @@ -2405,7 +2722,7 @@ void IntegerExp::toMangleBuffer(OutBuffer *buf) */ ErrorExp::ErrorExp() - : IntegerExp(0, 0, Type::terror) + : IntegerExp(Loc(), 0, Type::terror) { op = TOKerror; } @@ -2432,6 +2749,10 @@ RealExp::RealExp(Loc loc, real_t value, Type *type) char *RealExp::toChars() { + /** sizeof(value)*3 is because each byte of mantissa is max + of 256 (3 characters). The string will be "-M.MMMMe-4932". + (ie, 8 chars more than mantissa). Plus one for trailing \0. + Plus one for rounding. */ char buffer[sizeof(value) * 3 + 8 + 1 + 1]; #ifdef IN_GCC @@ -2442,7 +2763,7 @@ char *RealExp::toChars() if (type->isimaginary()) strcat(buffer, "i"); - assert(strlen(buffer) < sizeof(buffer)); + assert(strlen(buffer) < sizeof(buffer) / sizeof(buffer[0])); return mem.strdup(buffer); } @@ -2492,10 +2813,10 @@ complex_t RealExp::toComplex() int RealEquals(real_t x1, real_t x2) { return (Port::isNan(x1) && Port::isNan(x2)) || - // and zero, in order to distinguish +0 from -0 - (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) || - // otherwise just compare - (x1 != 0. && x1 == x2); + /* In some cases, the REALPAD bytes get garbage in them, + * so be sure and ignore them. + */ + memcmp(&x1, &x2, Target::realsize - Target::realpad) == 0; } int RealExp::equals(Object *o) @@ -2542,9 +2863,9 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) */ char buffer[32]; ld_sprint(buffer, 'g', value); - assert(strlen(buffer) < sizeof(buffer)); + assert(strlen(buffer) < sizeof(buffer) / sizeof(buffer[0])); #if _WIN32 && __DMC__ - char *save = __locale_decpoint; + const char *save = __locale_decpoint; __locale_decpoint = "."; real_t r = strtold(buffer, NULL); __locale_decpoint = save; @@ -2622,14 +2943,9 @@ void realToMangleBuffer(OutBuffer *buf, real_t value) buf->writestring("NAN"); // no -NAN bugs else { -#if IN_LLVM - // The buffer is too small for a longdouble on PPC. char buffer[36]; -#else - char buffer[32]; -#endif int n = ld_sprint(buffer, 'A', value); - assert(n > 0 && n < sizeof(buffer)); + assert(n > 0 && n < sizeof(buffer) / sizeof(buffer[0])); for (int i = 0; i < n; i++) { char c = buffer[i]; @@ -2686,7 +3002,7 @@ char *ComplexExp::toChars() ld_sprint(buf2, 'g', cimagl(value)); #endif sprintf(buffer, "(%s+%si)", buf1, buf2); - assert(strlen(buffer) < sizeof(buffer)); + assert(strlen(buffer) < sizeof(buffer) / sizeof(buffer[0])); return mem.strdup(buffer); } @@ -2803,11 +3119,13 @@ Expression *IdentifierExp::semantic(Scope *sc) s = sc->search(loc, ident, &scopesym); if (s) { Expression *e; - WithScopeSymbol *withsym; + + if (s->errors) + return new ErrorExp(); /* See if the symbol was a member of an enclosing 'with' */ - withsym = scopesym->isWithScopeSymbol(); + WithScopeSymbol *withsym = scopesym->isWithScopeSymbol(); if (withsym) { #if DMDV2 @@ -2860,7 +3178,7 @@ Expression *IdentifierExp::semantic(Scope *sc) { if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's tempdecl = tempdecl->overroot; // then get the start - e = new TemplateExp(loc, tempdecl); + e = new TemplateExp(loc, tempdecl, f); e = e->semantic(sc); return e; } @@ -2968,8 +3286,6 @@ Lagain: //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); - if (type && !s->needThis()) - return this; if (!s->isFuncDeclaration()) // functions are checked after overloading checkDeprecated(sc, s); Dsymbol *olds = s; @@ -3001,9 +3317,13 @@ Lagain: if (em) { e = em->value; - e->loc = loc; - e = e->semantic(sc); - return e; + if (!e) + { + em->errors = true; + error("forward reference of %s %s", s->kind(), s->toChars()); + return new ErrorExp(); + } + return em->getVarExp(loc, sc); } v = s->isVarDeclaration(); if (v) @@ -3014,14 +3334,21 @@ Lagain: v->semantic(v->scope); type = v->type; if (!v->type) - { error("forward reference of %s %s", v->kind(), v->toChars()); + { error("forward reference of %s %s", s->kind(), s->toChars()); return new ErrorExp(); } } if ((v->storage_class & STCmanifest) && v->init) { - e = v->init->toExpression(); + if (v->scope) + { + v->inuse++; + v->init->semantic(v->scope, v->type, INITinterpret); + v->scope = NULL; + v->inuse--; + } + e = v->init->toExpression(v->type); if (!e) { error("cannot make expression out of initializer for %s", v->toChars()); return new ErrorExp(); @@ -3067,7 +3394,7 @@ Lagain: o = s->isOverloadSet(); if (o) { //printf("'%s' is an overload set\n", o->toChars()); - return new OverExp(o); + return new OverExp(loc, o); } imp = s->isImport(); if (imp) @@ -3106,24 +3433,6 @@ Lagain: TupleDeclaration *tup = s->isTupleDeclaration(); if (tup) { - for (size_t i = 0; i < tup->objects->dim; i++) - { - Dsymbol *sa = getDsymbol((*tup->objects)[i]); - if (sa && sa->needThis()) - { - if (hasThis(sc) -#if DMDV2 - && !sa->isFuncDeclaration() -#endif - ) - { - // Supply an implicit 'this', as in - // this.ident - (*tup->objects)[i] = new DotVarExp(loc, new ThisExp(loc), sa->isDeclaration()); - } - } - } - e = new TupleExp(loc, tup); e = e->semantic(sc); return e; @@ -3149,7 +3458,8 @@ Lagain: Dsymbol *p = td->toParent2(); FuncDeclaration *fdthis = hasThis(sc); AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL; - if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad) + if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad && + (td->scope->stc & STCstatic) == 0) { e = new DotTemplateExp(loc, new ThisExp(loc), td); } @@ -3211,7 +3521,7 @@ Expression *ThisExp::semantic(Scope *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 == 1) { // Find enclosing struct or class for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) @@ -3308,7 +3618,7 @@ Expression *SuperExp::semantic(Scope *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 == 1) { // Find enclosing class for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent) @@ -3704,13 +4014,14 @@ int StringExp::isLvalue() /* string literal is rvalue in default, but * conversion to reference of static array is only allowed. */ - return 0; + return (type && type->toBasetype()->ty == Tsarray); } Expression *StringExp::toLvalue(Scope *sc, Expression *e) { - //printf("StringExp::toLvalue(%s)\n", toChars()); - return this; + //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL); + return (type && type->toBasetype()->ty == Tsarray) + ? this : Expression::toLvalue(sc, e); } Expression *StringExp::modifiableLvalue(Scope *sc, Expression *e) @@ -4015,7 +4326,7 @@ void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) Expression *value = (*values)[i]; if (i) - buf->writeByte(','); + buf->writestring(", "); expToCBuffer(buf, hgs, key, PREC_assign); buf->writeByte(':'); expToCBuffer(buf, hgs, value, PREC_assign); @@ -4057,14 +4368,42 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * this->ownedByCtfe = false; this->ctorinit = 0; #if IN_LLVM - constType = NULL; + this->inProgressMemory = NULL; + this->globalVar = NULL; #endif + this->origin = this; + this->stageflags = 0; + this->inlinecopy = NULL; //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars()); } +int StructLiteralExp::equals(Object *o) +{ + if (this == o) + return 1; + if (o && o->dyncast() == DYNCAST_EXPRESSION && + ((Expression *)o)->op == TOKstructliteral) + { + StructLiteralExp *se = (StructLiteralExp *)o; + if (sd != se->sd) + return 0; + if (elements->dim != se->elements->dim) + return 0; + for (size_t i = 0; i < elements->dim; i++) + { + if (!(*elements)[i]->equals((*se->elements)[i])) + return 0; + } + return 1; + } + return 0; +} + Expression *StructLiteralExp::syntaxCopy() { - return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype); + StructLiteralExp *exp = new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype); + exp->origin = this; + return exp; } Expression *StructLiteralExp::semantic(Scope *sc) @@ -4079,7 +4418,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) sd->size(loc); if (sd->sizeok != SIZEOKdone) return new ErrorExp(); - size_t nfields = sd->fields.dim - sd->isnested; + size_t nfields = sd->fields.dim - sd->isNested(); elements = arrayExpressionSemantic(elements, sc); // run semantic() on each element expandTuples(elements); @@ -4126,7 +4465,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) if (e->op == TOKerror) return e; - (*elements)[i] = e; + (*elements)[i] = callCpCtor(e->loc, sc, e, 1); } /* Fill out remainder of elements[] with default initializers for fields[] @@ -4144,32 +4483,24 @@ Expression *StructLiteralExp::semantic(Scope *sc) else { if (v->init) - { if (v->init->isVoidInitializer()) + { + 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(); - } - else if (v->scope) - { // Do deferred semantic analysis - Initializer *i2 = v->init->syntaxCopy(); - i2 = i2->semantic(v->scope, v->type, INITinterpret); - e = i2->toExpression(); - // remove v->scope (see bug 3426) - // but not if gagged, for we might be called again. - if (!global.gag) - { v->scope = NULL; - v->init = i2; // save result - } - } - } + e = v->getConstInitializer(false); } - else if (v->type->needsNested() && ctorinit) - e = v->type->defaultInit(loc); else - e = v->type->defaultInitLiteral(loc); + { + if (v->storage_class & STCnodefaultctor) + { + error("field %s.%s must be initialized because it has no default constructor", + sd->type->toChars(), v->toChars()); + } + if (v->type->needsNested() && ctorinit) + e = v->type->defaultInit(loc); + else + e = v->type->defaultInitLiteral(loc); + } offset = v->offset + v->type->size(); } elements->push(e); @@ -4184,7 +4515,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) if (sd->dtor && sc->func) { Identifier *idtmp = Lexer::uniqueId("__sl"); - VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this)); + VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(Loc(), this)); tmp->storage_class |= STCctfe; Expression *ae = new DeclarationExp(loc, tmp); Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp)); @@ -4289,7 +4620,19 @@ void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(sd->toChars()); buf->writeByte('('); +#if IN_LLVM // Backport of DMD pull request 2183. + if (stageflags & 32) + buf->writestring("..."); + else + { + int old = stageflags; + stageflags |= 32; +#endif argsToCBuffer(buf, elements, hgs); +#if IN_LLVM + stageflags = old; + } +#endif buf->writeByte(')'); } @@ -4315,7 +4658,7 @@ void StructLiteralExp::toMangleBuffer(OutBuffer *buf) * cast(foo).size */ -Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident) +DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident) { return new DotIdExp(loc, new TypeExp(loc, type), ident); } @@ -4411,6 +4754,20 @@ Lagain: if (ti && !ti->errors) { unsigned olderrs = global.errors; + if (ti->needsTypeInference(sc)) + { + TemplateDeclaration *td = ti->tempdecl; + Dsymbol *p = td->toParent2(); + FuncDeclaration *fdthis = hasThis(sc); + AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL; + if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad && + (td->scope->stc & STCstatic) == 0) + { + Expression *e = new DotTemplateInstanceExp(loc, new ThisExp(loc), ti->name, ti->tiargs); + return e->semantic(sc); + } + return this; + } if (!ti->semanticRun) ti->semantic(sc); if (ti->inst) @@ -4486,11 +4843,12 @@ void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) // Mainly just a placeholder -TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) +TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd) : Expression(loc, TOKtemplate, sizeof(TemplateExp)) { //printf("TemplateExp(): %s\n", td->toChars()); this->td = td; + this->fd = fd; } void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -4504,6 +4862,20 @@ int TemplateExp::rvalue() return 0; } +int TemplateExp::isLvalue() +{ + return fd != NULL; +} + +Expression *TemplateExp::toLvalue(Scope *sc, Expression *e) +{ + if (!fd) + return Expression::toLvalue(sc, e); + Expression *ex = new DsymbolExp(loc, fd, 1); + ex = ex->semantic(sc); + return ex; +} + /********************** NewExp **************************************/ /* thisexp.new(newargs) newtype(arguments) */ @@ -4534,6 +4906,7 @@ Expression *NewExp::semantic(Scope *sc) { Type *tb; ClassDeclaration *cdthis = NULL; + size_t nargs; #if LOGSEMANTIC printf("NewExp::semantic() %s\n", toChars()); @@ -4578,6 +4951,8 @@ Lagain: arrayExpressionSemantic(arguments, sc); preFunctionParameters(loc, sc, arguments); + nargs = arguments ? arguments->dim : 0; + if (thisexp && tb->ty != Tclass) { error("e.new is only for allocating nested classes, not %s", tb->toChars()); goto Lerr; @@ -4598,13 +4973,13 @@ Lagain: for (size_t i = 0; i < cd->vtbl.dim; i++) { FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration(); if (fd && fd->isAbstract()) - error("function %s is abstract", fd->toChars()); + errorSupplemental(loc, "function '%s' is not implemented", fd->toFullSignature()); } goto Lerr; } - if (cd->noDefaultCtor && (!arguments || !arguments->dim)) - { error("default construction is disabled for type %s", cd->toChars()); + if (cd->noDefaultCtor && !nargs) + { error("default construction is disabled for type %s", cd->type->toChars()); goto Lerr; } checkDeprecated(sc, cd); @@ -4648,7 +5023,7 @@ Lagain: goto Lerr; } } - } + } else if (thisexp) { error("e.new is only for allocating nested classes"); goto Lerr; @@ -4678,7 +5053,7 @@ Lagain: FuncDeclaration *f = NULL; if (cd->ctor) - f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0); + f = resolveFuncCall(loc, sc, cd->ctor, NULL, tb, arguments, 0); if (f) { checkDeprecated(sc, f); @@ -4692,14 +5067,13 @@ Lagain: if (!arguments) arguments = new Expressions(); unsigned olderrors = global.errors; - functionParameters(loc, sc, tf, NULL, arguments, f); + type = functionParameters(loc, sc, tf, type, arguments, f); if (olderrors != global.errors) return new ErrorExp(); - type = type->addMod(tf->nextOf()->mod); } else { - if (arguments && arguments->dim) + if (nargs) { error("no constructor for %s", cd->toChars()); goto Lerr; } @@ -4713,7 +5087,9 @@ Lagain: newargs = new Expressions(); newargs->shift(e); - f = cd->aggNew->overloadResolve(loc, NULL, newargs); + f = resolveFuncCall(loc, sc, cd->aggNew, NULL, tb, newargs); + if (!f) + goto Lerr; allocator = f->isNewDeclaration(); assert(allocator); @@ -4722,7 +5098,6 @@ Lagain: functionParameters(loc, sc, tf, NULL, newargs, f); if (olderrors != global.errors) return new ErrorExp(); - } else { @@ -4738,8 +5113,8 @@ Lagain: StructDeclaration *sd = ts->sym; if (sd->scope) sd->semantic(NULL); - if (sd->noDefaultCtor && (!arguments || !arguments->dim)) - { error("default construction is disabled for type %s", sd->toChars()); + if (sd->noDefaultCtor && !nargs) + { error("default construction is disabled for type %s", sd->type->toChars()); goto Lerr; } @@ -4751,7 +5126,9 @@ Lagain: newargs = new Expressions(); newargs->shift(e); - FuncDeclaration *f = sd->aggNew->overloadResolve(loc, NULL, newargs); + FuncDeclaration *f = resolveFuncCall(loc, sc, sd->aggNew, NULL, tb, newargs); + if (!f) + goto Lerr; allocator = f->isNewDeclaration(); assert(allocator); @@ -4770,8 +5147,8 @@ Lagain: } FuncDeclaration *f = NULL; - if (sd->ctor) - f = resolveFuncCall(sc, loc, sd->ctor, NULL, NULL, arguments, 0); + if (sd->ctor && nargs) + f = resolveFuncCall(loc, sc, sd->ctor, NULL, tb, arguments, 0); if (f) { checkDeprecated(sc, f); @@ -4781,16 +5158,15 @@ Lagain: sd->accessCheck(loc, sc, member); TypeFunction *tf = (TypeFunction *)f->type; - type = tf->next; if (!arguments) arguments = new Expressions(); unsigned olderrors = global.errors; - functionParameters(loc, sc, tf, NULL, arguments, f); + type = functionParameters(loc, sc, tf, type, arguments, f); if (olderrors != global.errors) return new ErrorExp(); } - else if (arguments && arguments->dim) + else if (nargs) { Type *tptr = type->pointerTo(); @@ -4819,9 +5195,18 @@ Lagain: type = type->pointerTo(); } - else if (tb->ty == Tarray && (arguments && arguments->dim)) + else if (tb->ty == Tarray && nargs) { - for (size_t i = 0; i < arguments->dim; i++) + Type *tn = tb->nextOf()->toBasetype(); + while (tn->ty == Tsarray) + tn = tn->nextOf()->toBasetype(); + Dsymbol *s = tn->toDsymbol(sc); + AggregateDeclaration *ad = s ? s->isAggregateDeclaration() : NULL; + if (ad && ad->noDefaultCtor) + { error("default construction is disabled for type %s", tb->nextOf()->toChars()); + goto Lerr; + } + for (size_t i = 0; i < nargs; i++) { if (tb->ty != Tarray) { error("too many arguments for array"); @@ -4842,7 +5227,7 @@ Lagain: } else if (tb->isscalar()) { - if (arguments && arguments->dim) + if (nargs) { error("no constructor for %s", type->toChars()); goto Lerr; } @@ -4918,7 +5303,10 @@ Expression *NewAnonClassExp::semantic(Scope *sc) #endif Expression *d = new DeclarationExp(loc, cd); + int needctfe = sc->needctfe; + sc->needctfe = 0; d = d->semantic(sc); + sc->needctfe = needctfe; Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); @@ -5122,13 +5510,17 @@ void VarExp::checkEscapeRef() int VarExp::isLvalue() { - if (var->storage_class & (STClazy | STCtemp)) + if (var->storage_class & (STClazy | STCtemp | STCmanifest)) return 0; return 1; } Expression *VarExp::toLvalue(Scope *sc, Expression *e) { + if (var->storage_class & STCmanifest) + { error("manifest constant '%s' is not lvalue", var->toChars()); + return new ErrorExp(); + } if (var->storage_class & STClazy) { error("lazy variables cannot be lvalues"); return new ErrorExp(); @@ -5151,19 +5543,11 @@ int VarExp::checkModifiable(Scope *sc, int flag) Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) { //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); - //if (type && type->toBasetype()->ty == Tsarray) - //error("cannot change reference to static array '%s'", var->toChars()); - -#if (BUG6652 == 1) - VarDeclaration *v = var->isVarDeclaration(); - if (v && (v->storage_class & STCbug6652) && v->type->isMutable()) - warning("variable modified in foreach body requires ref storage class"); -#elif (BUG6652 == 2) - VarDeclaration *v = var->isVarDeclaration(); - if (v && (v->storage_class & STCbug6652) && v->type->isMutable()) - deprecation("variable modified in foreach body requires ref storage class"); -#endif - + if (var->storage_class & STCmanifest) + { + error("Cannot modify '%s'", toChars()); + return new ErrorExp(); + } // See if this expression is a modifiable lvalue (i.e. not const) return Expression::modifiableLvalue(sc, e); } @@ -5172,7 +5556,7 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) /******************************** OverExp **************************/ #if DMDV2 -OverExp::OverExp(OverloadSet *s) +OverExp::OverExp(Loc loc, OverloadSet *s) : Expression(loc, TOKoverloadset, sizeof(OverExp)) { //printf("OverExp(this = %p, '%s')\n", this, var->toChars()); @@ -5194,42 +5578,49 @@ Expression *OverExp::toLvalue(Scope *sc, Expression *e) /******************************** TupleExp **************************/ +TupleExp::TupleExp(Loc loc, Expression *e0, Expressions *exps) + : Expression(loc, TOKtuple, sizeof(TupleExp)) +{ + //printf("TupleExp(this = %p)\n", this); + this->e0 = e0; + this->exps = exps; +} + TupleExp::TupleExp(Loc loc, Expressions *exps) : Expression(loc, TOKtuple, sizeof(TupleExp)) { //printf("TupleExp(this = %p)\n", this); + this->e0 = NULL; this->exps = exps; - this->type = NULL; } - TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) : Expression(loc, TOKtuple, sizeof(TupleExp)) { - exps = new Expressions(); - type = NULL; + this->e0 = NULL; + this->exps = new Expressions(); - exps->reserve(tup->objects->dim); + this->exps->reserve(tup->objects->dim); for (size_t i = 0; i < tup->objects->dim; i++) { Object *o = (*tup->objects)[i]; - if (o->dyncast() == DYNCAST_EXPRESSION) + if (Dsymbol *s = getDsymbol(o)) + { + /* If tuple element represents a symbol, translate to DsymbolExp + * to supply implicit 'this' if needed later. + */ + Expression *e = new DsymbolExp(loc, s); + this->exps->push(e); + } + else if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; - if (e->op == TOKdsymbol) - e = e->syntaxCopy(); - exps->push(e); - } - else if (o->dyncast() == DYNCAST_DSYMBOL) - { - Dsymbol *s = (Dsymbol *)o; - Expression *e = new DsymbolExp(loc, s); - exps->push(e); + this->exps->push(e); } else if (o->dyncast() == DYNCAST_TYPE) { Type *t = (Type *)o; Expression *e = new TypeExp(loc, t); - exps->push(e); + this->exps->push(e); } else { @@ -5247,6 +5638,8 @@ int TupleExp::equals(Object *o) TupleExp *te = (TupleExp *)o; if (exps->dim != te->exps->dim) return 0; + if (e0 && !e0->equals(te->e0) || !e0 && te->e0) + return 0; for (size_t i = 0; i < exps->dim; i++) { Expression *e1 = (*exps)[i]; Expression *e2 = (*te->exps)[i]; @@ -5261,7 +5654,7 @@ int TupleExp::equals(Object *o) Expression *TupleExp::syntaxCopy() { - return new TupleExp(loc, arraySyntaxCopy(exps)); + return new TupleExp(loc, e0 ? e0->syntaxCopy() : NULL, arraySyntaxCopy(exps)); } Expression *TupleExp::semantic(Scope *sc) @@ -5272,6 +5665,9 @@ Expression *TupleExp::semantic(Scope *sc) if (type) return this; + if (e0) + e0 = e0->semantic(sc); + // Run semantic() on each argument for (size_t i = 0; i < exps->dim; i++) { Expression *e = (*exps)[i]; @@ -5293,9 +5689,20 @@ Expression *TupleExp::semantic(Scope *sc) void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - buf->writestring("tuple("); - argsToCBuffer(buf, exps, hgs); - buf->writeByte(')'); + if (e0) + { + buf->writeByte('('); + e0->toCBuffer(buf, hgs); + buf->writestring(", tuple("); + argsToCBuffer(buf, exps, hgs); + buf->writestring("))"); + } + else + { + buf->writestring("tuple("); + argsToCBuffer(buf, exps, hgs); + buf->writeByte(')'); + } } @@ -5329,6 +5736,11 @@ Expression *FuncExp::semantic(Scope *sc) printf("FuncExp::semantic(%s)\n", toChars()); if (fd->treq) printf(" treq = %s\n", fd->treq->toChars()); #endif + Expression *e = this; + + int needctfe = sc->needctfe; + sc->needctfe = 0; + if (!type || type == Type::tvoid) { /* fd->treq might be incomplete type, @@ -5358,10 +5770,9 @@ Expression *FuncExp::semantic(Scope *sc) td->semantic(sc); type = Type::tvoid; // temporary type - if (!fd->treq) // defer type determination - return this; - - return inferType(fd->treq); + if (fd->treq) // defer type determination + e = inferType(fd->treq); + goto Ldone; } unsigned olderrors = global.errors; @@ -5416,7 +5827,9 @@ Expression *FuncExp::semantic(Scope *sc) } fd->tookAddressOf++; } - return this; +Ldone: + sc->needctfe = needctfe; + return e; } // used from CallExp::semantic() @@ -5713,7 +6126,7 @@ void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { for (size_t i = 0; i < args->dim; i++) { - buf->writeByte(','); + buf->writestring(", ");; Object *oarg = (*args)[i]; ObjectToCBuffer(buf, hgs, oarg); } @@ -5876,6 +6289,8 @@ Expression *IsExp::semantic(Scope *sc) { ClassDeclaration *cd = ((TypeClass *)targ)->sym; Parameters *args = new Parameters; args->reserve(cd->baseclasses->dim); + if (cd->scope && !cd->symtab) + cd->semantic(cd->scope); for (size_t i = 0; i < cd->baseclasses->dim; i++) { BaseClass *b = (*cd->baseclasses)[i]; args->push(new Parameter(STCin, b->type, NULL, NULL)); @@ -5961,21 +6376,51 @@ Expression *IsExp::semantic(Scope *sc) } goto Lyes; } - else if (id && tspec) + else if (tspec && !id && !(parameters && parameters->dim)) + { + /* Evaluate to TRUE if targ matches tspec + * is(targ == tspec) + * 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); + if (tok == TOKcolon) + { if (targ->implicitConvTo(tspec)) + goto Lyes; + else + goto Lno; + } + else /* == */ + { if (targ->equals(tspec)) + goto Lyes; + else + goto Lno; + } + } + else if (tspec) { /* Evaluate to TRUE if targ matches tspec. * If TRUE, declare id as an alias for the specialized type. + * is(targ == tspec, tpl) + * is(targ : tspec, tpl) + * is(targ id == tspec) + * is(targ id : tspec) + * is(targ id == tspec, tpl) + * is(targ id : tspec, tpl) */ - assert(parameters && parameters->dim); + Identifier *tid = id ? id : Lexer::uniqueId("__isexp_id"); + TemplateParameter *tp = new TemplateTypeParameter(loc, tid, NULL, NULL); + parameters->insert(0, tp); Objects dedtypes; dedtypes.setDim(parameters->dim); dedtypes.zero(); MATCH m = targ->deduceType(sc, tspec, parameters, &dedtypes); -//printf("targ: %s\n", targ->toChars()); -//printf("tspec: %s\n", tspec->toChars()); + //printf("targ: %s\n", targ->toChars()); + //printf("tspec: %s\n", tspec->toChars()); if (m == MATCHnomatch || (m != MATCHexact && tok == TOKequal)) { @@ -6013,32 +6458,11 @@ Expression *IsExp::semantic(Scope *sc) else if (id) { /* Declare id as an alias for type targ. Evaluate to TRUE + * is(targ id) */ tded = targ; goto Lyes; } - else if (tspec) - { - /* Evaluate to TRUE if targ matches tspec - * is(targ == tspec) - * 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); - if (tok == TOKcolon) - { if (targ->implicitConvTo(tspec)) - goto Lyes; - else - goto Lno; - } - else /* == */ - { if (targ->equals(tspec)) - goto Lyes; - else - goto Lno; - } - } Lyes: if (id) @@ -6084,10 +6508,10 @@ 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 = 0; i < parameters->dim; i++) { - buf->writeByte(','); + buf->writestring(", "); TemplateParameter *tp = (*parameters)[i]; tp->toCBuffer(buf, hgs); } @@ -6103,6 +6527,7 @@ UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) : Expression(loc, op, size) { this->e1 = e1; + this->att1 = NULL; } Expression *UnaExp::syntaxCopy() @@ -6143,6 +6568,9 @@ BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) { this->e1 = e1; this->e2 = e2; + + this->att1 = NULL; + this->att2 = NULL; } Expression *BinExp::syntaxCopy() @@ -6350,8 +6778,7 @@ Expression *BinAssignExp::semantic(Scope *sc) e = e->semantic(sc); return e; } - - if (e1->op == TOKslice) + else if (e1->op == TOKslice) { // T[] op= ... e = typeCombine(sc); @@ -6361,8 +6788,9 @@ Expression *BinAssignExp::semantic(Scope *sc) return arrayOp(sc); } - e1 = e1->modifiableLvalue(sc, e1); e1 = e1->semantic(sc); + e1 = e1->optimize(WANTvalue); + e1 = e1->modifiableLvalue(sc, e1); type = e1->type; checkScalar(); @@ -6421,7 +6849,8 @@ Expression *BinAssignExp::semantic(Scope *sc) if (e1->op == TOKerror || e2->op == TOKerror) return new ErrorExp(); - return checkComplexOpAssign(sc); + checkComplexOpAssign(sc); + return reorderSettingAAElem(sc); } #if DMDV2 @@ -6488,7 +6917,7 @@ Expression *CompileExp::semantic(Scope *sc) #if LOGSEMANTIC printf("CompileExp::semantic('%s')\n", toChars()); #endif - UnaExp::semantic(sc); + e1 = e1->ctfeSemantic(sc); e1 = resolveProperties(sc, e1); if (e1->op == TOKerror) return e1; @@ -6508,7 +6937,10 @@ Expression *CompileExp::semantic(Scope *sc) p.loc = loc; p.nextToken(); //printf("p.loc.linnum = %d\n", p.loc.linnum); + unsigned errors = global.errors; Expression *e = p.parseExpression(); + if (global.errors != errors) + return new ErrorExp(); if (p.token.value != TOKeof) { error("incomplete mixin expression (%s)", se->toChars()); return new ErrorExp(); @@ -6538,7 +6970,7 @@ Expression *FileExp::semantic(Scope *sc) #if LOGSEMANTIC printf("FileExp::semantic('%s')\n", toChars()); #endif - UnaExp::semantic(sc); + e1 = e1->ctfeSemantic(sc); e1 = resolveProperties(sc, e1); e1 = e1->ctfeInterpret(); if (e1->op != TOKstring) @@ -6647,7 +7079,7 @@ void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) expToCBuffer(buf, hgs, e1, PREC_assign); if (msg) { - buf->writeByte(','); + buf->writestring(", "); expToCBuffer(buf, hgs, msg, PREC_assign); } buf->writeByte(')'); @@ -6663,66 +7095,32 @@ DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) Expression *DotIdExp::semantic(Scope *sc) { - // Indicate we need to resolve by UFCS. - return semantic(sc, 0); -} - -Expression *DotIdExp::semantic(Scope *sc, int flag) -{ Expression *e; - Expression *eleft; - Expression *eright; - #if LOGSEMANTIC printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); #endif - -//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } - - /* Special case: rewrite this.id and super.id - * to be classtype.id and baseclasstype.id - * if we have no this pointer. - */ - if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) - { ClassDeclaration *cd; - StructDeclaration *sd; - AggregateDeclaration *ad; - - ad = sc->getStructClassScope(); - if (ad) - { - cd = ad->isClassDeclaration(); - if (cd) - { - if (e1->op == TOKthis) - { - e = typeDotIdExp(loc, cd->type, ident); - return e->semantic(sc); - } - else if (cd->baseClass && e1->op == TOKsuper) - { - e = typeDotIdExp(loc, cd->baseClass->type, ident); - return e->semantic(sc); - } - } - else - { - sd = ad->isStructDeclaration(); - if (sd) - { - if (e1->op == TOKthis) - { - e = typeDotIdExp(loc, sd->type, ident); - return e->semantic(sc); - } - } - } - } + Expression *e = semanticY(sc, 1); + if (!e) // if failed to find the property + { + /* If ident is not a valid property, rewrite: + * e1.ident + * as: + * .ident(e1) + */ + e = resolveUFCSProperties(sc, this); } + return e; +} -// Type *t1save = e1->type; +// Run sematnic in e1 +Expression *DotIdExp::semanticX(Scope *sc) +{ + //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars()); + Expression *e; UnaExp::semantic(sc); + if (e1->op == TOKerror) + return e1; if (ident == Id::mangleof) { // symbol.mangleof @@ -6734,8 +7132,8 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) case TOKdotvar: ds = ((DotVarExp *)e1)->var; goto L1; default: break; L1: - char* s = ds->mangle(); - e = new StringExp(loc, s, strlen(s), 'c'); + const char* s = ds->mangle(); + e = new StringExp(loc, (void*)s, strlen(s), 'c'); e = e->semantic(sc); return e; } @@ -6743,15 +7141,10 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) if (e1->op == TOKdotexp) { - DotExp *de = (DotExp *)e1; - eleft = de->e1; - eright = de->e2; } else { - e1 = resolveProperties(sc, e1); - eleft = NULL; - eright = e1; + e1 = resolvePropertiesX(sc, e1); } #if DMDV2 if (e1->op == TOKtuple && ident == Id::offsetof) @@ -6766,7 +7159,8 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) e = new DotIdExp(e->loc, e, Id::offsetof); (*exps)[i] = e; } - e = new TupleExp(loc, exps); + // Don't evaluate te->e0 in runtime + e = new TupleExp(loc, /*te->e0*/NULL, exps); e = e->semantic(sc); return e; } @@ -6775,6 +7169,7 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) if (e1->op == TOKtuple && ident == Id::length) { TupleExp *te = (TupleExp *)e1; + // Don't evaluate te->e0 in runtime e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); return e; } @@ -6791,6 +7186,67 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) return new ErrorExp(); } + return this; +} + +// Resolve e1.ident without seeing UFCS. +// If flag == 1, stop "not a property" error and return NULL. +Expression *DotIdExp::semanticY(Scope *sc, int flag) +{ + //printf("DotIdExp::semanticY(this = %p, '%s')\n", this, toChars()); + +//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } + + /* Special case: rewrite this.id and super.id + * to be classtype.id and baseclasstype.id + * if we have no this pointer. + */ + if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) + { + if (AggregateDeclaration *ad = sc->getStructClassScope()) + { + if (ClassDeclaration *cd = ad->isClassDeclaration()) + { + if (e1->op == TOKthis) + { + DotIdExp *die = typeDotIdExp(loc, cd->type, ident); + return die->semanticY(sc, flag); + } + else if (cd->baseClass && e1->op == TOKsuper) + { + DotIdExp *die = typeDotIdExp(loc, cd->baseClass->type, ident); + return die->semanticY(sc, flag); + } + } + else if (StructDeclaration *sd = ad->isStructDeclaration()) + { + if (e1->op == TOKthis) + { + DotIdExp *die = typeDotIdExp(loc, sd->type, ident); + return die->semanticY(sc, flag); + } + } + } + } + + Expression *e = semanticX(sc); + if (e != this) + return e; + + Expression *eleft; + Expression *eright; + if (e1->op == TOKdotexp) + { + DotExp *de = (DotExp *)e1; + eleft = de->e1; + eright = de->e2; + } + else + { + eleft = NULL; + eright = e1; + } + Type *t1b = e1->type->toBasetype(); if (eright->op == TOKimport) // also used for template alias's @@ -6809,7 +7265,7 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) * aliases to private symbols are public. */ if (Declaration *d = s->isDeclaration()) - accessCheck(loc, sc, 0, d); + accessCheck(loc, sc, NULL, d); s = s->toAlias(); checkDeprecated(sc, s); @@ -6817,9 +7273,7 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) EnumMember *em = s->isEnumMember(); if (em) { - e = em->value; - e = e->semantic(sc); - return e; + return em->getVarExp(loc, sc); } VarDeclaration *v = s->isVarDeclaration(); @@ -6855,6 +7309,8 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) if (f) { //printf("it's a function\n"); + if (!f->functionSemantic()) + return new ErrorExp(); if (f->needThis()) { if (!eleft) @@ -6876,7 +7332,7 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) OverloadSet *o = s->isOverloadSet(); if (o) { //printf("'%s' is an overload set\n", o->toChars()); - return new OverExp(o); + return new OverExp(loc, o); } #endif @@ -6930,6 +7386,14 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) e = e->semantic(sc); return e; } + if (ie->sds->isPackage() || + ie->sds->isImport() || + ie->sds->isModule()) + { + flag = 0; + } + if (flag) + return NULL; s = ie->sds->search_correct(ident); if (s) error("undefined identifier '%s', did you mean '%s %s'?", @@ -6947,68 +7411,19 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) * as: * (*p).ident */ + if (flag && t1b->nextOf()->ty == Tvoid) + return NULL; e = new PtrExp(loc, e1); - e->type = ((TypePointer *)t1b)->next; - return e->type->dotExp(sc, e, ident); - } -#if DMDV2 - else if (!flag) - { /* If ident is not a valid property, rewrite: - * e1.ident - * as: - * .ident(e1) - */ - if (e1->op == TOKtype || - t1b->ty == Tvoid || - (t1b->ty == Tarray || t1b->ty == Tsarray || t1b->ty == Taarray) && - (ident == Id::sort || ident == Id::reverse || ident == Id::dup || ident == Id::idup)) - { goto L2; - } - - /* This would be much better if we added a "hasProperty" method to types, - * i.e. the gagging is a bad way. - */ - - if (t1b->ty == Taarray) - { - TypeAArray *taa = (TypeAArray *)t1b; - if (!taa->impl && - ident != Id::__sizeof && - ident != Id::__xalignof && - ident != Id::init && - ident != Id::mangleof && - ident != Id::stringof && - ident != Id::offsetof) - { - // Find out about these errors when not gagged - taa->getImpl(); - } - } - - Type *t1 = e1->type; - unsigned errors = global.startGagging(); - e = t1->dotExp(sc, e1, ident); - if (global.endGagging(errors)) // if failed to find the property - { - e1->type = t1; // kludge to restore type - errors = global.startGagging(); - e = resolveUFCSProperties(sc, this); - if (global.endGagging(errors)) - { - // both lookups failed, lookup property again for better error message - e1->type = t1; // restore type - e = t1->dotExp(sc, e1, ident); - } - } e = e->semantic(sc); - return e; + return e->type->dotExp(sc, e, ident, flag); } -#endif else { - L2: - e = e1->type->dotExp(sc, e1, ident); - e = e->semantic(sc); + if (e1->op == TOKtemplate) + flag = 0; + e = e1->type->dotExp(sc, e1, ident, flag); + if (!flag || e) + e = e->semantic(sc); return e; } } @@ -7066,8 +7481,21 @@ Expression *DotVarExp::semantic(Scope *sc) * with: * tuple(e1.a, e1.b, e1.c) */ + e1 = e1->semantic(sc); Expressions *exps = new Expressions; + Expression *e0 = NULL; Expression *ev = e1; + if (sc->func && e1->hasSideEffect()) + { + Identifier *id = Lexer::uniqueId("__tup"); + ExpInitializer *ei = new ExpInitializer(e1->loc, e1); + VarDeclaration *v = new VarDeclaration(e1->loc, NULL, id, ei); + v->storage_class |= STCctfe | STCref | STCforeach; + e0 = new DeclarationExp(e1->loc, v); + ev = new VarExp(e1->loc, v); + e0 = e0->semantic(sc); + ev = ev->semantic(sc); + } exps->reserve(tup->objects->dim); for (size_t i = 0; i < tup->objects->dim; i++) @@ -7079,20 +7507,7 @@ Expression *DotVarExp::semantic(Scope *sc) if (e->op == TOKdsymbol) { Dsymbol *s = ((DsymbolExp *)e)->s; - if (i == 0 && sc->func && tup->objects->dim > 1 && - e1->hasSideEffect()) - { - Identifier *id = Lexer::uniqueId("__tup"); - ExpInitializer *ei = new ExpInitializer(e1->loc, e1); - VarDeclaration *v = new VarDeclaration(e1->loc, NULL, id, ei); - v->storage_class |= STCctfe | STCref | STCforeach; - - ev = new VarExp(e->loc, v); - e = new CommaExp(e1->loc, new DeclarationExp(e1->loc, v), ev); - e = new DotVarExp(loc, e, s->isDeclaration()); - } - else - e = new DotVarExp(loc, ev, s->isDeclaration()); + e = new DotVarExp(loc, ev, s->isDeclaration()); } } else if (o->dyncast() == DYNCAST_DSYMBOL) @@ -7110,7 +7525,7 @@ Expression *DotVarExp::semantic(Scope *sc) } exps->push(e); } - Expression *e = new TupleExp(loc, exps); + Expression *e = new TupleExp(loc, e0, exps); e = e->semantic(sc); return e; } @@ -7150,9 +7565,24 @@ Expression *DotVarExp::semantic(Scope *sc) accessCheck(loc, sc, e1, var); VarDeclaration *v = var->isVarDeclaration(); - Expression *e = expandVar(WANTvalue, v); - if (e) +#if PULL93 + if (v && (v->isDataseg() || (v->storage_class & STCmanifest))) +#endif + { + Expression *e = expandVar(WANTvalue, v); + if (e) + return e; + } + + if (v && v->isDataseg()) // fix bugzilla 8238 + { + // (e1, v) + accessCheck(loc, sc, e1, v); + VarExp *ve = new VarExp(loc, v); + Expression *e = new CommaExp(loc, e1, ve); + e = e->semantic(sc); return e; + } } Dsymbol *s; if (sc->func && !sc->intypeof && t1->hasPointers() && @@ -7201,8 +7631,8 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1) if (s) fd = s->isFuncDeclaration(); if (fd && - ((fd->isCtorDeclaration() && var->storage_class & STCfield) || - (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && + ((fd->isCtorDeclaration() && var->isField()) || + (fd->isStaticCtorDeclaration() && !var->isField())) && fd->toParent2() == var->toParent2() && (!e1 || e1->op == TOKthis) ) @@ -7297,54 +7727,48 @@ TemplateDeclaration *DotTemplateInstanceExp::getTempdecl(Scope *sc) } Expression *DotTemplateInstanceExp::semantic(Scope *sc) -{ - // Indicate we need to resolve by UFCS. - return semantic(sc, 0); -} -Expression *DotTemplateInstanceExp::semantic(Scope *sc, int flag) { #if LOGSEMANTIC printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); #endif - UnaExp::semantic(sc); - if (e1->op == TOKerror) - return e1; + // Indicate we need to resolve by UFCS. + Expression *e = semanticY(sc, 1); + if (!e) + e = resolveUFCSProperties(sc, this); + return e; +} + +// Resolve e1.ident!tiargs without seeing UFCS. +// If flag == 1, stop "not a property" error and return NULL. +Expression *DotTemplateInstanceExp::semanticY(Scope *sc, int flag) +{ +#if LOGSEMANTIC + printf("DotTemplateInstanceExpY::semantic('%s')\n", toChars()); +#endif - Expression *e; DotIdExp *die = new DotIdExp(loc, e1, ti->name); - if (flag || !e1->type || e1->op == TOKtype || - (e1->op == TOKimport && ((ScopeExp *)e1)->sds->isModule())) - { - e = die->semantic(sc, 1); - } - else + Expression *e = die->semanticX(sc); + if (e == die) { + e1 = die->e1; // take back + Type *t1b = e1->type->toBasetype(); if (t1b->ty == Tarray || t1b->ty == Tsarray || t1b->ty == Taarray || t1b->ty == Tnull || (t1b->isTypeBasic() && t1b->ty != Tvoid)) { - /* No built-in type has templatized property, so can short cut. + /* No built-in type has templatized properties, so do shortcut. + * It is necessary in: 1024.max!"a < b" */ - return resolveUFCSProperties(sc, this); - } - - unsigned errors = global.startGagging(); - e = die->semantic(sc, 1); - Type *t = e1->type; - if (global.endGagging(errors)) - { - errors = global.startGagging(); - e = resolveUFCSProperties(sc, this); - if (!global.endGagging(errors)) - return e; - - // both lookups failed, lookup property again for better error message - e->type = t; // restore type - e = die->semantic(sc, 1); + if (flag) + return NULL; } + e = die->semanticY(sc, flag); + if (flag && !e) + return NULL; } + assert(e); L1: if (e->op == TOKerror) @@ -7368,7 +7792,7 @@ L1: return new ErrorExp(); Dsymbol *s = ti->inst->toAlias(); Declaration *v = s->isDeclaration(); - if (v) + if (v && (v->isFuncDeclaration() || v->isVarDeclaration())) { /* Fix for Bugzilla 4003 * The problem is a class template member function v returning a reference to the same @@ -7393,6 +7817,12 @@ L1: e = e->semantic(sc); return e; } + if (eleft->op == TOKtype) + { + e = new DsymbolExp(loc, s); + e = e->semantic(sc); + return e; + } e = new ScopeExp(loc, ti); e = new DotExp(loc, eleft, e); e = e->semantic(sc); @@ -7566,136 +7996,14 @@ Expression *CallExp::syntaxCopy() return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); } - -Expression *CallExp::resolveUFCS(Scope *sc) -{ - Expression *e; - Identifier *ident; - Objects *tiargs; - - if (e1->op == TOKdot) - { - DotIdExp *die = (DotIdExp *)e1; - e = (die->e1 = die->e1->semantic(sc)); - ident = die->ident; - tiargs = NULL; - } - else if (e1->op == TOKdotti) - { - DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)e1; - e = (dti->e1 = dti->e1->semantic(sc)); - ident = dti->ti->name; - tiargs = dti->ti->tiargs; - } - else - return NULL; - - if (e->op == TOKerror || !e->type) - return NULL; - - if (e->op == TOKtype || e->op == TOKimport || e->op == TOKdotexp) - return NULL; - - e = resolveProperties(sc, e); - - Type *t = e->type->toBasetype(); - //printf("resolveUCSS %s, e = %s, %s, %s\n", - // toChars(), Token::toChars(e->op), t->toChars(), e->toChars()); - if (t->ty == Taarray) - { - if (tiargs) - { - goto Lshift; - } - else if (ident == Id::remove) - { - /* Transform: - * aa.remove(arg) into delete aa[arg] - */ - if (!arguments || arguments->dim != 1) - { error("expected key as argument to aa.remove()"); - return new ErrorExp(); - } - if (!e->type->isMutable()) - { error("cannot remove key from %s associative array %s", MODtoChars(e->type->mod), e->toChars()); - return new ErrorExp(); - } - Expression *key = (*arguments)[0]; - key = key->semantic(sc); - key = resolveProperties(sc, key); - - TypeAArray *taa = (TypeAArray *)t; - key = key->implicitCastTo(sc, taa->index); - - if (!key->rvalue()) - return new ErrorExp(); - - return new RemoveExp(loc, e, key); - } - else if (ident == Id::apply || ident == Id::applyReverse) - { - return NULL; - } - else - { TypeAArray *taa = (TypeAArray *)t; - assert(taa->ty == Taarray); - StructDeclaration *sd = taa->getImpl(); - Dsymbol *s = sd->search(0, ident, 2); - if (s) - return NULL; - goto Lshift; - } - } - else if (t->ty == Tarray || t->ty == Tsarray || - t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid)) - { - /* In basic, built-in types don't have normal and templatized - * member functions. So can short cut. - */ -Lshift: - if (!arguments) - arguments = new Expressions(); - arguments->shift(e); - if (!tiargs) - { - /* Transform: - * array.id(args) into .id(array,args) - */ - e1 = new DotIdExp(e1->loc, - new IdentifierExp(e1->loc, Id::empty), - ident); - } - else - { - /* Transform: - * array.foo!(tiargs)(args) into .foo!(tiargs)(array,args) - */ - e1 = new DotTemplateInstanceExp(e1->loc, - new IdentifierExp(e1->loc, Id::empty), - ident, tiargs); - } - } - else - { - DotIdExp *die = new DotIdExp(e->loc, e, ident); - - unsigned errors = global.startGagging(); - Expression *ex = die->semantic(sc, 1); - if (global.endGagging(errors)) - { - goto Lshift; - } - } - return NULL; -} - Expression *CallExp::semantic(Scope *sc) { Type *t1; int istemp; - Objects *targsi = NULL; // initial list of template arguments + Objects *tiargs = NULL; // initial list of template arguments TemplateInstance *tierror = NULL; Expression *ethis = NULL; + Type *tthis = NULL; #if LOGSEMANTIC printf("CallExp::semantic() %s\n", toChars()); @@ -7740,7 +8048,7 @@ Expression *CallExp::semantic(Scope *sc) return e1; } - Expression *e = resolveUFCS(sc); + Expression *e = resolveUFCS(sc, this); if (e) return e; @@ -7763,9 +8071,10 @@ Expression *CallExp::semantic(Scope *sc) { /* Go with partial explicit specialization */ - targsi = ti->tiargs; + tiargs = ti->tiargs; tierror = ti; // for error reporting - e1 = new IdentifierExp(loc, ti->name); + assert(ti->tempdecl); + e1 = new TemplateExp(loc, ti->tempdecl); } else { @@ -7795,7 +8104,7 @@ Ldotti: { /* Go with partial explicit specialization */ - targsi = ti->tiargs; + tiargs = ti->tiargs; tierror = ti; // for error reporting e1 = new DotIdExp(loc, se->e1, ti->name); } @@ -7877,6 +8186,7 @@ Lagain: if (de->e2->op == TOKoverloadset) { ethis = de->e1; + tthis = de->e1->type; e1 = de->e2; } @@ -7898,6 +8208,9 @@ Lagain: if (e1->type) t1 = e1->type->toBasetype(); + arguments = arrayExpressionSemantic(arguments, sc); + preFunctionParameters(loc, sc, arguments); + // Check for call operator overload if (t1) { AggregateDeclaration *ad; @@ -7907,14 +8220,18 @@ Lagain: ad = ((TypeStruct *)t1)->sym; #if DMDV2 - if (ad->sizeok == SIZEOKnone && !ad->ctor && - ad->search(0, Id::ctor, 0)) + if (ad->sizeok == SIZEOKnone) { - // The constructor hasn't been found yet, see bug 8741 - // This can happen if we are inferring type from - // from VarDeclaration::semantic() in declaration.c - error("cannot create a struct until its size is determined"); - return new ErrorExp(); + if (ad->scope) + ad->semantic(ad->scope); + else if (!ad->ctor && ad->search(Loc(), Id::ctor, 0)) + { + // The constructor hasn't been found yet, see bug 8741 + // This can happen if we are inferring type from + // from VarDeclaration::semantic() in declaration.c + error("cannot create a struct until its size is determined"); + return new ErrorExp(); + } } // First look for constructor @@ -7957,8 +8274,10 @@ Lagain: if (e1->op != TOKtype) { - if (ad->aliasthis) + if (ad->aliasthis && e1->type != att1) { + if (!att1 && e1->type->checkAliasThisRec()) + att1 = e1->type; e1 = resolveAliasThis(sc, e1); goto Lagain; } @@ -7985,9 +8304,6 @@ Lagain: } } - arguments = arrayExpressionSemantic(arguments, sc); - preFunctionParameters(loc, sc, arguments); - // If there was an error processing any argument, or the call, // return an error without trying to resolve the function call. if (arguments && arguments->dim) @@ -8003,10 +8319,10 @@ Lagain: // If there was an error processing any template argument, // return an error without trying to resolve the template. - if (targsi && targsi->dim) + if (tiargs && tiargs->dim) { - for (size_t k = 0; k < targsi->dim; k++) - { Object *o = (*targsi)[k]; + for (size_t k = 0; k < tiargs->dim; k++) + { Object *o = (*tiargs)[k]; if (isError(o)) return new ErrorExp(); } @@ -8021,6 +8337,7 @@ Lagain: UnaExp *ue = (UnaExp *)(e1); Expression *ue1 = ue->e1; + Expression *ue1old = ue1; // need for 'right this' check VarDeclaration *v; if (ue1->op == TOKvar && (v = ((VarExp *)ue1)->var->isVarDeclaration()) != NULL && @@ -8030,34 +8347,30 @@ Lagain: ue1 = NULL; } + Dsymbol *s; if (e1->op == TOKdotvar) - { // Do overload resolution + { dve = (DotVarExp *)(e1); - - f = dve->var->isFuncDeclaration(); - assert(f); - f = f->overloadResolve(loc, ue1, arguments); - - ad = f->toParent()->isAggregateDeclaration(); + s = dve->var; } else { dte = (DotTemplateExp *)(e1); - TemplateDeclaration *td = dte->td; - assert(td); - if (!arguments) - // Should fix deduceFunctionTemplate() so it works on NULL argument - arguments = new Expressions(); - f = td->deduceFunctionTemplate(sc, loc, targsi, ue1, arguments); - if (!f) - return new ErrorExp(); - ad = td->toParent()->isAggregateDeclaration(); + s = dte->td; } + + // Do overload resolution + f = resolveFuncCall(loc, sc, s, tiargs, ue1 ? ue1->type : NULL, arguments); + if (!f) + return new ErrorExp(); + ad = f->toParent2()->isAggregateDeclaration(); + if (f->needThis()) { ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); if (ue->e1->op == TOKerror) return ue->e1; ethis = ue->e1; + tthis = ue->e1->type; } /* Cannot call public functions from inside invariant @@ -8089,6 +8402,7 @@ Lagain: } else { + checkRightThis(sc, ue1old); if (e1->op == TOKdotvar) { dve->var = f; @@ -8151,7 +8465,8 @@ Lagain: sc->callSuper |= CSXany_ctor | CSXsuper_ctor; } - f = resolveFuncCall(sc, loc, cd->baseClass->ctor, NULL, NULL, arguments, 0); + tthis = cd->type->addMod(sc->func->type->mod); + f = resolveFuncCall(loc, sc, cd->baseClass->ctor, NULL, tthis, arguments, 0); if (!f) return new ErrorExp(); accessCheck(loc, sc, NULL, f); @@ -8191,7 +8506,8 @@ Lagain: sc->callSuper |= CSXany_ctor | CSXthis_ctor; } - f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0); + tthis = cd->type->addMod(sc->func->type->mod); + f = resolveFuncCall(loc, sc, cd->ctor, NULL, tthis, arguments, 0); if (!f) return new ErrorExp(); checkDeprecated(sc, f); @@ -8218,16 +8534,7 @@ Lagain: Dsymbol *s = NULL; for (size_t i = 0; i < eo->vars->a.dim; i++) { s = eo->vars->a[i]; - FuncDeclaration *f2 = s->isFuncDeclaration(); - if (f2) - { - f2 = f2->overloadResolve(loc, ethis, arguments, 1); - } - else - { TemplateDeclaration *td = s->isTemplateDeclaration(); - assert(td); - f2 = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1); - } + FuncDeclaration *f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, 1); if (f2) { if (f) /* Error if match in more than one overload set, @@ -8283,7 +8590,7 @@ Lagain: else if (e1->op == TOKtemplate) { TemplateExp *te = (TemplateExp *)e1; - f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); + f = resolveFuncCall(loc, sc, te->td, tiargs, NULL, arguments); if (!f) { if (tierror) tierror->error("errors instantiating template"); // give better error message @@ -8299,9 +8606,9 @@ Lagain: e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); goto Lagain; } - else if (!sc->intypeof && !sc->getStructClassScope()) + else if (isNeedThisScope(sc, f)) { - error("need 'this' for %s type %s", f->toChars(), f->type->toChars()); + error("need 'this' for '%s' of type '%s'", f->toChars(), f->type->toChars()); return new ErrorExp(); } } @@ -8314,12 +8621,12 @@ Lagain: return new ErrorExp(); } - if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) + if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug) && !sc->needctfe) { if (sc->func->setImpure()) error("pure function '%s' cannot call impure %s '%s'", sc->func->toPrettyChars(), p, e1->toChars()); } - if (sc->func && tf->trust <= TRUSTsystem) + if (sc->func && tf->trust <= TRUSTsystem && !sc->needctfe) { if (sc->func->setUnsafe()) error("safe function '%s' cannot call system %s '%s'", sc->func->toPrettyChars(), p, e1->toChars()); @@ -8336,8 +8643,8 @@ Lagain: argExpTypesToCBuffer(&buf, arguments, &hgs); buf.writeByte(')'); - if (ethis) - ethis->type->modToBuffer(&buf); + if (tthis) + tthis->modToBuffer(&buf); } else buf.writeByte(')'); @@ -8367,9 +8674,10 @@ Lagain: assert(f); if (ve->hasOverloads) - f = f->overloadResolve(loc, NULL, arguments, 2); + f = resolveFuncCall(loc, sc, f, tiargs, NULL, arguments, 2); else { + f = f->toAliasFunc(); TypeFunction *tf = (TypeFunction *)f->type; if (!tf->callMatch(NULL, arguments)) { @@ -8392,6 +8700,8 @@ Lagain: return new ErrorExp(); } } + if (!f) + return new ErrorExp(); if (f->needThis()) { @@ -8403,9 +8713,9 @@ Lagain: e1 = new DotVarExp(loc, (new ThisExp(loc))->semantic(sc), ve->var); goto Lagain; } - else if (!sc->intypeof && !sc->getStructClassScope()) + else if (isNeedThisScope(sc, f)) { - error("need 'this' for %s type %s", f->toChars(), f->type->toChars()); + error("need 'this' for '%s' of type '%s'", f->toChars(), f->type->toChars()); return new ErrorExp(); } } @@ -8419,10 +8729,13 @@ Lagain: accessCheck(loc, sc, NULL, f); ethis = NULL; + tthis = NULL; - ve->var = f; -// ve->hasOverloads = 0; - ve->type = f->type; + if (ve->hasOverloads) + { + e1 = new VarExp(ve->loc, f, 0); + e1->type = f->type; + } t1 = f->type; } assert(t1->ty == Tfunction); @@ -8431,7 +8744,7 @@ Lagain: if (!arguments) arguments = new Expressions(); int olderrors = global.errors; - type = functionParameters(loc, sc, tf, ethis, arguments, f); + type = functionParameters(loc, sc, tf, tthis, arguments, f); if (olderrors != global.errors) return new ErrorExp(); @@ -8555,6 +8868,36 @@ Expression *AddrExp::semantic(Scope *sc) if (e1->type == Type::terror) return new ErrorExp(); int wasCond = e1->op == TOKquestion; + if (e1->op == TOKdotti) + { + DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1; + TemplateInstance *ti = dti->ti; + assert(!ti->semanticRun); + //assert(ti->needsTypeInference(sc)); + ti->semantic(sc); + if (!ti->inst) // if template failed to expand + return new ErrorExp; + Dsymbol *s = ti->inst->toAlias(); + FuncDeclaration *f = s->isFuncDeclaration(); + assert(f); + e1 = new DotVarExp(e1->loc, dti->e1, f); + e1 = e1->semantic(sc); + } + else if (e1->op == TOKimport && + ((ScopeExp *)e1)->sds->isTemplateInstance()) + { + TemplateInstance *ti = (TemplateInstance *)((ScopeExp *)e1)->sds; + assert(!ti->semanticRun); + //assert(ti->needsTypeInference(sc)); + ti->semantic(sc); + if (!ti->inst) // if template failed to expand + return new ErrorExp; + Dsymbol *s = ti->inst->toAlias(); + FuncDeclaration *f = s->isFuncDeclaration(); + assert(f); + e1 = new VarExp(e1->loc, f); + e1 = e1->semantic(sc); + } e1 = e1->toLvalue(sc, NULL); if (e1->op == TOKerror) return e1; @@ -8590,9 +8933,9 @@ Expression *AddrExp::semantic(Scope *sc) { DotVarExp *dve = (DotVarExp *)e1; FuncDeclaration *f = dve->var->isFuncDeclaration(); - if (f) { + f = f->toAliasFunc(); // FIXME, should see overlods - Bugzilla 1983 if (!dve->hasOverloads) f->tookAddressOf++; @@ -8630,7 +8973,6 @@ Expression *AddrExp::semantic(Scope *sc) } FuncDeclaration *f = ve->var->isFuncDeclaration(); - if (f) { #if IN_LLVM @@ -8694,6 +9036,7 @@ Expression *AddrExp::semantic(Scope *sc) ce->e2->type = NULL; ce->e2 = ce->e2->semantic(sc); } + return optimize(WANTvalue); } return this; @@ -8884,6 +9227,8 @@ Expression *NotExp::semantic(Scope *sc) UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); e1 = e1->checkToBoolean(sc); + if (e1->type == Type::terror) + return e1; type = Type::tboolean; } return this; @@ -8911,6 +9256,8 @@ Expression *BoolExp::semantic(Scope *sc) UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); e1 = e1->checkToBoolean(sc); + if (e1->type == Type::terror) + return e1; type = Type::tboolean; } return this; @@ -8985,7 +9332,7 @@ Expression *DeleteExp::semantic(Scope *sc) if (fd) { Expression *e = ea ? new VarExp(loc, v) : e1; - e = new DotVarExp(0, e, fd, 0); + e = new DotVarExp(Loc(), e, fd, 0); eb = new CallExp(loc, e); eb = eb->semantic(sc); } @@ -9083,10 +9430,10 @@ Expression *CastExp::semantic(Scope *sc) if (type) return this; UnaExp::semantic(sc); + e1 = resolveProperties(sc, e1); + if (e1->type) // if not a tuple { - e1 = resolveProperties(sc, e1); - if (!to) { /* Handle cast(const) and cast(immutable), etc. @@ -9162,7 +9509,13 @@ Expression *CastExp::semantic(Scope *sc) } if (tob->isintegral() && t1b->ty == Tarray) - deprecation("casting %s to %s is deprecated", e1->type->toChars(), to->toChars()); + { + error("cannot cast %s to integral type %s", e1->toChars(), to->toChars()); + return new ErrorExp(); + } + + if (tob->ty == Tpointer && t1b->ty == Tdelegate) + deprecation("casting from %s to %s is deprecated", e1->type->toChars(), to->toChars()); } else if (!to) { error("cannot cast tuple"); @@ -9366,6 +9719,26 @@ Lagain: e = new TypeExp(loc, e1->type->arrayOf()); return e->semantic(sc); } + if (!lwr && !upr) + { + if (e1->op == TOKarrayliteral) + { // Convert [a,b,c][] to [a,b,c] + Type *t1b = e1->type->toBasetype(); + Expression *e = e1; + if (t1b->ty == Tsarray) + { + e = e->copy(); + e->type = t1b->nextOf()->arrayOf(); + } + return e; + } + if (e1->op == TOKslice) + { // Convert e[][] to e[] + SliceExp *se = (SliceExp *)e1; + if (!se->lwr && !se->upr) + return se; + } + } e = this; @@ -9408,8 +9781,10 @@ Lagain: e = e->semantic(sc); return e; } - if (ad->aliasthis) + if (ad->aliasthis && e1->type != att1) { + if (!att1 && e1->type->checkAliasThisRec()) + att1 = e1->type; e1 = resolveAliasThis(sc, e1); goto Lagain; } @@ -9440,14 +9815,22 @@ Lagain: } if (lwr) - { lwr = lwr->semantic(sc2); + { + if (t->ty == Ttuple) + lwr = lwr->ctfeSemantic(sc2); + else + 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); + { + if (t->ty == Ttuple) + upr = upr->ctfeSemantic(sc2); + else + upr = upr->semantic(sc2); upr = resolveProperties(sc2, upr); upr = upr->implicitCastTo(sc2, Type::tsize_t); if (upr->type == Type::terror) @@ -9491,13 +9874,7 @@ Lagain: { Expression *e = (*te->exps)[j1 + i]; (*exps)[i] = e; } - if (j1 > 0 && j1 != j2 && sc->func && (*te->exps)[0]->op == TOKdotvar) - { - Expression *einit = ((DotVarExp *)(*te->exps)[0])->e1->isTemp(); - if (einit) - ((DotVarExp *)(*exps)[0])->e1 = einit; - } - e = new TupleExp(loc, exps); + e = new TupleExp(loc, te->e0, exps); } else { Parameters *args = new Parameters; @@ -9549,16 +9926,6 @@ void SliceExp::checkEscapeRef() e1->checkEscapeRef(); } -int SliceExp::isLvalue() -{ - return 1; -} - -Expression *SliceExp::toLvalue(Scope *sc, Expression *e) -{ - return this; -} - int SliceExp::checkModifiable(Scope *sc, int flag) { //printf("SliceExp::checkModifiable %s\n", toChars()); @@ -9571,6 +9938,21 @@ int SliceExp::checkModifiable(Scope *sc, int flag) return 1; } +int SliceExp::isLvalue() +{ + /* slice expression is rvalue in default, but + * conversion to reference of static array is only allowed. + */ + return (type && type->toBasetype()->ty == Tsarray); +} + +Expression *SliceExp::toLvalue(Scope *sc, Expression *e) +{ + //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL); + return (type && type->toBasetype()->ty == Tsarray) + ? this : Expression::toLvalue(sc, e); +} + Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) { error("slice expression %s is not a modifiable lvalue", toChars()); @@ -9922,7 +10304,10 @@ Expression *IndexExp::semantic(Scope *sc) sc = sc->push(sym); } - e2 = e2->semantic(sc); + if (t1->ty == Ttuple) + e2 = e2->ctfeSemantic(sc); + else + e2 = e2->semantic(sc); e2 = resolveProperties(sc, e2); if (e2->type == Type::terror) goto Lerr; @@ -10001,12 +10386,7 @@ Expression *IndexExp::semantic(Scope *sc) if (e1->op == TOKtuple) { e = (*te->exps)[(size_t)index]; - if (sc->func && (*te->exps)[0]->op == TOKdotvar) - { - Expression *einit = ((DotVarExp *)(*te->exps)[0])->e1->isTemp(); - if (einit) - ((DotVarExp *)e)->e1 = einit; - } + e = combine(te->e0, e); } else e = new TypeExp(e1->loc, Parameter::getNth(tup->arguments, (size_t)index)->type); @@ -10094,6 +10474,9 @@ PostExp::PostExp(enum TOK op, Loc loc, Expression *e) Expression *PostExp::semantic(Scope *sc) { Expression *e = this; +#if LOGSEMANTIC + printf("PostExp::semantic('%s')\n", toChars()); +#endif if (!type) { BinExp::semantic(sc); @@ -10110,6 +10493,7 @@ Expression *PostExp::semantic(Scope *sc) return new ErrorExp(); } + e1 = e1->optimize(WANTvalue); if (e1->op != TOKarraylength) e1 = e1->modifiableLvalue(sc, e1); @@ -10246,6 +10630,7 @@ Expression *AssignExp::semantic(Scope *sc) ae->e1 = ae->e1->semantic(sc); ae->e1 = resolveProperties(sc, ae->e1); + Expression *e1 = ae->e1; Type *t1 = ae->e1->type->toBasetype(); if (t1->ty == Tstruct) { @@ -10264,7 +10649,7 @@ Expression *AssignExp::semantic(Scope *sc) Expressions *a = (Expressions *)ae->arguments->copy(); a->insert(0, e2); - Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); + Expression *e = new DotIdExp(loc, e1, Id::indexass); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; @@ -10272,18 +10657,20 @@ Expression *AssignExp::semantic(Scope *sc) } // No opIndexAssign found yet, but there might be an alias this to try. - if (ad && ad->aliasthis) - { Expression *e = resolveAliasThis(sc, ae->e1); - Type *t = e->type->toBasetype(); - - if (t->ty == Tstruct) + if (ad && ad->aliasthis && t1 != att1) + { + if (!att1 && t1->checkAliasThisRec()) + att1 = t1; + e1 = resolveAliasThis(sc, e1); + t1 = e1->type->toBasetype(); + if (t1->ty == Tstruct) { - ad = ((TypeStruct *)t)->sym; + ad = ((TypeStruct *)t1)->sym; goto L1; } - else if (t->ty == Tclass) + else if (t1->ty == Tclass) { - ad = ((TypeClass *)t)->sym; + ad = ((TypeClass *)t1)->sym; goto L1; } } @@ -10293,14 +10680,15 @@ Expression *AssignExp::semantic(Scope *sc) * converted to a.opSlice() already. */ if (e1->op == TOKslice) - { Type *t1; + { SliceExp *ae = (SliceExp *)e1; AggregateDeclaration *ad = NULL; Identifier *id = Id::index; ae->e1 = ae->e1->semantic(sc); ae->e1 = resolveProperties(sc, ae->e1); - t1 = ae->e1->type->toBasetype(); + Expression *e1 = ae->e1; + Type *t1 = ae->e1->type->toBasetype(); if (t1->ty == Tstruct) { ad = ((TypeStruct *)t1)->sym; @@ -10321,7 +10709,7 @@ Expression *AssignExp::semantic(Scope *sc) { a->push(ae->lwr); a->push(ae->upr); } - Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); + Expression *e = new DotIdExp(loc, e1, Id::sliceass); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; @@ -10329,18 +10717,20 @@ Expression *AssignExp::semantic(Scope *sc) } // No opSliceAssign found yet, but there might be an alias this to try. - if (ad && ad->aliasthis) - { Expression *e = resolveAliasThis(sc, ae->e1); - Type *t = e->type->toBasetype(); - - if (t->ty == Tstruct) + if (ad && ad->aliasthis && t1 != att1) + { + if (!att1 && t1->checkAliasThisRec()) + att1 = t1; + e1 = resolveAliasThis(sc, e1); + t1 = e1->type->toBasetype(); + if (t1->ty == Tstruct) { - ad = ((TypeStruct *)t)->sym; + ad = ((TypeStruct *)t1)->sym; goto L2; } - else if (t->ty == Tclass) + else if (t1->ty == Tclass) { - ad = ((TypeClass *)t)->sym; + ad = ((TypeClass *)t1)->sym; goto L2; } } @@ -10354,23 +10744,19 @@ Expression *AssignExp::semantic(Scope *sc) */ if (e1->op == TOKdotti) { - Expression *e = resolveProperty(sc, &e1, e2); - if (e) return e; + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)e1; + Expression *e = dti->semanticY(sc, 1); + if (!e) + return resolveUFCSProperties(sc, e1, e2); + e1 = e; } else if (e1->op == TOKdot) { - Expression *e = resolveProperty(sc, &e1, e2); - if (e) return e; - - VarDeclaration * vd = NULL; - if (e1->op == TOKvar) - vd = ((VarExp *)e1)->var->isVarDeclaration(); - - if (vd && vd->needThis()) - { - error("need 'this' to access member %s", e1->toChars()); - return new ErrorExp(); - } + DotIdExp *die = (DotIdExp *)e1; + Expression *e = die->semanticY(sc, 1); + if (!e) + return resolveUFCSProperties(sc, e1, e2); + e1 = e; } e1 = e1->semantic(sc); if (e1->op == TOKerror) @@ -10383,31 +10769,31 @@ Expression *AssignExp::semantic(Scope *sc) * f() = value */ TemplateDeclaration *td; - Objects *targsi; + Objects *tiargs; FuncDeclaration *fd; - Expression *ethis; + Type *tthis; if (e1->op == TOKdotti) { DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1; td = dti->getTempdecl(sc); dti->ti->semanticTiargs(sc); - targsi = dti->ti->tiargs; - ethis = dti->e1; + tiargs = dti->ti->tiargs; + tthis = dti->e1->type; goto L3; } else if (e1->op == TOKdottd) { DotTemplateExp *dte = (DotTemplateExp *)e1; td = dte->td; - targsi = NULL; - ethis = dte->e1; + tiargs = NULL; + tthis = dte->e1->type; goto L3; } else if (e1->op == TOKtemplate) { td = ((TemplateExp *)e1)->td; - targsi = NULL; - ethis = NULL; + tiargs = NULL; + tthis = NULL; L3: { e2 = e2->semantic(sc); @@ -10419,11 +10805,11 @@ Expression *AssignExp::semantic(Scope *sc) Expressions a; a.push(e2); - fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, &a, 1); + fd = resolveFuncCall(loc, sc, td, tiargs, tthis, &a, 1); if (fd && fd->type) goto Lsetter; - fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, NULL, 1); + fd = resolveFuncCall(loc, sc, td, tiargs, tthis, NULL, 1); if (fd && fd->type) goto Lgetter; } @@ -10433,13 +10819,13 @@ Expression *AssignExp::semantic(Scope *sc) { DotVarExp *dve = (DotVarExp *)e1; fd = dve->var->isFuncDeclaration(); - ethis = dve->e1; + tthis = dve->e1->type; goto L4; } else if (e1->op == TOKvar && e1->type->toBasetype()->ty == Tfunction) { fd = ((VarExp *)e1)->var->isFuncDeclaration(); - ethis = NULL; + tthis = NULL; L4: { e2 = e2->semantic(sc); @@ -10452,11 +10838,11 @@ Expression *AssignExp::semantic(Scope *sc) Expressions a; a.push(e2); - fd = f->overloadResolve(loc, ethis, &a, 1); + fd = resolveFuncCall(loc, sc, f, NULL, tthis, &a, 1); if (fd && fd->type) goto Lsetter; - fd = f->overloadResolve(loc, ethis, NULL, 1); + fd = resolveFuncCall(loc, sc, f, NULL, tthis, NULL, 1); if (fd && fd->type) goto Lgetter; @@ -10490,6 +10876,8 @@ Expression *AssignExp::semantic(Scope *sc) return new ErrorExp(); } + e1 = checkRightThis(sc, e1); + assert(e1->type); Type *t1 = e1->type->toBasetype(); @@ -10515,15 +10903,17 @@ Ltupleassign: return new ErrorExp(); } else - { Expressions *exps = new Expressions; + { + Expressions *exps = new Expressions; exps->setDim(dim); + Expression *e0 = combine(tup1->e0, tup2->e0); for (size_t i = 0; i < dim; i++) { Expression *ex1 = (*tup1->exps)[i]; Expression *ex2 = (*tup2->exps)[i]; (*exps)[i] = new AssignExp(loc, ex1, ex2); } - Expression *e = new TupleExp(loc, exps); + Expression *e = new TupleExp(loc, e0, exps); e = e->semantic(sc); return e; } @@ -10540,11 +10930,12 @@ Ltupleassign: ExpInitializer *ei = new ExpInitializer(e2->loc, e2); VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, ei); v->storage_class = STCctfe | STCref | STCforeach; - Expression *ve = new VarExp(e2->loc, v); - ve->type = e2->type; + Expression *e0 = new DeclarationExp(e2->loc, v); + Expression *ev = new VarExp(e2->loc, v); + ev->type = e2->type; Expressions *iexps = new Expressions(); - iexps->push(ve); + iexps->push(ev); for (size_t u = 0; u < iexps->dim ; u++) { @@ -10565,8 +10956,7 @@ Ltupleassign: goto Lnomatch; } } - (*iexps)[0] = new CommaExp(loc, new DeclarationExp(e2->loc, v), (*iexps)[0]); - e2 = new TupleExp(e2->loc, iexps); + e2 = new TupleExp(e2->loc, e0, iexps); e2 = e2->semantic(sc); goto Ltupleassign; @@ -10602,7 +10992,7 @@ Ltupleassign: Type * aaValueType = ((TypeAArray *)((IndexExp*)e1)->e1->type->toBasetype())->next; Identifier *id = Lexer::uniqueId("__aatmp"); VarDeclaration *v = new VarDeclaration(loc, aaValueType, - id, new VoidInitializer(0)); + id, new VoidInitializer(Loc())); v->storage_class |= STCctfe; v->semantic(sc); v->parent = sc->parent; @@ -10698,11 +11088,31 @@ Ltupleassign: else { // Convert e2 to e2[], unless e2-> e1[0] - if (t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) + if (e2->op != TOKarrayliteral && t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) { e2 = new SliceExp(e2->loc, e2, NULL, NULL); e2 = e2->semantic(sc); } + else if (global.params.warnings && !global.gag && op == TOKassign && + e2->op != TOKarrayliteral && e2->op != TOKstring) + { // Disallow sa = da (Converted to sa[] = da[]) + // Disallow sa = e (Converted to sa[] = e) + const char* e1str = e1->toChars(); + const char* e2str = e2->toChars(); + if (e2->op == TOKslice || t2->implicitConvTo(t1->nextOf())) + warning("explicit element-wise assignment (%s)[] = %s is better than %s = %s", + e1str, e2str, e1str, e2str); + else + warning("explicit element-wise assignment (%s)[] = (%s)[] is better than %s = %s", + e1str, e2str, e1str, e2str); + + // Convert e2 to e2[] to avoid duplicated error message. + if (t2->ty == Tarray) + { + Expression *e = new SliceExp(e2->loc, e2, NULL, NULL); + e2 = e->semantic(sc); + } + } // Convert e1 to e1[] Expression *e = new SliceExp(e1->loc, e1, NULL, NULL); @@ -10717,6 +11127,7 @@ Ltupleassign: ArrayLengthExp *ale = (ArrayLengthExp *)e1; ale->e1 = ale->e1->modifiableLvalue(sc, e1); + checkDefCtor(ale->loc, ale->e1->type->toBasetype()->nextOf()); } else if (e1->op == TOKslice) { @@ -10732,7 +11143,7 @@ Ltupleassign: if (e1->op != TOKvar) e1 = e1->optimize(WANTvalue); - if (op != TOKconstruct) + if (op == TOKassign) e1 = e1->modifiableLvalue(sc, e1old); } @@ -10771,19 +11182,25 @@ Ltupleassign: (t2->ty == Tarray || t2->ty == Tsarray) && t2->nextOf()->implicitConvTo(t1->nextOf())) { - if (((SliceExp *)e1)->lwr == NULL) + SliceExp *se1 = (SliceExp *)e1; + Type *tx1 = se1->e1->type->toBasetype(); + if (se1->lwr == NULL && tx1->ty == Tsarray) { - Type *tx1 = ((SliceExp *)e1)->e1->type->toBasetype(); Type *tx2 = t2; if (e2->op == TOKslice && ((SliceExp *)e2)->lwr == NULL) tx2 = ((SliceExp *)e2)->e1->type->toBasetype(); - if (tx1->ty == Tsarray && tx2->ty == Tsarray) + uinteger_t dim1, dim2; + if (e2->op == TOKarrayliteral) + { dim2 = ((ArrayLiteralExp *)e2)->elements->dim; + goto Lsa; + } + if (tx2->ty == Tsarray) { // sa1[] = sa2[]; // sa1[] = sa2; - TypeSArray *tsa1 = (TypeSArray *)tx1; - TypeSArray *tsa2 = (TypeSArray *)tx2; - uinteger_t dim1 = tsa1->dim->toInteger(); - uinteger_t dim2 = tsa2->dim->toInteger(); + // sa1[] = [ ... ]; + dim2 = ((TypeSArray *)tx2)->dim->toInteger(); + Lsa: + dim1 = ((TypeSArray *)tx1)->dim->toInteger(); if (dim1 != dim2) { error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2); @@ -10798,6 +11215,23 @@ Ltupleassign: { checkPostblit(e2->loc, t2->nextOf()); } + if (global.params.warnings && !global.gag && op == TOKassign && + e2->op != TOKslice && e2->op != TOKassign && + e2->op != TOKarrayliteral && e2->op != TOKstring && + !(e2->op == TOKadd || e2->op == TOKmin || + e2->op == TOKmul || e2->op == TOKdiv || + e2->op == TOKmod || e2->op == TOKxor || + e2->op == TOKand || e2->op == TOKor || + #if DMDV2 + e2->op == TOKpow || + #endif + e2->op == TOKtilde || e2->op == TOKneg)) + { + const char* e1str = e1->toChars(); + const char* e2str = e2->toChars(); + warning("explicit element-wise assignment %s = (%s)[] is better than %s = %s", + e1str, e2str, e1str, e2str); + } if (op == TOKconstruct) e2 = e2->castTo(sc, e1->type->constOf()); else @@ -10805,6 +11239,18 @@ Ltupleassign: } else { + if (global.params.warnings && !global.gag && op == TOKassign && + t1->ty == Tarray && t2->ty == Tsarray && + e2->op != TOKslice && //e2->op != TOKarrayliteral && + t2->implicitConvTo(t1)) + { // Disallow ar[] = sa (Converted to ar[] = sa[]) + // Disallow da = sa (Converted to da = sa[]) + const char* e1str = e1->toChars(); + const char* e2str = e2->toChars(); + warning("explicit %s assignment %s = (%s)[] is better than %s = %s", + e1->op == TOKslice ? "element-wise" : "slice", + e1str, e2str, e1str, e2str); + } e2 = e2->implicitCastTo(sc, e1->type); } if (e2->op == TOKerror) @@ -10839,7 +11285,7 @@ Ltupleassign: type = e1->type; assert(type); - return this; + return reorderSettingAAElem(sc); } Expression *AssignExp::checkToBoolean(Scope *sc) @@ -10915,7 +11361,7 @@ Expression *CatAssignExp::semantic(Scope *sc) (e2->implicitConvTo(e1->type) #if DMDV2 || (tb2->nextOf()->implicitConvTo(tb1next) && - (tb2->nextOf()->size(0) == tb1next->size(0) || + (tb2->nextOf()->size(Loc()) == tb1next->size(Loc()) || tb1next->ty == Tchar || tb1next->ty == Twchar || tb1next->ty == Tdchar)) #endif ) @@ -10924,7 +11370,6 @@ Expression *CatAssignExp::semantic(Scope *sc) checkPostblit(e1->loc, tb1next); e2 = e2->castTo(sc, e1->type); type = e1->type; - e = this; } else if ((tb1->ty == Tarray) && e2->implicitConvTo(tb1next) @@ -10933,7 +11378,6 @@ Expression *CatAssignExp::semantic(Scope *sc) checkPostblit(e2->loc, tb2); e2 = e2->castTo(sc, tb1next); type = e1->type; - e = this; } else if (tb1->ty == Tarray && (tb1next->ty == Tchar || tb1next->ty == Twchar) && @@ -10943,7 +11387,6 @@ Expression *CatAssignExp::semantic(Scope *sc) { // Append dchar to char[] or wchar[] e2 = e2->castTo(sc, Type::tdchar); type = e1->type; - e = this; /* Do not allow appending wchar to char[] because if wchar happens * to be a surrogate pair, nothing good can result. @@ -10953,9 +11396,9 @@ Expression *CatAssignExp::semantic(Scope *sc) { if (tb1 != Type::terror && tb2 != Type::terror) error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); - e = new ErrorExp(); + return new ErrorExp(); } - return e; + return reorderSettingAAElem(sc); } /************************************************************/ @@ -11062,6 +11505,9 @@ Expression *PowAssignExp::semantic(Scope *sc) else { e1 = e1->modifiableLvalue(sc, e1); + + e = reorderSettingAAElem(sc); + if (e != this) return e; } if ( (e1->type->isintegral() || e1->type->isfloating()) && @@ -11212,7 +11658,7 @@ Expression *MinExp::semantic(Scope *sc) } else { - e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); + e = new DivExp(loc, this, new IntegerExp(Loc(), stride, Type::tptrdiff_t)); e->type = Type::tptrdiff_t; } return e; @@ -11322,7 +11768,7 @@ Expression *CatExp::semantic(Scope *sc) checkPostblit(e2->loc, tb2); e2 = e2->implicitCastTo(sc, tb1next); type = tb1next->arrayOf(); - if (tb2->ty == Tarray) + if (tb2->ty == Tarray || tb2->ty == Tsarray) { // Make e2 into [e2] e2 = new ArrayLiteralExp(e2->loc, e2); e2->type = type; @@ -11336,7 +11782,7 @@ Expression *CatExp::semantic(Scope *sc) checkPostblit(e1->loc, tb1); e1 = e1->implicitCastTo(sc, tb2next); type = tb2next->arrayOf(); - if (tb1->ty == Tarray) + if (tb1->ty == Tarray || tb1->ty == Tsarray) { // Make e1 into [e1] e1 = new ArrayLiteralExp(e1->loc, e1); e1->type = type; @@ -11655,7 +12101,7 @@ Expression *PowExp::semantic(Scope *sc) // Replace x^^2 with (tmp = x, tmp*tmp) // Replace x^^3 with (tmp = x, tmp*tmp*tmp) Identifier *idtmp = Lexer::uniqueId("__powtmp"); - VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1)); + VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(Loc(), e1)); tmp->storage_class = STCctfe; Expression *ve = new VarExp(loc, tmp); Expression *ae = new DeclarationExp(loc, tmp); @@ -12249,7 +12695,7 @@ int needDirectEq(Type *t1, Type *t2) if (t->ty != Tstruct) return FALSE; - return ((TypeStruct *)t)->sym->xeq == StructDeclaration::xerreq; + return ((TypeStruct *)t)->sym->hasIdentityEquals; } Expression *EqualExp::semantic(Scope *sc) @@ -12339,6 +12785,62 @@ Expression *EqualExp::semantic(Scope *sc) return new ErrorExp(); } + if (t1->ty == Tstruct && t2->ty == Tstruct) + { + StructDeclaration *sd = ((TypeStruct *)t1)->sym; + if (sd == ((TypeStruct *)t2)->sym) + { + if (sd->needOpEquals()) + { + this->e1 = new DotIdExp(loc, e1, Id::tupleof); + this->e2 = new DotIdExp(loc, e2, Id::tupleof); + e = this; + } + else + { + e = new IdentityExp(op == TOKequal ? TOKidentity : TOKnotidentity, loc, e1, e2); + } + e = e->semantic(sc); + return e; + } + } + + if (e1->op == TOKtuple && e2->op == TOKtuple) + { + TupleExp *tup1 = (TupleExp *)e1; + TupleExp *tup2 = (TupleExp *)e2; + size_t dim = tup1->exps->dim; + Expression *e = NULL; + if (dim != tup2->exps->dim) + { + error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); + return new ErrorExp(); + } + if (dim == 0) + { + // zero-length tuple comparison should always return true or false. + e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); + } + else + { + for (size_t i = 0; i < dim; i++) + { + Expression *ex1 = (*tup1->exps)[i]; + Expression *ex2 = (*tup2->exps)[i]; + Expression *eeq = new EqualExp(op, loc, ex1, ex2); + if (!e) + e = eeq; + else if (op == TOKequal) + e = new AndAndExp(loc, e, eeq); + else + e = new OrOrExp(loc, e, eeq); + } + } + assert(e); + e = combine(combine(tup1->e0, tup2->e0), e); + return e->semantic(sc); + } + e = typeCombine(sc); if (e->op == TOKerror) return e; @@ -12604,7 +13106,7 @@ FileInitExp::FileInitExp(Loc loc) Expression *FileInitExp::semantic(Scope *sc) { //printf("FileInitExp::semantic()\n"); - type = Type::tchar->invariantOf()->arrayOf(); + type = Type::tstring; return this; } @@ -12638,6 +13140,107 @@ Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc) return e; } +/****************************************************************/ + +ModuleInitExp::ModuleInitExp(Loc loc) + : DefaultInitExp(loc, TOKmodulestring, sizeof(ModuleInitExp)) +{ +} + +Expression *ModuleInitExp::semantic(Scope *sc) +{ + //printf("ModuleInitExp::semantic()\n"); + type = Type::tstring; + return this; +} + +Expression *ModuleInitExp::resolveLoc(Loc loc, Scope *sc) +{ + const char *s; + if (sc->callsc) + s = sc->callsc->module->toPrettyChars(); + else + s = sc->module->toPrettyChars(); + Expression *e = new StringExp(loc, (char *)s); + e = e->semantic(sc); + e = e->castTo(sc, type); + return e; +} + +/****************************************************************/ + +FuncInitExp::FuncInitExp(Loc loc) + : DefaultInitExp(loc, TOKfuncstring, sizeof(FuncInitExp)) +{ +} + +Expression *FuncInitExp::semantic(Scope *sc) +{ + //printf("FuncInitExp::semantic()\n"); + type = Type::tstring; + if (sc->func) return this->resolveLoc(Loc(), sc); + return this; +} + +Expression *FuncInitExp::resolveLoc(Loc loc, Scope *sc) +{ + const char *s; + if (sc->callsc && sc->callsc->func) + s = sc->callsc->func->Dsymbol::toPrettyChars(); + else if (sc->func) + s = sc->func->Dsymbol::toPrettyChars(); + else + s = ""; + Expression *e = new StringExp(loc, (char *)s); + e = e->semantic(sc); + e = e->castTo(sc, type); + return e; +} + +/****************************************************************/ + +PrettyFuncInitExp::PrettyFuncInitExp(Loc loc) + : DefaultInitExp(loc, TOKprettyfunc, sizeof(PrettyFuncInitExp)) +{ +} + +Expression *PrettyFuncInitExp::semantic(Scope *sc) +{ + //printf("PrettyFuncInitExp::semantic()\n"); + type = Type::tstring; + if (sc->func) return this->resolveLoc(Loc(), sc); + return this; +} + +Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc) +{ + FuncDeclaration *fd; + if (sc->callsc && sc->callsc->func) + fd = sc->callsc->func; + else + fd = sc->func; + + const char *s; + if (fd) + { + const char *funcStr = fd->Dsymbol::toPrettyChars(); + HdrGenState hgs; + OutBuffer buf; + functionToCBuffer2((TypeFunction *)fd->type, &buf, &hgs, 0, funcStr); + buf.writebyte(0); + s = (const char *)buf.extractData(); + } + else + { + s = ""; + } + + Expression *e = new StringExp(loc, (char *)s); + e = e->semantic(sc); + e = e->castTo(sc, type); + return e; +} + /************************************** * Runs semantic on ae->arguments. Declares temporary variables * if '$' was used. @@ -12665,7 +13268,7 @@ ArrayExp *resolveOpDollar(Scope *sc, ArrayExp *ae) if (ae->lengthVar) { // If $ was used, declare it now Expression *de = new DeclarationExp(ae->loc, ae->lengthVar); - e = new CommaExp(0, de, e); + e = new CommaExp(Loc(), de, e); e = e->semantic(sc); } (*ae->arguments)[i] = e; @@ -12705,9 +13308,69 @@ SliceExp *resolveOpDollar(Scope *sc, SliceExp *se) if (se->lengthVar) { // If $ was used, declare it now Expression *de = new DeclarationExp(se->loc, se->lengthVar); - se->lwr = new CommaExp(0, de, se->lwr); + se->lwr = new CommaExp(Loc(), de, se->lwr); se->lwr = se->lwr->semantic(sc); } sc = sc->pop(); return se; } + +Expression *BinExp::reorderSettingAAElem(Scope *sc) +{ + if (this->e1->op != TOKindex) + return this; + IndexExp *ie = (IndexExp *)e1; + Type *t1 = ie->e1->type->toBasetype(); + if (t1->ty != Taarray) + return this; + + /* Check recursive conversion */ + VarDeclaration *var; + bool isrefvar = (e2->op == TOKvar && + (var = ((VarExp *)e2)->var->isVarDeclaration()) != NULL && + (var->storage_class & STCref)); + if (isrefvar) + return this; + + /* Fix evaluation order of setting AA element. (Bugzilla 3825) + * Rewrite: + * aa[key] op= val; + * as: + * ref __aatmp = aa; + * ref __aakey = key; + * ref __aaval = val; + * __aatmp[__aakey] op= __aaval; // assignment + */ + Expression *ec = NULL; + if (ie->e1->hasSideEffect()) + { + Identifier *id = Lexer::uniqueId("__aatmp"); + VarDeclaration *vd = new VarDeclaration(ie->e1->loc, ie->e1->type, id, new ExpInitializer(ie->e1->loc, ie->e1)); + vd->storage_class |= STCref | STCforeach; + Expression *de = new DeclarationExp(ie->e1->loc, vd); + + ec = de; + ie->e1 = new VarExp(ie->e1->loc, vd); + } + if (ie->e2->hasSideEffect()) + { + Identifier *id = Lexer::uniqueId("__aakey"); + VarDeclaration *vd = new VarDeclaration(ie->e2->loc, ie->e2->type, id, new ExpInitializer(ie->e2->loc, ie->e2)); + vd->storage_class |= STCref | STCforeach; + Expression *de = new DeclarationExp(ie->e2->loc, vd); + + ec = ec ? new CommaExp(loc, ec, de) : de; + ie->e2 = new VarExp(ie->e2->loc, vd); + } + { + Identifier *id = Lexer::uniqueId("__aaval"); + VarDeclaration *vd = new VarDeclaration(loc, this->e2->type, id, new ExpInitializer(this->e2->loc, this->e2)); + vd->storage_class |= STCref | STCforeach; + Expression *de = new DeclarationExp(this->e2->loc, vd); + + ec = ec ? new CommaExp(loc, ec, de) : de; + this->e2 = new VarExp(this->e2->loc, vd); + } + ec = new CommaExp(loc, ec, this); + return ec->semantic(sc); +} diff --git a/dmd2/expression.h b/dmd2/expression.h index 94fe0e46e7..47794e61a6 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -52,7 +52,7 @@ struct Initializer; struct StringExp; #if IN_LLVM struct AssignExp; -struct StaticStructInitDeclaration; +struct SymbolDeclaration; #endif enum TOK; @@ -76,6 +76,7 @@ class DValue; namespace llvm { class Constant; class ConstantInt; + class GlobalVariable; class StructType; } #endif @@ -102,7 +103,7 @@ int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); #if DMDV2 Expression *resolveAliasThis(Scope *sc, Expression *e); Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope); -int checkPostblit(Loc loc, Type *t); +bool checkPostblit(Loc loc, Type *t); #endif struct ArrayExp *resolveOpDollar(Scope *sc, struct ArrayExp *ae); struct SliceExp *resolveOpDollar(Scope *sc, struct SliceExp *se); @@ -118,6 +119,13 @@ enum CtfeGoal ctfeNeedNothing // The return value is not required }; +#define WANTflags 1 +#define WANTvalue 2 +// 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 + struct Expression : Object { Loc loc; // file location @@ -127,11 +135,13 @@ struct Expression : Object unsigned char parens; // if this is a parenthesized expression Expression(Loc loc, enum TOK op, int size); + static void init(); Expression *copy(); virtual Expression *syntaxCopy(); virtual int apply(apply_fp_t fp, void *param); virtual Expression *semantic(Scope *sc); Expression *trySemantic(Scope *sc); + Expression *ctfeSemantic(Scope *sc); int dyncast() { return DYNCAST_EXPRESSION; } // kludge for template.isExpression() @@ -161,7 +171,7 @@ struct Expression : Object virtual MATCH implicitConvTo(Type *t); virtual IntRange getIntRange(); virtual Expression *castTo(Scope *sc, Type *t); - virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); + virtual Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL); virtual void checkEscape(); virtual void checkEscapeRef(); virtual Expression *resolveLoc(Loc loc, Scope *sc); @@ -185,12 +195,6 @@ struct Expression : Object Expression *toDelegate(Scope *sc, Type *t); virtual Expression *optimize(int result, bool keepLvalue = false); - #define WANTflags 1 - #define WANTvalue 2 - // 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 // Entry point for CTFE. // A compile-time result is required. Give an error if not possible @@ -329,7 +333,6 @@ struct ComplexExp : Expression int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); - OutBuffer hexp; #if IN_DMD elem *toElem(IRState *irs); dt_t **toDt(dt_t **pdt); @@ -345,7 +348,6 @@ struct IdentifierExp : Expression Declaration *var; IdentifierExp(Loc loc, Identifier *ident); - IdentifierExp(Loc loc, Declaration *var); Expression *semantic(Scope *sc); char *toChars(); void dump(int indent); @@ -476,8 +478,17 @@ struct StringExp : Expression struct TupleExp : Expression { + Expression *e0; // side-effect part + /* Tuple-field access may need to take out its side effect part. + * For example: + * foo().tupleof + * is rewritten as: + * (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...)) + * The declaration of temporary variable __tup will be stored in TupleExp::e0. + */ Expressions *exps; + TupleExp(Loc loc, Expression *e0, Expressions *exps); TupleExp(Loc loc, Expressions *exps); TupleExp(Loc loc, TupleDeclaration *tup); Expression *syntaxCopy(); @@ -513,6 +524,11 @@ struct ArrayLiteralExp : Expression int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); int isBool(int result); +#if IN_LLVM + DValue* toElem(IRState* irs); +#else + elem *toElem(IRState *irs); +#endif StringExp *toString(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); @@ -520,18 +536,15 @@ struct ArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); + Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL); +#if IN_LLVM + llvm::Constant *toConstElem(IRState *irs); +#else + dt_t **toDt(dt_t **pdt); +#endif Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); - -#if IN_DMD - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -#elif IN_LLVM - DValue* toElem(IRState* irs); - llvm::Constant *toConstElem(IRState *irs); -#endif }; struct AssocArrayLiteralExp : Expression @@ -555,7 +568,7 @@ struct AssocArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); + Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -565,6 +578,17 @@ struct AssocArrayLiteralExp : Expression #endif }; +// scrubReturnValue is running +#define stageScrub 0x1 +// hasNonConstPointers is running +#define stageSearchPointers 0x2 +// optimize is running +#define stageOptimize 0x4 +// apply is running +#define stageApply 0x8 +//inlineScan is running +#define stageInlineScan 0x10 + struct StructLiteralExp : Expression { StructDeclaration *sd; // which aggregate this is for @@ -581,8 +605,19 @@ struct StructLiteralExp : Expression bool ownedByCtfe; // true = created in CTFE int ctorinit; - StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); + StructLiteralExp *origin; // pointer to the origin instance of the expression. + // once a new expression is created, origin is set to 'this'. + // anytime when an expression copy is created, 'origin' pointer is set to + // 'origin' pointer value of the original expression. + StructLiteralExp *inlinecopy; // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. + int stageflags; // anytime when recursive function is calling, 'stageflags' marks with bit flag of + // current stage and unmarks before return from this function. + // 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline' + // (with infinite recursion) of this expression. + + StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL); + int equals(Object *o); Expression *syntaxCopy(); int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); @@ -592,35 +627,37 @@ struct StructLiteralExp : Expression void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); +#if IN_LLVM + DValue* toElem(IRState* irs); + // With the introduction of pointers returned from CTFE, struct literals can + // now contain pointers to themselves. While in toElem, contains a pointer + // to the memory used to build the literal for resolving such references. + llvm::Value* inProgressMemory; + + llvm::Constant *toConstElem(IRState *irs); + // A global variable for taking the address of this struct literal constant, + // if it already exists. Used to resolve self-references. + llvm::GlobalVariable *globalVar; + + /// Set if this is really the result of a struct .init access and should be + /// resolved codegen'd as an access to the given SymbolDeclaration. + // LDC_FIXME: Figure out whether this, i.e. imitating the DMD behavior, is + // really the best way to fix the nested struct constant folding issue. + SymbolDeclaration *sinit; +#else + dt_t **toDt(dt_t **pdt); + Symbol *toSymbol(); +#endif MATCH implicitConvTo(Type *t); + Expression *castTo(Scope *sc, Type *t); int inlineCost3(InlineCostState *ics); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); - -#if IN_DMD - elem *toElem(IRState *irs); - dt_t **toDt(dt_t **pdt); -#elif IN_LLVM - DValue* toElem(IRState* irs); - llvm::Constant *toConstElem(IRState *irs); - llvm::StructType *constType; - - /// Set if this is really the result of a struct .init access and should be - /// resolved codegen'd as an access to the given StaticStructInitDeclaration. - // LDC_FIXME: Figure out whether this, i.e. imitating the DMD behavior, is - // really the best way to fix the nested struct constant folding issue. - StaticStructInitDeclaration *sinit; -#endif }; -Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident); -#if IN_DMD -#endif - -#if IN_LLVM - DValue* toElem(IRState* irs); -#endif +struct DotIdExp; +DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident); struct TypeExp : Expression { @@ -659,10 +696,13 @@ struct ScopeExp : Expression struct TemplateExp : Expression { TemplateDeclaration *td; + FuncDeclaration *fd; - TemplateExp(Loc loc, TemplateDeclaration *td); + TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd = NULL); int rvalue(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + int isLvalue(); + Expression *toLvalue(Scope *sc, Expression *e); }; struct NewExp : Expression @@ -743,6 +783,7 @@ struct SymOffExp : SymbolExp SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads = 0); Expression *semantic(Scope *sc); + Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void checkEscape(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -800,7 +841,7 @@ struct OverExp : Expression { OverloadSet *vars; - OverExp(OverloadSet *s); + OverExp(Loc loc, OverloadSet *s); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); }; @@ -822,7 +863,7 @@ struct FuncExp : Expression Expression *implicitCastTo(Scope *sc, Type *t); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); + Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD @@ -926,6 +967,7 @@ struct IsExp : Expression struct UnaExp : Expression { Expression *e1; + Type *att1; // Save alias this type to detect recursion UnaExp(Loc loc, enum TOK op, int size, Expression *e1); Expression *syntaxCopy(); @@ -934,8 +976,7 @@ struct UnaExp : Expression void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *optimize(int result, bool keepLvalue = false); void dump(int indent); - Expression *interpretCommon(InterState *istate, CtfeGoal goal, - Expression *(*fp)(Type *, Expression *)); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *resolveLoc(Loc loc, Scope *sc); Expression *doInline(InlineDoState *ids); @@ -949,6 +990,9 @@ struct BinExp : Expression Expression *e1; Expression *e2; + Type *att1; // Save alias this type to detect recursion + Type *att2; // Save alias this type to detect recursion + BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); Expression *syntaxCopy(); int apply(apply_fp_t fp, void *param); @@ -963,6 +1007,7 @@ struct BinExp : Expression Expression *incompatibleTypes(); void dump(int indent); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCompareCommon(InterState *istate, CtfeGoal goal, @@ -977,6 +1022,7 @@ struct BinExp : Expression Expression *op_overload(Scope *sc); Expression *compare_overload(Scope *sc, Identifier *id); + Expression *reorderSettingAAElem(Scope *sc); #if IN_DMD elem *toElemBin(IRState *irs, int op); @@ -993,6 +1039,8 @@ struct BinAssignExp : BinExp Expression *semantic(Scope *sc); Expression *arrayOp(Scope *sc); + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *op_overload(Scope *sc); int isLvalue(); @@ -1045,7 +1093,8 @@ struct DotIdExp : UnaExp DotIdExp(Loc loc, Expression *e, Identifier *ident); Expression *semantic(Scope *sc); - Expression *semantic(Scope *sc, int flag); + Expression *semanticX(Scope *sc); + Expression *semanticY(Scope *sc, int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int i); }; @@ -1091,7 +1140,7 @@ struct DotTemplateInstanceExp : UnaExp Expression *syntaxCopy(); TemplateDeclaration *getTempdecl(Scope *sc); Expression *semantic(Scope *sc); - Expression *semantic(Scope *sc, int flag); + Expression *semanticY(Scope *sc, int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); }; @@ -1147,7 +1196,6 @@ struct CallExp : UnaExp Expression *syntaxCopy(); int apply(apply_fp_t fp, void *param); - Expression *resolveUFCS(Scope *sc); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); @@ -1186,6 +1234,8 @@ struct AddrExp : UnaExp #if IN_LLVM DValue* toElem(IRState* irs); llvm::Constant *toConstElem(IRState *irs); +#else + dt_t **toDt(dt_t **pdt); #endif }; @@ -1220,7 +1270,6 @@ struct NegExp : UnaExp NegExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1251,7 +1300,6 @@ struct ComExp : UnaExp ComExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1273,7 +1321,6 @@ struct NotExp : UnaExp NotExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); #if IN_DMD elem *toElem(IRState *irs); @@ -1289,7 +1336,6 @@ struct BoolExp : UnaExp BoolExp(Loc loc, Expression *e, Type *type); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); #if IN_DMD elem *toElem(IRState *irs); @@ -1344,6 +1390,8 @@ struct CastExp : UnaExp #if IN_LLVM DValue* toElem(IRState* irs); llvm::Constant *toConstElem(IRState *irs); +#else + dt_t **toDt(dt_t **pdt); #endif }; @@ -1383,6 +1431,9 @@ struct SliceExp : UnaExp Expression *modifiableLvalue(Scope *sc, Expression *e); int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + Type *toStaticArrayType(); + MATCH implicitConvTo(Type *t); + Expression *castTo(Scope *sc, Type *t); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void dump(int indent); @@ -1568,7 +1619,6 @@ struct op##AssignExp : BinAssignExp \ { \ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ S(Expression *semantic(Scope *sc);) \ - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ X(Expression *buildArrayLoop(Parameters *fparams);) \ \ @@ -1619,7 +1669,6 @@ struct AddExp : BinExp AddExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1644,7 +1693,6 @@ struct MinExp : BinExp MinExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1688,7 +1736,6 @@ struct MulExp : BinExp MulExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1712,7 +1759,6 @@ struct DivExp : BinExp DivExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1735,7 +1781,6 @@ struct ModExp : BinExp ModExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1759,7 +1804,6 @@ struct PowExp : BinExp PowExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); @@ -1782,7 +1826,6 @@ struct ShlExp : BinExp ShlExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); IntRange getIntRange(); // For operator overloading @@ -1803,7 +1846,6 @@ struct ShrExp : BinExp ShrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); IntRange getIntRange(); // For operator overloading @@ -1824,7 +1866,6 @@ struct UshrExp : BinExp UshrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); IntRange getIntRange(); // For operator overloading @@ -1845,7 +1886,6 @@ struct AndExp : BinExp AndExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); IntRange getIntRange(); @@ -1869,7 +1909,6 @@ struct OrExp : BinExp OrExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); MATCH implicitConvTo(Type *t); @@ -1894,7 +1933,6 @@ struct XorExp : BinExp XorExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); void buildArrayIdent(OutBuffer *buf, Expressions *arguments); Expression *buildArrayLoop(Parameters *fparams); MATCH implicitConvTo(Type *t); @@ -1953,7 +1991,6 @@ struct CmpExp : BinExp CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); // For operator overloading @@ -2011,7 +2048,6 @@ struct EqualExp : BinExp EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); int isBit(); // For operator overloading @@ -2036,13 +2072,10 @@ struct IdentityExp : BinExp Expression *semantic(Scope *sc); int isBit(); Expression *optimize(int result, bool keepLvalue = false); - Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); -#if IN_DMD - elem *toElem(IRState *irs); -#endif - #if IN_LLVM DValue* toElem(IRState* irs); +#else + elem *toElem(IRState *irs); #endif }; @@ -2068,7 +2101,7 @@ struct CondExp : BinExp void toCBuffer(OutBuffer *buf, HdrGenState *hgs); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); + Expression *inferType(Type *t, int flag = 0, Scope *sc = NULL, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -2106,6 +2139,28 @@ struct LineInitExp : DefaultInitExp Expression *semantic(Scope *sc); Expression *resolveLoc(Loc loc, Scope *sc); }; + +struct ModuleInitExp : DefaultInitExp +{ + ModuleInitExp(Loc loc); + Expression *semantic(Scope *sc); + Expression *resolveLoc(Loc loc, Scope *sc); +}; + +struct FuncInitExp : DefaultInitExp +{ + FuncInitExp(Loc loc); + Expression *semantic(Scope *sc); + Expression *resolveLoc(Loc loc, Scope *sc); +}; + +struct PrettyFuncInitExp : DefaultInitExp +{ + PrettyFuncInitExp(Loc loc); + Expression *semantic(Scope *sc); + Expression *resolveLoc(Loc loc, Scope *sc); +}; + #endif /****************************************************************/ @@ -2132,11 +2187,11 @@ struct GEPExp : UnaExp /* Special values used by the interpreter */ -#define EXP_CANT_INTERPRET ((Expression *)1) -#define EXP_CONTINUE_INTERPRET ((Expression *)2) -#define EXP_BREAK_INTERPRET ((Expression *)3) -#define EXP_GOTO_INTERPRET ((Expression *)4) -#define EXP_VOID_INTERPRET ((Expression *)5) +extern Expression *EXP_CANT_INTERPRET; +extern Expression *EXP_CONTINUE_INTERPRET; +extern Expression *EXP_BREAK_INTERPRET; +extern Expression *EXP_GOTO_INTERPRET; +extern Expression *EXP_VOID_INTERPRET; Expression *expType(Type *type, Expression *e); diff --git a/dmd2/func.c b/dmd2/func.c index c24bfb49d4..61595c0281 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -24,6 +24,9 @@ #include "statement.h" #include "template.h" #include "hdrgen.h" +#include "target.h" + +void functionToCBuffer2(TypeFunction *t, OutBuffer *buf, HdrGenState *hgs, int mod, const char *kind); /********************************* FuncDeclaration ****************************/ @@ -68,6 +71,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla inlineStatusStmt = ILSuninitialized; inlineNest = 0; isArrayOp = 0; + dArrayOp = NULL; semanticRun = PASSinit; semantic3Errors = 0; #if DMDV1 @@ -234,6 +238,9 @@ void FuncDeclaration::semantic(Scope *sc) if (StructDeclaration *sd = ad->isStructDeclaration()) sd->makeNested(); } + // Remove prefix storage classes silently. + if ((storage_class & STC_TYPECTOR) && !(ad || isNested())) + storage_class &= ~STC_TYPECTOR; //printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal()); @@ -246,12 +253,34 @@ void FuncDeclaration::semantic(Scope *sc) userAttributes = sc->userAttributes; if (!originalType) - originalType = type; + originalType = type->syntaxCopy(); if (!type->deco) { sc = sc->push(); sc->stc |= storage_class & STCdisable; // forward to function type TypeFunction *tf = (TypeFunction *)type; +#if 1 + /* If the parent is @safe, then this function defaults to safe + * too. + * If the parent's @safe-ty is inferred, then this function's @safe-ty needs + * to be inferred first. + */ + if (tf->trust == TRUSTdefault && + !(//isFuncLiteralDeclaration() || + parent->isTemplateInstance() || + ad && ad->parent && ad->parent->isTemplateInstance())) + { + for (Dsymbol *p = sc->func; p; p = p->toParent2()) + { FuncDeclaration *fd = p->isFuncDeclaration(); + if (fd) + { + if (fd->isSafeBypassingInference()) + tf->trust = TRUSTsafe; // default to @safe + break; + } + } + } +#endif if (tf->isref) sc->stc |= STCref; if (tf->isnothrow) sc->stc |= STCnothrow; if (tf->isproperty) sc->stc |= STCproperty; @@ -261,10 +290,37 @@ void FuncDeclaration::semantic(Scope *sc) if (tf->trust == TRUSTtrusted) sc->stc |= STCtrusted; if (isCtorDeclaration()) + { sc->flags |= SCOPEctor; + Type *tret; + if (!ad || parent->isUnionDeclaration()) + { + error("constructors are only for class or struct definitions"); + tret = Type::tvoid; + } + else + { tret = ad->handle; + assert(tret); + tret = tret->addStorageClass(storage_class | sc->stc); + tret = tret->addMod(type->mod); + } + tf->next = tret; + + if (ad && ad->isStructDeclaration()) + sc->stc |= STCref; + } + sc->linkage = linkage; + if (!tf->isNaked() && !(isThis() || isNested())) + { + OutBuffer buf; + MODtoBuffer(&buf, tf->mod); + error("without 'this' cannot be %s", buf.toChars()); + tf->mod = 0; // remove qualifiers + } + /* Apply const, immutable, wild and shared storage class * to the function type. Do this before type semantic. */ @@ -330,37 +386,27 @@ void FuncDeclaration::semantic(Scope *sc) error("%s must be a function instead of %s", toChars(), type->toChars()); return; } - f = (TypeFunction *)(type); + f = (TypeFunction *)type; size_t nparams = Parameter::dim(f->parameters); - /* Purity and safety can be inferred for some functions by examining - * the function body. - */ - if (fbody && - (isFuncLiteralDeclaration() || parent->isTemplateInstance())) - { - if (f->purity == PUREimpure) // purity not specified - flags |= FUNCFLAGpurityInprocess; - - if (f->trust == TRUSTdefault) - flags |= FUNCFLAGsafetyInprocess; - - if (!f->isnothrow) - flags |= FUNCFLAGnothrowInprocess; - } - if (storage_class & STCscope) error("functions cannot be scope"); if (isAbstract() && !isVirtual()) - error("non-virtual functions cannot be abstract"); + { + const char *sfunc; + if (isStatic()) + sfunc = "static"; + else if (protection == PROTprivate || protection == PROTpackage) + sfunc = Pprotectionnames[protection]; + else + sfunc = "non-virtual"; + error("%s functions cannot be abstract", sfunc); + } if (isOverride() && !isVirtual()) error("cannot override a non-virtual function"); - if ((f->isConst() || f->isImmutable()) && !isThis()) - error("without 'this' cannot be const/immutable"); - if (isAbstract() && isFinal()) error("cannot be both final and abstract"); #if 0 @@ -397,8 +443,8 @@ void FuncDeclaration::semantic(Scope *sc) error("special member functions not allowed for %ss", sd->kind()); } - if (!sd->inv) - sd->inv = isInvariantDeclaration(); + if (isInvariantDeclaration()) + sd->invs.push(this); if (!sd->aggNew) sd->aggNew = isNewDeclaration(); @@ -439,7 +485,6 @@ void FuncDeclaration::semantic(Scope *sc) { size_t vi; CtorDeclaration *ctor; DtorDeclaration *dtor; - InvariantDeclaration *inv; if (isCtorDeclaration()) { @@ -458,10 +503,9 @@ void FuncDeclaration::semantic(Scope *sc) cd->dtor = dtor; } - inv = isInvariantDeclaration(); - if (inv) + if (isInvariantDeclaration()) { - cd->inv = inv; + cd->invs.push(this); } if (isNewDeclaration()) @@ -491,6 +535,20 @@ void FuncDeclaration::semantic(Scope *sc) if (type->nextOf() == Type::terror) goto Ldone; + if (cd->baseClass) + { + Dsymbol *cbd = cd->baseClass; + if (cbd->parent && cbd->parent->isTemplateInstance()) + { + for (size_t i = 0; i < cd->baseClass->vtbl.dim; i++) + { + FuncDeclaration *f = cd->baseClass->vtbl[i]->isFuncDeclaration(); + if (f && f->ident == ident && !f->functionSemantic()) + goto Ldone; + } + } + } + /* Find index of existing function in base class's vtbl[] to override * (the index will be the same as in cd's current vtbl[]) */ @@ -513,9 +571,12 @@ void FuncDeclaration::semantic(Scope *sc) if (s) { FuncDeclaration *f = s->isFuncDeclaration(); - f = f->overloadExactMatch(type); - if (f && f->isFinal() && f->prot() != PROTprivate) - error("cannot override final function %s", f->toPrettyChars()); + if (f) + { + f = f->overloadExactMatch(type); + if (f && f->isFinal() && f->prot() != PROTprivate) + error("cannot override final function %s", f->toPrettyChars()); + } } } @@ -893,6 +954,26 @@ void FuncDeclaration::semantic(Scope *sc) } Ldone: + /* Purity and safety can be inferred for some functions by examining + * the function body. + */ + if (fbody && + (isFuncLiteralDeclaration() || + parent->isTemplateInstance() || + ad && ad->parent && ad->parent->isTemplateInstance() && !isVirtualMethod())) + { + /* isVirtualMethod() needs setting correct foverrides + */ + if (f->purity == PUREimpure) // purity not specified + flags |= FUNCFLAGpurityInprocess; + + if (f->trust == TRUSTdefault) + flags |= FUNCFLAGsafetyInprocess; + + if (!f->isnothrow) + flags |= FUNCFLAGnothrowInprocess; + } + Module::dprogress++; //LDC relies on semanticRun variable not being reset here if(semanticRun < PASSsemanticdone) @@ -903,6 +984,21 @@ Ldone: */ scope = new Scope(*sc); scope->setNoFree(); + + static bool printedMain = false; // semantic might run more than once + if (global.params.verbose && !printedMain) + { + const char *type = isMain() ? "main" : isWinMain() ? "winmain" : isDllMain() ? "dllmain" : (const char *)NULL; + Module *mod = sc->module; + + if (type && mod) + { + printedMain = true; + const char *name = FileName::searchPath(global.path, mod->srcfile->toChars(), 1); + printf("%-10s%-10s\t%s\n", "entry", type, name); + } + } + return; } @@ -944,7 +1040,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (!type || type->ty != Tfunction) return; - f = (TypeFunction *)(type); + f = (TypeFunction *)type; if (!inferRetType && f->next->ty == Terror) return; @@ -1012,7 +1108,8 @@ void FuncDeclaration::semantic3(Scope *sc) sc2->protection = PROTpublic; sc2->explicitProtection = 0; sc2->structalign = STRUCTALIGN_DEFAULT; - sc2->flags = sc->flags & ~SCOPEcontract; + if (this->ident != Id::require && this->ident != Id::ensure) + sc2->flags = sc->flags & ~SCOPEcontract; #if IN_LLVM sc2->enclosingFinally = NULL; sc2->enclosingScopeExit = NULL; @@ -1022,6 +1119,7 @@ void FuncDeclaration::semantic3(Scope *sc) sc2->noctor = 0; sc2->speculative = sc->speculative || isSpeculative() != NULL; sc2->userAttributes = NULL; + if (sc2->intypeof == 1) sc2->intypeof = 2; // Declare 'this' AggregateDeclaration *ad = isThis(); @@ -1064,7 +1162,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->linkage == LINKd) { // Declare _arguments[] - v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); + v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); v_arguments->storage_class = STCparameter; v_arguments->semantic(sc2); sc2->insert(v_arguments); @@ -1072,7 +1170,7 @@ void FuncDeclaration::semantic3(Scope *sc) //t = Type::typeinfo->type->constOf()->arrayOf(); t = Type::typeinfo->type->arrayOf(); - _arguments = new VarDeclaration(0, t, Id::_arguments, NULL); + _arguments = new VarDeclaration(Loc(), t, Id::_arguments, NULL); _arguments->semantic(sc2); sc2->insert(_arguments); _arguments->parent = this; @@ -1080,7 +1178,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) { // Declare _argptr t = Type::tvalist; - argptr = new VarDeclaration(0, t, Id::_argptr, NULL); + argptr = new VarDeclaration(Loc(), t, Id::_argptr, NULL); argptr->semantic(sc2); sc2->insert(argptr); argptr->parent = this; @@ -1095,7 +1193,7 @@ void FuncDeclaration::semantic3(Scope *sc) { for (size_t i = 0; i < Parameter::dim(f->parameters); i++) { Parameter *arg = (Parameter *)Parameter::getNth(f->parameters, i); - Type* nw = arg->type->semantic(0, sc); + Type* nw = arg->type->semantic(Loc(), sc); if (arg->type != nw) { arg->type = nw; // Examine this index again. @@ -1152,8 +1250,6 @@ void FuncDeclaration::semantic3(Scope *sc) arg->ident = id = Identifier::generateId("_param_", i); } Type *vtype = arg->type; - //if (isPure()) - //vtype = vtype->addMod(MODconst); VarDeclaration *v = new VarDeclaration(loc, vtype, id, NULL); //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); v->storage_class |= STCparameter; @@ -1193,7 +1289,7 @@ void FuncDeclaration::semantic3(Scope *sc) for (size_t j = 0; j < dim; j++) { Parameter *narg = Parameter::getNth(t->arguments, j); assert(narg->ident); - VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration(); + VarDeclaration *v = sc2->search(Loc(), narg->ident, NULL)->isVarDeclaration(); assert(v); Expression *e = new VarExp(v->loc, v); (*exps)[j] = e; @@ -1218,7 +1314,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (isDtorDeclaration()) { // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; + FuncDeclaration *inv = ad->inv; ClassDeclaration *cd = ad->isClassDeclaration(); while (!inv && cd) @@ -1230,8 +1326,8 @@ void FuncDeclaration::semantic3(Scope *sc) } if (inv) { - e = new DsymbolExp(0, inv); - e = new CallExp(0, e); + e = new DsymbolExp(Loc(), inv); + e = new CallExp(Loc(), e); e = e->semantic(sc2); } } @@ -1239,22 +1335,22 @@ void FuncDeclaration::semantic3(Scope *sc) { // Call invariant virtually #if IN_LLVM // We actually need a valid 'var' for codegen. - ThisExp* tv = new ThisExp(0); + ThisExp* tv = new ThisExp(Loc()); tv->var = vthis; Expression *v = tv; #else - Expression *v = new ThisExp(0); + Expression *v = new ThisExp(Loc()); #endif v->type = vthis->type; if (ad->isStructDeclaration()) v = v->addressOf(sc); - Expression *se = new StringExp(0, (char *)"null this"); + Expression *se = new StringExp(Loc(), (char *)"null this"); se = se->semantic(sc); se->type = Type::tchar->arrayOf(); e = new AssertExp(loc, v, se); } if (e) - fpreinv = new ExpStatement(0, e); + fpreinv = new ExpStatement(Loc(), e); } // Postcondition invariant @@ -1265,7 +1361,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (isCtorDeclaration()) { // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; + FuncDeclaration *inv = ad->inv; ClassDeclaration *cd = ad->isClassDeclaration(); while (!inv && cd) @@ -1277,8 +1373,8 @@ void FuncDeclaration::semantic3(Scope *sc) } if (inv) { - e = new DsymbolExp(0, inv); - e = new CallExp(0, e); + e = new DsymbolExp(Loc(), inv); + e = new CallExp(Loc(), e); e = e->semantic(sc2); } } @@ -1286,19 +1382,19 @@ void FuncDeclaration::semantic3(Scope *sc) { // Call invariant virtually #if IN_LLVM // We actually need a valid 'var' for codegen. - ThisExp* tv = new ThisExp(0); + ThisExp* tv = new ThisExp(Loc()); tv->var = vthis; Expression *v = tv; #else - Expression *v = new ThisExp(0); + Expression *v = new ThisExp(Loc()); #endif v->type = vthis->type; if (ad->isStructDeclaration()) v = v->addressOf(sc); - e = new AssertExp(0, v); + e = new AssertExp(Loc(), v); } if (e) - fpostinv = new ExpStatement(0, e); + fpostinv = new ExpStatement(Loc(), e); } if (fensure || addPostInvariant()) @@ -1337,7 +1433,7 @@ void FuncDeclaration::semantic3(Scope *sc) fbody = fbody->semantic(sc2); if (!fbody) - fbody = new CompoundStatement(0, new Statements()); + fbody = new CompoundStatement(Loc(), new Statements()); if (inferRetType) { // If no return type inferred yet, then infer a void @@ -1428,19 +1524,18 @@ void FuncDeclaration::semantic3(Scope *sc) sc2->callSuper = 0; // Insert implicit super() at start of fbody - Expression *e1 = new SuperExp(0); - Expression *e = new CallExp(0, e1); - - e = e->trySemantic(sc2); - if (!e) + if (!resolveFuncCall(Loc(), sc2, cd->baseClass->ctor, NULL, NULL, NULL, 1)) { - const char* impGen = ((CtorDeclaration*)this)->isImplicit ? "implicitly generated " : ""; - error("no match for implicit super() call in %sconstructor", impGen); + error("no match for implicit super() call in constructor"); } else { - Statement *s = new ExpStatement(0, e); - fbody = new CompoundStatement(0, s, fbody); + Expression *e1 = new SuperExp(Loc()); + Expression *e = new CallExp(Loc(), e1); + e = e->semantic(sc2); + + Statement *s = new ExpStatement(Loc(), e); + fbody = new CompoundStatement(Loc(), s, fbody); } } @@ -1461,8 +1556,8 @@ void FuncDeclaration::semantic3(Scope *sc) else if (fes) { // For foreach(){} body, append a return 0; Expression *e = new IntegerExp(0); - Statement *s = new ReturnStatement(0, e); - fbody = new CompoundStatement(0, fbody, s); + Statement *s = new ReturnStatement(Loc(), e); + fbody = new CompoundStatement(Loc(), fbody, s); assert(!returnLabel); } else if (!hasReturnExp && type->nextOf()->ty != Tvoid) @@ -1509,10 +1604,10 @@ void FuncDeclaration::semantic3(Scope *sc) } else e = new HaltExp(endloc); - e = new CommaExp(0, e, type->nextOf()->defaultInit()); + e = new CommaExp(Loc(), e, type->nextOf()->defaultInit()); e = e->semantic(sc2); - Statement *s = new ExpStatement(0, e); - fbody = new CompoundStatement(0, fbody, s); + Statement *s = new ExpStatement(Loc(), e); + fbody = new CompoundStatement(Loc(), fbody, s); } } } @@ -1585,7 +1680,7 @@ void FuncDeclaration::semantic3(Scope *sc) assert(ie); if (ie->exp->op == TOKconstruct) ie->exp->op = TOKassign; // construction occured in parameter processing - a->push(new ExpStatement(0, ie->exp)); + a->push(new ExpStatement(Loc(), ie->exp)); } } } @@ -1602,12 +1697,12 @@ void FuncDeclaration::semantic3(Scope *sc) Type *t = argptr->type; if (global.params.is64bit && !global.params.isWindows) { // Initialize _argptr to point to v_argsave - Expression *e1 = new VarExp(0, argptr); - Expression *e = new SymOffExp(0, v_argsave, 6*8 + 8*16); + Expression *e1 = new VarExp(Loc(), argptr); + Expression *e = new SymOffExp(Loc(), v_argsave, 6*8 + 8*16); e->type = argptr->type; - e = new AssignExp(0, e1, e); + e = new AssignExp(Loc(), e1, e); e = e->semantic(sc); - a->push(new ExpStatement(0, e)); + a->push(new ExpStatement(Loc(), e)); } else { // Initialize _argptr to point past non-variadic arg @@ -1615,7 +1710,7 @@ void FuncDeclaration::semantic3(Scope *sc) unsigned offset = 0; Expression *e; - Expression *e1 = new VarExp(0, argptr); + Expression *e1 = new VarExp(Loc(), argptr); // Find the last non-ref parameter if (parameters && parameters->dim) { @@ -1627,7 +1722,7 @@ void FuncDeclaration::semantic3(Scope *sc) */ while (p->storage_class & (STCout | STCref)) { - offset += PTRSIZE; + offset += Target::ptrsize; if (lastNonref-- == 0) { p = v_arguments; @@ -1639,34 +1734,34 @@ void FuncDeclaration::semantic3(Scope *sc) else p = v_arguments; // last parameter is _arguments[] if (global.params.is64bit && global.params.isWindows) - { offset += PTRSIZE; - if (p->storage_class & STClazy) + { offset += Target::ptrsize; + if (p->storage_class & STClazy || p->type->size() > Target::ptrsize) { /* Necessary to offset the extra level of indirection the Win64 * ABI demands */ - e = new SymOffExp(0,p,0); + e = new SymOffExp(Loc(),p,0); e->type = Type::tvoidptr; - e = new AddrExp(0, e); + e = new AddrExp(Loc(), e); e->type = Type::tvoidptr; - e = new AddExp(0, e, new IntegerExp(offset)); + e = new AddExp(Loc(), e, new IntegerExp(offset)); e->type = Type::tvoidptr; goto L1; } } else if (p->storage_class & STClazy) // If the last parameter is lazy, it's the size of a delegate - offset += PTRSIZE * 2; + offset += Target::ptrsize * 2; else offset += p->type->size(); - offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); // assume stack aligns on pointer size - e = new SymOffExp(0, p, offset); + offset = (offset + Target::ptrsize - 1) & ~(Target::ptrsize - 1); // assume stack aligns on pointer size + e = new SymOffExp(Loc(), p, offset); e->type = Type::tvoidptr; //e = e->semantic(sc); L1: - e = new AssignExp(0, e1, e); + e = new AssignExp(Loc(), e1, e); e->type = t; - a->push(new ExpStatement(0, e)); + a->push(new ExpStatement(Loc(), e)); p->isargptr = TRUE; } #endif @@ -1681,12 +1776,12 @@ void FuncDeclaration::semantic3(Scope *sc) /* Advance to elements[] member of TypeInfo_Tuple with: * _arguments = v_arguments.elements; */ - Expression *e = new VarExp(0, v_arguments); - e = new DotIdExp(0, e, Id::elements); - Expression *e1 = new VarExp(0, _arguments); - e = new ConstructExp(0, e1, e); + Expression *e = new VarExp(Loc(), v_arguments); + e = new DotIdExp(Loc(), e, Id::elements); + Expression *e1 = new VarExp(Loc(), _arguments); + e = new ConstructExp(Loc(), e1, e); e = e->semantic(sc2); - a->push(new ExpStatement(0, e)); + a->push(new ExpStatement(Loc(), e)); } #endif // !IN_LLVM @@ -1698,7 +1793,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (!freq) freq = fpreinv; else if (fpreinv) - freq = new CompoundStatement(0, freq, fpreinv); + freq = new CompoundStatement(Loc(), freq, fpreinv); a->push(freq); } @@ -1711,9 +1806,9 @@ void FuncDeclaration::semantic3(Scope *sc) if (!fens) fens = fpostinv; else if (fpostinv) - fens = new CompoundStatement(0, fpostinv, fens); + fens = new CompoundStatement(Loc(), fpostinv, fens); - LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fens); + LabelStatement *ls = new LabelStatement(Loc(), Id::returnLabel, fens); returnLabel->statement = ls; a->push(returnLabel->statement); @@ -1722,32 +1817,32 @@ void FuncDeclaration::semantic3(Scope *sc) #if IN_LLVM Expression *e = 0; if (isCtorDeclaration()) { - ThisExp *te = new ThisExp(0); + ThisExp *te = new ThisExp(Loc()); te->type = vthis->type; te->var = vthis; e = te; } else { - e = new VarExp(0, vresult); + e = new VarExp(Loc(), vresult); } #else // Create: return vresult; - Expression *e = new VarExp(0, vresult); + Expression *e = new VarExp(Loc(), vresult); #endif if (tintro) { e = e->implicitCastTo(sc, tintro->nextOf()); e = e->semantic(sc); } - ReturnStatement *s = new ReturnStatement(0, e); + ReturnStatement *s = new ReturnStatement(Loc(), e); a->push(s); } } if (isMain() && type->nextOf()->ty == Tvoid) { // Add a return 0; statement - Statement *s = new ReturnStatement(0, new IntegerExp(0)); + Statement *s = new ReturnStatement(Loc(), new IntegerExp(0)); a->push(s); } - fbody = new CompoundStatement(0, a); + fbody = new CompoundStatement(Loc(), a); #if DMDV2 /* Append destructor calls for parameters as finally blocks. */ @@ -1764,7 +1859,7 @@ void FuncDeclaration::semantic3(Scope *sc) Expression *e = v->edtor; if (e) - { Statement *s = new ExpStatement(0, e); + { Statement *s = new ExpStatement(Loc(), e); s = s->semantic(sc2); int nothrowErrors = global.errors; bool isnothrow = f->isnothrow & !(flags & FUNCFLAGnothrowInprocess); @@ -1774,9 +1869,9 @@ void FuncDeclaration::semantic3(Scope *sc) if (flags & FUNCFLAGnothrowInprocess && blockexit & BEthrow) f->isnothrow = FALSE; if (fbody->blockExit(f->isnothrow) == BEfallthru) - fbody = new CompoundStatement(0, fbody, s); + fbody = new CompoundStatement(Loc(), fbody, s); else - fbody = new TryFinallyStatement(0, fbody, s); + fbody = new TryFinallyStatement(Loc(), fbody, s); } } } @@ -1798,7 +1893,11 @@ void FuncDeclaration::semantic3(Scope *sc) #else global.params.isWindows && #endif - !isStatic() && !fbody->usesEH()) + !isStatic() && !fbody->usesEH() +#if !IN_LLVM + && !global.params.trace +#endif + ) { /* The back end uses the "jmonitor" hack for syncing; * no need to do the sync at this level. @@ -1855,6 +1954,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (!f->deco) { sc = sc->push(); + sc->stc = 0; sc->linkage = linkage; // Bugzilla 8496 type = f->semantic(loc, sc); sc = sc->pop(); @@ -1898,8 +1998,12 @@ bool FuncDeclaration::functionSemantic() } // if inferring return type, sematic3 needs to be run - if (scope && (inferRetType && type && !type->nextOf() || - getFuncTemplateDecl(this))) + TemplateInstance *ti; + AggregateDeclaration *ad; + if (scope && + (inferRetType && type && !type->nextOf() || + (ti = parent->isTemplateInstance()) != NULL && !ti->isTemplateMixin() && ti->name == ident || + (ad = isThis()) != NULL && ad->parent && ad->parent->isTemplateInstance() && !isVirtualMethod())) { return functionSemantic3(); } @@ -1974,8 +2078,6 @@ VarDeclaration *FuncDeclaration::declareThis(Scope *sc, AggregateDeclaration *ad Type *thandle = ad->handle; thandle = thandle->addMod(type->mod); thandle = thandle->addStorageClass(storage_class); - //if (isPure()) - //thandle = thandle->addMod(MODconst); v = new ThisDeclaration(loc, thandle); //v = new ThisDeclaration(loc, isCtorDeclaration() ? ad->handle : thandle); v->storage_class |= STCparameter; @@ -2098,7 +2200,7 @@ void FuncDeclaration::buildResultVar() assert(type->nextOf()); assert(type->nextOf()->toBasetype()->ty != Tvoid); - TypeFunction *tf = (TypeFunction *)(type); + TypeFunction *tf = (TypeFunction *)type; Loc loc = this->loc; @@ -2278,11 +2380,11 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Expressions *params) * to match offset difference in covariant return. * See bugzilla 5204. */ - ExpInitializer *ei = new ExpInitializer(0, eresult); - VarDeclaration *v = new VarDeclaration(0, t1, Lexer::uniqueId("__covres"), ei); - DeclarationExp *de = new DeclarationExp(0, v); - VarExp *ve = new VarExp(0, v); - eresult = new CommaExp(0, de, ve); + ExpInitializer *ei = new ExpInitializer(Loc(), eresult); + VarDeclaration *v = new VarDeclaration(Loc(), t1, Lexer::uniqueId("__covres"), ei); + DeclarationExp *de = new DeclarationExp(Loc(), v); + VarExp *ve = new VarExp(Loc(), v); + eresult = new CommaExp(Loc(), de, ve); } } #if IN_LLVM @@ -2415,26 +2517,23 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) int FuncDeclaration::overloadInsert(Dsymbol *s) { - FuncDeclaration *f; - AliasDeclaration *a; - //printf("FuncDeclaration::overloadInsert(s = %s) this = %s\n", s->toChars(), toChars()); - a = s->isAliasDeclaration(); - if (a) + AliasDeclaration *ad = s->isAliasDeclaration(); + if (ad) { if (overnext) - return overnext->overloadInsert(a); - if (!a->aliassym && a->type->ty != Tident && a->type->ty != Tinstance) + return overnext->overloadInsert(ad); + if (!ad->aliassym && ad->type->ty != Tident && ad->type->ty != Tinstance) { - //printf("\ta = '%s'\n", a->type->toChars()); + //printf("\tad = '%s'\n", ad->type->toChars()); return FALSE; } - overnext = a; + overnext = ad; //printf("\ttrue: no conflict\n"); return TRUE; } - f = s->isFuncDeclaration(); - if (!f) + FuncDeclaration *fd = s->isFuncDeclaration(); + if (!fd) return FALSE; #if 0 @@ -2445,11 +2544,11 @@ int FuncDeclaration::overloadInsert(Dsymbol *s) */ if (type) { printf("type = %s\n", type->toChars()); - printf("f->type = %s\n", f->type->toChars()); + printf("fd->type = %s\n", fd->type->toChars()); } - if (type && f->type && // can be NULL for overloaded constructors - f->type->covariant(type) && - f->type->mod == type->mod && + if (type && fd->type && // can be NULL for overloaded constructors + fd->type->covariant(type) && + fd->type->mod == type->mod && !isFuncAliasDeclaration()) { //printf("\tfalse: conflict %s\n", kind()); @@ -2458,8 +2557,8 @@ int FuncDeclaration::overloadInsert(Dsymbol *s) #endif if (overnext) - return overnext->overloadInsert(f); - overnext = f; + return overnext->overloadInsert(fd); + overnext = fd; //printf("\ttrue: no conflict\n"); return TRUE; } @@ -2619,7 +2718,7 @@ struct Param2 { Match *m; #if DMDV2 - Expression *ethis; + Type *tthis; int property; // 0: unintialized // 1: seen @property // 2: not @property @@ -2628,10 +2727,10 @@ struct Param2 }; int fp2(void *param, FuncDeclaration *f) -{ Param2 *p = (Param2 *)param; +{ + Param2 *p = (Param2 *)param; Match *m = p->m; Expressions *arguments = p->arguments; - MATCH match; if (f != m->lastf) // skip duplicates { @@ -2644,12 +2743,26 @@ int fp2(void *param, FuncDeclaration *f) else if (p->property != property) error(f->loc, "cannot overload both property and non-property functions"); - /* For constructors, don't worry about the right type of ethis. It's a problem - * anyway, because the constructor attribute may not match the ethis attribute, - * but we don't care because the attribute on the ethis doesn't matter until - * after it's constructed. + /* For constructors, qualifier check will be opposite direction. + * Qualified constructor always makes qualified object, then will be checked + * that it is implicitly convertible to tthis. */ - match = (MATCH) tf->callMatch(f->needThis() && !f->isCtorDeclaration() ? p->ethis : NULL, arguments); + Type *tthis = f->needThis() ? p->tthis : NULL; + if (tthis && f->isCtorDeclaration()) + { + //printf("%s tf->mod = x%x tthis->mod = x%x %d\n", tf->toChars(), + // tf->mod, tthis->mod, f->isolateReturn()); + if (MODimplicitConv(tf->mod, tthis->mod) || + tf->isWild() && tf->isShared() == tthis->isShared() || + f->isolateReturn()/* && tf->isShared() == tthis->isShared()*/) + { // Uniquely constructed object can ignore shared qualifier. + // TODO: Is this appropriate? + tthis = NULL; + } + else + return 0; // MATCHnomatch + } + MATCH match = tf->callMatch(tthis, arguments); //printf("test1: match = %d\n", match); if (match != MATCHnomatch) { @@ -2719,11 +2832,11 @@ int fp2(void *param, FuncDeclaration *f) void overloadResolveX(Match *m, FuncDeclaration *fstart, - Expression *ethis, Expressions *arguments) + Type *tthis, Expressions *arguments) { Param2 p; p.m = m; - p.ethis = ethis; + p.tthis = tthis; p.property = 0; p.arguments = arguments; overloadApply(fstart, &fp2, &p); @@ -2752,35 +2865,45 @@ static void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char buf->writestring("mutable "); } -FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expression *ethis, Expressions *arguments, int flags) +FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Type *tthis, Expressions *arguments, int flags) { - TypeFunction *tf; - Match m; - #if 0 -printf("FuncDeclaration::overloadResolve('%s')\n", toChars()); -if (arguments) -{ int i; - - for (i = 0; i < arguments->dim; i++) - { Expression *arg; - - arg = (*arguments)[i]; - assert(arg->type); - printf("\t%s: ", arg->toChars()); - arg->type->print(); + printf("FuncDeclaration::overloadResolve('%s')\n", toChars()); + if (arguments) + { + for (size_t i = 0; i < arguments->dim; i++) + { + Expression *arg = (*arguments)[i]; + assert(arg->type); + printf("\t%s: ", arg->toChars()); + arg->type->print(); + } } -} #endif + Match m; memset(&m, 0, sizeof(m)); m.last = MATCHnomatch; - overloadResolveX(&m, this, ethis, arguments); + overloadResolveX(&m, this, tthis, arguments); if (m.count == 1) // exactly one match { + if (!(flags & 1)) + m.lastf->functionSemantic(); return m.lastf; } + + if (m.last != MATCHnomatch && (flags & 2) && !tthis && m.lastf->needThis()) + { + return m.lastf; + } + + /* Failed to find a best match. + * Do nothing or print error. + */ + if (m.last == MATCHnomatch && (flags & 1)) + { // if do not print error messages + } else { OutBuffer buf; @@ -2792,20 +2915,17 @@ if (arguments) argExpTypesToCBuffer(&buf, arguments, &hgs); } buf.writeByte(')'); - if (ethis) - ethis->type->modToBuffer(&buf); + if (tthis) + tthis->modToBuffer(&buf); if (m.last == MATCHnomatch) { - if (flags & 1) // if do not print error messages - return NULL; // no match - - tf = (TypeFunction *)type; - if (ethis && !MODimplicitConv(ethis->type->mod, tf->mod)) // modifier mismatch + TypeFunction *tf = (TypeFunction *)type; + if (tthis && !MODimplicitConv(tthis->mod, tf->mod)) // modifier mismatch { OutBuffer thisBuf, funcBuf; - MODMatchToBuffer(&thisBuf, ethis->type->mod, tf->mod); - MODMatchToBuffer(&funcBuf, tf->mod, ethis->type->mod); + MODMatchToBuffer(&thisBuf, tthis->mod, tf->mod); + MODMatchToBuffer(&funcBuf, tf->mod, tthis->mod); ::error(loc, "%smethod %s is not callable using a %sobject", funcBuf.toChars(), this->toPrettyChars(), thisBuf.toChars()); } @@ -2817,14 +2937,9 @@ if (arguments) tf->modToChars(), buf.toChars()); } - - return m.anyf; // as long as it's not a FuncAliasDeclaration } else { - if ((flags & 2) && m.lastf->needThis() && !ethis) - return m.lastf; -#if 1 TypeFunction *t1 = (TypeFunction *)m.lastf->type; TypeFunction *t2 = (TypeFunction *)m.nextf->type; @@ -2832,15 +2947,9 @@ if (arguments) buf.toChars(), m.lastf->loc.filename, m.lastf->loc.linnum, m.lastf->toPrettyChars(), Parameter::argsTypesToChars(t1->parameters, t1->varargs), m.nextf->loc.filename, m.nextf->loc.linnum, m.nextf->toPrettyChars(), Parameter::argsTypesToChars(t2->parameters, t2->varargs)); -#else - error(loc, "overloads %s and %s both match argument list for %s", - m.lastf->type->toChars(), - m.nextf->type->toChars(), - m.lastf->toChars()); -#endif - return m.lastf; } } + return NULL; } /************************************* @@ -2875,12 +2984,19 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) /* If both functions have a 'this' pointer, and the mods are not * the same and g's is not const, then this is less specialized. */ - if (needThis() && g->needThis()) + if (needThis() && g->needThis() && tf->mod != tg->mod) { - if (tf->mod != tg->mod) + if (isCtorDeclaration()) + { + if (MODimplicitConv(tg->mod, tf->mod)) + match = MATCHconst; + else + return MATCHnomatch; + } + else { if (MODimplicitConv(tf->mod, tg->mod)) - match = MATCHconst; + match = MATCHconst; else return MATCHnomatch; } @@ -2896,11 +3012,11 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) Expression *e; if (p->storageClass & (STCref | STCout)) { - e = new IdentifierExp(0, p->ident); + e = new IdentifierExp(Loc(), p->ident); e->type = p->type; } else - e = p->type->defaultInitLiteral(0); + e = p->type->defaultInitLiteral(Loc()); args[u] = e; } @@ -2928,29 +3044,36 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) /******************************************* * Given a symbol that could be either a FuncDeclaration or * a function template, resolve it to a function symbol. - * sc instantiation scope * loc instantiation location - * targsi initial list of template arguments - * ethis if !NULL, the 'this' pointer argument + * sc instantiation scope + * tiargs initial list of template arguments + * tthis if !NULL, the 'this' pointer argument * fargs arguments to function * flags 1: do not issue error message on no match, just return NULL + * 2: overloadResolve only */ -FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, +FuncDeclaration *resolveFuncCall(Loc loc, Scope *sc, Dsymbol *s, Objects *tiargs, - Expression *ethis, + Type *tthis, Expressions *arguments, int flags) { if (!s) return NULL; // no match + if (tiargs && arrayObjectIsError(tiargs) || + arguments && arrayObjectIsError((Objects *)arguments)) + { + return NULL; + } FuncDeclaration *f = s->isFuncDeclaration(); if (f) - f = f->overloadResolve(loc, ethis, arguments); + f = f->overloadResolve(loc, tthis, arguments, flags); else { TemplateDeclaration *td = s->isTemplateDeclaration(); assert(td); - f = td->deduceFunctionTemplate(sc, loc, tiargs, NULL, arguments, flags); + if (!sc) sc = td->scope; + f = td->deduceFunctionTemplate(loc, sc, tiargs, tthis, arguments, flags); } return f; } @@ -3083,7 +3206,7 @@ Lerr: void FuncDeclaration::appendExp(Expression *e) { Statement *s; - s = new ExpStatement(0, e); + s = new ExpStatement(Loc(), e); appendState(s); } @@ -3102,7 +3225,7 @@ void FuncDeclaration::appendState(Statement *s) cs->statements->push(s); } else - fbody = new CompoundStatement(0, fbody, s); + fbody = new CompoundStatement(Loc(), fbody, s); } } @@ -3114,6 +3237,16 @@ const char *FuncDeclaration::toPrettyChars() return Dsymbol::toPrettyChars(); } +/** for diagnostics, e.g. 'int foo(int x, int y) pure' */ +const char *FuncDeclaration::toFullSignature() +{ + OutBuffer buf; + HdrGenState hgs; + functionToCBuffer2((TypeFunction *)type, &buf, &hgs, 0, toChars()); + buf.writeByte(0); + return buf.extractData(); +} + int FuncDeclaration::isMain() { return ident == Id::main && @@ -3253,9 +3386,9 @@ enum PURE FuncDeclaration::isPure() purity = PUREweak; if (purity > PUREweak && needThis()) { // The attribute of the 'this' reference affects purity strength - if (type->mod & (MODimmutable | MODwild)) + if (type->mod & MODimmutable) ; - else if (type->mod & MODconst && purity >= PUREconst) + else if (type->mod & (MODconst | MODwild) && purity >= PUREconst) purity = PUREconst; else purity = PUREweak; @@ -3270,8 +3403,6 @@ enum PURE FuncDeclaration::isPureBypassingInference() { if (flags & FUNCFLAGpurityInprocess) return PUREfwdref; - else if (type->nextOf() == NULL) - return PUREfwdref; else return isPure(); } @@ -3333,6 +3464,172 @@ bool FuncDeclaration::setUnsafe() return FALSE; } +/************************************** + * Returns an indirect type one step from t. + */ + +Type *getIndirection(Type *t) +{ + t = t->toBasetype(); + + if (t->ty == Tsarray) + { while (t->ty == Tsarray) + t = t->nextOf()->toBasetype(); + } + if (t->ty == Tarray || t->ty == Tpointer) + return t->nextOf()->toBasetype(); + if (t->ty == Taarray || t->ty == Tclass) + return t; + if (t->ty == Tstruct) + return t->hasPointers() ? t : NULL; // TODO + + // should consider TypeDelegate? + return NULL; +} + +/************************************** + * Traverse this and t, and then check the indirections convertibility. + */ + +int traverseIndirections(Type *ta, Type *tb, void *p = NULL, bool a2b = true) +{ + if (a2b) // check ta appears in tb + { + //printf("\ttraverse(1) %s appears in %s\n", ta->toChars(), tb->toChars()); + if (ta->constConv(tb)) + return 1; + else if (ta->invariantOf()->equals(tb->invariantOf())) + return 0; + else if (tb->ty == Tvoid && MODimplicitConv(ta->mod, tb->mod)) + return 1; + } + else // check tb appears in ta + { + //printf("\ttraverse(2) %s appears in %s\n", tb->toChars(), ta->toChars()); + if (tb->constConv(ta)) + return 1; + else if (tb->invariantOf()->equals(ta->invariantOf())) + return 0; + else if (ta->ty == Tvoid && MODimplicitConv(tb->mod, ta->mod)) + return 1; + } + + // context date to detect circular look up + struct Ctxt + { + Ctxt *prev; + Type *type; + }; + Ctxt *ctxt = (Ctxt *)p; + + Type *tbb = tb->toBasetype(); + if (tbb != tb) + return traverseIndirections(ta, tbb, ctxt, a2b); + + if (tb->ty == Tsarray) + { while (tb->toBasetype()->ty == Tsarray) + tb = tb->toBasetype()->nextOf(); + } + if (tb->ty == Tclass || tb->ty == Tstruct) + { + for (Ctxt *c = ctxt; c; c = c->prev) + if (tb == c->type) return 0; + Ctxt c; + c.prev = ctxt; + c.type = tb; + + AggregateDeclaration *sym = tb->toDsymbol(NULL)->isAggregateDeclaration(); + for (size_t i = 0; i < sym->fields.dim; i++) + { + VarDeclaration *v = sym->fields[i]; + Type *tprmi = v->type->addMod(tb->mod); + if (!(v->storage_class & STCref)) + tprmi = getIndirection(tprmi); + if (!tprmi) + continue; + + //printf("\ttb = %s, tprmi = %s\n", tb->toChars(), tprmi->toChars()); + if (traverseIndirections(ta, tprmi, &c, a2b)) + return 1; + } + } + else if (tb->ty == Tarray || tb->ty == Taarray || tb->ty == Tpointer) + { + Type *tind = tb->nextOf(); + if (traverseIndirections(ta, tind, ctxt, a2b)) + return 1; + } + else if (tb->hasPointers()) + { + // FIXME: function pointer/delegate types should be considered. + return 1; + } + if (a2b) + return traverseIndirections(tb, ta, ctxt, false); + + return 0; +} + +/******************************************** + * Returns true if the function return value has no indirection + * which comes from the parameters. + */ + +bool FuncDeclaration::isolateReturn() +{ + assert(type->ty == Tfunction); + TypeFunction *tf = (TypeFunction *)type; + assert(tf->next); + + Type *treti = tf->next; + treti = tf->isref ? treti : getIndirection(treti); + if (!treti) + return true; // target has no mutable indirection + return parametersIntersect(treti); +} + +/******************************************** + * Returns true if an object typed t can have indirections + * which come from the parameters. + */ + +bool FuncDeclaration::parametersIntersect(Type *t) +{ + assert(t); + if (!isPureBypassingInference() || isNested()) + return false; + + assert(type->ty == Tfunction); + TypeFunction *tf = (TypeFunction *)type; + + //printf("parametersIntersect(%s) t = %s\n", tf->toChars(), t->toChars()); + + size_t dim = Parameter::dim(tf->parameters); + for (size_t i = 0; i < dim; i++) + { + Parameter *fparam = Parameter::getNth(tf->parameters, i); + if (!fparam->type) + continue; + Type *tprmi = (fparam->storageClass & (STClazy | STCout | STCref)) + ? fparam->type : getIndirection(fparam->type); + if (!tprmi) + continue; // there is no mutable indirection + + //printf("\t[%d] tprmi = %d %s\n", i, tprmi->ty, tprmi->toChars()); + if (traverseIndirections(tprmi, t)) + return false; + } + if (AggregateDeclaration *ad = isCtorDeclaration() ? NULL : isThis()) + { + Type *tthis = ad ? ad->getType()->addMod(tf->mod) : NULL; + //printf("\ttthis = %s\n", tthis->toChars()); + if (traverseIndirections(tthis, t)) + return false; + } + + return true; +} + // Determine if function needs // a static frame pointer to its lexically enclosing function @@ -3409,8 +3706,12 @@ FuncDeclaration *FuncDeclaration::genCfunc(Parameters *args, Type *treturn, Iden } else { +#if IN_LLVM tf = new TypeFunction(args, treturn, 0, LINKc); - fd = new FuncDeclaration(0, 0, id, STCstatic, tf); +#else + tf = new TypeFunction(NULL, treturn, 0, LINKc); +#endif + fd = new FuncDeclaration(Loc(), Loc(), id, STCstatic, tf); fd->protection = PROTpublic; fd->linkage = LINKc; @@ -3493,7 +3794,7 @@ void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc) */ void markAsNeedingClosure(Dsymbol *f, FuncDeclaration *outerFunc) { - for (Dsymbol *sx = f; sx != outerFunc; sx = sx->parent) + for (Dsymbol *sx = f; sx && sx != outerFunc; sx = sx->parent) { FuncDeclaration *fy = sx->isFuncDeclaration(); if (fy && fy->closureVars.dim) @@ -3706,9 +4007,6 @@ FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOv { assert(funcalias != this); this->funcalias = funcalias; -#if IN_LLVM - importprot = PROTundefined; -#endif this->hasOverloads = hasOverloads; if (hasOverloads) @@ -3831,7 +4129,6 @@ CtorDeclaration::CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *ty : FuncDeclaration(loc, endloc, Id::ctor, stc, type) { //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars()); - this->isImplicit = false; } Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s) @@ -3863,34 +4160,13 @@ void CtorDeclaration::semantic(Scope *sc) sc->stc &= ~STCstatic; // not a static constructor sc->flags |= SCOPEctor; - parent = sc->parent; - Dsymbol *parent = toParent2(); - Type *tret; - AggregateDeclaration *ad = parent->isAggregateDeclaration(); - if (!ad || parent->isUnionDeclaration()) - { - error("constructors are only for class or struct definitions"); - fatal(); - tret = Type::tvoid; - } - else - { tret = ad->handle; - assert(tret); - tret = tret->addStorageClass(storage_class | sc->stc); - tret = tret->addMod(type->mod); - } - tf->next = tret; - if (!originalType) - originalType = type->syntaxCopy(); - type = type->semantic(loc, sc); - - if (ad && ad->isStructDeclaration()) - ((TypeFunction *)type)->isref = 1; - FuncDeclaration::semantic(sc); sc->pop(); + Dsymbol *parent = toParent2(); + AggregateDeclaration *ad = parent->isAggregateDeclaration(); + /* See if it's the default constructor * But, template constructor should not become a default constructor. */ @@ -4021,15 +4297,15 @@ DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc) { } -DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id) - : FuncDeclaration(loc, endloc, id, STCundefined, NULL) +DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id) + : FuncDeclaration(loc, endloc, id, stc, NULL) { } Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s) { assert(!s); - DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident); + DtorDeclaration *dd = new DtorDeclaration(loc, endloc, storage_class, ident); return FuncDeclaration::syntaxCopy(dd); } @@ -4054,7 +4330,7 @@ void DtorDeclaration::semantic(Scope *sc) ad->dtors.push(this); if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); sc = sc->push(); sc->stc &= ~STCstatic; // not a static destructor @@ -4149,19 +4425,19 @@ void StaticCtorDeclaration::semantic(Scope *sc) * during static construction. */ Identifier *id = Lexer::idPool("__gate"); - VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); + VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL); v->storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls; Statements *sa = new Statements(); - Statement *s = new ExpStatement(0, v); + Statement *s = new ExpStatement(Loc(), v); sa->push(s); - Expression *e = new IdentifierExp(0, id); - e = new AddAssignExp(0, e, new IntegerExp(1)); - e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(1)); - s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); + Expression *e = new IdentifierExp(Loc(), id); + e = new AddAssignExp(Loc(), e, new IntegerExp(1)); + e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(1)); + s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL); sa->push(s); if (fbody) sa->push(fbody); - fbody = new CompoundStatement(0, sa); + fbody = new CompoundStatement(Loc(), sa); } FuncDeclaration::semantic(sc); @@ -4283,19 +4559,19 @@ void StaticDtorDeclaration::semantic(Scope *sc) * during static destruction. */ Identifier *id = Lexer::idPool("__gate"); - VarDeclaration *v = new VarDeclaration(0, Type::tint32, id, NULL); + VarDeclaration *v = new VarDeclaration(Loc(), Type::tint32, id, NULL); v->storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls; Statements *sa = new Statements(); - Statement *s = new ExpStatement(0, v); + Statement *s = new ExpStatement(Loc(), v); sa->push(s); - Expression *e = new IdentifierExp(0, id); - e = new AddAssignExp(0, e, new IntegerExp((uint64_t)-1)); - e = new EqualExp(TOKnotequal, 0, e, new IntegerExp(0)); - s = new IfStatement(0, NULL, e, new ReturnStatement(0, NULL), NULL); + Expression *e = new IdentifierExp(Loc(), id); + e = new AddAssignExp(Loc(), e, new IntegerExp(-1)); // LDC_FIXME: Previously had (uint64_t)-1, double-check this. + e = new EqualExp(TOKnotequal, Loc(), e, new IntegerExp(0)); + s = new IfStatement(Loc(), NULL, e, new ReturnStatement(Loc(), NULL), NULL); sa->push(s); if (fbody) sa->push(fbody); - fbody = new CompoundStatement(0, sa); + fbody = new CompoundStatement(Loc(), sa); vgate = v; } @@ -4370,8 +4646,10 @@ void SharedStaticDtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /********************************* InvariantDeclaration ****************************/ -InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc) - : FuncDeclaration(loc, endloc, Id::classInvariant, STCundefined, NULL) +InvariantDeclaration::InvariantDeclaration(Loc loc, Loc endloc, StorageClass stc, Identifier *id) + : FuncDeclaration(loc, endloc, + id ? id : Identifier::generateId("__invariant"), + stc, NULL) { } @@ -4380,7 +4658,7 @@ Dsymbol *InvariantDeclaration::syntaxCopy(Dsymbol *s) InvariantDeclaration *id; assert(!s); - id = new InvariantDeclaration(loc, endloc); + id = new InvariantDeclaration(loc, endloc, storage_class); FuncDeclaration::syntaxCopy(id); return id; } @@ -4400,13 +4678,12 @@ void InvariantDeclaration::semantic(Scope *sc) error("invariants are only for struct/union/class definitions"); return; } - else if (ad->inv && ad->inv != this && semanticRun < PASSsemantic) + if (ident != Id::classInvariant && semanticRun < PASSsemantic) { - error("more than one invariant for %s", ad->toChars()); + ad->invs.push(this); } - ad->inv = this; if (!type) - type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd); + type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd, storage_class); sc = sc->push(); sc->stc &= ~STCstatic; // not a static invariant @@ -4450,22 +4727,21 @@ void InvariantDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) * instances per module. */ -#if __DMC__ || _MSC_VER -#define snprintf _snprintf -#endif static Identifier *unitTestId(Loc loc) { char name[24]; +#if __DMC__ || _MSC_VER + _snprintf(name, 24, "__unittestL%u_", loc.linnum); +#else snprintf(name, 24, "__unittestL%u_", loc.linnum); +#endif return Lexer::uniqueId(name); } -#if __DMC__ || _MSC_VER -#undef snprintf -#endif -UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc) +UnitTestDeclaration::UnitTestDeclaration(Loc loc, Loc endloc, char *codedoc) : FuncDeclaration(loc, endloc, unitTestId(loc), STCundefined, NULL) { + this->codedoc = codedoc; } Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) @@ -4473,13 +4749,15 @@ Dsymbol *UnitTestDeclaration::syntaxCopy(Dsymbol *s) UnitTestDeclaration *utd; assert(!s); - utd = new UnitTestDeclaration(loc, endloc); + utd = new UnitTestDeclaration(loc, endloc, codedoc); return FuncDeclaration::syntaxCopy(utd); } void UnitTestDeclaration::semantic(Scope *sc) { + protection = sc->protection; + if (scope) { sc = scope; scope = NULL; diff --git a/dmd2/identifier.c b/dmd2/identifier.c index 825d78b6aa..e17ab7e78e 100644 --- a/dmd2/identifier.c +++ b/dmd2/identifier.c @@ -51,7 +51,6 @@ const char *Identifier::toHChars2() 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"; @@ -65,6 +64,8 @@ const char *Identifier::toHChars2() p = "static this"; else if (memcmp(p, "_staticDtor", 11) == 0) p = "static ~this"; + else if (memcmp(p, "__invariant", 11) == 0) + p = "invariant"; } } @@ -73,7 +74,7 @@ const char *Identifier::toHChars2() void Identifier::print() { - fprintf(stdmsg, "%s",string); + fprintf(stderr, "%s",string); } int Identifier::dyncast() diff --git a/dmd2/identifier.h b/dmd2/identifier.h index b46c654f06..e6cda8eca1 100644 --- a/dmd2/identifier.h +++ b/dmd2/identifier.h @@ -36,7 +36,6 @@ struct Identifier : Object int compare(Object *o); void print(); char *toChars(); - char *toHChars(); const char *toHChars2(); int dyncast(); diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 25b97eaebc..e22b69f44b 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -108,6 +108,9 @@ Msgtable msgtable[] = { "LINE", "__LINE__" }, { "FILE", "__FILE__" }, + { "MODULE", "__MODULE__" }, + { "FUNCTION", "__FUNCTION__" }, + { "PRETTY_FUNCTION", "__PRETTY_FUNCTION__" }, { "DATE", "__DATE__" }, { "TIME", "__TIME__" }, { "TIMESTAMP", "__TIMESTAMP__" }, @@ -260,10 +263,10 @@ Msgtable msgtable[] = { "_ArrayEq" }, // For pragma's - { "GNU_asm" }, { "lib" }, { "msg" }, { "startaddress" }, + { "mangle" }, #if IN_LLVM // LDC-specific pragmas. @@ -353,6 +356,7 @@ Msgtable msgtable[] = { "isAssociativeArray" }, { "isFinalClass" }, { "isPOD" }, + { "isNested" }, { "isFloating" }, { "isIntegral" }, { "isScalar" }, diff --git a/dmd2/impcnvgen.c b/dmd2/impcnvgen.c index 8f182364d9..298ed37924 100644 --- a/dmd2/impcnvgen.c +++ b/dmd2/impcnvgen.c @@ -381,44 +381,64 @@ int main() fprintf(fp,"unsigned char Type::impcnvResult[TMAX][TMAX] =\n{\n"); for (i = 0; i < TMAX; i++) { + if (i) + fprintf(fp, ","); + fprintf(fp, "{"); for (j = 0; j < TMAX; j++) { - fprintf(fp, "%d,",impcnvResult[i][j]); + if (j) + fprintf(fp, ","); + fprintf(fp, "%d",impcnvResult[i][j]); } - fprintf(fp, "\n"); + fprintf(fp, "}\n"); } fprintf(fp,"};\n"); fprintf(fp,"unsigned char Type::impcnvType1[TMAX][TMAX] =\n{\n"); for (i = 0; i < TMAX; i++) { + if (i) + fprintf(fp, ","); + fprintf(fp, "{"); for (j = 0; j < TMAX; j++) { - fprintf(fp, "%d,",impcnvType1[i][j]); + if (j) + fprintf(fp, ","); + fprintf(fp, "%d",impcnvType1[i][j]); } - fprintf(fp, "\n"); + fprintf(fp, "}\n"); } fprintf(fp,"};\n"); fprintf(fp,"unsigned char Type::impcnvType2[TMAX][TMAX] =\n{\n"); for (i = 0; i < TMAX; i++) { + if (i) + fprintf(fp, ","); + fprintf(fp, "{"); for (j = 0; j < TMAX; j++) { - fprintf(fp, "%d,",impcnvType2[i][j]); + if (j) + fprintf(fp, ","); + fprintf(fp, "%d",impcnvType2[i][j]); } - fprintf(fp, "\n"); + fprintf(fp, "}\n"); } fprintf(fp,"};\n"); fprintf(fp,"unsigned char Type::impcnvWarn[TMAX][TMAX] =\n{\n"); for (i = 0; i < TMAX; i++) { + if (i) + fprintf(fp, ","); + fprintf(fp, "{"); for (j = 0; j < TMAX; j++) { - fprintf(fp, "%d,",impcnvWarn[i][j]); + if (j) + fprintf(fp, ","); + fprintf(fp, "%d",impcnvWarn[i][j]); } - fprintf(fp, "\n"); + fprintf(fp, "}\n"); } fprintf(fp,"};\n"); diff --git a/dmd2/import.c b/dmd2/import.c index a9fecd1e6a..9e2117185c 100644 --- a/dmd2/import.c +++ b/dmd2/import.c @@ -164,7 +164,7 @@ void Import::importAll(Scope *sc) { load(sc); if (mod) // if successfully loaded module - { mod->importAll(0); + { mod->importAll(NULL); if (!isstatic && !aliasId && !names.dim) { @@ -189,7 +189,7 @@ void Import::semantic(Scope *sc) if (!mod) { load(sc); if (mod) - mod->importAll(0); + mod->importAll(NULL); } if (mod) @@ -245,7 +245,6 @@ void Import::semantic(Scope *sc) if (mod->search(loc, names[i], 0)) { ad->semantic(sc); - ad->import = NULL; // forward reference resolved } else { diff --git a/dmd2/init.c b/dmd2/init.c index b0d2dacb1b..0835e90dfd 100644 --- a/dmd2/init.c +++ b/dmd2/init.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -65,15 +65,48 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai) } char *Initializer::toChars() -{ OutBuffer *buf; +{ HdrGenState hgs; memset(&hgs, 0, sizeof(hgs)); - buf = new OutBuffer(); + OutBuffer *buf = new OutBuffer(); toCBuffer(buf, &hgs); return buf->toChars(); } +/********************************** ErrorInitializer ***************************/ + +ErrorInitializer::ErrorInitializer() + : Initializer(Loc()) +{ +} + + +Initializer *ErrorInitializer::syntaxCopy() +{ + return this; +} + + +Initializer *ErrorInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) +{ + //printf("ErrorInitializer::semantic(t = %p)\n", t); + return this; +} + + +Expression *ErrorInitializer::toExpression(Type *t) +{ + return new ErrorExp(); +} + + +void ErrorInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring("__error__"); +} + + /********************************** VoidInitializer ***************************/ VoidInitializer::VoidInitializer(Loc loc) @@ -97,10 +130,10 @@ Initializer *VoidInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInt } -Expression *VoidInitializer::toExpression() +Expression *VoidInitializer::toExpression(Type *t) { error(loc, "void initializer has no value"); - return new IntegerExp(0); + return new ErrorExp(); } @@ -173,9 +206,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI errors = 1; goto Lerror; } - size_t nfields = sd->fields.dim; - if (sd->isnested) - nfields--; + size_t nfields = sd->fields.dim - sd->isNested(); for (size_t i = 0; i < field.dim; i++) { Identifier *id = field[i]; @@ -233,6 +264,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI val = val->semantic(sc, v->type->addMod(t->mod), needInterpret); value[i] = val; vars[i] = v; + if (val->isErrorInitializer()) + errors = 1; } else { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); @@ -246,7 +279,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI */ Parameters *arguments = new Parameters; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); - FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); + FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, TOKdelegate, NULL); fd->fbody = new CompoundStatement(loc, new Statements()); fd->endloc = loc; Expression *e = new FuncExp(loc, fd); @@ -261,9 +294,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needI Lerror: if (errors) { - field.setDim(0); - value.setDim(0); - vars.setDim(0); + return new ErrorInitializer(); } return this; } @@ -273,7 +304,7 @@ Lerror: * a struct literal. In the future, the two should be the * same thing. */ -Expression *StructInitializer::toExpression() +Expression *StructInitializer::toExpression(Type *t) { Expression *e; size_t offset; @@ -285,11 +316,7 @@ Expression *StructInitializer::toExpression() return NULL; Expressions *elements = new Expressions(); - size_t nfields = ad->fields.dim; -#if DMDV2 - if (sd->isnested) - nfields--; -#endif + size_t nfields = ad->fields.dim - sd->isNested(); elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { @@ -305,7 +332,7 @@ Expression *StructInitializer::toExpression() if (!s) { error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); - goto Lno; + goto Lerror; } s = s->toAlias(); @@ -315,7 +342,7 @@ Expression *StructInitializer::toExpression() if (fieldi >= nfields) { s->error("is not a per-instance initializable field"); - goto Lno; + goto Lerror; } if (s == ad->fields[fieldi]) break; @@ -323,7 +350,7 @@ Expression *StructInitializer::toExpression() } else if (fieldi >= nfields) { error(loc, "too many initializers for '%s'", ad->toChars()); - goto Lno; + goto Lerror; } Initializer *iz = value[i]; if (!iz) @@ -334,7 +361,7 @@ Expression *StructInitializer::toExpression() if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", ad->fields[fieldi]->toChars()); - goto Lno; + goto Lerror; } (*elements)[fieldi] = ex; ++fieldi; @@ -399,7 +426,7 @@ Expression *StructInitializer::toExpression() error(loc, "%s cannot have initializers for fields %s and %s in same union", ad->toChars(), v1->toChars(), v->toChars()); - goto Lno; + goto Lerror; } found = j; } @@ -407,12 +434,19 @@ Expression *StructInitializer::toExpression() { error(loc, "no initializer for union that contains field %s", vd->toChars()); - goto Lno; + goto Lerror; } } i += unionSize; #endif } + + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; + if (e && e->op == TOKerror) + return e; + } + e = new StructLiteralExp(loc, sd, elements); e->type = sd->type; return e; @@ -420,6 +454,10 @@ Expression *StructInitializer::toExpression() Lno: delete elements; return NULL; + +Lerror: + delete elements; + return new ErrorExp(); } @@ -430,7 +468,7 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 0; i < field.dim; i++) { if (i > 0) - buf->writebyte(','); + buf->writestring(", "); Identifier *id = field[i]; if (id) { @@ -488,6 +526,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn { size_t length; const unsigned amax = 0x80000000; + bool errors = false; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run @@ -522,10 +561,12 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn { Expression *idx = index[i]; if (idx) - { idx = idx->semantic(sc); + { idx = idx->ctfeSemantic(sc); idx = idx->ctfeInterpret(); index[i] = idx; length = idx->toInteger(); + if (idx->op == TOKerror) + errors = true; } Initializer *val = value[i]; @@ -533,6 +574,8 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn if (ei && !idx) ei->expandTuples = 1; val = val->semantic(sc, t->nextOf(), needInterpret); + if (val->isErrorInitializer()) + errors = true; ei = val->isExpInitializer(); // found a tuple, expand it @@ -573,6 +616,8 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn goto Lerr; } } + if (errors) + goto Lerr; if ((uinteger_t) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size())); @@ -581,7 +626,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needIn return this; Lerr: - return new ExpInitializer(loc, new ErrorExp()); + return new ErrorInitializer(); } /******************************** @@ -589,12 +634,12 @@ Lerr: * Otherwise return NULL. */ -Expression *ArrayInitializer::toExpression() -{ Expressions *elements; - +Expression *ArrayInitializer::toExpression(Type *tx) +{ //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); //static int i; if (++i == 2) halt(); + Expressions *elements; size_t edim; Type *t = NULL; if (type) @@ -670,6 +715,12 @@ Expression *ArrayInitializer::toExpression() } } + for (size_t i = 0; i < edim; i++) + { Expression *e = (*elements)[i]; + if (e->op == TOKerror) + return e; + } + Expression *e = new ArrayLiteralExp(loc, elements); e->type = type; return e; @@ -785,7 +836,7 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 0; i < index.dim; i++) { if (i > 0) - buf->writebyte(','); + buf->writestring(", "); Expression *ex = index[i]; if (ex) { @@ -845,6 +896,27 @@ bool hasNonConstPointers(Expression *e) return arrayHasNonConstPointers(ae->keys); return false; } + if(e->op == TOKaddress) + { + AddrExp *ae = (AddrExp *)e; + if (ae->e1->op == TOKstructliteral) + { + StructLiteralExp *se = (StructLiteralExp *)ae->e1; + if (!(se->stageflags & stageSearchPointers)) + { + int old = se->stageflags; + se->stageflags |= stageSearchPointers; + bool ret = arrayHasNonConstPointers(se->elements); + se->stageflags = old; + return ret; + } + else + { + return false; + } + } + return true; + } if (e->type->ty== Tpointer && e->type->nextOf()->ty != Tfunction) { if (e->op == TOKsymoff) // address of a global is OK @@ -873,7 +945,10 @@ bool arrayHasNonConstPointers(Expressions *elems) Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); - exp = exp->semantic(sc); + if (needInterpret) + exp = exp->ctfeSemantic(sc); + else + exp = exp->semantic(sc); exp = resolveProperties(sc, exp); if (exp->op == TOKerror) return this; @@ -887,13 +962,16 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte return this; // Failed, suppress duplicate error messages if (exp->op == TOKtype) + { exp->error("initializer must be an expression, not '%s'", exp->toChars()); + return new ErrorInitializer(); + } // Make sure all pointers are constants if (needInterpret && hasNonConstPointers(exp)) { exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", exp->toChars()); - return this; + return new ErrorInitializer(); } Type *tb = t->toBasetype(); @@ -949,6 +1027,9 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInte exp->implicitConvTo(tb->nextOf()) ) { + /* If the variable is not actually used in compile time, array creation is + * redundant. So delay it until invocation of toExpression() or toDt(). + */ t = tb->nextOf(); } @@ -983,7 +1064,10 @@ Type *ExpInitializer::inferType(Scope *sc) if (exp->op == TOKsymoff) { SymOffExp *se = (SymOffExp *)exp; if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique()) + { exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); + return Type::terror; + } } // Give error for overloaded function addresses @@ -992,7 +1076,10 @@ Type *ExpInitializer::inferType(Scope *sc) if (se->hasOverloads && se->func->isFuncDeclaration() && !se->func->isFuncDeclaration()->isUnique()) + { exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); + return Type::terror; + } } Type *t = exp->type; @@ -1001,8 +1088,24 @@ Type *ExpInitializer::inferType(Scope *sc) return t; } -Expression *ExpInitializer::toExpression() +Expression *ExpInitializer::toExpression(Type *t) { + if (t) + { + Type *tb = t->toBasetype(); + if (tb->ty == Tsarray && exp->implicitConvTo(tb->nextOf())) + { + TypeSArray *tsa = (TypeSArray *)tb; + size_t d = tsa->dim->toInteger(); + Expressions *elements = new Expressions(); + elements->setDim(d); + for (size_t i = 0; i < d; i++) + (*elements)[i] = exp; + ArrayLiteralExp *ae = new ArrayLiteralExp(exp->loc, elements); + ae->type = t; + exp = ae; + } + } return exp; } diff --git a/dmd2/init.h b/dmd2/init.h index 88db748772..ba3b5683f9 100644 --- a/dmd2/init.h +++ b/dmd2/init.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2007 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -22,6 +22,7 @@ struct Scope; struct Type; struct dt_t; struct AggregateDeclaration; +struct ErrorInitializer; struct VoidInitializer; struct StructInitializer; struct ArrayInitializer; @@ -45,7 +46,7 @@ struct Initializer : Object // needInterpret is INITinterpret if must be a manifest constant, 0 if not. virtual Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); virtual Type *inferType(Scope *sc); - virtual Expression *toExpression() = 0; + virtual Expression *toExpression(Type *t = NULL) = 0; virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; char *toChars(); @@ -55,10 +56,11 @@ struct Initializer : Object virtual dt_t *toDt(); #endif - virtual VoidInitializer *isVoidInitializer() { return NULL; } + virtual ErrorInitializer *isErrorInitializer() { return NULL; } + virtual VoidInitializer *isVoidInitializer() { return NULL; } virtual StructInitializer *isStructInitializer() { return NULL; } - virtual ArrayInitializer *isArrayInitializer() { return NULL; } - virtual ExpInitializer *isExpInitializer() { return NULL; } + virtual ArrayInitializer *isArrayInitializer() { return NULL; } + virtual ExpInitializer *isExpInitializer() { return NULL; } }; struct VoidInitializer : Initializer @@ -68,7 +70,7 @@ struct VoidInitializer : Initializer VoidInitializer(Loc loc); Initializer *syntaxCopy(); Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); - Expression *toExpression(); + Expression *toExpression(Type *t = NULL); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD @@ -78,6 +80,17 @@ struct VoidInitializer : Initializer virtual VoidInitializer *isVoidInitializer() { return this; } }; +struct ErrorInitializer : Initializer +{ + ErrorInitializer(); + Initializer *syntaxCopy(); + Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); + Expression *toExpression(Type *t = NULL); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + + virtual ErrorInitializer *isErrorInitializer() { return this; } +}; + struct StructInitializer : Initializer { Identifiers field; // of Identifier *'s @@ -90,7 +103,7 @@ struct StructInitializer : Initializer Initializer *syntaxCopy(); void addInit(Identifier *field, Initializer *value); Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); - Expression *toExpression(); + Expression *toExpression(Type *t = NULL); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD @@ -117,7 +130,7 @@ struct ArrayInitializer : Initializer Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); int isAssociativeArray(); Type *inferType(Scope *sc); - Expression *toExpression(); + Expression *toExpression(Type *t = NULL); Expression *toAssocArrayLiteral(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -137,7 +150,7 @@ struct ExpInitializer : Initializer Initializer *syntaxCopy(); Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); Type *inferType(Scope *sc); - Expression *toExpression(); + Expression *toExpression(Type *t = NULL); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD diff --git a/dmd2/inline.c b/dmd2/inline.c index 3b3313d6ee..8f982203d5 100644 --- a/dmd2/inline.c +++ b/dmd2/inline.c @@ -219,7 +219,7 @@ int VarExp::inlineCost3(InlineCostState *ics) if (tb->ty == Tstruct) { StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->isnested) + if (sd->isNested()) /* An inner struct will be nested inside another function hierarchy than where * we're inlining into, so don't inline it. * At least not until we figure out how to 'move' the struct to be nested @@ -254,7 +254,7 @@ int StructLiteralExp::inlineCost3(InlineCostState *ics) { //printf("StructLiteralExp::inlineCost3() %s\n", toChars()); #if DMDV2 - if (sd->isnested) + if (sd->isNested()) return COST_MAX; #endif return 1; @@ -594,7 +594,7 @@ Expression *IfStatement::doInline(InlineDoState *ids) Expression *ReturnStatement::doInline(InlineDoState *ids) { //printf("ReturnStatement::doInline() '%s'\n", exp ? exp->toChars() : ""); - return exp ? exp->doInline(ids) : 0; + return exp ? exp->doInline(ids) : NULL; } #if DMDV2 @@ -892,6 +892,8 @@ Expression *TupleExp::doInline(InlineDoState *ids) TupleExp *ce; ce = (TupleExp *)copy(); + if (e0) + ce->e0 = e0->doInline(ids); ce->exps = arrayExpressiondoInline(exps, ids); return ce; } @@ -920,10 +922,12 @@ Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids) Expression *StructLiteralExp::doInline(InlineDoState *ids) { + if(inlinecopy) return inlinecopy; StructLiteralExp *ce; - ce = (StructLiteralExp *)copy(); + inlinecopy = ce; ce->elements = arrayExpressiondoInline(elements, ids); + inlinecopy = NULL; return ce; } @@ -1194,14 +1198,6 @@ Statement *ThrowStatement::inlineScan(InlineScanState *iss) } -Statement *VolatileStatement::inlineScan(InlineScanState *iss) -{ - if (statement) - statement = statement->inlineScan(iss); - return this; -} - - Statement *LabelStatement::inlineScan(InlineScanState *iss) { if (statement) @@ -1373,6 +1369,8 @@ Expression *TupleExp::inlineScan(InlineScanState *iss) { Expression *e = this; //printf("TupleExp::inlineScan()\n"); + if (e0) + e0->inlineScan(iss); arrayInlineScan(iss, exps); return e; @@ -1404,8 +1402,11 @@ Expression *StructLiteralExp::inlineScan(InlineScanState *iss) { Expression *e = this; //printf("StructLiteralExp::inlineScan()\n"); + if(stageflags & stageInlineScan) return e; + int old = stageflags; + stageflags |= stageInlineScan; arrayInlineScan(iss, elements); - + stageflags = old; return e; } @@ -1496,7 +1497,8 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) if (type) { assert(type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)(type); + + TypeFunction *tf = (TypeFunction *)type; #if IN_LLVM // LDC: Only extern(C) varargs count. if (tf->linkage != LINKd) @@ -1679,7 +1681,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi // Set up parameters if (ethis) { - e = new DeclarationExp(0, ids.vthis); + e = new DeclarationExp(Loc(), ids.vthis); e->type = Type::tvoid; if (as) as->push(new ExpStatement(e->loc, e)); @@ -1719,11 +1721,11 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi ids.from.push(vfrom); ids.to.push(vto); - de = new DeclarationExp(0, vto); + de = new DeclarationExp(Loc(), vto); de->type = Type::tvoid; if (as) - as->push(new ExpStatement(0, de)); + as->push(new ExpStatement(Loc(), de)); else e = Expression::combine(e, de); } @@ -1734,7 +1736,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi inlineNest++; Statement *s = fbody->doInlineStatement(&ids); as->push(s); - *ps = new ScopeStatement(0, new CompoundStatement(0, as)); + *ps = new ScopeStatement(Loc(), new CompoundStatement(Loc(), as)); inlineNest--; } else @@ -1778,7 +1780,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi ei->exp = new ConstructExp(loc, ve, e); ei->exp->type = ve->type; - DeclarationExp* de = new DeclarationExp(0, vd); + DeclarationExp* de = new DeclarationExp(Loc(), vd); de->type = Type::tvoid; // Chain the two together: diff --git a/dmd2/interpret.c b/dmd2/interpret.c index ee1a889521..3876b033ac 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -59,22 +59,30 @@ private: VarDeclarations vars; // corresponding variables ArrayBase savedId; // id of the previous state of that var + ArrayBase frames; // all previous frame pointers + Expressions savedThis; // all previous values of localThis + /* 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 + + size_t framepointer; // current frame pointer + size_t maxStackPointer; // most stack we've ever used + Expression *localThis; // value of 'this', or NULL if none public: CtfeStack(); size_t stackPointer(); + // The current value of 'this', or NULL if none + Expression *getThis(); + // Largest number of stack positions we've used size_t maxStackUsage(); - // return the previous frame - size_t startFrame(); - void endFrame(size_t oldframe); + // Start a new stack frame, using the provided 'this'. + void startFrame(Expression *thisexp); + void endFrame(); bool isInCurrentFrame(VarDeclaration *v); Expression *getValue(VarDeclaration *v); void setValue(VarDeclaration *v, Expression *e); @@ -88,13 +96,11 @@ struct InterState { InterState *caller; // calling function's InterState FuncDeclaration *fd; // function being interpreted - 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). */ - 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. InterState(); @@ -113,24 +119,34 @@ size_t CtfeStack::stackPointer() return values.dim; } +Expression *CtfeStack::getThis() +{ + return localThis; +} + // Largest number of stack positions we've used size_t CtfeStack::maxStackUsage() { return maxStackPointer; } -// return the previous frame -size_t CtfeStack::startFrame() +void CtfeStack::startFrame(Expression *thisexp) { size_t oldframe = framepointer; + frames.push((void *)(size_t)(framepointer)); + savedThis.push(localThis); framepointer = stackPointer(); - return oldframe; + localThis = thisexp; } -void CtfeStack::endFrame(size_t oldframe) +void CtfeStack::endFrame() { + size_t oldframe = (size_t)(frames[frames.dim-1]); + localThis = savedThis[savedThis.dim-1]; popAll(framepointer); framepointer = oldframe; + frames.setDim(frames.dim - 1); + savedThis.setDim(savedThis.dim -1); } bool CtfeStack::isInCurrentFrame(VarDeclaration *v) @@ -240,9 +256,9 @@ void printCtfePerformanceStats() } -Expression * resolveReferences(Expression *e, Expression *thisval); +Expression * resolveReferences(Expression *e); Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal); -VarDeclaration *findParentVar(Expression *e, Expression *thisval); +VarDeclaration *findParentVar(Expression *e); Expression *evaluateIfBuiltin(InterState *istate, Loc loc, FuncDeclaration *fd, Expressions *arguments, Expression *pthis); Expression *scrubReturnValue(Loc loc, Expression *e); @@ -299,15 +315,8 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument // 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; + thisarg = ctfeStack.getThis(); - InterState istatex; - istatex.caller = istate; - istatex.fd = this; - istatex.localThis = thisarg; - istatex.framepointer = ctfeStack.startFrame(); - - Expressions vsave; // place to save previous parameter values size_t dim = 0; if (needThis() && !thisarg) { // error, no this. Prevent segfault. @@ -320,16 +329,19 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument return EXP_CANT_INTERPRET; } static int evaluatingArgs = 0; + + // Place to hold all the arguments to the function while + // we are evaluating them. + Expressions eargs; + if (arguments) { dim = arguments->dim; assert(!dim || (parameters && (parameters->dim == dim))); - vsave.setDim(dim); /* Evaluate all the arguments to the function, * store the results in eargs[] */ - Expressions eargs; eargs.setDim(dim); for (size_t i = 0; i < dim; i++) { Expression *earg = (*arguments)[i]; @@ -387,6 +399,18 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument } eargs[i] = earg; } + } + + // Now that we've evaluated all the arguments, we can start the frame + // (this is the moment when the 'call' actually takes place). + + InterState istatex; + istatex.caller = istate; + istatex.fd = this; + ctfeStack.startFrame(thisarg); + + if (arguments) + { for (size_t i = 0; i < dim; i++) { Expression *earg = eargs[i]; @@ -471,7 +495,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument // Leave the function --CtfeStatus::callDepth; - ctfeStack.endFrame(istatex.framepointer); + ctfeStack.endFrame(); // If fell off the end of a void function, return void if (!e && type->toBasetype()->nextOf()->ty == Tvoid) @@ -731,8 +755,16 @@ 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; + StructLiteralExp *se = ((ClassReferenceExp*)e)->value; + se->ownedByCtfe = false; + if (!(se->stageflags & stageScrub)) + { + int old = se->stageflags; + se->stageflags |= stageScrub; + if (!scrubArray(loc, se->elements, true)) + return EXP_CANT_INTERPRET; + se->stageflags = old; + } } if (e->op == TOKvoid) { @@ -747,8 +779,14 @@ Expression *scrubReturnValue(Loc loc, Expression *e) { StructLiteralExp *se = (StructLiteralExp *)e; se->ownedByCtfe = false; - if (!scrubArray(loc, se->elements, true)) - return EXP_CANT_INTERPRET; + if (!(se->stageflags & stageScrub)) + { + int old = se->stageflags; + se->stageflags |= stageScrub; + if (!scrubArray(loc, se->elements, true)) + return EXP_CANT_INTERPRET; + se->stageflags = old; + } } if (e->op == TOKstring) { @@ -1097,10 +1135,6 @@ Expression *SwitchStatement::interpret(InterState *istate) s = sdefault; } -#if IN_LLVM - if (!s) - return EXP_CANT_INTERPRET; -#endif assert(s); istate->start = s; e = body ? body->interpret(istate) : NULL; @@ -1361,12 +1395,11 @@ Expression *Expression::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; - if (istate && istate->localThis) - return istate->localThis->interpret(istate, goal); + Expression *localThis = ctfeStack.getThis(); + if (localThis && localThis->op == TOKstructliteral) + return localThis; + if (localThis) + return localThis->interpret(istate, goal); error("value of 'this' is not known at compile time"); return EXP_CANT_INTERPRET; } @@ -1407,11 +1440,11 @@ Expression *StringExp::interpret(InterState *istate, CtfeGoal goal) * In D2, we also disallow casts of read-only literals to mutable, * though it isn't strictly necessary. */ -#if DMDV2 +#if 0 //DMDV2 // Fixed-length char arrays always get duped later anyway. if (type->ty == Tsarray) return this; - if (!(((TypeNext *)type)->next->mod & (MODconst | MODimmutable))) + if (!(((TypeNext *)type)->next->toBasetype()->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; @@ -1437,12 +1470,42 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) { return this; } + if (isTypeInfo_Class(type) && offset == 0) + { + return this; + } if (type->ty != Tpointer) { // Probably impossible error("Cannot interpret %s at compile time", toChars()); return EXP_CANT_INTERPRET; } Type *pointee = ((TypePointer *)type)->next; + if ( var->isThreadlocal()) + { + error("cannot take address of thread-local variable %s at compile time", var->toChars()); + return EXP_CANT_INTERPRET; + } + // Check for taking an address of a shared variable. + // If the shared variable is an array, the offset might not be zero. + VarDeclaration *vd = var->isVarDeclaration(); + Type *fromType = NULL; + if (var->type->ty == Tarray || var->type->ty == Tsarray) + { + fromType = ((TypeArray *)(var->type))->next; + } + if ( var->isDataseg() && ( + (offset == 0 && isSafePointerCast(var->type, pointee)) || + (fromType && isSafePointerCast(fromType, pointee)) + ) && !(vd && vd->init && +#if DMDV2 + (var->isConst() || var->isImmutable()) +#else + var>isConst() +#endif + )) + { + return this; + } Expression *val = getVarExp(loc, istate, var, goal); if (val == EXP_CANT_INTERPRET) return val; @@ -1529,17 +1592,19 @@ Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) 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) { for(;;) { if (e->op == TOKthis) { + Expression *thisval = ctfeStack.getThis(); assert(thisval); assert(e != thisval); e = thisval; @@ -1579,11 +1644,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal { Expression *e = EXP_CANT_INTERPRET; VarDeclaration *v = d->isVarDeclaration(); -#if IN_LLVM - StaticStructInitDeclaration *s = d->isStaticStructInitDeclaration(); -#else SymbolDeclaration *s = d->isSymbolDeclaration(); -#endif if (v) { #if DMDV2 @@ -1596,7 +1657,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal #else if (v->isConst() && v->init && !v->isCTFE()) #endif - { e = v->init->toExpression(); + { e = v->init->toExpression(v->type); if (e && (e->op == TOKconstruct || e->op == TOKblit)) { AssignExp *ae = (AssignExp *)e; e = ae->e2; @@ -1693,20 +1754,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal } else if (s) { // Struct static initializers, for example -#if !IN_LLVM - if (s->dsym->toInitializer() == s->sym) -#endif - { e = s->dsym->type->defaultInitLiteral(loc); - e = e->semantic(NULL); - if (e->op == TOKerror) - e = EXP_CANT_INTERPRET; - else // Convert NULL to VoidExp - e = e->interpret(istate, goal); - } -#if !IN_LLVM - else - error(loc, "cannot interpret symbol %s at compile time", s->toChars()); -#endif + e = s->dsym->type->defaultInitLiteral(loc); + e = e->semantic(NULL); + if (e->op == TOKerror) + e = EXP_CANT_INTERPRET; + else // Convert NULL to VoidExp + e = e->interpret(istate, goal); } else error(loc, "cannot interpret declaration %s at compile time", d->toChars()); @@ -1770,8 +1823,9 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) if (!v2->isDataseg() || v2->isCTFE()) ctfeStack.push(v2); } + return NULL; } - if (!v->isDataseg() || v->isCTFE()) + if (!(v->isDataseg() || v->storage_class & STCmanifest) || v->isCTFE()) ctfeStack.push(v); Dsymbol *s = v->toAlias(); if (s == v && !v->isStatic() && v->init) @@ -1847,6 +1901,12 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) #endif Expressions *expsx = NULL; + if (e0) + { + if (e0->interpret(istate) == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + } + for (size_t i = 0; i < exps->dim; i++) { Expression *e = (*exps)[i]; Expression *ex; @@ -2223,31 +2283,27 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) return EXP_CANT_INTERPRET; } -Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *)) +Expression *UnaExp::interpret(InterState *istate, CtfeGoal goal) { Expression *e; Expression *e1; #if LOG - printf("%s UnaExp::interpretCommon() %s\n", loc.toChars(), toChars()); + printf("%s UnaExp::interpret() %s\n", loc.toChars(), toChars()); #endif e1 = this->e1->interpret(istate); if (exceptionOrCantInterpret(e1)) return e1; - e = (*fp)(type, e1); + switch(op) + { + case TOKneg: e = Neg(type, e1); break; + case TOKtilde: e = Com(type, e1); break; + case TOKnot: e = Not(type, e1); break; + case TOKtobool: e = Bool(type, e1); break; + default: assert(0); + } return e; } -#define UNA_INTERPRET(op) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ - return interpretCommon(istate, goal, &op); \ -} - -UNA_INTERPRET(Neg) -UNA_INTERPRET(Com) -UNA_INTERPRET(Not) -UNA_INTERPRET(Bool) - typedef Expression *(*fp_t)(Type *, Expression *, Expression *); Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp) @@ -2314,31 +2370,8 @@ Lcant: return EXP_CANT_INTERPRET; } -#define BIN_INTERPRET(op) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ - return interpretCommon(istate, goal, &op); \ -} - -BIN_INTERPRET(Add) -BIN_INTERPRET(Min) -BIN_INTERPRET(Mul) -BIN_INTERPRET(Div) -BIN_INTERPRET(Mod) -BIN_INTERPRET(Shl) -BIN_INTERPRET(Shr) -BIN_INTERPRET(Ushr) -BIN_INTERPRET(And) -BIN_INTERPRET(Or) -BIN_INTERPRET(Xor) -#if DMDV2 -BIN_INTERPRET(Pow) -#endif - - typedef int (*fp2_t)(Loc loc, enum TOK, Expression *, Expression *); - Expression *BinExp::interpretCompareCommon(InterState *istate, CtfeGoal goal, fp2_t fp) { Expression *e1; @@ -2390,47 +2423,59 @@ Expression *BinExp::interpretCompareCommon(InterState *istate, CtfeGoal goal, fp return new IntegerExp(loc, cmp, type); } -#define BIN_INTERPRET2(op, opfunc) \ -Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ -{ \ - return interpretCompareCommon(istate, goal, &opfunc); \ +Expression *BinExp::interpret(InterState *istate, CtfeGoal goal) +{ + switch(op) + { + case TOKadd: return interpretCommon(istate, goal, &Add); + case TOKmin: return interpretCommon(istate, goal, &Min); + case TOKmul: return interpretCommon(istate, goal, &Mul); + case TOKdiv: return interpretCommon(istate, goal, &Div); + case TOKmod: return interpretCommon(istate, goal, &Mod); + case TOKshl: return interpretCommon(istate, goal, &Shl); + case TOKshr: return interpretCommon(istate, goal, &Shr); + case TOKushr: return interpretCommon(istate, goal, &Ushr); + case TOKand: return interpretCommon(istate, goal, &And); + case TOKor: return interpretCommon(istate, goal, &Or); + case TOKxor: return interpretCommon(istate, goal, &Xor); +#if DMDV2 + case TOKpow: return interpretCommon(istate, goal, &Pow); +#endif + case TOKequal: + case TOKnotequal: + return interpretCompareCommon(istate, goal, &ctfeEqual); + case TOKidentity: + case TOKnotidentity: + return interpretCompareCommon(istate, goal, &ctfeIdentity); + case TOKlt: + case TOKle: + case TOKgt: + case TOKge: + case TOKleg: + case TOKlg: + case TOKunord: + case TOKue: + case TOKug: + case TOKuge: + case TOKul: + case TOKule: + return interpretCompareCommon(istate, goal, &ctfeCmp); + default: + assert(0); + return NULL; + } } -BIN_INTERPRET2(Equal, ctfeEqual) -BIN_INTERPRET2(Identity, ctfeIdentity) -BIN_INTERPRET2(Cmp, ctfeCmp) - /* Helper functions for BinExp::interpretAssignCommon */ -// Return true if e is derived from UnaryExp. -// Consider moving this function into Expression. -UnaExp *isUnaExp(Expression *e) -{ - switch (e->op) - { - case TOKdotvar: - case TOKindex: - case TOKslice: - case TOKcall: - case TOKdot: - case TOKdotti: - case TOKdottype: - case TOKcast: - return (UnaExp *)e; - default: - break; - } - return NULL; -} - // Returns the variable which is eventually modified, or NULL if an rvalue. // thisval is the current value of 'this'. -VarDeclaration * findParentVar(Expression *e, Expression *thisval) +VarDeclaration * findParentVar(Expression *e) { for (;;) { - e = resolveReferences(e, thisval); + e = resolveReferences(e); if (e->op == TOKvar) break; if (e->op == TOKindex) @@ -2449,7 +2494,6 @@ VarDeclaration * findParentVar(Expression *e, Expression *thisval) return v; } - Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post) { #if LOG @@ -2525,7 +2569,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ * 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); + VarDeclaration * targetVar = findParentVar(e2); if (!(targetVar && targetVar->isConst())) wantRef = true; // slice assignment of static arrays is not reference assignment @@ -2566,7 +2610,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // First, deal with this = e; and call() = e; if (e1->op == TOKthis) { - e1 = istate->localThis; + e1 = ctfeStack.getThis(); } if (e1->op == TOKcall) { @@ -2581,7 +2625,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // 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), + new IntegerExp(Loc(), 0, Type::tsize_t), ArrayLength(Type::tsize_t, e1)); e1->type = type; } @@ -2636,7 +2680,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ return oldval; while (oldval->op == TOKvar) { - oldval = resolveReferences(oldval, istate->localThis); + oldval = resolveReferences(oldval); oldval = oldval->interpret(istate); if (exceptionOrCantInterpret(oldval)) return oldval; @@ -2705,7 +2749,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ { // Get the old array literal. oldval = e1->interpret(istate); while (oldval->op == TOKvar) - { oldval = resolveReferences(oldval, istate->localThis); + { oldval = resolveReferences(oldval); oldval = oldval->interpret(istate); } } @@ -2757,14 +2801,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // ------------------------------------------------- // Make sure we're not trying to modify a global or static variable // We do this by locating the ultimate parent variable which gets modified. - VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis); + VarDeclaration * ultimateVar = findParentVar(e1); if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", ultimateVar->toChars()); return EXP_CANT_INTERPRET; } - e1 = resolveReferences(e1, istate->localThis); + e1 = resolveReferences(e1); // Unless we have a simple var assignment, we're // only modifying part of the variable. So we need to make sure @@ -2825,7 +2869,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ie = (IndexExp *)ie->e1; ++depth; } - Expression *aggregate = resolveReferences(ie->e1, istate->localThis); + Expression *aggregate = resolveReferences(ie->e1); 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) @@ -3075,7 +3119,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ArrayLiteralExp *existingAE = NULL; StringExp *existingSE = NULL; - Expression *aggregate = resolveReferences(ie->e1, istate->localThis); + Expression *aggregate = resolveReferences(ie->e1); // Set the index to modify, and check that it is in range dinteger_t indexToModify = index->toInteger(); @@ -3101,6 +3145,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (aggregate->op != TOKslice && aggregate->op != TOKstring && aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral) { + if (aggregate->op == TOKsymoff) + { + error("mutable variable %s cannot be modified at compile time, even through a pointer", ((SymOffExp *)aggregate)->var->toChars()); + return EXP_CANT_INTERPRET; + } if (indexToModify != 0) { error("pointer index [%lld] lies outside memory block [0..1]", indexToModify); @@ -3251,6 +3300,11 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (oldval->op != TOKarrayliteral && oldval->op != TOKstring && oldval->op != TOKslice && oldval->op != TOKnull) { + if (oldval->op == TOKsymoff) + { + error("pointer %s cannot be sliced at compile time (it points to a static variable)", sexp->e1->toChars()); + return EXP_CANT_INTERPRET; + } if (assignmentToSlicedPointer) { error("pointer %s cannot be sliced at compile time (it does not point to an array)", @@ -3298,7 +3352,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (upperbound == lowerbound) return newval; - Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis); + Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1); dinteger_t firstIndex = lowerbound; ArrayLiteralExp *existingAE = NULL; @@ -3515,29 +3569,30 @@ Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal) 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(op) BIN_ASSIGN_INTERPRET_CTFE(op, op) - -BIN_ASSIGN_INTERPRET(Add) -BIN_ASSIGN_INTERPRET(Min) -BIN_ASSIGN_INTERPRET_CTFE(Cat, ctfeCat) -BIN_ASSIGN_INTERPRET(Mul) -BIN_ASSIGN_INTERPRET(Div) -BIN_ASSIGN_INTERPRET(Mod) -BIN_ASSIGN_INTERPRET(Shl) -BIN_ASSIGN_INTERPRET(Shr) -BIN_ASSIGN_INTERPRET(Ushr) -BIN_ASSIGN_INTERPRET(And) -BIN_ASSIGN_INTERPRET(Or) -BIN_ASSIGN_INTERPRET(Xor) +Expression *BinAssignExp::interpret(InterState *istate, CtfeGoal goal) +{ + switch(op) + { + case TOKaddass: return interpretAssignCommon(istate, goal, &Add); + case TOKminass: return interpretAssignCommon(istate, goal, &Min); + case TOKcatass: return interpretAssignCommon(istate, goal, &ctfeCat); + case TOKmulass: return interpretAssignCommon(istate, goal, &Mul); + case TOKdivass: return interpretAssignCommon(istate, goal, &Div); + case TOKmodass: return interpretAssignCommon(istate, goal, &Mod); + case TOKshlass: return interpretAssignCommon(istate, goal, &Shl); + case TOKshrass: return interpretAssignCommon(istate, goal, &Shr); + case TOKushrass: return interpretAssignCommon(istate, goal, &Ushr); + case TOKandass: return interpretAssignCommon(istate, goal, &And); + case TOKorass: return interpretAssignCommon(istate, goal, &Or); + case TOKxorass: return interpretAssignCommon(istate, goal, &Xor); #if DMDV2 -BIN_ASSIGN_INTERPRET(Pow) + case TOKpowass: return interpretAssignCommon(istate, goal, &Pow); #endif + default: + assert(0); + return NULL; + } +} Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) { @@ -3897,7 +3952,7 @@ 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) + if (vd && vd->hasValue() && vd->getValue()->op == TOKsymoff) fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration(); else { @@ -3938,7 +3993,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) else if (ecall->op == TOKvar) { VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration(); - if (vd && vd->getValue()) + if (vd && vd->hasValue()) ecall = vd->getValue(); else // Calling a function fd = ((VarExp *)e1)->var->isFuncDeclaration(); @@ -3959,7 +4014,7 @@ 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. + { // 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()); @@ -3988,8 +4043,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) { // Make a virtual function call. Expression *thisval = pthis; if (pthis->op == TOKvar) - { assert(((VarExp*)thisval)->var->isVarDeclaration()); - thisval = ((VarExp*)thisval)->var->isVarDeclaration()->getValue(); + { + VarDeclaration *vthis = ((VarExp*)thisval)->var->isVarDeclaration(); + assert(vthis); + thisval = getVarExp(loc, istate, vthis, ctfeNeedLvalue); // If it is a reference, resolve it if (thisval->op != TOKnull && thisval->op != TOKclassreference) thisval = pthis->interpret(istate); @@ -4042,6 +4099,8 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) } return e; } + if (fd->dArrayOp) + return fd->dArrayOp->interpret(istate, arguments, pthis); if (!fd->fbody) { error("%s cannot be interpreted at compile time," @@ -4076,7 +4135,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) InterState istateComma; if (!istate && firstComma->e1->op == TOKdeclaration) { - ctfeStack.startFrame(); + ctfeStack.startFrame(NULL); istate = &istateComma; } @@ -4104,7 +4163,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) if (exceptionOrCantInterpret(newval)) { if (istate == &istateComma) - ctfeStack.endFrame(0); + ctfeStack.endFrame(); return newval; } if (newval != EXP_VOID_INTERPRET) @@ -4126,7 +4185,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) } // If we created a temporary stack frame, end it now. if (istate == &istateComma) - ctfeStack.endFrame(0); + ctfeStack.endFrame(); return e; } @@ -4227,6 +4286,11 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) } else { // Pointer to a non-array variable + if (agg->op == TOKsymoff) + { + error("mutable variable %s cannot be read at compile time, even through a pointer", ((SymOffExp *)agg)->var->toChars()); + return EXP_CANT_INTERPRET; + } if ((indx + ofs) != 0) { error("pointer index [%lld] lies outside memory block [0..1]", @@ -4380,6 +4444,11 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) error("cannot slice null pointer %s", this->e1->toChars()); return EXP_CANT_INTERPRET; } + if (agg->op == TOKsymoff) + { + error("slicing pointers to static variables is not supported in CTFE"); + return EXP_CANT_INTERPRET; + } if (agg->op != TOKarrayliteral && agg->op != TOKstring) { error("pointer %s cannot be sliced at compile time (it does not point to an array)", @@ -4681,17 +4750,21 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) return e; } } - if (e1->op == TOKvar) + if (e1->op == TOKvar || e1->op == TOKsymoff) { // type painting operation - Type *origType = ((VarExp *)e1)->var->type; + Type *origType = (e1->op == TOKvar) ? ((VarExp *)e1)->var->type : + ((SymOffExp *)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; + if (e1->op == TOKvar) + e = new VarExp(loc, ((VarExp *)e1)->var); + else + e = new SymOffExp(loc, ((SymOffExp *)e1)->var, 0); + e->type = to; return e; } @@ -4833,12 +4906,39 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) #else // this is required for D1, where structs return *this instead of 'this'. else if (e1->op == TOKthis) { - if(istate->localThis) - return istate->localThis->interpret(istate); + if (ctfeStack.getThis()) + return ctfeStack.getThis()->interpret(istate); } #endif else - { // It's possible we have an array bounds error. We need to make sure it + { + // Check for .classinfo, which is lowered in the semantic pass into **(class). + if (e1->op == TOKstar && e1->type->ty == Tpointer && isTypeInfo_Class(e1->type->nextOf())) + { + e = (((PtrExp *)e1)->e1)->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(e)) + return e; + if (e->op == TOKnull) + { + error("Null pointer dereference evaluating typeid. '%s' is null", ((PtrExp *)e1)->e1->toChars()); + return EXP_CANT_INTERPRET; + } + if (e->op != TOKclassreference) + { error("CTFE internal error determining classinfo"); + return EXP_CANT_INTERPRET; + } + ClassDeclaration *cd = ((ClassReferenceExp *)e)->originalClass(); + assert(cd); + + // Create the classinfo, if it doesn't yet exist. + // TODO: This belongs in semantic, CTFE should not have to do this. + if (!cd->vclassinfo) + cd->vclassinfo = new TypeInfoClassDeclaration(cd->type); + e = new SymOffExp(loc, cd->vclassinfo, 0); + e->type = type; + return e; + } + // 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)) @@ -4846,7 +4946,10 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) if (!(e->op == TOKvar || e->op == TOKdotvar || e->op == TOKindex || e->op == TOKslice || e->op == TOKaddress)) { - error("dereference of invalid pointer '%s'", e->toChars()); + if (e->op == TOKsymoff) + error("cannot dereference pointer to static variable %s at compile time", ((SymOffExp *)e)->var->toChars()); + else + error("dereference of invalid pointer '%s'", e->toChars()); return EXP_CANT_INTERPRET; } if (goal != ctfeNeedLvalue) diff --git a/dmd2/json.c b/dmd2/json.c index 24503b07a1..373215d359 100644 --- a/dmd2/json.c +++ b/dmd2/json.c @@ -68,7 +68,6 @@ struct JsonOut void property(const char *name, Type* type); void property(const char *name, const char *deconame, Type* type); void property(const char *name, Parameters* parameters); - void property(const char *name, Expressions* expressions); void property(const char *name, enum TRUST trust); void property(const char *name, enum PURE purity); void property(const char *name, enum LINK linkage); @@ -545,7 +544,7 @@ void TypeQualified::toJson(JsonOut *json) // ident.ident.ident.etc json->arrayStart(); for (size_t i = 0; i < idents.dim; i++) - { Identifier *ident = idents[i]; + { Object *ident = idents[i]; json->item(ident->toChars()); } @@ -629,9 +628,11 @@ void Dsymbol::toJson(JsonOut *json) void Dsymbol::jsonProperties(JsonOut *json) { - json->property("name", toChars()); if (!isTemplateDeclaration()) // TemplateDeclaration::kind() acts weird sometimes + { + json->property("name", toChars()); json->property("kind", kind()); + } if (prot() != PROTpublic) json->property("protection", Pprotectionnames[prot()]); @@ -848,6 +849,16 @@ void Declaration::jsonProperties(JsonOut *json) } } +void TemplateDeclaration::jsonProperties(JsonOut *json) +{ + Dsymbol::jsonProperties(json); + + if (onemember && onemember->isCtorDeclaration()) + json->property("name", "this"); // __ctor -> this + else + json->property("name", ident->toChars()); // Foo(T) -> Foo +} + void TypedefDeclaration::toJson(JsonOut *json) { json->objectStart(); @@ -1071,7 +1082,7 @@ void VarDeclaration::toJson(JsonOut *json) if (init) json->property("init", init->toChars()); - if (storage_class & STCfield) + if (isField()) json->property("offset", offset); if (alignment && alignment != STRUCTALIGN_DEFAULT) diff --git a/dmd2/lexer.c b/dmd2/lexer.c index 4d92e3577b..b00de9d12f 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -38,7 +38,7 @@ #if _WIN32 && __DMC__ // from \dm\src\include\setlocal.h -extern "C" char * __cdecl __locale_decpoint; +extern "C" const char * __cdecl __locale_decpoint; #endif extern int HtmlNamedEntity(unsigned char *p, size_t length); @@ -96,7 +96,7 @@ void *Token::operator new(size_t size) #ifdef DEBUG void Token::print() { - fprintf(stdmsg, "%s\n", toChars()); + fprintf(stderr, "%s\n", toChars()); } #endif @@ -678,7 +678,7 @@ void Lexer::scan(Token *t) } else if (id == Id::VENDOR) { - t->ustring = (unsigned char *)"LDC"; + t->ustring = (unsigned char *)global.compiler.vendor; goto Lstr; } else if (id == Id::TIMESTAMP) @@ -909,6 +909,8 @@ void Lexer::scan(Token *t) } continue; } + default: + break; } t->value = TOKdiv; return; @@ -1911,7 +1913,9 @@ TOK Lexer::number(Token *t) enum STATE state; enum FLAGS - { FLAGS_decimal = 1, // decimal + { + FLAGS_none = 0, + FLAGS_decimal = 1, // decimal FLAGS_unsigned = 2, // u or U suffix FLAGS_long = 4, // l or L suffix }; @@ -2175,7 +2179,7 @@ done: switch (flags) { - case 0: + case FLAGS_none: /* Octal or Hexadecimal constant. * First that fits: int, uint, long, ulong */ @@ -2359,7 +2363,7 @@ done: stringbuffer.writeByte(0); #if _WIN32 && __DMC__ - char *save = __locale_decpoint; + const char *save = __locale_decpoint; __locale_decpoint = "."; #endif #ifdef IN_GCC @@ -2794,7 +2798,7 @@ Identifier *Lexer::uniqueId(const char *s, int num) { char buffer[32]; size_t slen = strlen(s); - assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer)); + assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer) / sizeof(buffer[0])); sprintf(buffer, "%s%d", s, num); return idPool(buffer); } @@ -2933,13 +2937,15 @@ static Keyword keywords[] = #if DMDV2 { "pure", TOKpure }, { "nothrow", TOKnothrow }, - { "__thread", TOKtls }, { "__gshared", TOKgshared }, { "__traits", TOKtraits }, { "__vector", TOKvector }, { "__overloadset", TOKoverloadset }, { "__FILE__", TOKfile }, { "__LINE__", TOKline }, + { "__MODULE__", TOKmodulestring }, + { "__FUNCTION__", TOKfuncstring }, + { "__PRETTY_FUNCTION__", TOKprettyfunc }, { "shared", TOKshared }, { "immutable", TOKimmutable }, #endif @@ -2959,7 +2965,7 @@ void Lexer::initKeywords() { size_t nkeywords = sizeof(keywords) / sizeof(keywords[0]); - stringtable.init(6151); + stringtable._init(6151); if (global.params.Dversion == 1) nkeywords -= 2; diff --git a/dmd2/lexer.h b/dmd2/lexer.h index c3f3a82624..88fdb4d6ec 100644 --- a/dmd2/lexer.h +++ b/dmd2/lexer.h @@ -161,10 +161,12 @@ enum TOK TOKoverloadset, TOKpure, TOKnothrow, - TOKtls, TOKgshared, TOKline, TOKfile, + TOKmodulestring, + TOKfuncstring, + TOKprettyfunc, TOKshared, TOKat, TOKpow, @@ -263,7 +265,9 @@ struct Token Token() : next(NULL) {} int isKeyword(); +#ifdef DEBUG void print(); +#endif const char *toChars(); static const char *toChars(enum TOK); }; @@ -310,7 +314,6 @@ struct Lexer TOK escapeStringConstant(Token *t, int wide); TOK charConstant(Token *t, int wide); void stringPostfix(Token *t); - unsigned wchar(unsigned u); TOK number(Token *t); TOK inreal(Token *t); void error(const char *format, ...); diff --git a/dmd2/mangle.c b/dmd2/mangle.c index e79318c923..03b1849ffb 100644 --- a/dmd2/mangle.c +++ b/dmd2/mangle.c @@ -109,7 +109,7 @@ L1: return id; } -char *Declaration::mangle(bool isv) +const char *Declaration::mangle(bool isv) #if __DMC__ __out(result) { @@ -157,7 +157,7 @@ char *Declaration::mangle(bool isv) return ident->toChars(); default: - fprintf(stdmsg, "'%s', linkage = %d\n", toChars(), linkage); + fprintf(stderr, "'%s', linkage = %d\n", toChars(), linkage); assert(0); } } @@ -171,7 +171,7 @@ char *Declaration::mangle(bool isv) return p; } -char *FuncDeclaration::mangle(bool isv) +const char *FuncDeclaration::mangle(bool isv) #if __DMC__ __out(result) { @@ -180,6 +180,9 @@ char *FuncDeclaration::mangle(bool isv) __body #endif { + if (mangleOverride) + return mangleOverride; + if (isMain()) return (char *)"_Dmain"; @@ -190,22 +193,36 @@ char *FuncDeclaration::mangle(bool isv) return Declaration::mangle(isv); } +const char *VarDeclaration::mangle(bool isv) +#if __DMC__ + __out(result) + { + assert(strlen(result) > 0); + } + __body +#endif + { + if (mangleOverride) + return mangleOverride; -char *TypedefDeclaration::mangle(bool isv) + return Declaration::mangle(); + } + +const char *TypedefDeclaration::mangle(bool isv) { //printf("TypedefDeclaration::mangle() '%s'\n", toChars()); return Dsymbol::mangle(isv); } -char *AggregateDeclaration::mangle(bool isv) +const char *AggregateDeclaration::mangle(bool isv) { #if 1 //printf("AggregateDeclaration::mangle() '%s'\n", toChars()); if (Dsymbol *p = toParent2()) { if (FuncDeclaration *fd = p->isFuncDeclaration()) { // This might be the Voldemort Type - char *id = Dsymbol::mangle(fd->inferRetType || getFuncTemplateDecl(fd)); + const char *id = Dsymbol::mangle(fd->inferRetType || getFuncTemplateDecl(fd)); //printf("isv ad %s, %s\n", toChars(), id); return id; } @@ -214,13 +231,13 @@ char *AggregateDeclaration::mangle(bool isv) return Dsymbol::mangle(isv); } -char *StructDeclaration::mangle(bool isv) +const char *StructDeclaration::mangle(bool isv) { //printf("StructDeclaration::mangle() '%s'\n", toChars()); return AggregateDeclaration::mangle(isv); } -char *ClassDeclaration::mangle(bool isv) +const char *ClassDeclaration::mangle(bool isv) { Dsymbol *parentsave = parent; @@ -248,13 +265,13 @@ char *ClassDeclaration::mangle(bool isv) ) parent = NULL; - char *id = AggregateDeclaration::mangle(isv); + const char *id = AggregateDeclaration::mangle(isv); parent = parentsave; return id; } -char *TemplateInstance::mangle(bool isv) +const char *TemplateInstance::mangle(bool isv) { OutBuffer buf; @@ -264,15 +281,15 @@ char *TemplateInstance::mangle(bool isv) printf(" parent = %s %s", parent->kind(), parent->toChars()); printf("\n"); #endif - char *id = ident ? ident->toChars() : toChars(); + const char *id = ident ? ident->toChars() : toChars(); if (!tempdecl) error("is not defined"); else { - Dsymbol *par = isnested || isTemplateMixin() ? parent : tempdecl->parent; + Dsymbol *par = enclosing || isTemplateMixin() ? parent : tempdecl->parent; if (par) { - char *p = par->mangle(); + const char *p = par->mangle(); if (p[0] == '_' && p[1] == 'D') p += 2; buf.writestring(p); @@ -287,7 +304,7 @@ char *TemplateInstance::mangle(bool isv) -char *Dsymbol::mangle(bool isv) +const char *Dsymbol::mangle(bool isv) { OutBuffer buf; char *id; @@ -301,7 +318,7 @@ char *Dsymbol::mangle(bool isv) id = ident ? ident->toChars() : toChars(); if (parent) { - char *p = parent->mangle(isv); + const char *p = parent->mangle(isv); if (p[0] == '_' && p[1] == 'D') p += 2; buf.writestring(p); diff --git a/dmd2/mars.c b/dmd2/mars.c index 2d9392dc1b..046a01f355 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -26,6 +26,7 @@ #if !IN_LLVM #include "async.h" #endif +#include "target.h" #include "mars.h" #include "module.h" @@ -59,7 +60,7 @@ static bool parse_arch(size_t argc, char** argv, bool is64bit); Global global; -Global::Global() +void Global::init() { mars_ext = "d"; sym_ext = "d"; @@ -99,14 +100,16 @@ Global::Global() version = "v" #include "verstr.h" ; + compiler.vendor = "Digital Mars D"; #endif #if IN_LLVM - version = "v2.062"; + version = "v2.063"; ldc_version = "trunk"; llvm_version = "LLVM " LDC_LLVM_VERSION_STRING; + compiler.vendor = "LDC"; #endif - global.structalign = STRUCTALIGN_DEFAULT; + main_d = "__main.d"; // This should only be used as a global, so the other fields are // automatically initialized to zero when the program is loaded. @@ -213,24 +216,24 @@ void verrorPrint(Loc loc, const char *header, const char *format, va_list ap, char *p = loc.toChars(); if (*p) - fprintf(stdmsg, "%s: ", p); + fprintf(stderr, "%s: ", p); mem.free(p); - fputs(header, stdmsg); + fputs(header, stderr); if (p1) - fprintf(stdmsg, "%s ", p1); + fprintf(stderr, "%s ", p1); if (p2) - fprintf(stdmsg, "%s ", p2); + fprintf(stderr, "%s ", p2); #if _MSC_VER // MS doesn't recognize %zu format OutBuffer tmp; tmp.vprintf(format, ap); - fprintf(stdmsg, "%s", tmp.toChars()); + fprintf(stderr, "%s", tmp.toChars()); #else - vfprintf(stdmsg, format, ap); + vfprintf(stderr, format, ap); #endif - fprintf(stdmsg, "\n"); - fflush(stdmsg); + fprintf(stderr, "\n"); + fflush(stderr); } // header is "Error: " by default (see mars.h) @@ -317,8 +320,8 @@ void usage() #else const char fpic[] = ""; #endif - printf("DMD%d D Compiler %s\n%s %s\n", - sizeof(size_t) * 8, + printf("DMD%llu D Compiler %s\n%s %s\n", + (unsigned long long) sizeof(size_t) * 8, global.version, global.copyright, global.written); printf("\ Documentation: http://dlang.org/\n\ @@ -329,6 +332,7 @@ Usage:\n\ @cmdfile read arguments from cmdfile\n\ -c do not link\n\ -cov do code coverage analysis\n\ + -cov=nnn require at least %%nnn code coverage\n\ -D generate documentation\n\ -Dddocdir write documentation file to docdir directory\n\ -Dffilename write documentation file to filename\n\ @@ -359,23 +363,24 @@ Usage:\n\ " -m32 generate 32 bit code\n\ -m64 generate 64 bit code\n" #endif -" -man open web browser on manual page\n\ +" -main add default main() (e.g. for unittesting)\n\ + -man open web browser on manual page\n\ -map generate linker .map file\n\ -noboundscheck turns off array bounds checking for all functions\n\ -O optimize\n\ -o- do not write object file\n\ -odobjdir write object & library files to directory objdir\n\ -offilename name output file to filename\n\ - -op do not strip paths from source file\n\ + -op preserve source path for output files\n\ -profile profile runtime performance of generated code\n\ -property enforce property syntax\n\ -quiet suppress unnecessary messages\n\ -release compile release version\n\ - -run srcfile args... run resulting program, passing args\n" -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS -" -shared generate shared library\n" -#endif -" -unittest compile in unit tests\n\ + -run srcfile args... run resulting program, passing args\n\ + -shared generate shared library (DLL)\n\ + -transition=id show additional info about language change identified by 'id'\n\ + -transition=? list all language changes\n\ + -unittest compile in unit tests\n\ -v verbose\n\ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ @@ -414,6 +419,7 @@ int tryMain(size_t argc, char *argv[]) char noboundscheck = 0; int setdefaultlib = 0; const char *inifilename = NULL; + global.init(); #ifdef DEBUG printf("DMD %s DEBUG\n", global.version); @@ -425,7 +431,7 @@ int tryMain(size_t argc, char *argv[]) if (argc < 1 || !argv) { Largs: - error(0, "missing or null command line arguments"); + error(Loc(), "missing or null command line arguments"); fatal(); } for (size_t i = 0; i < argc; i++) @@ -435,7 +441,7 @@ int tryMain(size_t argc, char *argv[]) } if (response_expand(&argc,&argv)) // expand response files - error(0, "can't open response file"); + error(Loc(), "can't open response file"); files.reserve(argc - 1); @@ -465,7 +471,9 @@ int tryMain(size_t argc, char *argv[]) #if TARGET_WINDOS global.params.is64bit = 0; global.params.defaultlibname = "phobos"; -#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS +#elif TARGET_LINUX + global.params.defaultlibname = "libphobos2.a"; +#elif TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS global.params.defaultlibname = "phobos2"; #else #error "fix this" @@ -552,9 +560,29 @@ int tryMain(size_t argc, char *argv[]) global.params.useDeprecated = 2; else if (strcmp(p + 1, "c") == 0) global.params.link = 0; - else if (strcmp(p + 1, "cov") == 0) - global.params.cov = 1; -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS + else if (memcmp(p + 1, "cov", 3) == 0) + { + global.params.cov = true; + // Parse: + // -cov + // -cov=nnn + if (p[4] == '=') + { + if (isdigit((unsigned char)p[5])) + { long percent; + + errno = 0; + percent = strtol(p + 5, &p, 10); + if (*p || errno || percent > 100) + goto Lerror; + global.params.covPercent = percent; + } + else + goto Lerror; + } + else if (p[4]) + goto Lerror; + } else if (strcmp(p + 1, "shared") == 0 #if TARGET_OSX // backwards compatibility with old switch @@ -562,6 +590,7 @@ int tryMain(size_t argc, char *argv[]) #endif ) global.params.dll = 1; +#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS else if (strcmp(p + 1, "fPIC") == 0) global.params.pic = 1; #endif @@ -578,7 +607,7 @@ int tryMain(size_t argc, char *argv[]) else if (strcmp(p + 1, "gx") == 0) global.params.stackstomp = true; else if (strcmp(p + 1, "gt") == 0) - { error(0, "use -profile instead of -gt"); + { error(Loc(), "use -profile instead of -gt"); global.params.trace = 1; } else if (strcmp(p + 1, "m32") == 0) @@ -592,13 +621,57 @@ int tryMain(size_t argc, char *argv[]) #if DMDV2 else if (strcmp(p + 1, "vtls") == 0) global.params.vtls = 1; + else if (memcmp(p + 1, "transition", 10) == 0) + { + // Parse: + // -transition=number + if (p[11] == '=') + { + if (strcmp(p + 12, "?") == 0) + { + printf("\ +Language changes listed by -transition=id:\n\ + =field,3449 do list all non-mutable fields occupies object instance\n\ + =tls do list all variables going into thread local storage\n\ +"); + return EXIT_FAILURE; + } + if (isdigit((unsigned char)p[12])) + { long num; + + errno = 0; + num = strtol(p + 12, &p, 10); + if (*p || errno || num > INT_MAX) + goto Lerror; + switch (num) // Bugzilla issue number + { + case 3449: + global.params.vfield = 1; + break; + default: + goto Lerror; + } + } + else if (Lexer::isValidIdentifier(p + 12)) + { + if (strcmp(p + 12, "tls") == 0) + global.params.vtls = 1; + else if (strcmp(p + 12, "field") == 0) + global.params.vfield = 1; + } + else + goto Lerror; + } + else + goto Lerror; + } #endif else if (strcmp(p + 1, "v1") == 0) { #if DMDV1 global.params.Dversion = 1; #else - error(0, "use DMD 1.0 series compilers for -v1 switch"); + error(Loc(), "use DMD 1.0 series compilers for -v1 switch"); break; #endif } @@ -635,7 +708,7 @@ int tryMain(size_t argc, char *argv[]) break; case 0: - error(0, "-o no longer supported, use -of or -od"); + error(Loc(), "-o no longer supported, use -of or -od"); break; default: @@ -826,6 +899,10 @@ int tryMain(size_t argc, char *argv[]) goto Lnoarg; global.params.moduleDeps = new OutBuffer; } + else if (strcmp(p + 1, "main") == 0) + { + global.params.addMain = true; + } else if (memcmp(p + 1, "man", 3) == 0) { #if _WIN32 @@ -874,7 +951,7 @@ int tryMain(size_t argc, char *argv[]) if (ext && FileName::equals(ext, "d") == 0 && FileName::equals(ext, "di") == 0) { - error(0, "-run must be followed by a source file, not '%s'", argv[i + 1]); + error(Loc(), "-run must be followed by a source file, not '%s'", argv[i + 1]); break; } @@ -891,11 +968,11 @@ int tryMain(size_t argc, char *argv[]) else { Lerror: - error(0, "unrecognized switch '%s'", argv[i]); + error(Loc(), "unrecognized switch '%s'", argv[i]); continue; Lnoarg: - error(0, "argument expected for switch '%s'", argv[i]); + error(Loc(), "argument expected for switch '%s'", argv[i]); continue; } } @@ -914,7 +991,7 @@ int tryMain(size_t argc, char *argv[]) } if(global.params.is64bit != is64bit) - error(0, "the architecture must not be changed in the %s section of %s", + error(Loc(), "the architecture must not be changed in the %s section of %s", is64bit ? "Environment64" : "Environment32", inifilename); if (global.errors) @@ -935,7 +1012,7 @@ int tryMain(size_t argc, char *argv[]) #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS if (global.params.lib && global.params.dll) - error(0, "cannot mix -lib and -shared"); + error(Loc(), "cannot mix -lib and -shared"); #endif if (global.params.release) @@ -997,7 +1074,7 @@ int tryMain(size_t argc, char *argv[]) } else if (global.params.run) { - error(0, "flags conflict with -run"); + error(Loc(), "flags conflict with -run"); fatal(); } else @@ -1057,6 +1134,8 @@ int tryMain(size_t argc, char *argv[]) Type::init(); Id::initialize(); Module::init(); + Target::init(); + Expression::init(); initPrecedence(); if (global.params.verbose) @@ -1101,10 +1180,15 @@ int tryMain(size_t argc, char *argv[]) } } + if (global.params.addMain) + { + files.push(const_cast(global.main_d)); // a dummy name, we never actually look up this file + } + // Create Modules Modules modules; modules.reserve(files.dim); - int firstmodule = 1; + bool firstmodule = true; for (size_t i = 0; i < files.dim; i++) { const char *ext; @@ -1196,12 +1280,12 @@ int tryMain(size_t argc, char *argv[]) strcmp(name, ".") == 0) { Linvalid: - error(0, "invalid file name '%s'", files[i]); + error(Loc(), "invalid file name '%s'", files[i]); fatal(); } } else - { error(0, "unrecognized file extension %s", ext); + { error(Loc(), "unrecognized file extension %s", ext); fatal(); } } @@ -1221,11 +1305,30 @@ int tryMain(size_t argc, char *argv[]) if (firstmodule) { global.params.objfiles->push((char *)m->objfile->name->str); - firstmodule = 0; + firstmodule = false; } } // Read files + + /* Start by "reading" the dummy main.d file + */ + if (global.params.addMain) + { + for (size_t i = 0; 1; i++) + { + assert(i != modules.dim); + Module *m = modules[i]; + if (strcmp(m->srcfile->name->str, global.main_d) == 0) + { + static const char buf[] = "int main(){return 0;}"; + m->srcfile->setbuffer((void *)buf, sizeof(buf)); + m->srcfile->ref = 1; + break; + } + } + } + #define ASYNCREAD 1 #if ASYNCREAD // Multi threaded @@ -1261,7 +1364,7 @@ int tryMain(size_t argc, char *argv[]) #if ASYNCREAD if (aw->read(filei)) { - error(0, "cannot read file %s", m->srcfile->name->toChars()); + error(Loc(), "cannot read file %s", m->srcfile->name->toChars()); fatal(); } #endif @@ -1296,7 +1399,7 @@ int tryMain(size_t argc, char *argv[]) if (anydocfiles && modules.dim && (global.params.oneobj || global.params.objname)) { - error(0, "conflicting Ddoc and obj generation options"); + error(Loc(), "conflicting Ddoc and obj generation options"); fatal(); } if (global.errors) @@ -1325,7 +1428,7 @@ int tryMain(size_t argc, char *argv[]) m = modules[i]; if (global.params.verbose) printf("importall %s\n", m->toChars()); - m->importAll(0); + m->importAll(NULL); } if (global.errors) fatal(); @@ -1537,7 +1640,7 @@ int tryMain(size_t argc, char *argv[]) if (!global.params.objfiles->dim) { if (global.params.link) - error(0, "no object files to link"); + error(Loc(), "no object files to link"); } else { @@ -1573,15 +1676,15 @@ int main(int argc, char *argv[]) #if WINDOWS_SEH __try { -#endif status = tryMain(argc, argv); -#if WINDOWS_SEH } __except (__ehfilter(GetExceptionInformation())) { printf("Stack overflow\n"); fatal(); } +#else + status = tryMain(argc, argv); #endif return status; } diff --git a/dmd2/mars.h b/dmd2/mars.h index 544e074a05..dc391adee3 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -102,9 +102,7 @@ void unittests(); #define DMDV2 1 // Version 2.0 features #define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN #define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class -#define BUG6652 2 // Making foreach range statement parameter non-ref in default - // 1: Modifying iteratee in body is warned with -w switch - // 2: Modifying iteratee in body is error without -d switch +#define PULL93 0 // controversial pull #93 for bugzilla 3449 // Set if C++ mangling is done by the front end #define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || IN_LLVM)) @@ -159,24 +157,27 @@ struct Param { bool obj; // write object file bool link; // perform link -#if !IN_LLVM +#if IN_LLVM + bool verbose; // verbose compile + bool vtls; // identify thread local variables + bool vfield; // identify non-mutable field variables + ubyte symdebug; // insert debug symbolic information + bool is64bit; // generate 64 bit code +#else char dll; // generate shared dynamic library char lib; // write library file instead of object file(s) char multiobj; // break one object file into multiple ones char oneobj; // write one object file instead of multiple ones bool trace; // insert profiling hooks char quiet; // suppress non-error messages -#endif - bool verbose; // verbose compile - bool vtls; // identify thread local variables - ubyte symdebug; // insert debug symbolic information -#if !IN_LLVM - char alwaysframe; // always emit standard stack frame - char optimize; // run optimizer -#endif + char verbose; // verbose compile + char vtls; // identify thread local variables + char vfield; // identify non-mutable field variables + char symdebug; // insert debug symbolic information + bool alwaysframe; // always emit standard stack frame + bool optimize; // run optimizer char map; // generate linker .map file - bool is64bit; // generate 64 bit code -#if !IN_LLVM + char is64bit; // generate 64 bit code char isLinux; // generate code for linux char isOSX; // generate code for Mac OSX char isWindows; // generate code for Windows @@ -192,13 +193,9 @@ struct Param bool useInvariants; // generate class invariant checks bool useIn; // generate precondition checks bool useOut; // generate postcondition checks -#if IN_LLVM - bool useArrayBounds; -#else char useArrayBounds; // 0: no array bounds checks // 1: array bounds checks for safe functions only // 2: array bounds checks for all functions -#endif bool noboundscheck; // no array bounds checking at all bool stackstomp; // add stack stomping code bool useSwitchError; // check for switches without a default @@ -211,16 +208,21 @@ struct Param ubyte warnings; // 0: enable warnings // 1: warnings as errors // 2: informational warnings (no errors) -#if !IN_LLVM - char pic; // generate position-independent-code for shared libs - char cov; // generate code coverage data - char nofloat; // code should not pull in floating point support -#endif +#if IN_LLVM ubyte Dversion; // D version number bool ignoreUnsupportedPragmas; // rather than error on them bool enforcePropertySyntax; -#if !IN_LLVM + bool addMain; // LDC_FIXME: Implement. +#else + bool pic; // generate position-independent-code for shared libs + bool cov; // generate code coverage data + unsigned char covPercent; // 0..100 code coverage percentage required + bool nofloat; // code should not pull in floating point support + char Dversion; // D version number + char ignoreUnsupportedPragmas; // rather than error on them + char enforcePropertySyntax; char betterC; // be a "better C" compiler; no dependency on D runtime + bool addMain; // add a default main() function #endif char *argv0; // program name @@ -304,6 +306,11 @@ struct Param #endif }; +struct Compiler +{ + const char *vendor; // Compiler backend name +}; + typedef unsigned structalign_t; #define STRUCTALIGN_DEFAULT ~0 // magic value means "match whatever the underlying C compiler does" // other values are all powers of 2 @@ -328,11 +335,10 @@ struct Global const char *map_ext; // for .map files const char *copyright; const char *written; + const char *main_d; // dummy filename for dummy main() Strings *path; // Array of char*'s which form the import lookup path Strings *filePath; // Array of char*'s which form the file import lookup path - structalign_t structalign; // default alignment for struct fields - const char *version; #if IN_LLVM char *ldc_version; @@ -341,6 +347,7 @@ struct Global bool inExtraInliningSemantic; #endif + Compiler compiler; Param params; unsigned errors; // number of errors reported so far unsigned warnings; // number of warnings reported so far @@ -361,7 +368,7 @@ struct Global */ bool endGagging(unsigned oldGagged); - Global(); + void init(); }; extern Global global; @@ -417,14 +424,6 @@ typedef d_uns32 d_dchar; typedef longdouble real_t; #endif -// Modify OutBuffer::writewchar to write the correct size of wchar -#if _WIN32 -#define writewchar writeword -#else -// This needs a configuration test... -#define writewchar write4 -#endif - #ifdef IN_GCC #include "d-gcc-complex_t.h" #endif @@ -443,12 +442,6 @@ struct Loc filename = NULL; } - Loc(int x) - { - linnum = x; - filename = NULL; - } - Loc(Module *mod, unsigned linnum); char *toChars(); @@ -534,13 +527,6 @@ void halt(); void util_progress(); #endif -/*** Where to send error messages ***/ -#if defined(IN_GCC) || IN_LLVM -#define stdmsg stderr -#else -#define stdmsg stderr -#endif - #if !IN_LLVM struct Dsymbol; class Library; diff --git a/dmd2/module.c b/dmd2/module.c index 77b8aea0d7..b62807c353 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -476,11 +476,11 @@ bool Module::read(Loc loc) for (size_t i = 0; i < global.path->dim; i++) { char *p = (*global.path)[i]; - fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p); + fprintf(stderr, "import path[%llu] = %s\n", (ulonglong)i, p); } } else - fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); + fprintf(stderr, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); fatal(); } return false; @@ -766,7 +766,8 @@ void Module::parse() p.nextToken(); members = p.parseModule(); - ::free(srcfile->buffer); + if (srcfile->ref == 0) + ::free(srcfile->buffer); srcfile->buffer = NULL; srcfile->len = 0; @@ -804,8 +805,14 @@ void Module::parse() assert(prev); Module *mprev = prev->isModule(); if (mprev) - error(loc, "from file %s conflicts with another module %s from file %s", - srcname, mprev->toChars(), mprev->srcfile->toChars()); + { + if (strcmp(srcname, mprev->srcfile->toChars()) == 0) + error(loc, "from file %s must be imported as module '%s'", + srcname, toPrettyChars()); + else + error(loc, "from file %s conflicts with another module %s from file %s", + srcname, mprev->toChars(), mprev->srcfile->toChars()); + } else { Package *pkg = prev->isPackage(); @@ -846,7 +853,7 @@ void Module::importAll(Scope *prevsc) // would fail inside object.d. if (members->dim == 0 || ((*members)[0])->ident != Id::object) { - Import *im = new Import(0, NULL, Id::object, NULL, 0); + Import *im = new Import(Loc(), NULL, Id::object, NULL, 0); members->shift(im); } @@ -1113,7 +1120,7 @@ Dsymbol *Module::search(Loc loc, Identifier *ident, int flags) Dsymbol *Module::symtabInsert(Dsymbol *s) { - searchCacheIdent = 0; // symbol is inserted, so invalidate cache + searchCacheIdent = NULL; // symbol is inserted, so invalidate cache return Package::symtabInsert(s); } diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 8cad225118..eefbaa30d3 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -32,6 +32,7 @@ #include "rmem.h" #include "port.h" +#include "target.h" #include "dsymbol.h" #include "mtype.h" @@ -44,58 +45,22 @@ #include "template.h" #include "id.h" #include "enum.h" +#include "module.h" #include "import.h" #include "aggregate.h" #include "hdrgen.h" #if IN_LLVM -//#include "gen/tollvm.h" Ir* Type::sir = NULL; -unsigned GetTypeAlignment(Ir* ir, Type* t); -unsigned GetPointerSize(Ir* ir); -unsigned GetTypeStoreSize(Ir* ir, Type* t); -unsigned GetTypeAllocSize(Ir* ir, Type* t); #endif FuncDeclaration *hasThis(Scope *sc); -void ObjectNotFound(Identifier *id); - #define LOGDOTEXP 0 // log ::dotExp() #define LOGDEFAULTINIT 0 // log ::defaultInit() -// Allow implicit conversion of T[] to T* -#define IMPLICIT_ARRAY_TO_PTR global.params.useDeprecated - -/* These have default values for 32 bit code, they get - * adjusted for 64 bit code. - */ - -int PTRSIZE = 4; - -/* REALSIZE = size a real consumes in memory - * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE - * REALALIGNSIZE = alignment for reals - */ -#if TARGET_OSX -int REALSIZE = 16; -int REALPAD = 6; -int REALALIGNSIZE = 16; -#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS -int REALSIZE = 12; -int REALPAD = 2; -int REALALIGNSIZE = 4; -#elif TARGET_WINDOS -int REALSIZE = 10; -int REALPAD = 0; -int REALALIGNSIZE = 2; -#elif defined(IN_GCC) || defined(IN_LLVM) -int REALSIZE = 0; -int REALPAD = 0; -int REALALIGNSIZE = 0; -#else -#error "fix this" -#endif +// Allow implicit conversion of T[] to T* --> Removed in 2.063 +#define IMPLICIT_ARRAY_TO_PTR 0 int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; @@ -124,6 +89,44 @@ ClassDeclaration *Type::typeinfowild; TemplateDeclaration *Type::associativearray; TemplateDeclaration *Type::rtinfo; +Type *Type::tvoid; +Type *Type::tint8; +Type *Type::tuns8; +Type *Type::tint16; +Type *Type::tuns16; +Type *Type::tint32; +Type *Type::tuns32; +Type *Type::tint64; +Type *Type::tuns64; +Type *Type::tint128; +Type *Type::tuns128; +Type *Type::tfloat32; +Type *Type::tfloat64; +Type *Type::tfloat80; + +Type *Type::timaginary32; +Type *Type::timaginary64; +Type *Type::timaginary80; + +Type *Type::tcomplex32; +Type *Type::tcomplex64; +Type *Type::tcomplex80; + +Type *Type::tbool; +Type *Type::tchar; +Type *Type::twchar; +Type *Type::tdchar; + +Type *Type::tshiftcnt; +Type *Type::tboolean; +Type *Type::terror; +Type *Type::tnull; + +Type *Type::tsize_t; +Type *Type::tptrdiff_t; +Type *Type::thash_t; +Type *Type::tindex; + Type *Type::tvoidptr; Type *Type::tstring; Type *Type::tvalist; @@ -172,7 +175,7 @@ const char *Type::kind() Type *Type::syntaxCopy() { print(); - fprintf(stdmsg, "ty = %d\n", ty); + fprintf(stderr, "ty = %d\n", ty); assert(0); return this; } @@ -204,9 +207,9 @@ void Type::init(Ir* _sir) void Type::init() #endif { - stringtable.init(1543); + stringtable._init(1543); #if IN_LLVM - deco_stringtable.init(); + deco_stringtable._init(); #endif Lexer::initKeywords(); @@ -286,7 +289,7 @@ void Type::init() for (size_t i = 0; i < TMAX; i++) { if (!mangleChar[i]) - fprintf(stdmsg, "ty = %llu\n", (ulonglong)i); + fprintf(stderr, "ty = %llu\n", (ulonglong)i); assert(mangleChar[i]); } @@ -307,6 +310,38 @@ void Type::init() } basic[Terror] = new TypeError(); + tvoid = basic[Tvoid]; + tint8 = basic[Tint8]; + tuns8 = basic[Tuns8]; + tint16 = basic[Tint16]; + tuns16 = basic[Tuns16]; + tint32 = basic[Tint32]; + tuns32 = basic[Tuns32]; + tint64 = basic[Tint64]; + tuns64 = basic[Tuns64]; + tint128 = basic[Tint128]; + tuns128 = basic[Tuns128]; + tfloat32 = basic[Tfloat32]; + tfloat64 = basic[Tfloat64]; + tfloat80 = basic[Tfloat80]; + + timaginary32 = basic[Timaginary32]; + timaginary64 = basic[Timaginary64]; + timaginary80 = basic[Timaginary80]; + + tcomplex32 = basic[Tcomplex32]; + tcomplex64 = basic[Tcomplex64]; + tcomplex80 = basic[Tcomplex80]; + + tbool = basic[Tbool]; + tchar = basic[Tchar]; + twchar = basic[Twchar]; + tdchar = basic[Tdchar]; + + tshiftcnt = tint32; + tboolean = tbool; + terror = basic[Terror]; + tnull = basic[Tnull]; tnull = new TypeNull(); tnull->deco = tnull->merge()->deco; @@ -314,74 +349,41 @@ void Type::init() tstring = tchar->invariantOf()->arrayOf(); tvalist = tvoid->pointerTo(); -#if IN_DMD if (global.params.is64bit) { - PTRSIZE = 8; - if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris) - { - REALSIZE = 16; - REALPAD = 6; - REALALIGNSIZE = 16; - } Tsize_t = Tuns64; Tptrdiff_t = Tint64; } else { - PTRSIZE = 4; -#if TARGET_OSX - REALSIZE = 16; - REALPAD = 6; -#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS - REALSIZE = 12; - REALPAD = 2; -#elif TARGET_WINDOS - REALSIZE = 10; - REALPAD = 0; -#elif defined(IN_GCC) -#else - assert(0); -#endif Tsize_t = Tuns32; Tptrdiff_t = Tint32; } -#endif #if IN_LLVM sir = _sir; - - if (global.params.is64bit) - { - Tsize_t = Tuns64; - Tptrdiff_t = Tint64; - } - else - { - Tsize_t = Tuns32; - Tptrdiff_t = Tint32; - } - PTRSIZE = GetPointerSize(sir); - REALSIZE = GetTypeAllocSize(sir, Type::basic[Tfloat80]); - REALPAD = REALSIZE - GetTypeStoreSize(sir, Type::basic[Tfloat80]); - REALALIGNSIZE = GetTypeAlignment(sir, Type::basic[Tfloat80]); #endif + + tsize_t = basic[Tsize_t]; + tptrdiff_t = basic[Tptrdiff_t]; + thash_t = tsize_t; + tindex = tsize_t; } d_uns64 Type::size() { - return size(0); + return size(Loc()); } d_uns64 Type::size(Loc loc) { error(loc, "no size for type %s", toChars()); - return 1; + return SIZE_INVALID; } unsigned Type::alignsize() { - return size(0); + return size(Loc()); } Type *Type::semantic(Loc loc, Scope *sc) @@ -408,6 +410,36 @@ Type *Type::trySemantic(Loc loc, Scope *sc) return t; } +/******************************** + * Return a copy of this type with all attributes null-initialized. + * Useful for creating a type with different modifiers. + */ + +Type *Type::nullAttributes() +{ + unsigned sz = sizeTy[ty]; + Type *t = (Type *)mem.malloc(sz); + memcpy(t, this, sz); + // t->mod = NULL; // leave mod unchanged + t->deco = NULL; + t->arrayof = NULL; + t->pto = NULL; + t->rto = NULL; + t->cto = NULL; + t->ito = NULL; + t->sto = NULL; + t->scto = NULL; + t->wto = NULL; + t->swto = NULL; + t->vtinfo = NULL; +#if !IN_LLVM + t->ctype = NULL; +#endif + if (t->ty == Tstruct) ((TypeStruct *)t)->att = RECfwdref; + if (t->ty == Tclass) ((TypeClass *)t)->att = RECfwdref; + return t; +} + /******************************** * Convert to 'const'. */ @@ -558,21 +590,11 @@ Type *Type::unSharedOf() if (!t) { - unsigned sz = sizeTy[ty]; - t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + t = this->nullAttributes(); t->mod = mod & ~MODshared; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; +#if !IN_LLVM + t->ctype = ctype; +#endif t = t->merge(); t->fixTo(this); @@ -966,175 +988,57 @@ void Type::check() Type *Type::makeConst() { //printf("Type::makeConst() %p, %s\n", this, toChars()); - if (cto) - return cto; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (cto) return cto; + Type *t = this->nullAttributes(); t->mod = MODconst; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif //printf("-Type::makeConst() %p, %s\n", t, toChars()); return t; } Type *Type::makeInvariant() { - if (ito) - return ito; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (ito) return ito; + Type *t = this->nullAttributes(); t->mod = MODimmutable; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif return t; } Type *Type::makeShared() { - if (sto) - return sto; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (sto) return sto; + Type *t = this->nullAttributes(); t->mod = MODshared; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif return t; } Type *Type::makeSharedConst() { - if (scto) - return scto; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (scto) return scto; + Type *t = this->nullAttributes(); t->mod = MODshared | MODconst; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif return t; } Type *Type::makeWild() { - if (wto) - return wto; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (wto) return wto; + Type *t = this->nullAttributes(); t->mod = MODwild; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif return t; } Type *Type::makeSharedWild() { - if (swto) - return swto; - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); + if (swto) return swto; + Type *t = this->nullAttributes(); t->mod = MODshared | MODwild; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif return t; } Type *Type::makeMutable() { - unsigned sz = sizeTy[ty]; - Type *t = (Type *)mem.malloc(sz); - memcpy(t, this, sz); - t->mod = mod & MODshared; - t->deco = NULL; - t->arrayof = NULL; - t->pto = NULL; - t->rto = NULL; - t->cto = NULL; - t->ito = NULL; - t->sto = NULL; - t->scto = NULL; - t->wto = NULL; - t->swto = NULL; - t->vtinfo = NULL; -#if IN_DMD - t->ctype = NULL; -#endif + Type *t = this->nullAttributes(); + t->mod = mod & MODshared; return t; } @@ -1365,9 +1269,7 @@ Type *Type::aliasthisOf() } else if (d->isFuncDeclaration()) { - FuncDeclaration *fd = (FuncDeclaration *)d; - Expression *ethis = this->defaultInit(0); - fd = fd->overloadResolve(0, ethis, NULL, 1); + FuncDeclaration *fd = resolveFuncCall(Loc(), NULL, d, NULL, this, NULL, 1); if (fd && fd->functionSemantic()) { t = fd->type->nextOf(); @@ -1387,8 +1289,7 @@ Type *Type::aliasthisOf() TemplateDeclaration *td = ad->aliasthis->isTemplateDeclaration(); if (td) { assert(td->scope); - Expression *ethis = defaultInit(0); - FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1); + FuncDeclaration *fd = resolveFuncCall(Loc(), NULL, td, NULL, this, NULL, 1); if (fd && fd->functionSemantic()) { Type *t = fd->type->nextOf(); @@ -1403,6 +1304,27 @@ Type *Type::aliasthisOf() return NULL; } +int Type::checkAliasThisRec() +{ + Type *tb = toBasetype(); + enum AliasThisRec* pflag; + if (tb->ty == Tstruct) + pflag = &((TypeStruct *)tb)->att; + else if (tb->ty == Tclass) + pflag = &((TypeClass *)tb)->att; + else + return 0; + + enum AliasThisRec flag = (enum AliasThisRec)(*pflag & ~RECtracing); + if (flag == RECfwdref) + { + Type *att = aliasthisOf(); + flag = att && att->implicitConvTo(this) ? RECyes : RECno; + } + *pflag = (AliasThisRec)(flag | (*pflag & RECtracing)); + return flag == RECyes; +} + Dsymbol *Type::toDsymbol(Scope *sc) { return NULL; @@ -2044,7 +1966,12 @@ Type *Type::toHeadMutable() return mutableOf(); } -Expression *Type::getProperty(Loc loc, Identifier *ident) +/*************************************** + * Calculate built-in properties which just the type is necessary. + * + * If flag == 1, don't report "not a property" error and just return NULL. + */ +Expression *Type::getProperty(Loc loc, Identifier *ident, int flag) { Expression *e; #if LOGDOTEXP @@ -2052,7 +1979,10 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) #endif if (ident == Id::__sizeof) { - e = new IntegerExp(loc, size(loc), Type::tsize_t); + d_uns64 sz = size(loc); + if (sz == SIZE_INVALID) + return new ErrorExp(); + e = new IntegerExp(loc, sz, Type::tsize_t); } else if (ident == Id::__xalignof) { @@ -2071,7 +2001,7 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) { StructLiteralExp *se = (StructLiteralExp *)e; #if IN_LLVM - se->sinit = (StaticStructInitDeclaration*) + se->sinit = (SymbolDeclaration*) (((VarExp*)defaultInit(loc))->var); #else se->sinit = se->sd->toInitializer(); @@ -2079,16 +2009,18 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) } } else if (ident == Id::mangleof) - { const char *s; + { if (!deco) - { s = toChars(); - error(loc, "forward reference of type %s.mangleof", s); + { + error(loc, "forward reference of type %s.mangleof", toChars()); + e = new ErrorExp(); } else - s = deco; - e = new StringExp(loc, (char *)s, strlen(s), 'c'); - Scope sc; - e = e->semantic(&sc); + { + e = new StringExp(loc, (char *)deco, strlen(deco), 'c'); + Scope sc; + e = e->semantic(&sc); + } } else if (ident == Id::stringof) { char *s = toChars(); @@ -2096,6 +2028,10 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) Scope sc; e = e->semantic(&sc); } + else if (flag && this != Type::terror) + { + return NULL; + } else { Dsymbol *s = NULL; @@ -2115,7 +2051,12 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) return e; } -Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) +/*************************************** + * Access the members of the object e. This type is same as e->type. + * + * If flag == 1, don't report "not a property" error and just return NULL. + */ +Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { VarDeclaration *v = NULL; #if LOGDOTEXP @@ -2141,7 +2082,7 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) else if (ident == Id::offsetof) { Loffset: - if (v->storage_class & STCfield) + if (v->isField()) { e = new IntegerExp(e->loc, v->offset, Type::tsize_t); return e; @@ -2183,10 +2124,11 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) e = new StringExp(e->loc, s, strlen(s), 'c'); } else - e = getProperty(e->loc, ident); + e = getProperty(e->loc, ident, flag); Lreturn: - e = e->semantic(sc); + if (!flag || e) + e = e->semantic(sc); return e; } @@ -2202,8 +2144,10 @@ structalign_t Type::alignment() /*************************************** * Figures out what to do with an undefined member reference * for classes and structs. + * + * If flag == 1, don't report "not a property" error and just return NULL. */ -Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) +Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident, int flag) { assert(ty == Tstruct || ty == Tclass); AggregateDeclaration *sym = toDsymbol(sc)->isAggregateDeclaration(); @@ -2249,7 +2193,12 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) tiargs->push(se); DotTemplateInstanceExp *dti = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); dti->ti->tempdecl = td; - return dti->semantic(sc, 1); + + unsigned errors = flag ? global.startGagging() : 0; + Expression *e = dti->semanticY(sc, 0); + if (flag && global.endGagging(errors)) + e = NULL; + return e; } /* See if we should forward to the alias this. @@ -2260,11 +2209,11 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) */ e = resolveAliasThis(sc, e); DotIdExp *die = new DotIdExp(e->loc, e, ident); - return die->semantic(sc, 1); + return die->semanticY(sc, flag); } } - return Type::dotExp(sc, e, ident); + return Type::dotExp(sc, e, ident, flag); } void Type::error(Loc loc, const char *format, ...) @@ -2305,7 +2254,7 @@ Identifier *Type::getTypeInfoIdent(int internal) char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)malloc(namelen); assert(name); - sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data); + sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data); //printf("name = %s\n", name); assert(strlen(name) < namelen); // don't overflow the buffer @@ -2435,9 +2384,9 @@ void TypeError::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) buf->writestring("_error_"); } -d_uns64 TypeError::size(Loc loc) { return 1; } -Expression *TypeError::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); } -Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); } +d_uns64 TypeError::size(Loc loc) { return SIZE_INVALID; } +Expression *TypeError::getProperty(Loc loc, Identifier *ident, int flag) { return new ErrorExp(); } +Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { return new ErrorExp(); } Expression *TypeError::defaultInit(Loc loc) { return new ErrorExp(); } Expression *TypeError::defaultInitLiteral(Loc loc) { return new ErrorExp(); } @@ -2699,11 +2648,6 @@ void TypeNext::transitive() /* ============================= TypeBasic =========================== */ -TypeBasic::TypeBasic(TY ty) - : Type(ty) -{ const char *d; - unsigned flags; - #define TFLAGSintegral 1 #define TFLAGSfloating 2 #define TFLAGSunsigned 4 @@ -2712,6 +2656,11 @@ TypeBasic::TypeBasic(TY ty) #define TFLAGScomplex 0x20 #define TFLAGSvector 0x40 // valid for a SIMD vector type +TypeBasic::TypeBasic(TY ty) + : Type(ty) +{ const char *d; + unsigned flags; + flags = 0; switch (ty) { @@ -2867,7 +2816,7 @@ d_uns64 TypeBasic::size(Loc loc) size = 8; break; case Tfloat80: case Timaginary80: - size = REALSIZE; break; + size = Target::realsize; break; case Tcomplex32: size = 8; break; case Tcomplex64: @@ -2875,7 +2824,7 @@ d_uns64 TypeBasic::size(Loc loc) case Tuns128: size = 16; break; case Tcomplex80: - size = REALSIZE * 2; break; + size = Target::realsize * 2; break; case Tvoid: //size = Type::size(); // error message @@ -2897,47 +2846,7 @@ d_uns64 TypeBasic::size(Loc loc) unsigned TypeBasic::alignsize() { -#if IN_LLVM - if (ty == Tvoid) - return 1; - return GetTypeAlignment(sir, this); -#endif - - unsigned sz; - - switch (ty) - { - case Tfloat80: - case Timaginary80: - case Tcomplex80: - sz = REALALIGNSIZE; - break; - -#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS - case Tint64: - case Tuns64: - sz = global.params.is64bit ? 8 : 4; - break; - - case Tfloat64: - case Timaginary64: - sz = global.params.is64bit ? 8 : 4; - break; - - case Tcomplex32: - sz = 4; - break; - - case Tcomplex64: - sz = global.params.is64bit ? 8 : 4; - break; -#endif - - default: - sz = size(0); - break; - } - return sz; + return Target::alignsize(this); } #if IN_LLVM @@ -2952,7 +2861,7 @@ unsigned TypeBasic::alignment() } #endif -Expression *TypeBasic::getProperty(Loc loc, Identifier *ident) +Expression *TypeBasic::getProperty(Loc loc, Identifier *ident, int flag) { Expression *e; d_int64 ivalue; @@ -3179,7 +3088,7 @@ Expression *TypeBasic::getProperty(Loc loc, Identifier *ident) } } - return Type::getProperty(loc, ident); + return Type::getProperty(loc, ident, flag); Livalue: e = new IntegerExp(loc, ivalue, this); @@ -3212,7 +3121,7 @@ Lint: return e; } -Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -3243,7 +3152,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) break; default: - e = Type::getProperty(e->loc, ident); + e = Type::getProperty(e->loc, ident, flag); break; } } @@ -3275,15 +3184,16 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) break; default: - e = Type::getProperty(e->loc, ident); + e = Type::getProperty(e->loc, ident, flag); break; } } else { - return Type::dotExp(sc, e, ident); + return Type::dotExp(sc, e, ident, flag); } - e = e->semantic(sc); + if (!flag || e) + e = e->semantic(sc); return e; } @@ -3317,7 +3227,7 @@ Expression *TypeBasic::defaultInit(Loc loc) * C ABIs pad them out to 12 or even 16 bytes, so * leave enough space in the snan array. */ - assert(REALSIZE <= sizeof(snan)); + assert(Target::realsize <= sizeof(snan)); d_float80 fvalue = snan.ld; #endif @@ -3385,8 +3295,9 @@ int TypeBasic::isZeroInit(Loc loc) case Tcomplex64: case Tcomplex80: return 0; // no + default: + return 1; // yes } - return 1; // yes } int TypeBasic::isintegral() @@ -3470,8 +3381,8 @@ MATCH TypeBasic::implicitConvTo(Type *to) #if DMDV2 // If converting from integral to integral if (tob->flags & TFLAGSintegral) - { d_uns64 sz = size(0); - d_uns64 tosz = tob->size(0); + { d_uns64 sz = size(Loc()); + d_uns64 tosz = tob->size(Loc()); /* Can't convert to smaller size */ @@ -3535,7 +3446,7 @@ const char *TypeVector::kind() Type *TypeVector::syntaxCopy() { - return new TypeVector(0, basetype->syntaxCopy()); + return new TypeVector(Loc(), basetype->syntaxCopy()); } Type *TypeVector::semantic(Loc loc, Scope *sc) @@ -3624,12 +3535,12 @@ unsigned TypeVector::alignsize() return (unsigned)basetype->size(); } -Expression *TypeVector::getProperty(Loc loc, Identifier *ident) +Expression *TypeVector::getProperty(Loc loc, Identifier *ident, int flag) { - return basetype->getProperty(loc, ident); + return basetype->getProperty(loc, ident, flag); } -Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeVector::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -3639,7 +3550,7 @@ Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident) e = e->castTo(sc, basetype); return e; } - return basetype->dotExp(sc, e->castTo(sc, basetype), ident); + return basetype->dotExp(sc, e->castTo(sc, basetype), ident, flag); } Expression *TypeVector::defaultInit(Loc loc) @@ -3690,7 +3601,7 @@ TypeArray::TypeArray(TY ty, Type *next) { } -Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { Type *n = this->next->toBasetype(); // uncover any typedef's @@ -3700,12 +3611,15 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) if (!n->isMutable()) if (ident == Id::sort || ident == Id::reverse) - error(e->loc, "can only %s a mutable array", ident->toChars()); + { error(e->loc, "can only %s a mutable array", ident->toChars()); + goto Lerror; + } if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar)) { + +#if IN_LLVM Expression *ec; - Expressions *arguments; //LDC: Build arguments. static FuncDeclaration *adReverseChar_fd = NULL; @@ -3724,11 +3638,18 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } if(n->ty == Twchar) - ec = new VarExp(0, adReverseWchar_fd); + ec = new VarExp(Loc(), adReverseWchar_fd); else - ec = new VarExp(0, adReverseChar_fd); + ec = new VarExp(Loc(), adReverseChar_fd); +#else + static const char *name[2] = { "_adReverseChar", "_adReverseWchar" }; + + const char *nm = name[n->ty == Twchar]; + FuncDeclaration *fd = FuncDeclaration::genCfunc(Type::tindex, nm); + Expression *ec = new VarExp(Loc(), fd); +#endif e = e->castTo(sc, n->arrayOf()); // convert to dynamic array - arguments = new Expressions(); + Expressions *arguments = new Expressions(); arguments->push(e); e = new CallExp(e->loc, ec, arguments); e->type = next->arrayOf(); @@ -3738,6 +3659,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *ec; Expressions *arguments; +#if IN_LLVM //LDC: Build arguments. static FuncDeclaration *adSortChar_fd = NULL; if(!adSortChar_fd) { @@ -3755,9 +3677,14 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } if(n->ty == Twchar) - ec = new VarExp(0, adSortWchar_fd); + ec = new VarExp(Loc(), adSortWchar_fd); else - ec = new VarExp(0, adSortChar_fd); + ec = new VarExp(Loc(), adSortChar_fd); +#else + nm = name[n->ty == Twchar]; + fd = FuncDeclaration::genCfunc(Type::tindex, nm); + ec = new VarExp(Loc(), fd); +#endif e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); arguments->push(e); @@ -3774,6 +3701,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *olde = e; assert(size); dup = (ident == Id::dup || ident == Id::idup); +#if IN_LLVM //LDC: Build arguments. static FuncDeclaration *adDup_fd = NULL; if(!adDup_fd) { @@ -3791,30 +3719,38 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } if(dup) - ec = new VarExp(0, adDup_fd); + ec = new VarExp(Loc(), adDup_fd); else - ec = new VarExp(0, adReverse_fd); + ec = new VarExp(Loc(), adReverse_fd); +#else + fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse); + ec = new VarExp(Loc(), fd); +#endif e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); if (dup) arguments->push(getTypeInfo(sc)); arguments->push(e); if (!dup) - arguments->push(new IntegerExp(0, size, Type::tsize_t)); + arguments->push(new IntegerExp(Loc(), size, Type::tsize_t)); e = new CallExp(e->loc, ec, arguments); if (ident == Id::idup) { Type *einv = next->invariantOf(); if (next->implicitConvTo(einv) < MATCHconst) - error(e->loc, "cannot implicitly convert element type %s to immutable in %s.idup", + { error(e->loc, "cannot implicitly convert element type %s to immutable in %s.idup", next->toChars(), olde->toChars()); + goto Lerror; + } e->type = einv->arrayOf(); } else if (ident == Id::dup) { Type *emut = next->mutableOf(); if (next->implicitConvTo(emut) < MATCHconst) - error(e->loc, "cannot implicitly convert element type %s to mutable in %s.dup", + { error(e->loc, "cannot implicitly convert element type %s to mutable in %s.dup", next->toChars(), olde->toChars()); + goto Lerror; + } e->type = emut->arrayOf(); } else @@ -3825,6 +3761,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *ec; Expressions *arguments; +#if IN_LLVM //LDC: Build arguments. static FuncDeclaration *adSort_fd = NULL; if(!adSort_fd) { @@ -3834,7 +3771,11 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort"); } - ec = new VarExp(0, adSort_fd); + ec = new VarExp(Loc(), adSort_fd); +#else + fd = FuncDeclaration::genCfunc(tint32->arrayOf(), "_adSort"); + ec = new VarExp(Loc(), fd); +#endif e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); arguments->push(e); @@ -3846,10 +3787,14 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } else { - e = Type::dotExp(sc, e, ident); + e = Type::dotExp(sc, e, ident, flag); } - e = e->semantic(sc); + if (!flag || e) + e = e->semantic(sc); return e; + +Lerror: + return new ErrorExp(); } @@ -3894,8 +3839,8 @@ d_uns64 TypeSArray::size(Loc loc) return sz; Loverflow: - error(loc, "index %lld overflow for static array", sz); - return 1; + error(loc, "index %lld overflow for static array", (long long)sz); + return SIZE_INVALID; } unsigned TypeSArray::alignsize() @@ -3914,12 +3859,12 @@ Expression *semanticLength(Scope *sc, Type *t, Expression *exp) sym->parent = sc->scopesym; sc = sc->push(sym); - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); sc->pop(); } else - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); return exp; } @@ -3929,7 +3874,7 @@ Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp) sym->parent = sc->scopesym; sc = sc->push(sym); - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); sc->pop(); return exp; @@ -3945,8 +3890,9 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol Expressions *exps = new Expressions(); exps->setDim(1); (*exps)[0] = dim; - Expression *e = new ArrayExp(loc, *pe, exps); - *pe = e; + if (Dsymbol *s = getDsymbol(*pe)) + *pe = new DsymbolExp(loc, s, 1); + *pe = new ArrayExp(loc, *pe, exps); } else if (*ps) { Dsymbol *s = *ps; @@ -3957,7 +3903,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sym->parent = sc->scopesym; sc = sc->push(sym); - dim = dim->semantic(sc); + dim = dim->ctfeSemantic(sc); dim = dim->ctfeInterpret(); uinteger_t d = dim->toUInteger(); @@ -4126,18 +4072,12 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) Parameter *arg = (*tt->arguments)[(size_t)d]; return arg->type->addMod(this->mod); } - case Tstruct: - { TypeStruct *ts = (TypeStruct *)tbn; - if (0 && ts->sym->isnested) - { error(loc, "cannot have static array of inner struct %s", ts->toChars()); - goto Lerror; - } - break; - } case Tfunction: case Tnone: error(loc, "can't have array of %s", tbn->toChars()); goto Lerror; + default: + break; } if (tbn->isscope()) { error(loc, "cannot have array of scope %s", tbn->toChars()); @@ -4181,7 +4121,7 @@ void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->printf("[%s]", dim->toChars()); } -Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -4204,9 +4144,10 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } else { - e = TypeArray::dotExp(sc, e, ident); + e = TypeArray::dotExp(sc, e, ident, flag); } - e = e->semantic(sc); + if (!flag && e) + e = e->semantic(sc); return e; } @@ -4331,12 +4272,16 @@ Expression *TypeSArray::defaultInitLiteral(Loc loc) printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars()); #endif size_t d = dim->toInteger(); - Expression *elementinit = next->defaultInitLiteral(loc); + Expression *elementinit; + if (next->ty == Tvoid) + elementinit = tuns8->defaultInitLiteral(loc); + else + elementinit = next->defaultInitLiteral(loc); Expressions *elements = new Expressions(); elements->setDim(d); for (size_t i = 0; i < d; i++) (*elements)[i] = elementinit; - ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); + ArrayLiteralExp *ae = new ArrayLiteralExp(Loc(), elements); ae->type = this; return ae; } @@ -4396,14 +4341,14 @@ Type *TypeDArray::syntaxCopy() d_uns64 TypeDArray::size(Loc loc) { //printf("TypeDArray::size()\n"); - return PTRSIZE * 2; + return Target::ptrsize * 2; } unsigned TypeDArray::alignsize() { // A DArray consists of two ptr-sized values, so align it on pointer size // boundary - return PTRSIZE; + return Target::ptrsize; } Type *TypeDArray::semantic(Loc loc, Scope *sc) @@ -4418,17 +4363,13 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc) error(loc, "can't have array of %s", tbn->toChars()); case Terror: return Type::terror; - - case Tstruct: - { TypeStruct *ts = (TypeStruct *)tbn; - if (0 && ts->sym->isnested) - error(loc, "cannot have dynamic array of inner struct %s", ts->toChars()); + default: break; - } } if (tn->isscope()) - error(loc, "cannot have array of scope %s", tn->toChars()); - + { error(loc, "cannot have array of scope %s", tn->toChars()); + return Type::terror; + } next = tn; transitive(); return merge(); @@ -4441,8 +4382,9 @@ void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); if (*pe) { // It's really a slice expression - Expression *e = new SliceExp(loc, *pe, NULL, NULL); - *pe = e; + if (Dsymbol *s = getDsymbol(*pe)) + *pe = new DsymbolExp(loc, s, 1); + *pe = new SliceExp(loc, *pe, NULL, NULL); } else if (*ps) { @@ -4480,7 +4422,7 @@ void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) } } -Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -4505,7 +4447,7 @@ Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident) } else { - e = TypeArray::dotExp(sc, e, ident); + e = TypeArray::dotExp(sc, e, ident, flag); } return e; } @@ -4535,7 +4477,7 @@ MATCH TypeDArray::implicitConvTo(Type *to) return MATCHconvert; } - return next->constConv(to) ? MATCHconvert : MATCHnomatch; + return next->constConv(tp->next) ? MATCHconvert : MATCHnomatch; } if (to->ty == Tarray) @@ -4601,7 +4543,7 @@ TypeAArray::TypeAArray(Type *t, Type *index) { this->index = index; this->impl = NULL; - this->loc = 0; + this->loc = Loc(); this->sc = NULL; } @@ -4625,7 +4567,7 @@ Type *TypeAArray::syntaxCopy() d_uns64 TypeAArray::size(Loc loc) { - return PTRSIZE /* * 2*/; + return Target::ptrsize /* * 2*/; } @@ -4725,7 +4667,7 @@ StructDeclaration *TypeAArray::getImpl() next = terror; // Head off future failures - StructDeclaration *s = new StructDeclaration(0, NULL); + StructDeclaration *s = new StructDeclaration(Loc(), NULL); s->type = terror; impl = s; return impl; @@ -4756,9 +4698,12 @@ StructDeclaration *TypeAArray::getImpl() dti->semantic(sc); TemplateInstance *ti = dti->ti; #endif - ti->semantic(sc); - ti->semantic2(sc); - ti->semantic3(sc); + // Instantiate on the root module of import dependency graph. + Scope *scx = sc->push(sc->module->importedFrom); + ti->semantic(scx); + ti->semantic2(scx); + ti->semantic3(scx); + scx->pop(); impl = ti->toAlias()->isStructDeclaration(); #ifdef DEBUG if (!impl) @@ -4800,102 +4745,10 @@ void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol } -Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); -#endif -#if 0 - if (ident == Id::length) - { - Expression *ec; - Expressions *arguments; - - //LDC: Build arguments. - static FuncDeclaration *aaLen_fd = NULL; - if(!aaLen_fd) { - Arguments* args = new Arguments; - args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - aaLen_fd = FuncDeclaration::genCfunc(args, Type::tsize_t, Id::aaLen); - } - - ec = new VarExp(0, aaLen_fd); - arguments = new Expressions(); - arguments->push(e); - e = new CallExp(e->loc, ec, arguments); - e->type = aaLen_fd->type->nextOf(); - } - else - if (ident == Id::keys) - { - Expression *ec; - Expressions *arguments; - int size = index->size(e->loc); - - assert(size); - //LDC: Build arguments. - static FuncDeclaration *aaKeys_fd = NULL; - if(!aaKeys_fd) { - Arguments* args = new Arguments; - args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); - aaKeys_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::aaKeys); - } - - ec = new VarExp(0, aaKeys_fd); - arguments = new Expressions(); - arguments->push(e); - arguments->push(new IntegerExp(0, size, Type::tsize_t)); - e = new CallExp(e->loc, ec, arguments); - e->type = index->arrayOf(); - } - else if (ident == Id::values) - { - Expression *ec; - Expressions *arguments; - - //LDC: Build arguments. - static FuncDeclaration *aaValues_fd = NULL; - if(!aaValues_fd) { - Arguments* args = new Arguments; - args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); - args->push(new Argument(STCin, Type::tsize_t, NULL, NULL)); - aaValues_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::aaValues); - } - - ec = new VarExp(0, aaValues_fd); - arguments = new Expressions(); - arguments->push(e); - size_t keysize = index->size(e->loc); - keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1); - arguments->push(new IntegerExp(0, keysize, Type::tsize_t)); - arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t)); - e = new CallExp(e->loc, ec, arguments); - e->type = next->arrayOf(); - } - else if (ident == Id::rehash) - { - Expression *ec; - Expressions *arguments; - - //LDC: Build arguments. - static FuncDeclaration *aaRehash_fd = NULL; - if(!aaRehash_fd) { - Arguments* args = new Arguments; - args->push(new Argument(STCin, Type::tvoid->pointerTo(), NULL, NULL)); - args->push(new Argument(STCin, Type::typeinfo->type, NULL, NULL)); - aaRehash_fd = FuncDeclaration::genCfunc(args, Type::tvoidptr, Id::aaRehash); - } - - ec = new VarExp(0, aaRehash_fd); - arguments = new Expressions(); - arguments->push(e->addressOf(sc)); - arguments->push(index->getInternalTypeInfo(sc)); // LDC doesn't support getInternalTypeInfo, see above - e = new CallExp(e->loc, ec, arguments); - e->type = this; - } - else #endif if (ident != Id::__sizeof && ident != Id::__xalignof && @@ -4904,15 +4757,13 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) ident != Id::stringof && ident != Id::offsetof) { -//printf("test1: %s, %s\n", e->toChars(), e->type->toChars()); Type *t = getImpl()->type; -//printf("test2: %s, %s\n", e->toChars(), e->type->toChars()); + e = e->copy(); e->type = t; - e = t->dotExp(sc, e, ident); -//printf("test3: %s, %s\n", e->toChars(), e->type->toChars()); + e = t->dotExp(sc, e, ident, flag); } else - e = Type::dotExp(sc, e, ident); + e = Type::dotExp(sc, e, ident, flag); return e; } @@ -5074,6 +4925,8 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) error(loc, "can't have pointer to %s", n->toChars()); case Terror: return Type::terror; + default: + break; } if (n != next) { @@ -5099,7 +4952,7 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) d_uns64 TypePointer::size(Loc loc) { - return PTRSIZE; + return Target::ptrsize; } void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -5249,7 +5102,7 @@ Type *TypeReference::semantic(Loc loc, Scope *sc) d_uns64 TypeReference::size(Loc loc) { - return PTRSIZE; + return Target::ptrsize; } void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -5262,14 +5115,14 @@ void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writeByte('&'); } -Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); #endif // References just forward things along - return next->dotExp(sc, e, ident); + return next->dotExp(sc, e, ident, flag); } Expression *TypeReference::defaultInit(Loc loc) @@ -5478,7 +5331,8 @@ int Type::covariant(Type *t, StorageClass *pstc) } else if (t1n->ty == t2n->ty && t1n->implicitConvTo(t2n)) goto Lcovariant; - else if (t1n->ty == Tnull && t1n->implicitConvTo(t2n)) + else if (t1n->ty == Tnull && t1n->implicitConvTo(t2n) && + t1n->size() == t2n->size()) goto Lcovariant; } goto Lnotcovariant; @@ -5491,11 +5345,15 @@ Lcovariant: */ if (!MODimplicitConv(t2->mod, t1->mod)) { +#if 0//stop attribute inference with const // If adding 'const' will make it covariant if (MODimplicitConv(t2->mod, MODmerge(t1->mod, MODconst))) stc |= STCconst; else goto Lnotcovariant; +#else + goto Ldistinct; +#endif } /* Can convert pure to impure, and nothrow to throw @@ -5857,7 +5715,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) tf->isproperty = TRUE; tf->linkage = sc->linkage; - +#if 0 /* If the parent is @safe, then this function defaults to safe * too. * If the parent's @safe-ty is inferred, then this function's @safe-ty needs @@ -5873,7 +5731,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) break; } } - +#endif bool wildreturn = FALSE; if (tf->next) { @@ -6055,170 +5913,80 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) } -Type *getIndirection(Type *t) -{ - t = t->toBasetype(); - - if (t->ty == Tsarray) - { while (t->ty == Tsarray) - t = t->nextOf()->toBasetype(); - } - if (t->ty == Tarray || t->ty == Tpointer) - return t->nextOf()->toBasetype(); - if (t->ty == Taarray || t->ty == Tclass) - return t; - if (t->ty == Tstruct) - return t->hasPointers() ? t : NULL; // TODO - - // should consider TypeDelegate? - return NULL; -} - /******************************************** * Do this lazily, as the parameter types might be forward referenced. */ void TypeFunction::purityLevel() { - //printf("purityLevel(%s)\n", toChars()); - TypeFunction *tf = this; - if (tf->purity == PUREfwdref && tf->next) + if (tf->purity == PUREfwdref) { /* Evaluate what kind of purity based on the modifiers for the parameters */ - enum PURE purity = PUREstrong; // assume strong until something weakens it - size_t dim = Parameter::dim(tf->parameters); - - if (dim) + tf->purity = PUREstrong; // assume strong until something weakens it + if (tf->parameters) { - Type *tret = tf->next; - assert(tret); - Type *treti = tf->isref ? tret->toBasetype() : getIndirection(tret); - if (treti && (treti->mod & MODimmutable)) - treti = NULL; // indirection is immutable - //printf(" tret = %s, treti = %s\n", tret->toChars(), treti ? treti->toChars() : "NULL"); - + size_t dim = Parameter::dim(tf->parameters); for (size_t i = 0; i < dim; i++) { Parameter *fparam = Parameter::getNth(tf->parameters, i); if (fparam->storageClass & STClazy) { - purity = PUREweak; + tf->purity = PUREweak; break; } if (fparam->storageClass & STCout) { - purity = PUREweak; + tf->purity = PUREweak; break; } if (!fparam->type) continue; - - Type *tprm = fparam->type; - Type *tprmi = fparam->storageClass & STCref ? tprm->toBasetype() : getIndirection(tprm); - //printf(" [%d] tprm = %s, tprmi = %s\n", i, tprm->toChars(), tprmi ? tprmi->toChars() : "NULL"); - - if (!tprmi || (tprmi->mod & MODimmutable)) - continue; // there is no mutable indirection - if (tprmi->isMutable()) - { purity = PUREweak; // indirection is mutable - break; - } - if (!treti) - continue; // mutable indirection is never returned - - if (purity < PUREstrong) - continue; - - // Determine the parameter is really PUREconst or not - assert(tprmi->mod & (MODconst | MODwild)); - if (tprmi->constConv(treti)) // simple case - purity = PUREconst; - else if (tprmi->invariantOf()->equals(treti->invariantOf())) - continue; - else + if (fparam->storageClass & STCref) { - /* The rest of this is little strict; fix later. - * For example: - * - * struct S { immutable* p; } - * pure S foo(const int* p); - * - * which would maintain strong purity. - */ - if (tprmi->hasPointers() || treti->hasPointers()) - purity = PUREconst; + if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild))) + { tf->purity = PUREweak; + break; + } + if (fparam->type->mod & MODconst) + { tf->purity = PUREconst; + continue; + } + } + Type *t = fparam->type->toBasetype(); + if (!t->hasPointers()) + continue; + if (t->mod & MODimmutable) + continue; + /* The rest of this is too strict; fix later. + * For example, the only pointer members of a struct may be immutable, + * which would maintain strong purity. + */ + if (t->mod & (MODconst | MODwild)) + { tf->purity = PUREconst; + continue; + } + Type *tn = t->nextOf(); + if (tn) + { tn = tn->toBasetype(); + if (tn->ty == Tpointer || tn->ty == Tarray) + { /* Accept immutable(T)* and immutable(T)[] as being strongly pure + */ + if (tn->mod & MODimmutable) + continue; + if (tn->mod & (MODconst | MODwild)) + { tf->purity = PUREconst; + continue; + } + } } - /* Should catch delegates and function pointers, and fold in their purity */ + tf->purity = PUREweak; // err on the side of too strict + break; } } - - //printf(" --> purity: %d\n", purity); - tf->purity = purity; } } -/******************************************** - * FIXME: This function is a workaround for fixing Bugzilla 9210. - * In 2.061, TypeFunction::purityLevel() improved to make more functions - * strong purity, but immutable conversion on return statemet had broken by that. - * Because, it is essentially unrelated to PUREstrong. This function is - * necessary to check the convertibility. - */ -bool TypeFunction::hasMutableIndirectionParams() -{ - TypeFunction *tf = this; - size_t dim = Parameter::dim(tf->parameters); - for (size_t i = 0; i < dim; i++) - { - Parameter *fparam = Parameter::getNth(tf->parameters, i); - if (fparam->storageClass & STClazy) - { - return true; - } - if (fparam->storageClass & STCout) - { - return true; - } - if (!fparam->type) - continue; - if (fparam->storageClass & STCref) - { - if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild))) - return true; - if (fparam->type->mod & MODconst) - return true; - } - Type *t = fparam->type->toBasetype(); - if (!t->hasPointers()) - continue; - if (t->mod & (MODimmutable | MODwild)) - continue; - /* The rest of this is too strict; fix later. - * For example, the only pointer members of a struct may be immutable, - * which would maintain strong purity. - */ - if (t->mod & MODconst) - return true; - Type *tn = t->nextOf(); - if (tn) - { tn = tn->toBasetype(); - if (tn->ty == Tpointer || tn->ty == Tarray) - { /* Accept immutable(T)* and immutable(T)[] as being strongly pure - */ - if (tn->mod & (MODimmutable | MODwild)) - continue; - if (tn->mod & MODconst) - return true; - } - } - /* Should catch delegates and function pointers, and fold in their purity - */ - return true; - } - return false; -} - /******************************** * 'args' are being matched to function 'this' @@ -6229,14 +5997,14 @@ bool TypeFunction::hasMutableIndirectionParams() * MATCHxxxx */ -MATCH TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) +MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag) { //printf("TypeFunction::callMatch() %s\n", toChars()); MATCH match = MATCHexact; // assume exact match unsigned wildmatch = 0; - if (ethis) - { Type *t = ethis->type; + if (tthis) + { Type *t = tthis; if (t->toBasetype()->ty == Tpointer) t = t->toBasetype()->nextOf(); // change struct* to struct if (t->mod != mod) @@ -6323,6 +6091,8 @@ MATCH TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) { Expression *arg = (*args)[u]; assert(arg); + if (Expression *e = arg->isTemp()) + arg = e; if (arg->op == TOKfunction) { @@ -6351,24 +6121,34 @@ MATCH TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) // Non-lvalues do not match ref or out parameters if (p->storageClass & STCref) - { if (m && !arg->isLvalue()) - { - Type *ta = targ->aliasthisOf(); - if (arg->op == TOKstring && tprm->ty == Tsarray) - { if (targ->ty != Tsarray) - targ = new TypeSArray(targ->nextOf(), - new IntegerExp(0, ((StringExp *)arg)->len, - Type::tindex)); - } - else - goto Nomatch; - } - + { Type *targb = targ->toBasetype(); Type *tprmb = tprm->toBasetype(); //printf("%s\n", targb->toChars()); //printf("%s\n", tprmb->toChars()); + if (m && !arg->isLvalue()) + { + if (arg->op == TOKstring && tprmb->ty == Tsarray) + { if (targb->ty != Tsarray) + { + targb = new TypeSArray(tprmb->nextOf()->castMod(targb->nextOf()->mod), + new IntegerExp(Loc(), ((StringExp *)arg)->len, + Type::tindex)); + targb = targb->semantic(Loc(), NULL); + } + } + else if (arg->op == TOKslice && tprmb->ty == Tsarray) + { // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] + targb = new TypeSArray(targb->nextOf(), + new IntegerExp(Loc(), ((TypeSArray *)tprmb)->dim->toUInteger(), + Type::tindex)); + targb = targb->semantic(Loc(), NULL); + } + else + goto Nomatch; + } + /* find most derived alias this type being matched. */ while (1) @@ -6530,7 +6310,7 @@ bool TypeFunction::parameterEscapes(Parameter *p) if (!nextOf()) return TRUE; - if (purity) + if (purity > PUREweak) { /* With pure functions, we need only be concerned if p escapes * via any return statement. */ @@ -6570,6 +6350,7 @@ Type *TypeFunction::addStorageClass(StorageClass stc) tf->isproperty = t->isproperty; tf->isref = t->isref; tf->trust = t->trust; + tf->iswild = t->iswild; if (stc & STCpure) tf->purity = PUREfwdref; @@ -6640,15 +6421,17 @@ Type *TypeDelegate::semantic(Loc loc, Scope *sc) d_uns64 TypeDelegate::size(Loc loc) { - return PTRSIZE * 2; + return Target::ptrsize * 2; } -// LDC added, no reason to align to 2*PTRSIZE unsigned TypeDelegate::alignsize() { - // A Delegate consists of two ptr values, so align it on pointer size - // boundary - return PTRSIZE; +#if DMDV1 + // See Bugzilla 942 for discussion + if (!global.params.is64bit) + return Target::ptrsize * 2; +#endif + return Target::ptrsize; } MATCH TypeDelegate::implicitConvTo(Type *to) @@ -6693,7 +6476,7 @@ int TypeDelegate::checkBoolean() return TRUE; } -Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -6712,7 +6495,7 @@ Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident) } else { - e = Type::dotExp(sc, e, ident); + e = Type::dotExp(sc, e, ident, flag); } return e; } @@ -6738,13 +6521,13 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t) idents.setDim(t->idents.dim); for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = t->idents[i]; + Object *id = t->idents[i]; if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; ti = (TemplateInstance *)ti->syntaxCopy(NULL); - id = (Identifier *)ti; + id = ti; } idents[i] = id; } @@ -6756,10 +6539,15 @@ void TypeQualified::addIdent(Identifier *ident) idents.push(ident); } +void TypeQualified::addInst(TemplateInstance *inst) +{ + idents.push(inst); +} + void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs) { for (size_t i = 0; i < idents.dim; i++) - { Identifier *id = idents[i]; + { Object *id = idents[i]; buf->writeByte('.'); @@ -6776,7 +6564,7 @@ void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs) d_uns64 TypeQualified::size(Loc loc) { error(this->loc, "size of type %s is not known", toChars()); - return 1; + return SIZE_INVALID; } /************************************* @@ -6791,11 +6579,6 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym, Expression **pe, Type **pt, Dsymbol **ps) { - VarDeclaration *v; - EnumMember *em; - Expression *e; - TemplateInstance *ti; - #if 0 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars()); if (scopesym) @@ -6812,66 +6595,53 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = idents[i]; + Object *id = idents[i]; Dsymbol *sm = s->searchX(loc, sc, id); //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); //printf("\tgetType = '%s'\n", s->getType()->toChars()); if (!sm) - { Type *t; - - v = s->isVarDeclaration(); - ti = s->isTemplateInstance(); - if (v && id == Id::length) - { - e = new VarExp(loc, v); - t = e->type; - if (!t) - goto Lerror; - goto L3; - } - else if ((v && (id == Id::stringof || id == Id::offsetof)) - || (ti && (id == Id::stringof || id == Id::mangleof))) - { - e = new DsymbolExp(loc, s, 0); - do + { + Type *t = s->getType(); // type symbol, type alias, or type tuple? + if (!t) + { if (s->isDeclaration()) // var, func, or tuple declaration? + { t = s->isDeclaration()->type; + if (!t && s->isTupleDeclaration()) // expression tuple? + goto L3; + } + else if (s->isTemplateInstance() || + s->isImport() || s->isPackage() || s->isModule()) { - id = idents[i]; - e = new DotIdExp(loc, e, id); - } while (++i < idents.dim); - e = e->semantic(sc); - *pe = e; - return; - } - - t = s->getType(); - if (!t && s->isDeclaration()) - { t = s->isDeclaration()->type; - if (!t && s->isTupleDeclaration()) - { - e = new TupleExp(loc, s->isTupleDeclaration()); - e = e->semantic(sc); - t = e->type; + goto L3; } } if (t) { sm = t->toDsymbol(sc); - if (sm) - { sm = sm->search(loc, id, 0); + if (sm && id->dyncast() == DYNCAST_IDENTIFIER) + { + sm = sm->search(loc, (Identifier *)id, 0); if (sm) goto L2; } - //e = t->getProperty(loc, id); - e = new TypeExp(loc, t); - e = t->dotExp(sc, e, id); - i++; L3: + Expression *e = new DsymbolExp(loc, s); + e = e->semantic(sc); for (; i < idents.dim; i++) { - id = idents[i]; + Object *id = idents[i]; //printf("e: '%s', id: '%s', type = %s\n", e->toChars(), id->toChars(), e->type->toChars()); - e = new DotIdExp(e->loc, e, id); - e = e->semantic(sc); + if (id->dyncast() == DYNCAST_IDENTIFIER) + { + DotIdExp *die = new DotIdExp(e->loc, e, (Identifier *)id); + e = die->semanticY(sc, 0); + } + else + { assert(id->dyncast() == DYNCAST_DSYMBOL); + TemplateInstance *ti = ((Dsymbol *)id)->isTemplateInstance(); + assert(ti); + DotTemplateInstanceExp *dte = new DotTemplateInstanceExp(e->loc, e, ti->name, ti->tiargs); + e = dte->semanticY(sc, 0); + } } if (e->op == TOKtype) *pt = e->type; @@ -6887,7 +6657,8 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, } else { - sm = s->search_correct(id); + assert(id->dyncast() == DYNCAST_IDENTIFIER); + sm = s->search_correct((Identifier *)id); if (sm) error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?", id->toChars(), toChars(), sm->kind(), sm->toChars()); @@ -6902,25 +6673,27 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, s = sm->toAlias(); } - v = s->isVarDeclaration(); - if (v) + if (VarDeclaration *v = s->isVarDeclaration()) { + if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 + { error(loc, "circular reference to '%s'", v->toPrettyChars()); + *pe = new ErrorExp(); + return; + } *pe = new VarExp(loc, v); return; } #if 0 - fd = s->isFuncDeclaration(); - if (fd) + if (FuncDeclaration *fd = s->isFuncDeclaration()) { *pe = new DsymbolExp(loc, fd, 1); return; } #endif - em = s->isEnumMember(); - if (em) + if (EnumMember *em = s->isEnumMember()) { // It's not a type, it's an expression - *pe = em->value->copy(); + *pe = em->getVarExp(loc, sc); return; } @@ -6929,10 +6702,7 @@ L1: if (!t) { // If the symbol is an import, try looking inside the import - Import *si; - - si = s->isImport(); - if (si) + if (Import *si = s->isImport()) { s = si->search(loc, s->ident, 0); if (s && s != si) @@ -6944,6 +6714,7 @@ L1: } if (t->ty == Tinstance && t != this && !t->deco) { error(loc, "forward reference to '%s'", t->toChars()); + *pt = Type::terror; return; } @@ -6963,6 +6734,7 @@ L1: { if (!scx) { error(loc, "forward reference to '%s'", t->toChars()); + *pt = Type::terror; return; } if (scx->scopesym == scopesym) @@ -7100,7 +6872,7 @@ Dsymbol *TypeIdentifier::toDsymbol(Scope *sc) { for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = idents[i]; + Object *id = idents[i]; s = s->searchX(loc, sc, id); if (!s) // failed to find a symbol { //printf("\tdidn't find a symbol\n"); @@ -7127,7 +6899,9 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc) { TypeTypedef *tt = (TypeTypedef *)t; if (tt->sym->sem == SemanticIn) - error(loc, "circular reference of typedef %s", tt->toChars()); + { error(loc, "circular reference of typedef %s", tt->toChars()); + return terror; + } } t = t->addMod(mod); } @@ -7170,8 +6944,17 @@ Expression *TypeIdentifier::toExpression() Expression *e = new IdentifierExp(loc, ident); for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = idents[i]; - e = new DotIdExp(loc, e, id); + Object *id = idents[i]; + if (id->dyncast() == DYNCAST_IDENTIFIER) + { + e = new DotIdExp(loc, e, (Identifier *)id); + } + else + { assert(id->dyncast() == DYNCAST_DSYMBOL); + TemplateInstance *ti = ((Dsymbol *)id)->isTemplateInstance(); + assert(ti); + e = new DotTemplateInstanceExp(loc, e, ti->name, ti->tiargs); + } } return e; @@ -7261,11 +7044,23 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc) } } else + { + unsigned errors = global.errors; resolve(loc, sc, &e, &t, &s); + // if we had an error evaluating the symbol, suppress further errors + if (!t && errors != global.errors) + return terror; + } if (!t) { - error(loc, "%s is used as a type", toChars()); + if (!e && s && s->errors) + { // if there was an error evaluating the symbol, it might actually + // be a type. Avoid misleading error messages. + error(loc, "%s had previous errors", toChars()); + } + else + error(loc, "%s is used as a type", toChars()); t = terror; } return t; @@ -7321,6 +7116,11 @@ Type *TypeInstance::reliesOnTident(TemplateParameters *tparams) } } +Expression *TypeInstance::toExpression() +{ + return new ScopeExp(loc, tempinst); +} + /***************************** TypeTypeof *****************************/ @@ -7369,70 +7169,26 @@ void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) toCBuffer2Helper(buf, hgs); } -Type *TypeTypeof::semantic(Loc loc, Scope *sc) +void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) { - Type *t; - - //printf("TypeTypeof::semantic() %s\n", toChars()); + *pe = NULL; + *pt = NULL; + *ps = NULL; + //printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars()); //static int nest; if (++nest == 50) *(char*)0=0; if (inuse) { inuse = 2; error(loc, "circular typeof definition"); - return Type::terror; + goto Lerr; } inuse++; -#if 0 - /* Special case for typeof(this) and typeof(super) since both - * should work even if they are not inside a non-static member function - */ - if (exp->op == TOKthis || exp->op == TOKsuper) - { - // Find enclosing struct or class - for (Dsymbol *s = sc->parent; 1; s = s->parent) - { - ClassDeclaration *cd; - StructDeclaration *sd; - - if (!s) - { - error(loc, "%s is not in a struct or class scope", exp->toChars()); - goto Lerr; - } - cd = s->isClassDeclaration(); - if (cd) - { - if (exp->op == TOKsuper) - { - cd = cd->baseClass; - if (!cd) - { error(loc, "class %s has no 'super'", s->toChars()); - goto Lerr; - } - } - t = cd->type; - break; - } - sd = s->isStructDeclaration(); - if (sd) - { - if (exp->op == TOKsuper) - { - error(loc, "struct %s has no 'super'", sd->toChars()); - goto Lerr; - } - t = sd->type->pointerTo(); - break; - } - } - } - else -#endif + Type *t; { Scope *sc2 = sc->push(); - sc2->intypeof++; + sc2->intypeof = 1; sc2->speculative = true; sc2->ignoreTemplates++; sc2->flags |= sc->flags & SCOPEstaticif; @@ -7463,44 +7219,71 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { error(loc, "forward reference to %s", toChars()); goto Lerr; } - - t = t->addMod(mod); - - /* typeof should reflect the true type, - * not what 'auto' would have gotten us. - */ - //t = t->toHeadMutable(); } - if (idents.dim) + if (idents.dim == 0) + *pt = t; + else { - Dsymbol *s = t->toDsymbol(sc); - for (size_t i = 0; i < idents.dim; i++) + if (Dsymbol *s = t->toDsymbol(sc)) + resolveHelper(loc, sc, s, NULL, pe, pt, ps); + else { - if (!s) - break; - Identifier *id = idents[i]; - s = s->searchX(loc, sc, id); - } - - if (s) - { - t = s->getType(); - if (!t) - { error(loc, "%s is not a type", s->toChars()); - goto Lerr; + Expression *e = new TypeExp(loc, t); + for (size_t i = 0; i < idents.dim; i++) + { + Object *id = idents[i]; + switch (id->dyncast()) + { + case DYNCAST_IDENTIFIER: + e = new DotIdExp(loc, e, (Identifier *)id); + break; + case DYNCAST_DSYMBOL: + { + TemplateInstance *ti = ((Dsymbol *)id)->isTemplateInstance(); + e = new DotExp(loc, e, new ScopeExp(loc, ti)); + break; + } + default: + assert(0); + } + } + e = e->semantic(sc); + if ((*ps = getDsymbol(e)) == NULL) + { + if (e->op == TOKtype) + *pt = e->type; + else + *pe = e; } } - else - { error(loc, "cannot resolve .property for %s", toChars()); - goto Lerr; - } } + if (*pt) + (*pt) = (*pt)->addMod(mod); inuse--; - return t; + return; Lerr: + *pt = Type::terror; inuse--; - return terror; + return; +} + +Type *TypeTypeof::semantic(Loc loc, Scope *sc) +{ + //printf("TypeTypeof::semantic() %s\n", toChars()); + + Expression *e; + Type *t; + Dsymbol *s; + resolve(loc, sc, &e, &t, &s); + if (s && (t = s->getType()) != NULL) + t = t->addMod(mod); + if (!t) + { + error(loc, "%s is used as a type", toChars()); + t = Type::terror; + } + return t; } d_uns64 TypeTypeof::size(Loc loc) @@ -7535,58 +7318,98 @@ Type *TypeReturn::syntaxCopy() Dsymbol *TypeReturn::toDsymbol(Scope *sc) { - Type *t = semantic(0, sc); + Type *t = semantic(Loc(), sc); if (t == this) return NULL; return t->toDsymbol(sc); } -Type *TypeReturn::semantic(Loc loc, Scope *sc) +void TypeReturn::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) { + *pe = NULL; + *pt = NULL; + *ps = NULL; + + //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, toChars()); Type *t; - FuncDeclaration *func = sc->func; - if (!func) - { error(loc, "typeof(return) must be inside function"); - goto Lerr; - } - if (func->fes) - func = func->fes->func; - - t = func->type->nextOf(); - if (!t) { - error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc->func->toChars()); - goto Lerr; - } - t = t->addMod(mod); + FuncDeclaration *func = sc->func; + if (!func) + { error(loc, "typeof(return) must be inside function"); + goto Lerr; + } + if (func->fes) + func = func->fes->func; - if (idents.dim) - { - Dsymbol *s = t->toDsymbol(sc); - for (size_t i = 0; i < idents.dim; i++) + t = func->type->nextOf(); + if (!t) { - if (!s) - break; - Identifier *id = idents[i]; - s = s->searchX(loc, sc, id); - } - if (s) - { - t = s->getType(); - if (!t) - { error(loc, "%s is not a type", s->toChars()); - goto Lerr; - } - } - else - { error(loc, "cannot resolve .property for %s", toChars()); + error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc->func->toChars()); goto Lerr; } } - return t; + if (idents.dim == 0) + *pt = t; + else + { + if (Dsymbol *s = t->toDsymbol(sc)) + resolveHelper(loc, sc, s, NULL, pe, pt, ps); + else + { + Expression *e = new TypeExp(loc, t); + for (size_t i = 0; i < idents.dim; i++) + { + Object *id = idents[i]; + switch (id->dyncast()) + { + case DYNCAST_IDENTIFIER: + e = new DotIdExp(loc, e, (Identifier *)id); + break; + case DYNCAST_DSYMBOL: + { + TemplateInstance *ti = ((Dsymbol *)id)->isTemplateInstance(); + e = new DotExp(loc, e, new ScopeExp(loc, ti)); + break; + } + default: + assert(0); + } + } + e = e->semantic(sc); + if ((*ps = getDsymbol(e)) == NULL) + { + if (e->op == TOKtype) + *pt = e->type; + else + *pe = e; + } + } + } + if (*pt) + (*pt) = (*pt)->addMod(mod); + return; Lerr: - return terror; + *pt = Type::terror; + return; +} + +Type *TypeReturn::semantic(Loc loc, Scope *sc) +{ + //printf("TypeReturn::semantic() %s\n", toChars()); + + Expression *e; + Type *t; + Dsymbol *s; + resolve(loc, sc, &e, &t, &s); + if (s && (t = s->getType()) != NULL) + t = t->addMod(mod); + if (!t) + { + error(loc, "%s is used as a type", toChars()); + t = Type::terror; + } + return t; } void TypeReturn::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -7637,7 +7460,7 @@ d_uns64 TypeEnum::size(Loc loc) if (!sym->memtype) { error(loc, "enum %s is forward referenced", sym->toChars()); - return 4; + return SIZE_INVALID; } return sym->memtype->size(loc); } @@ -7646,7 +7469,7 @@ unsigned TypeEnum::alignsize() { if (!sym->memtype) { - error(0, "enum %s is forward referenced", sym->toChars()); + error(Loc(), "enum %s is forward referenced", sym->toChars()); return 4; } return sym->memtype->alignsize(); @@ -7673,7 +7496,7 @@ Type *TypeEnum::toBasetype() if (!sym->memtype) { error(sym->loc, "enum %s is forward referenced", sym->toChars()); - return tint32; + return Type::terror; } return sym->memtype->toBasetype(); } @@ -7694,7 +7517,7 @@ void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writestring(sym->toChars()); } -Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); @@ -7709,17 +7532,15 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident) !sym->memtype ) { - return getProperty(e->loc, ident); + return getProperty(e->loc, ident, flag); } - return sym->memtype->dotExp(sc, e, ident); + return sym->memtype->dotExp(sc, e, ident, flag); } EnumMember *m = s->isEnumMember(); - Expression *em = m->value->copy(); - em->loc = e->loc; - return em; + return m->getVarExp(e->loc, sc); } -Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) +Expression *TypeEnum::getProperty(Loc loc, Identifier *ident, int flag) { Expression *e; if (ident == Id::max) @@ -7746,11 +7567,11 @@ Expression *TypeEnum::getProperty(Loc loc, Identifier *ident) } else if (ident == Id::mangleof) { - e = Type::getProperty(loc, ident); + e = Type::getProperty(loc, ident, flag); } else { - e = toBasetype()->getProperty(loc, ident); + e = toBasetype()->getProperty(loc, ident, flag); } return e; @@ -7903,7 +7724,7 @@ Type *TypeTypedef::semantic(Loc loc, Scope *sc) //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem); int errors = global.errors; sym->semantic(sc); - if (errors != global.errors) + if (errors != global.errors || sym->errors || sym->basetype->ty == Terror) return terror; return merge(); } @@ -7940,16 +7761,16 @@ void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writestring(sym->toChars()); } -Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars()); #endif if (ident == Id::init) { - return Type::dotExp(sc, e, ident); + return Type::dotExp(sc, e, ident, flag); } - return sym->basetype->dotExp(sc, e, ident); + return sym->basetype->dotExp(sc, e, ident, flag); } structalign_t TypeTypedef::alignment() @@ -7966,16 +7787,16 @@ structalign_t TypeTypedef::alignment() return a; } -Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident) +Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident, int flag) { #if LOGDOTEXP printf("TypeTypedef::getProperty(ident = '%s') '%s'\n", ident->toChars(), toChars()); #endif if (ident == Id::init) { - return Type::getProperty(loc, ident); + return Type::getProperty(loc, ident, flag); } - return sym->basetype->getProperty(loc, ident); + return sym->basetype->getProperty(loc, ident, flag); } int TypeTypedef::isintegral() @@ -8166,9 +7987,11 @@ TypeStruct::TypeStruct(StructDeclaration *sym) : Type(Tstruct) { this->sym = sym; + this->att = RECfwdref; - // LDC +#if IN_LLVM this->unaligned = 0; +#endif } const char *TypeStruct::kind() @@ -8213,7 +8036,7 @@ d_uns64 TypeStruct::size(Loc loc) unsigned TypeStruct::alignsize() { - sym->size(0); // give error for forward references + sym->size(Loc()); // give error for forward references return sym->alignsize; } @@ -8243,12 +8066,11 @@ void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writestring(sym->toChars()); } -Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { VarDeclaration *v; Dsymbol *s; DotVarExp *de; - Declaration *d; #if LOGDOTEXP printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars()); @@ -8271,27 +8093,24 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) Expressions *exps = new Expressions; exps->reserve(sym->fields.dim); + Expression *e0 = NULL; Expression *ev = e; - for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields[i]; - Expression *fe; - if (i == 0 && sc->func && sym->fields.dim > 1 && - e->hasSideEffect()) - { - Identifier *id = Lexer::uniqueId("__tup"); - ExpInitializer *ei = new ExpInitializer(e->loc, e); - VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); - vd->storage_class |= STCctfe | STCref | STCforeach; + if (sc->func && e->hasSideEffect()) + { + Identifier *id = Lexer::uniqueId("__tup"); + ExpInitializer *ei = new ExpInitializer(e->loc, e); + VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); + vd->storage_class |= STCctfe | STCref | STCforeach; - ev = new VarExp(e->loc, vd); - fe = new CommaExp(e->loc, new DeclarationExp(e->loc, vd), ev); - fe = new DotVarExp(e->loc, fe, v); - } - else - fe = new DotVarExp(ev->loc, ev, v); - exps->push(fe); + e0 = new DeclarationExp(e->loc, vd); + ev = new VarExp(e->loc, vd); } - e = new TupleExp(e->loc, exps); + for (size_t i = 0; i < sym->fields.dim; i++) + { + VarDeclaration *v = sym->fields[i]; + exps->push(new DotVarExp(ev->loc, ev, v)); + } + e = new TupleExp(e->loc, e0, exps); sc = sc->push(); sc->noaccesscheck = 1; e = e->semantic(sc); @@ -8322,25 +8141,24 @@ L1: { sym->semantic(NULL); s = sym->search(e->loc, ident, 0); - if (!s) - return noMember(sc, e, ident); } - else - return noMember(sc, e, ident); + if (!s) + return noMember(sc, e, ident, flag); } if (!s->isFuncDeclaration()) // because of overloading s->checkDeprecated(e->loc, sc); s = s->toAlias(); v = s->isVarDeclaration(); - if (v && !v->isDataseg()) + if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 + { e->error("circular reference to '%s'", v->toPrettyChars()); + return new ErrorExp(); + } + if (v && !v->isDataseg() && (v->storage_class & STCmanifest)) { - Expression *ei = v->getConstInitializer(); - if (ei) - { e = ei->copy(); // need to copy it if it's a StringExp - e = e->semantic(sc); - return e; - } + Expression *ve = new VarExp(e->loc, v); + ve = ve->semantic(sc); + return ve; } if (s->getType()) @@ -8351,8 +8169,7 @@ L1: EnumMember *em = s->isEnumMember(); if (em) { - assert(em->value); - return em->value->copy(); + return em->getVarExp(e->loc, sc); } TemplateMixin *tm = s->isTemplateMixin(); @@ -8366,7 +8183,10 @@ L1: TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) { - e = new DotTemplateExp(e->loc, e, td); + if (e->op == TOKtype) + e = new ScopeExp(e->loc, td); + else + e = new DotTemplateExp(e->loc, e, td); e = e->semantic(sc); return e; } @@ -8397,13 +8217,13 @@ L1: OverloadSet *o = s->isOverloadSet(); if (o) { - OverExp *oe = new OverExp(o); + OverExp *oe = new OverExp(e->loc, o); if (e->op == TOKtype) return oe; return new DotExp(e->loc, e, oe); } - d = s->isDeclaration(); + Declaration *d = s->isDeclaration(); #ifdef DEBUG if (!d) printf("d = %s '%s'\n", s->kind(), s->toChars()); @@ -8411,19 +8231,27 @@ L1: assert(d); if (e->op == TOKtype) - { FuncDeclaration *fd = sc->func; - - if (d->isTupleDeclaration()) + { + /* It's: + * Struct.d + */ + if (TupleDeclaration *tup = d->isTupleDeclaration()) { - e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = new TupleExp(e->loc, tup); e = e->semantic(sc); return e; } - else if (d->needThis() && fd && fd->vthis) + if (d->needThis() && sc->intypeof != 1) { - e = new DotVarExp(e->loc, new ThisExp(e->loc), d); - e = e->semantic(sc); - return e; + /* Rewrite as: + * this.d + */ + if (hasThis(sc)) + { + e = new DotVarExp(e->loc, new ThisExp(e->loc), d); + e = e->semantic(sc); + return e; + } } accessCheck(e->loc, sc, e, d); VarExp *ve = new VarExp(e->loc, d, 1); @@ -8432,14 +8260,13 @@ L1: return ve; } - if (d->isDataseg()) + bool unreal = e->op == TOKvar && ((VarExp *)e)->var->isField(); + if (d->isDataseg() || unreal && d->isField()) { // (e, d) - VarExp *ve; - accessCheck(e->loc, sc, e, d); - ve = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, ve); + Expression *ve = new VarExp(e->loc, d); + e = unreal ? ve : new CommaExp(e->loc, e, ve); e = e->semantic(sc); return e; } @@ -8469,7 +8296,7 @@ L1: structalign_t TypeStruct::alignment() { if (sym->alignment == 0) - sym->size(0); + sym->size(Loc()); return sym->alignment; } @@ -8478,12 +8305,7 @@ Expression *TypeStruct::defaultInit(Loc loc) #if LOGDEFAULTINIT printf("TypeStruct::defaultInit() '%s'\n", toChars()); #endif -#if IN_LLVM - Declaration *d = new StaticStructInitDeclaration(sym->loc, sym); -#else - Symbol *s = sym->toInitializer(); - Declaration *d = new SymbolDeclaration(sym->loc, s, sym); -#endif + Declaration *d = new SymbolDeclaration(sym->loc, sym); assert(d); d->type = this; return new VarExp(sym->loc, d); @@ -8501,25 +8323,24 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) //if (sym->isNested()) // return defaultInit(loc); Expressions *structelems = new Expressions(); - structelems->setDim(sym->fields.dim - sym->isnested); + structelems->setDim(sym->fields.dim - sym->isNested()); + unsigned offset = 0; for (size_t j = 0; j < structelems->dim; j++) { VarDeclaration *vd = sym->fields[j]; - Type *telem = vd->type->addMod(this->mod); Expression *e; - if (vd->init) - { if (vd->init->isVoidInitializer()) + if (vd->offset < offset) + e = NULL; + else if (vd->init) + { + if (vd->init->isVoidInitializer()) e = NULL; else - e = vd->init->toExpression(); + e = vd->getConstInitializer(false); } else e = vd->type->defaultInitLiteral(loc); - if (e && vd->scope) - { - e = e->semantic(vd->scope); - e = e->implicitCastTo(vd->scope, telem); - } + offset = vd->offset + vd->type->size(); (*structelems)[j] = e; } StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); @@ -8528,7 +8349,7 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) /* Copy from the initializer symbol for larger symbols, * otherwise the literals expressed as code get excessively large. */ - if (size(loc) > PTRSIZE * 4 && !needsNested()) + if (size(loc) > Target::ptrsize * 4 && !needsNested()) structinit->sinit = sym->toInitializer(); #endif @@ -8554,7 +8375,7 @@ int TypeStruct::needsDestruction() bool TypeStruct::needsNested() { - if (sym->isnested) + if (sym->isNested()) return true; for (size_t i = 0; i < sym->fields.dim; i++) @@ -8607,7 +8428,7 @@ int TypeStruct::hasPointers() // Probably should cache this information in sym rather than recompute StructDeclaration *s = sym; - sym->size(0); // give error for forward references + sym->size(Loc()); // give error for forward references for (size_t i = 0; i < s->fields.dim; i++) { Dsymbol *sm = s->fields[i]; @@ -8649,7 +8470,7 @@ MATCH TypeStruct::implicitConvTo(Type *to) for (size_t i = 0; i < sym->fields.dim; i++) { Dsymbol *s = sym->fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); // 'from' type Type *tvf = v->type->addMod(mod); @@ -8669,8 +8490,12 @@ MATCH TypeStruct::implicitConvTo(Type *to) } } } - else if (sym->aliasthis) + else if (sym->aliasthis && !(att & RECtracing)) + { + att = (AliasThisRec)(att | RECtracing); m = aliasthisOf()->implicitConvTo(to); + att = (AliasThisRec)(att & ~RECtracing); + } else m = MATCHnomatch; // no match return m; @@ -8691,13 +8516,16 @@ unsigned TypeStruct::wildConvTo(Type *tprm) if (ty == tprm->ty && sym == ((TypeStruct *)tprm)->sym) return Type::wildConvTo(tprm); - if (sym->aliasthis) - { Type *t = aliasthisOf(); - assert(t); - return t->wildConvTo(tprm); + unsigned mod = 0; + + if (sym->aliasthis && !(att & RECtracing)) + { + att = (AliasThisRec)(att | RECtracing); + mod = aliasthisOf()->wildConvTo(tprm); + att = (AliasThisRec)(att & ~RECtracing); } - return 0; + return mod; } Type *TypeStruct::toHeadMutable() @@ -8712,6 +8540,7 @@ TypeClass::TypeClass(ClassDeclaration *sym) : Type(Tclass) { this->sym = sym; + this->att = RECfwdref; } const char *TypeClass::kind() @@ -8742,7 +8571,7 @@ Type *TypeClass::semantic(Loc loc, Scope *sc) d_uns64 TypeClass::size(Loc loc) { - return PTRSIZE; + return Target::ptrsize; } Dsymbol *TypeClass::toDsymbol(Scope *sc) @@ -8767,7 +8596,7 @@ void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writestring(sym->toChars()); } -Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) +Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag) { VarDeclaration *v; Dsymbol *s; @@ -8809,30 +8638,26 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) Expressions *exps = new Expressions; exps->reserve(sym->fields.dim); + Expression *e0 = NULL; Expression *ev = e; + if (sc->func && e->hasSideEffect()) + { + Identifier *id = Lexer::uniqueId("__tup"); + ExpInitializer *ei = new ExpInitializer(e->loc, e); + VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); + vd->storage_class |= STCctfe | STCref | STCforeach; + + e0 = new DeclarationExp(e->loc, vd); + ev = new VarExp(e->loc, vd); + } for (size_t i = 0; i < sym->fields.dim; i++) { VarDeclaration *v = sym->fields[i]; // Don't include hidden 'this' pointer if (v->isThisDeclaration()) continue; - Expression *fe; - if (i == 0 && sc->func && sym->fields.dim > 1 && - e->hasSideEffect()) - { - Identifier *id = Lexer::uniqueId("__tup"); - ExpInitializer *ei = new ExpInitializer(e->loc, e); - VarDeclaration *vd = new VarDeclaration(e->loc, NULL, id, ei); - vd->storage_class |= STCctfe | STCref | STCforeach; - - ev = new VarExp(e->loc, vd); - fe = new CommaExp(e->loc, new DeclarationExp(e->loc, vd), ev); - fe = new DotVarExp(e->loc, fe, v); - } - else - fe = new DotVarExp(e->loc, ev, v); - exps->push(fe); + exps->push(new DotVarExp(ev->loc, ev, v)); } - e = new TupleExp(e->loc, exps); + e = new TupleExp(e->loc, e0, exps); sc = sc->push(); sc->noaccesscheck = 1; e = e->semantic(sc); @@ -8845,15 +8670,21 @@ L1: if (!s) { // See if it's 'this' class or a base class - if (e->op != TOKtype) + if (sym->ident == ident) { - Dsymbol *cbase = sym->ident == ident ? - sym : sym->searchBase(e->loc, ident); - if (cbase) - { - e = new DotTypeExp(0, e, cbase); - return e; - } + if (e->op == TOKtype) + return Type::getProperty(e->loc, ident, 0); + return new DotTypeExp(e->loc, e, sym); + } + if (ClassDeclaration *cbase = sym->searchBase(e->loc, ident)) + { + if (e->op == TOKtype) + return Type::getProperty(e->loc, ident, 0); + if (InterfaceDeclaration *ifbase = cbase->isInterfaceDeclaration()) + e = new CastExp(e->loc, e, ifbase->type); + else + e = new DotTypeExp(e->loc, e, cbase); + return e; } if (ident == Id::classinfo) @@ -8872,47 +8703,9 @@ L1: e->type = t; // do this so we don't get redundant dereference } else - { - /* For class objects, the classinfo reference is the first + { /* For class objects, the classinfo reference is the first * entry in the vtbl[] */ -#if IN_LLVM - - Type* ct; - if (sym->isInterfaceDeclaration()) { - ct = t->pointerTo()->pointerTo()->pointerTo(); - } - else { - ct = t->pointerTo()->pointerTo(); - } - - e = e->castTo(sc, ct); - e = new PtrExp(e->loc, e); - e->type = ct->nextOf(); - e = new PtrExp(e->loc, e); - e->type = ct->nextOf()->nextOf(); - - if (sym->isInterfaceDeclaration()) - { - if (sym->isCOMinterface()) - { /* COM interface vtbl[]s are different in that the - * first entry is always pointer to QueryInterface(). - * We can't get a .classinfo for it. - */ - error(e->loc, "no .classinfo for COM interface objects"); - } - /* For an interface, the first entry in the vtbl[] - * is actually a pointer to an instance of struct Interface. - * The first member of Interface is the .classinfo, - * so add an extra pointer indirection. - */ - e = new PtrExp(e->loc, e); - e->type = ct->nextOf()->nextOf()->nextOf(); - } - } - -#else - e = new PtrExp(e->loc, e); e->type = t->pointerTo(); if (sym->isInterfaceDeclaration()) @@ -8936,9 +8729,6 @@ L1: } e = new PtrExp(e->loc, e, t); } - -#endif // !LDC - return e; } @@ -8974,21 +8764,23 @@ L1: } else { - return noMember(sc, e, ident); + return noMember(sc, e, ident, flag); } } if (!s->isFuncDeclaration()) // because of overloading s->checkDeprecated(e->loc, sc); s = s->toAlias(); - v = s->isVarDeclaration(); - if (v && !v->isDataseg()) - { Expression *ei = v->getConstInitializer(); - if (ei) - { e = ei->copy(); // need to copy it if it's a StringExp - e = e->semantic(sc); - return e; - } + v = s->isVarDeclaration(); + if (v && v->inuse && (!v->type || !v->type->deco)) // Bugzilla 9494 + { e->error("circular reference to '%s'", v->toPrettyChars()); + return new ErrorExp(); + } + if (v && !v->isDataseg() && (v->storage_class & STCmanifest)) + { + Expression *ve = new VarExp(e->loc, v); + ve = ve->semantic(sc); + return ve; } if (s->getType()) @@ -8999,8 +8791,7 @@ L1: EnumMember *em = s->isEnumMember(); if (em) { - assert(em->value); - return em->value->copy(); + return em->getVarExp(e->loc, sc); } TemplateMixin *tm = s->isTemplateMixin(); @@ -9014,7 +8805,10 @@ L1: TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) { - e = new DotTemplateExp(e->loc, e, td); + if (e->op == TOKtype) + e = new ScopeExp(e->loc, td); + else + e = new DotTemplateExp(e->loc, e, td); e = e->semantic(sc); return e; } @@ -9045,7 +8839,7 @@ L1: OverloadSet *o = s->isOverloadSet(); if (o) { - OverExp *oe = new OverExp(o); + OverExp *oe = new OverExp(e->loc, o); if (e->op == TOKtype) return oe; return new DotExp(e->loc, e, oe); @@ -9063,30 +8857,21 @@ L1: /* It's: * Class.d */ - if (d->isTupleDeclaration()) + if (TupleDeclaration *tup = d->isTupleDeclaration()) { - e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = new TupleExp(e->loc, tup); e = e->semantic(sc); return e; } - - #if 1 // Workaround for Bugzilla 9213 - FuncDeclaration *fd = sc->func; - if (d->needThis() && d->isVarDeclaration() && fd && fd->vthis) + if (d->needThis() && sc->intypeof != 1) { - e = new DotVarExp(e->loc, new ThisExp(e->loc), d); - e = e->semantic(sc); - return e; - } - #endif - - FuncDeclaration *fdthis = hasThis(sc); - if (d->needThis() && fdthis) - { - if (d->isFuncDeclaration()) + /* Rewrite as: + * this.d + */ + if (hasThis(sc)) { // This is almost same as getRightThis() in expression.c - Expression *e1 = new VarExp(e->loc, fdthis->vthis); + Expression *e1 = new ThisExp(e->loc); e1 = e1->semantic(sc); L2: Type *t = e1->type->toBasetype(); @@ -9141,16 +8926,8 @@ L1: goto L2; } } - else - { - /* Rewrite as: - * this.d - */ - DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d); - e = de->semantic(sc); - return e; - } } + //printf("e = %s, d = %s\n", e->toChars(), d->toChars()); accessCheck(e->loc, sc, e, d); VarExp *ve = new VarExp(e->loc, d, 1); if (d->isVarDeclaration() && d->needThis()) @@ -9158,14 +8935,13 @@ L1: return ve; } - if (d->isDataseg()) + bool unreal = e->op == TOKvar && ((VarExp *)e)->var->isField(); + if (d->isDataseg() || unreal && d->isField()) { // (e, d) - VarExp *ve; - accessCheck(e->loc, sc, e, d); - ve = new VarExp(e->loc, d); - e = new CommaExp(e->loc, e, ve); + Expression *ve = new VarExp(e->loc, d); + e = unreal ? ve : new CommaExp(e->loc, e, ve); e = e->semantic(sc); return e; } @@ -9231,8 +9007,12 @@ MATCH TypeClass::implicitConvTo(Type *to) } m = MATCHnomatch; - if (sym->aliasthis) + if (sym->aliasthis && !(att & RECtracing)) + { + att = (AliasThisRec)(att | RECtracing); m = aliasthisOf()->implicitConvTo(to); + att = (AliasThisRec)(att & ~RECtracing); + } return m; } @@ -9248,7 +9028,7 @@ MATCH TypeClass::constConv(Type *to) /* Conversion derived to const(base) */ int offset = 0; - if (to->isBaseOf(this, &offset) && offset == 0 && !to->isMutable()) + if (to->isBaseOf(this, &offset) && offset == 0 && !to->isMutable() && !to->isWild()) return MATCHconvert; return MATCHnomatch; @@ -9265,10 +9045,16 @@ unsigned TypeClass::wildConvTo(Type *tprm) if (cdprm && cdprm->isBaseOf(sym, NULL)) return Type::wildConvTo(tprm); - if (sym->aliasthis) - return aliasthisOf()->wildConvTo(tprm); + unsigned mod = 0; - return 0; + if (sym->aliasthis && !(att & RECtracing)) + { + att = (AliasThisRec)(att | RECtracing); + mod = aliasthisOf()->wildConvTo(tprm); + att = (AliasThisRec)(att & ~RECtracing); + } + + return mod; } Type *TypeClass::toHeadMutable() @@ -9468,7 +9254,7 @@ void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) buf->printf("%d%.*s", len, len, (char *)buf2.extractData()); } -Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) +Expression *TypeTuple::getProperty(Loc loc, Identifier *ident, int flag) { Expression *e; #if LOGDOTEXP @@ -9482,6 +9268,10 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) { e = defaultInitLiteral(loc); } + else if (flag) + { + e = NULL; + } else { error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars()); @@ -9573,9 +9363,9 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol next->resolve(loc, sc, pe, pt, ps); if (*pe) { // It's really a slice expression - Expression *e; - e = new SliceExp(loc, *pe, lwr, upr); - *pe = e; + if (Dsymbol *s = getDsymbol(*pe)) + *pe = new DsymbolExp(loc, s, 1); + *pe = new SliceExp(loc, *pe, lwr, upr); } else if (*ps) { Dsymbol *s = *ps; @@ -9588,11 +9378,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sym->parent = sc->scopesym; sc = sc->push(sym); - lwr = lwr->semantic(sc); + lwr = lwr->ctfeSemantic(sc); lwr = lwr->ctfeInterpret(); uinteger_t i1 = lwr->toUInteger(); - upr = upr->semantic(sc); + upr = upr->ctfeSemantic(sc); upr = upr->ctfeInterpret(); uinteger_t i2 = upr->toUInteger(); @@ -9709,10 +9499,7 @@ void TypeNull::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) } d_uns64 TypeNull::size(Loc loc) { return tvoidptr->size(loc); } -//Expression *TypeNull::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); } -//Expression *TypeNull::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); } -Expression *TypeNull::defaultInit(Loc loc) { return new NullExp(0, Type::tnull); } -//Expression *TypeNull::defaultInitLiteral(Loc loc) { return new ErrorExp(); } +Expression *TypeNull::defaultInit(Loc loc) { return new NullExp(Loc(), Type::tnull); } /***************************** Parameter *****************************/ diff --git a/dmd2/mtype.h b/dmd2/mtype.h index 6dbda26122..6d2918d4af 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -121,17 +121,18 @@ extern int Tsize_t; extern int Tptrdiff_t; +/* pick this order of numbers so switch statements work better + */ +#define MODconst 1 // type is const +#define MODimmutable 4 // type is immutable +#define MODshared 2 // type is shared +#define MODwild 8 // type is wild +#define MODmutable 0x10 // type is mutable (only used in wildcard matching) + struct Type : Object { TY ty; unsigned char mod; // modifiers MODxxxx - /* pick this order of numbers so switch statements work better - */ - #define MODconst 1 // type is const - #define MODimmutable 4 // type is immutable - #define MODshared 2 // type is shared - #define MODwild 8 // type is wild - #define MODmutable 0x10 // type is mutable (only used in wildcard matching) char *deco; /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc. @@ -157,49 +158,47 @@ struct Type : Object type *ctype; // for back end #endif - #define tvoid basic[Tvoid] - #define tint8 basic[Tint8] - #define tuns8 basic[Tuns8] - #define tint16 basic[Tint16] - #define tuns16 basic[Tuns16] - #define tint32 basic[Tint32] - #define tuns32 basic[Tuns32] - #define tint64 basic[Tint64] - #define tuns64 basic[Tuns64] - #define tint128 basic[Tint128] - #define tuns128 basic[Tuns128] - #define tfloat32 basic[Tfloat32] - #define tfloat64 basic[Tfloat64] - #define tfloat80 basic[Tfloat80] + static Type *tvoid; + static Type *tint8; + static Type *tuns8; + static Type *tint16; + static Type *tuns16; + static Type *tint32; + static Type *tuns32; + static Type *tint64; + static Type *tuns64; + static Type *tint128; + static Type *tuns128; + static Type *tfloat32; + static Type *tfloat64; + static Type *tfloat80; - #define timaginary32 basic[Timaginary32] - #define timaginary64 basic[Timaginary64] - #define timaginary80 basic[Timaginary80] + static Type *timaginary32; + static Type *timaginary64; + static Type *timaginary80; - #define tcomplex32 basic[Tcomplex32] - #define tcomplex64 basic[Tcomplex64] - #define tcomplex80 basic[Tcomplex80] + static Type *tcomplex32; + static Type *tcomplex64; + static Type *tcomplex80; - #define tbool basic[Tbool] - #define tchar basic[Tchar] - #define twchar basic[Twchar] - #define tdchar basic[Tdchar] + static Type *tbool; + static Type *tchar; + static Type *twchar; + static Type *tdchar; // Some special types - #define tshiftcnt tint32 // right side of shift expression -// #define tboolean tint32 // result of boolean expression - #define tboolean tbool // result of boolean expression - #define tindex tsize_t // array/ptr index + static Type *tshiftcnt; + static Type *tboolean; static Type *tvoidptr; // void* static Type *tstring; // immutable(char)[] static Type *tvalist; // va_list alias - #define terror basic[Terror] // for error recovery + static Type *terror; // for error recovery + static Type *tnull; // for null type - #define tnull basic[Tnull] // for null type - - #define tsize_t basic[Tsize_t] // matches size_t alias - #define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias - #define thash_t tsize_t // matches hash_t alias + static Type *tsize_t; // matches size_t alias + static Type *tptrdiff_t; // matches ptrdiff_t alias + static Type *thash_t; // matches hash_t alias + static Type *tindex; // array/ptr index static ClassDeclaration *typeinfo; static ClassDeclaration *typeinfoclass; @@ -253,6 +252,8 @@ struct Type : Object #else static void init(); #endif + + #define SIZE_INVALID (~(d_uns64)0) d_uns64 size(); virtual d_uns64 size(Loc loc); virtual unsigned alignsize(); @@ -267,7 +268,6 @@ struct Type : Object void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod); void modToBuffer(OutBuffer *buf); char *modToChars(); - void toJsonProperty(JsonOut *json, const char *); virtual void toJson(JsonOut *json); #if CPP_MANGLE virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms); @@ -292,6 +292,7 @@ struct Type : Object int isWild() { return mod & MODwild; } int isSharedWild() { return mod == (MODshared | MODwild); } int isNaked() { return mod == 0; } + Type *nullAttributes(); Type *constOf(); Type *invariantOf(); Type *mutableOf(); @@ -310,6 +311,7 @@ struct Type : Object Type *referenceTo(); Type *arrayOf(); Type *aliasthisOf(); + int checkAliasThisRec(); virtual Type *makeConst(); virtual Type *makeInvariant(); virtual Type *makeShared(); @@ -326,14 +328,14 @@ struct Type : Object Type *substWildTo(unsigned mod); virtual Type *toHeadMutable(); virtual ClassDeclaration *isClassHandle(); - virtual Expression *getProperty(Loc loc, Identifier *ident); - virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + virtual Expression *getProperty(Loc loc, Identifier *ident, int flag); + virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); virtual structalign_t alignment(); - Expression *noMember(Scope *sc, Expression *e, Identifier *ident); - virtual Expression *defaultInit(Loc loc = 0); + Expression *noMember(Scope *sc, Expression *e, Identifier *ident, int flag); + virtual Expression *defaultInit(Loc loc = Loc()); virtual Expression *defaultInitLiteral(Loc loc); virtual Expression *voidInitLiteral(VarDeclaration *var); - virtual int isZeroInit(Loc loc = 0); // if initializer is 0 + virtual int isZeroInit(Loc loc = Loc()); // if initializer is 0 #if IN_DMD virtual dt_t **toDt(dt_t **pdt); #endif @@ -383,8 +385,8 @@ struct TypeError : Type void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); d_uns64 size(Loc loc); - Expression *getProperty(Loc loc, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident, int flag); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); TypeTuple *toArgTypes(); @@ -425,8 +427,8 @@ struct TypeBasic : Type #if IN_LLVM unsigned alignment(); #endif - Expression *getProperty(Loc loc, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident, int flag); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); char *toChars(); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); #if CPP_MANGLE @@ -459,8 +461,8 @@ struct TypeVector : Type Type *semantic(Loc loc, Scope *sc); d_uns64 size(Loc loc); unsigned alignsize(); - Expression *getProperty(Loc loc, Identifier *ident); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident, int flag); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); char *toChars(); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); #if IN_LLVM @@ -493,7 +495,7 @@ struct TypeVector : Type struct TypeArray : TypeNext { TypeArray(TY ty, Type *next); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); }; // Static array, one with a fixed dimension @@ -511,7 +513,7 @@ struct TypeSArray : TypeArray void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); int isString(); int isZeroInit(Loc loc); structalign_t alignment(); @@ -554,7 +556,7 @@ struct TypeDArray : TypeArray void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); int isString(); int isZeroInit(Loc loc); int checkBoolean(); @@ -592,7 +594,7 @@ struct TypeAArray : TypeArray void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); Expression *defaultInit(Loc loc); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); int isZeroInit(Loc loc); @@ -651,7 +653,7 @@ struct TypeReference : TypeNext d_uns64 size(Loc loc); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); Expression *defaultInit(Loc loc); int isZeroInit(Loc loc); #if CPP_MANGLE @@ -706,7 +708,6 @@ struct TypeFunction : TypeNext Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); void purityLevel(); - bool hasMutableIndirectionParams(); void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td); @@ -723,7 +724,7 @@ struct TypeFunction : TypeNext bool parameterEscapes(Parameter *p); Type *addStorageClass(StorageClass stc); - MATCH callMatch(Expression *ethis, Expressions *toargs, int flag = 0); + MATCH callMatch(Type *tthis, Expressions *toargs, int flag = 0); #if IN_DMD type *toCtype(); #endif @@ -761,7 +762,7 @@ struct TypeDelegate : TypeNext int isZeroInit(Loc loc); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); int hasPointers(); TypeTuple *toArgTypes(); #if CPP_MANGLE @@ -776,11 +777,13 @@ struct TypeDelegate : TypeNext struct TypeQualified : Type { Loc loc; - Identifiers idents; // array of Identifier's representing ident.ident.ident etc. + Objects idents; // array of Identifier and TypeInstance, + // representing ident.ident!tiargs.ident. ... etc. TypeQualified(TY ty, Loc loc); void syntaxCopyHelper(TypeQualified *t); void addIdent(Identifier *ident); + void addInst(TemplateInstance *inst); void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs); void toJson(JsonOut *json); d_uns64 size(Loc loc); @@ -826,6 +829,7 @@ struct TypeInstance : TypeQualified Dsymbol *toDsymbol(Scope *sc); Type *reliesOnTident(TemplateParameters *tparams = NULL); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); + Expression *toExpression(); }; struct TypeTypeof : TypeQualified @@ -839,6 +843,7 @@ struct TypeTypeof : TypeQualified Dsymbol *toDsymbol(Scope *sc); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); + void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); Type *semantic(Loc loc, Scope *sc); d_uns64 size(Loc loc); }; @@ -849,14 +854,26 @@ struct TypeReturn : TypeQualified const char *kind(); Type *syntaxCopy(); Dsymbol *toDsymbol(Scope *sc); + void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); Type *semantic(Loc loc, Scope *sc); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); }; +// Whether alias this dependency is recursive or not. +enum AliasThisRec +{ + RECno = 0, // no alias this recursion + RECyes = 1, // alias this has recursive dependency + RECfwdref = 2, // not yet known + + RECtracing = 0x4, // mark in progress of implicitConvTo/wildConvTo +}; + struct TypeStruct : Type { StructDeclaration *sym; + enum AliasThisRec att; TypeStruct(StructDeclaration *sym); const char *kind(); @@ -869,7 +886,7 @@ struct TypeStruct : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); structalign_t alignment(); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); @@ -919,8 +936,8 @@ struct TypeEnum : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - Expression *getProperty(Loc loc, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); + Expression *getProperty(Loc loc, Identifier *ident, int flag); int isintegral(); int isfloating(); int isreal(); @@ -965,9 +982,9 @@ struct TypeTypedef : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); structalign_t alignment(); - Expression *getProperty(Loc loc, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident, int flag); int isintegral(); int isfloating(); int isreal(); @@ -1007,6 +1024,7 @@ struct TypeTypedef : Type struct TypeClass : Type { ClassDeclaration *sym; + enum AliasThisRec att; TypeClass(ClassDeclaration *sym); const char *kind(); @@ -1018,7 +1036,7 @@ struct TypeClass : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toJson(JsonOut *json); - Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + Expression *dotExp(Scope *sc, Expression *e, Identifier *ident, int flag); ClassDeclaration *isClassHandle(); int isBaseOf(Type *t, int *poffset); MATCH implicitConvTo(Type *to); @@ -1066,7 +1084,7 @@ struct TypeTuple : Type void toDecoBuffer(OutBuffer *buf, int flag); #endif void toJson(JsonOut *json); - Expression *getProperty(Loc loc, Identifier *ident); + Expression *getProperty(Loc loc, Identifier *ident, int flag); Expression *defaultInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); }; @@ -1099,10 +1117,7 @@ struct TypeNull : Type void toJson(JsonOut *json); d_uns64 size(Loc loc); - //Expression *getProperty(Loc loc, Identifier *ident); - //Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *defaultInit(Loc loc); - //Expression *defaultInitLiteral(Loc loc); }; /**************************************************************/ @@ -1122,10 +1137,11 @@ struct Parameter : Object Type *isLazyArray(); void toDecoBuffer(OutBuffer *buf, bool mangle); int dyncast() { return DYNCAST_PARAMETER; } // kludge for template.isType() - void toJson(JsonOut *json); static Parameters *arraySyntaxCopy(Parameters *args); static char *argsTypesToChars(Parameters *args, int varargs); +#if CPP_MANGLE static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs); +#endif static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *arguments, int varargs); static void argsToDecoBuffer(OutBuffer *buf, Parameters *arguments, bool mangle); static int isTPL(Parameters *arguments); @@ -1136,10 +1152,6 @@ struct Parameter : Object static int foreach(Parameters *args, ForeachDg dg, void *ctx, size_t *pn=NULL); }; -extern int PTRSIZE; -extern int REALSIZE; -extern int REALPAD; -extern int REALALIGNSIZE; extern int Tsize_t; extern int Tptrdiff_t; diff --git a/dmd2/opover.c b/dmd2/opover.c index cf7d8cecf9..a4ddc52099 100644 --- a/dmd2/opover.c +++ b/dmd2/opover.c @@ -39,7 +39,7 @@ static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments); static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments); static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flags = 0); -static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments); +static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc, Objects *tiargs, Expression *ethis, Expressions *arguments); /******************************** Expression **************************/ @@ -202,11 +202,11 @@ Objects *opToArg(Scope *sc, enum TOK op) case TOKcatass: op = TOKcat; break; case TOKpowass: op = TOKpow; break; } - Expression *e = new StringExp(0, (char *)Token::toChars(op)); + Expression *e = new StringExp(Loc(), (char *)Token::toChars(op)); e = e->semantic(sc); - Objects *targsi = new Objects(); - targsi->push(e); - return targsi; + Objects *tiargs = new Objects(); + tiargs->push(e); + return tiargs; } /************************************ @@ -237,26 +237,29 @@ Expression *UnaExp::op_overload(Scope *sc) if (fd) { ae = resolveOpDollar(sc, ae); - Objects *targsi = opToArg(sc, op); - Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi); + Objects *tiargs = opToArg(sc, op); + Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs); e = new CallExp(loc, e, ae->arguments); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && ae->e1->type != att1) { /* Rewrite op(a[arguments]) as: * op(a.aliasthis[arguments]) */ Expression *e1 = ae->copy(); ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *ue = (UnaExp *)copy(); + if (!ue->att1 && ae->e1->type->checkAliasThisRec()) + ue->att1 = ae->e1->type; + ue->e1 = e1; + if (Expression *e = ue->trySemantic(sc)) + return e; } + att1 = NULL; } } else if (e1->op == TOKslice) @@ -281,26 +284,29 @@ Expression *UnaExp::op_overload(Scope *sc) { a->push(se->lwr); a->push(se->upr); } - Objects *targsi = opToArg(sc, op); - Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi); + Objects *tiargs = opToArg(sc, op); + Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && se->e1->type != att1) { /* Rewrite op(a[lwr..upr]) as: * op(a.aliasthis[lwr..upr]) */ Expression *e1 = se->copy(); ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *ue = (UnaExp *)copy(); + if (!ue->att1 && se->e1->type->checkAliasThisRec()) + ue->att1 = se->e1->type; + ue->e1 = e1; + if (Expression *e = ue->trySemantic(sc)) + return e; } + att1 = NULL; } } #endif @@ -344,24 +350,26 @@ Expression *UnaExp::op_overload(Scope *sc) fd = search_function(ad, Id::opUnary); if (fd) { - Objects *targsi = opToArg(sc, op); - Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi); + Objects *tiargs = opToArg(sc, op); + Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, tiargs); e = new CallExp(loc, e); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && this->e1->type != att1) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ + //printf("att una %s e1 = %s\n", Token::toChars(op), this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *ue = (UnaExp *)copy(); + if (!ue->att1 && this->e1->type->checkAliasThisRec()) + ue->att1 = this->e1->type; + ue->e1 = e1; + return ue->trySemantic(sc); } #endif } @@ -388,16 +396,18 @@ Expression *ArrayExp::op_overload(Scope *sc) } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && this->e1->type != att1) { /* Rewrite op(e1) as: * op(e1.aliasthis) */ + //printf("att arr e1 = %s\n", this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *ue = (UnaExp *)copy(); + if (!ue->att1 && this->e1->type->checkAliasThisRec()) + ue->att1 = this->e1->type; + ue->e1 = e1; + return ue->trySemantic(sc); } } return NULL; @@ -426,9 +436,9 @@ Expression *CastExp::op_overload(Scope *sc) return build_overload(loc, sc, e1, NULL, fd); } #endif - Objects *targsi = new Objects(); - targsi->push(to); - Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, targsi); + Objects *tiargs = new Objects(); + tiargs->push(to); + Expression *e = new DotTemplateInstanceExp(loc, e1, fd->ident, tiargs); e = new CallExp(loc, e); e = e->semantic(sc); return e; @@ -487,7 +497,7 @@ Expression *BinExp::op_overload(Scope *sc) } #endif - Objects *targsi = NULL; + Objects *tiargs = NULL; #if DMDV2 if (op == TOKplusplus || op == TOKminusminus) { // Bug4099 fix @@ -500,16 +510,28 @@ Expression *BinExp::op_overload(Scope *sc) /* Try the new D2 scheme, opBinary and opBinaryRight */ if (ad1) + { s = search_function(ad1, Id::opBinary); + if (s && !s->isTemplateDeclaration()) + { e1->error("%s.opBinary isn't a template", e1->toChars()); + return new ErrorExp(); + } + } if (ad2) + { s_r = search_function(ad2, Id::opBinaryRight); + if (s_r && !s_r->isTemplateDeclaration()) + { e2->error("%s.opBinaryRight isn't a template", e2->toChars()); + return new ErrorExp(); + } + } - // Set targsi, the template argument list, which will be the operator string + // Set tiargs, the template argument list, which will be the operator string if (s || s_r) { id = Id::opBinary; id_r = Id::opBinaryRight; - targsi = opToArg(sc, op); + tiargs = opToArg(sc, op); } } #endif @@ -541,7 +563,7 @@ Expression *BinExp::op_overload(Scope *sc) } else { TemplateDeclaration *td = s->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e1, &args2); + templateResolve(&m, td, loc, sc, tiargs, e1, &args2); } } @@ -556,7 +578,7 @@ Expression *BinExp::op_overload(Scope *sc) } else { TemplateDeclaration *td = s_r->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e2, &args1); + templateResolve(&m, td, loc, sc, tiargs, e2, &args1); } } @@ -571,7 +593,7 @@ Expression *BinExp::op_overload(Scope *sc) else if (m.last == MATCHnomatch) { m.lastf = m.anyf; - if (targsi) + if (tiargs) goto L1; } @@ -593,7 +615,7 @@ Expression *BinExp::op_overload(Scope *sc) L1: #if 1 // Retained for D1 compatibility - if (isCommutative() && !targsi) + if (isCommutative() && !tiargs) { s = NULL; s_r = NULL; @@ -634,7 +656,7 @@ L1: } else { TemplateDeclaration *td = s_r->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e1, &args2); + templateResolve(&m, td, loc, sc, tiargs, e1, &args2); } } FuncDeclaration *lastf = m.lastf; @@ -648,7 +670,7 @@ L1: } else { TemplateDeclaration *td = s->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e2, &args1); + templateResolve(&m, td, loc, sc, tiargs, e2, &args1); } } @@ -709,11 +731,15 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ + if (att1 && this->e1->type == att1) + return NULL; + //printf("att bin e1 = %s\n", this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att1 && this->e1->type->checkAliasThisRec()) + be->att1 = this->e1->type; + be->e1 = e1; + return be->trySemantic(sc); } // Try alias this on second operand @@ -726,11 +752,15 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ + if (att2 && this->e2->type == att2) + return NULL; + //printf("att bin e2 = %s\n", this->e2->type->toChars()); Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att2 && this->e2->type->checkAliasThisRec()) + be->att2 = this->e2->type; + be->e2 = e2; + return be->trySemantic(sc); } #endif return NULL; @@ -760,7 +790,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) s_r = NULL; } - Objects *targsi = NULL; + Objects *tiargs = NULL; if (s || s_r) { @@ -797,7 +827,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) } else { TemplateDeclaration *td = s->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e1, &args2); + templateResolve(&m, td, loc, sc, tiargs, e1, &args2); } } @@ -813,7 +843,7 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) } else { TemplateDeclaration *td = s_r->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e2, &args1); + templateResolve(&m, td, loc, sc, tiargs, e2, &args1); } } @@ -882,11 +912,15 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ + if (att1 && this->e1->type == att1) + return NULL; + //printf("att cmp_bin e1 = %s\n", this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att1 && this->e1->type->checkAliasThisRec()) + be->att1 = this->e1->type; + be->e1 = e1; + return be->trySemantic(sc); } // Try alias this on second operand @@ -895,11 +929,15 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ + if (att2 && this->e2->type == att2) + return NULL; + //printf("att cmp_bin e2 = %s\n", this->e2->type->toChars()); Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att2 && this->e2->type->checkAliasThisRec()) + be->att2 = this->e2->type; + be->e2 = e2; + return be->trySemantic(sc); } return NULL; @@ -979,26 +1017,29 @@ Expression *BinAssignExp::op_overload(Scope *sc) Expressions *a = (Expressions *)ae->arguments->copy(); a->insert(0, e2); - Objects *targsi = opToArg(sc, op); - Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi); + Objects *tiargs = opToArg(sc, op); + Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, tiargs); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && ae->e1->type != att1) { /* Rewrite a[arguments] op= e2 as: * a.aliasthis[arguments] op= e2 */ Expression *e1 = ae->copy(); ((ArrayExp *)e1)->e1 = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att1 && ae->e1->type->checkAliasThisRec()) + be->att1 = ae->e1->type; + be->e1 = e1; + if (Expression *e = be->trySemantic(sc)) + return e; } + att1 = NULL; } } else if (e1->op == TOKslice) @@ -1025,26 +1066,29 @@ Expression *BinAssignExp::op_overload(Scope *sc) a->push(se->upr); } - Objects *targsi = opToArg(sc, op); - Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, targsi); + Objects *tiargs = opToArg(sc, op); + Expression *e = new DotTemplateInstanceExp(loc, se->e1, fd->ident, tiargs); e = new CallExp(loc, e, a); e = e->semantic(sc); return e; } // Didn't find it. Forward to aliasthis - if (ad->aliasthis) + if (ad->aliasthis && se->e1->type != att1) { /* Rewrite a[lwr..upr] op= e2 as: * a.aliasthis[lwr..upr] op= e2 */ Expression *e1 = se->copy(); ((SliceExp *)e1)->e1 = new DotIdExp(loc, se->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att1 && se->e1->type->checkAliasThisRec()) + be->att1 = se->e1->type; + be->e1 = e1; + if (Expression *e = be->trySemantic(sc)) + return e; } + att1 = NULL; } } #endif @@ -1072,19 +1116,25 @@ Expression *BinAssignExp::op_overload(Scope *sc) } #endif - Objects *targsi = NULL; + Objects *tiargs = NULL; #if DMDV2 if (!s) { /* Try the new D2 scheme, opOpAssign */ if (ad1) + { s = search_function(ad1, Id::opOpAssign); + if (s && !s->isTemplateDeclaration()) + { error("%s.opOpAssign isn't a template", e1->toChars()); + return new ErrorExp(); + } + } - // Set targsi, the template argument list, which will be the operator string + // Set tiargs, the template argument list, which will be the operator string if (s) { id = Id::opOpAssign; - targsi = opToArg(sc, op); + tiargs = opToArg(sc, op); } } #endif @@ -1111,7 +1161,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) } else { TemplateDeclaration *td = s->isTemplateDeclaration(); - templateResolve(&m, td, sc, loc, targsi, e1, &args2); + templateResolve(&m, td, loc, sc, tiargs, e1, &args2); } } @@ -1126,7 +1176,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) else if (m.last == MATCHnomatch) { m.lastf = m.anyf; - if (targsi) + if (tiargs) goto L1; } @@ -1143,11 +1193,15 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ + if (att1 && this->e1->type == att1) + return NULL; + //printf("att %s e1 = %s\n", Token::toChars(op), this->e1->type->toChars()); Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att1 && this->e1->type->checkAliasThisRec()) + be->att1 = this->e1->type; + be->e1 = e1; + return be->trySemantic(sc); } // Try alias this on second operand @@ -1157,11 +1211,15 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ + if (att2 && this->e2->type == att2) + return NULL; + //printf("att %s e2 = %s\n", Token::toChars(op), this->e2->type->toChars()); Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *be = (BinExp *)copy(); + if (!be->att2 && this->e2->type->checkAliasThisRec()) + be->att2 = this->e2->type; + be->e2 = e2; + return be->trySemantic(sc); } #endif return NULL; @@ -1201,7 +1259,7 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid) FuncDeclaration *fd; TemplateDeclaration *td; - s = ad->search(0, funcid, 0); + s = ad->search(Loc(), funcid, 0); if (s) { Dsymbol *s2; @@ -1228,6 +1286,8 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) int sliced = 0; #endif Type *tab; + Type *att = NULL; + Expression *org_aggr = aggr; AggregateDeclaration *ad; while (1) @@ -1239,6 +1299,10 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) goto Lerr; tab = aggr->type->toBasetype(); + if (att == tab) + { aggr = org_aggr; + goto Lerr; + } switch (tab->ty) { case Tarray: @@ -1277,13 +1341,15 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) } } - if (Dsymbol *shead = ad->search(0, idfront, 0)) + if (Dsymbol *shead = ad->search(Loc(), idfront, 0)) { // range aggregate break; } if (ad->aliasthis) { + if (!att && tab->checkAliasThisRec()) + att = tab; aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident); continue; } @@ -1436,7 +1502,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) /* Look for a front() or back() overload */ Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback; - Dsymbol *s = ad->search(0, id, 0); + Dsymbol *s = ad->search(Loc(), id, 0); FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; if (fd) { @@ -1614,12 +1680,13 @@ void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments) /************************************** */ -static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments) +static void templateResolve(Match *m, TemplateDeclaration *td, Loc loc, Scope *sc, + Objects *tiargs, Expression *ethis, Expressions *arguments) { FuncDeclaration *fd; assert(td); - fd = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1); + fd = td->deduceFunctionTemplate(loc, sc, tiargs, ethis->type, arguments, 1); if (!fd) return; m->anyf = fd; diff --git a/dmd2/optimize.c b/dmd2/optimize.c index 2783ccfe5a..6b23a1e873 100644 --- a/dmd2/optimize.c +++ b/dmd2/optimize.c @@ -23,7 +23,7 @@ #include "declaration.h" #include "aggregate.h" #include "init.h" - +#include "enum.h" #ifdef IN_GCC #include "d-gcc-real.h" @@ -68,7 +68,7 @@ Expression *expandVar(int result, VarDeclaration *v) v->error("recursive initialization of constant"); goto L1; } - Expression *ei = v->init->toExpression(); + Expression *ei = v->getConstInitializer(); if (!ei) { if (v->storage_class & STCmanifest) v->error("enum cannot be initialized with %s", v->init->toChars()); @@ -91,24 +91,20 @@ Expression *expandVar(int result, VarDeclaration *v) } else if (ei->implicitConvTo(v->type) >= MATCHconst) { // const var initialized with non-const expression - ei = ei->implicitCastTo(0, v->type); - ei = ei->semantic(0); + ei = ei->implicitCastTo(NULL, v->type); + ei = ei->semantic(NULL); } else goto L1; } - if (v->scope) + else if (!(result & WANTinterpret) && + !(v->storage_class & STCmanifest) && + ei->isConst() != 1 && ei->op != TOKstring && + ei->op != TOKaddress) { - v->inuse++; - e = ei->syntaxCopy(); - e = e->semantic(v->scope); - e = e->implicitCastTo(v->scope, v->type); - // enabling this line causes test22 in test suite to fail - //ei->type = e->type; - v->scope = NULL; - v->inuse--; + goto L1; } - else if (!ei->type) + if (!ei->type) { goto L1; } @@ -177,6 +173,7 @@ Expression *fromConstInitializer(int result, Expression *e1) !(v->storage_class & STCtemplateparameter)) { e1->error("variable %s cannot be read at compile time", v->toChars()); + e = e->copy(); e->type = Type::terror; } } @@ -193,14 +190,22 @@ Expression *Expression::optimize(int result, bool keepLvalue) Expression *VarExp::optimize(int result, bool keepLvalue) { - return keepLvalue ? this : fromConstInitializer(result, this); + if (keepLvalue) + { + VarDeclaration *v = var->isVarDeclaration(); + if (v && !(v->storage_class & STCmanifest)) + return this; + } + return fromConstInitializer(result, this); } Expression *TupleExp::optimize(int result, bool keepLvalue) { + if (e0) + e0 = e0->optimize(WANTvalue | (result & WANTinterpret)); for (size_t i = 0; i < exps->dim; i++) - { Expression *e = (*exps)[i]; - + { + Expression *e = (*exps)[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); (*exps)[i] = e; } @@ -239,6 +244,9 @@ Expression *AssocArrayLiteralExp::optimize(int result, bool keepLvalue) Expression *StructLiteralExp::optimize(int result, bool keepLvalue) { + if(stageflags & stageOptimize) return this; + int old = stageflags; + stageflags |= stageOptimize; if (elements) { for (size_t i = 0; i < elements->dim; i++) @@ -249,6 +257,7 @@ Expression *StructLiteralExp::optimize(int result, bool keepLvalue) (*elements)[i] = e; } } + stageflags = old; return this; } @@ -316,6 +325,14 @@ Expression *BoolExp::optimize(int result, bool keepLvalue) return e; } +Expression *SymOffExp::optimize(int result, bool keepLvalue) +{ + assert(var); + if ((result & WANTinterpret) && var->isThreadlocal()) + error("cannot take address of thread-local variable %s at compile time", var->toChars()); + return this; +} + Expression *AddrExp::optimize(int result, bool keepLvalue) { Expression *e; @@ -332,13 +349,8 @@ Expression *AddrExp::optimize(int result, bool keepLvalue) return e->optimize(result); } - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - if (ve->var->storage_class & STCmanifest) - e1 = e1->optimize(result); - } - else - e1 = e1->optimize(result); + // Keep lvalue-ness + e1 = e1->optimize(result, true); // Convert &*ex to ex if (e1->op == TOKstar) @@ -489,7 +501,13 @@ Expression *NewExp::optimize(int result, bool keepLvalue) } if (result & WANTinterpret) { - error("cannot evaluate %s at compile time", toChars()); + Expression *eresult = interpret(NULL); + if (eresult == EXP_CANT_INTERPRET) + return this; + if (eresult && eresult != EXP_VOID_INTERPRET) + return eresult; + else + error("cannot evaluate %s at compile time", toChars()); } return this; } @@ -509,12 +527,8 @@ Expression *CallExp::optimize(int result, bool keepLvalue) size_t pdim = Parameter::dim(tf->parameters) - (tf->varargs == 2 ? 1 : 0); for (size_t i = 0; i < arguments->dim; i++) { - bool keepLvalue = false; - if (i < pdim) - { - Parameter *p = Parameter::getNth(tf->parameters, i); - keepLvalue = ((p->storageClass & (STCref | STCout)) != 0); - } + Parameter *p = Parameter::getNth(tf->parameters, i); + bool keepLvalue = (p ? (p->storageClass & (STCref | STCout)) != 0 : false); Expression *e = (*arguments)[i]; e = e->optimize(WANTvalue, keepLvalue); (*arguments)[i] = e; @@ -603,7 +617,7 @@ Expression *CastExp::optimize(int result, bool keepLvalue) if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && - e1->type->nextOf()->size() == type->nextOf()->size() + e1->type->toBasetype()->nextOf()->size() == type->nextOf()->size() ) { Expression *e = e1->castTo(NULL, type); @@ -801,19 +815,19 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E Expression *ShlExp::optimize(int result, bool keepLvalue) { //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Shl); + return shift_optimize(result, this, &Shl); } Expression *ShrExp::optimize(int result, bool keepLvalue) { //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Shr); + return shift_optimize(result, this, &Shr); } Expression *UshrExp::optimize(int result, bool keepLvalue) { //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); - return shift_optimize(result, this, Ushr); + return shift_optimize(result, this, &Ushr); } Expression *AndExp::optimize(int result, bool keepLvalue) @@ -984,7 +998,8 @@ Expression *IdentityExp::optimize(int result, bool keepLvalue) Expression *e = this; if ((this->e1->isConst() && this->e2->isConst()) || - (this->e1->op == TOKnull && this->e2->op == TOKnull)) + (this->e1->op == TOKnull && this->e2->op == TOKnull) || + (result & WANTinterpret)) { e = Identity(op, type, this->e1, this->e2); if (e == EXP_CANT_INTERPRET) @@ -1017,8 +1032,8 @@ void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr) return; // we don't know the length yet } - Expression *dollar = new IntegerExp(0, len, Type::tsize_t); - lengthVar->init = new ExpInitializer(0, dollar); + Expression *dollar = new IntegerExp(Loc(), len, Type::tsize_t); + lengthVar->init = new ExpInitializer(Loc(), dollar); lengthVar->storage_class |= STCstatic | STCconst; } @@ -1027,25 +1042,16 @@ Expression *IndexExp::optimize(int result, bool keepLvalue) { Expression *e; //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); - Expression *e1 = this->e1->optimize( - WANTvalue | (result & (WANTinterpret| WANTexpand))); - e1 = fromConstInitializer(result, e1); - if (this->e1->op == TOKvar) - { VarExp *ve = (VarExp *)this->e1; - if (ve->var->storage_class & STCmanifest) - { /* We generally don't want to have more than one copy of an - * array literal, but if it's an enum we have to because the - * enum isn't stored elsewhere. See Bugzilla 2559 - */ - this->e1 = e1; - } - } + e1 = e1->optimize(WANTvalue | (result & (WANTinterpret| WANTexpand))); + + Expression *ex = fromConstInitializer(result, e1); + // We might know $ now - setLengthVarIfKnown(lengthVar, e1); + setLengthVarIfKnown(lengthVar, ex); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); if (keepLvalue) return this; - e = Index(type, e1, e2); + e = Index(type, ex, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; diff --git a/dmd2/parse.c b/dmd2/parse.c index 603e0c4f6c..28b7e66462 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2012 by Digital Mars +// Copyright (c) 1999-2013 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -61,9 +61,9 @@ Parser::Parser(Module *module, unsigned char *base, size_t length, int doDocComm //printf("Parser::Parser()\n"); md = NULL; linkage = LINKd; - endloc = 0; + endloc = Loc(); inBrackets = 0; - lookingForElse = 0; + lookingForElse = Loc(); //nextToken(); // start up the scanner } @@ -143,7 +143,7 @@ Lerr: return new Dsymbols(); } -Dsymbols *Parser::parseDeclDefs(int once) +Dsymbols *Parser::parseDeclDefs(int once, Dsymbol **pLastDecl) { Dsymbol *s; Dsymbols *decldefs; Dsymbols *a; @@ -153,6 +153,9 @@ Dsymbols *Parser::parseDeclDefs(int once) StorageClass storageClass; Condition *condition; unsigned char *comment; + Dsymbol *lastDecl = NULL; // used to link unittest to its previous declaration + if (!pLastDecl) + pLastDecl = &lastDecl; //printf("Parser::parseDeclDefs()\n"); decldefs = new Dsymbols(); @@ -232,6 +235,7 @@ Dsymbols *Parser::parseDeclDefs(int once) case TOKinterface: Ldeclaration: a = parseDeclarations(STCundefined, NULL); + if (a->dim) *pLastDecl = (*a)[a->dim-1]; decldefs->append(a); continue; @@ -269,20 +273,7 @@ Dsymbols *Parser::parseDeclDefs(int once) case TOKunittest: s = parseUnitTest(); - if (decldefs && decldefs->dim) - { - Dsymbol *ds = (*decldefs)[decldefs->dim-1]; - AttribDeclaration *ad; - while ((ad = ds->isAttribDeclaration()) != NULL) - { - if (ad->decl && ad->decl->dim) - ds = (*ad->decl)[ad->decl->dim-1]; - else - break; - } - - ds->unittest = (UnitTestDeclaration *)s; - } + if (*pLastDecl) (*pLastDecl)->unittest = (UnitTestDeclaration *)s; break; case TOKnew: @@ -309,16 +300,21 @@ Dsymbols *Parser::parseDeclDefs(int once) s = parseStaticAssert(); else if (token.value == TOKif) { condition = parseStaticIfCondition(); - Loc lookingForElseSave = lookingForElse; - lookingForElse = loc; - a = parseBlock(); - lookingForElse = lookingForElseSave; + if (token.value == TOKcolon) + a = parseBlock(pLastDecl); + else + { + Loc lookingForElseSave = lookingForElse; + lookingForElse = loc; + a = parseBlock(pLastDecl); + lookingForElse = lookingForElseSave; + } aelse = NULL; if (token.value == TOKelse) { Loc elseloc = this->loc; nextToken(); - aelse = parseBlock(); + aelse = parseBlock(pLastDecl); checkDanglingElse(elseloc); } s = new StaticIfDeclaration(condition, a, aelse); @@ -381,7 +377,6 @@ Dsymbols *Parser::parseDeclDefs(int once) case TOKnothrow: stc = STCnothrow; goto Lstc; case TOKpure: stc = STCpure; goto Lstc; case TOKref: stc = STCref; goto Lstc; - case TOKtls: stc = STCtls; goto Lstc; case TOKgshared: stc = STCgshared; goto Lstc; //case TOKmanifest: stc = STCmanifest; goto Lstc; case TOKat: @@ -390,7 +385,7 @@ Dsymbols *Parser::parseDeclDefs(int once) stc = parseAttribute(&exps); if (stc) goto Lstc; // it's a predefined attribute - a = parseBlock(); + a = parseBlock(pLastDecl); s = new UserAttributeDeclaration(exps, a); break; } @@ -398,7 +393,7 @@ Dsymbols *Parser::parseDeclDefs(int once) Lstc: if (storageClass & stc) - error("redundant storage class %s", Token::toChars(token.value)); + error("redundant storage class '%s'", Token::toChars(token.value)); composeStorageClass(storageClass | stc); nextToken(); Lstc2: @@ -446,7 +441,6 @@ Dsymbols *Parser::parseDeclDefs(int once) case TOKnothrow: stc = STCnothrow; goto Lstc; case TOKpure: stc = STCpure; goto Lstc; case TOKref: stc = STCref; goto Lstc; - case TOKtls: stc = STCtls; goto Lstc; case TOKgshared: stc = STCgshared; goto Lstc; //case TOKmanifest: stc = STCmanifest; goto Lstc; case TOKat: @@ -468,6 +462,7 @@ Dsymbols *Parser::parseDeclDefs(int once) peek(&token)->value == TOKassign) { a = parseAutoDeclarations(storageClass, comment); + if (a->dim) *pLastDecl = (*a)[a->dim-1]; decldefs->append(a); continue; } @@ -488,10 +483,11 @@ Dsymbols *Parser::parseDeclDefs(int once) ) { a = parseDeclarations(storageClass, comment); + if (a->dim) *pLastDecl = (*a)[a->dim-1]; decldefs->append(a); continue; } - a = parseBlock(); + a = parseBlock(pLastDecl); s = new StorageClassDeclaration(storageClass, a); break; @@ -506,7 +502,7 @@ Dsymbols *Parser::parseDeclDefs(int once) check(TOKlparen); Expression *e = parseAssignExp(); check(TOKrparen); - a = parseBlock(); + a = parseBlock(pLastDecl); s = new DeprecatedDeclaration(e, a); break; } @@ -515,7 +511,7 @@ Dsymbols *Parser::parseDeclDefs(int once) { warning(loc, "use @(attributes) instead of [attributes]"); Expressions *exps = parseArguments(); - a = parseBlock(); + a = parseBlock(pLastDecl); s = new UserAttributeDeclaration(exps, a); break; } @@ -528,7 +524,7 @@ Dsymbols *Parser::parseDeclDefs(int once) { enum LINK linksave = linkage; linkage = parseLinkage(); - a = parseBlock(); + a = parseBlock(pLastDecl); s = new LinkDeclaration(linkage, a); linkage = linksave; break; @@ -552,7 +548,7 @@ Dsymbols *Parser::parseDeclDefs(int once) break; default: break; } - a = parseBlock(); + a = parseBlock(pLastDecl); s = new ProtDeclaration(prot, a); break; @@ -578,9 +574,9 @@ Dsymbols *Parser::parseDeclDefs(int once) check(TOKrparen); } else - n = global.structalign; // default + n = STRUCTALIGN_DEFAULT; // default - a = parseBlock(); + a = parseBlock(pLastDecl); s = new AlignDeclaration(n, a); break; } @@ -605,7 +601,7 @@ Dsymbols *Parser::parseDeclDefs(int once) if (token.value == TOKsemicolon) a = NULL; else - a = parseBlock(); + a = parseBlock(pLastDecl); s = new PragmaDeclaration(loc, ident, args, a); break; } @@ -658,12 +654,12 @@ Dsymbols *Parser::parseDeclDefs(int once) Lcondition: { if (token.value == TOKcolon) - a = parseBlock(); + a = parseBlock(pLastDecl); else { Loc lookingForElseSave = lookingForElse; lookingForElse = loc; - a = parseBlock(); + a = parseBlock(pLastDecl); lookingForElse = lookingForElseSave; } } @@ -672,7 +668,7 @@ Dsymbols *Parser::parseDeclDefs(int once) { Loc elseloc = this->loc; nextToken(); - aelse = parseBlock(); + aelse = parseBlock(pLastDecl); checkDanglingElse(elseloc); } s = new ConditionalDeclaration(condition, a, aelse); @@ -695,6 +691,8 @@ Dsymbols *Parser::parseDeclDefs(int once) if (s) { decldefs->push(s); addComment(s, comment); + if (!s->isAttribDeclaration()) + *pLastDecl = s; } } while (!once); return decldefs; @@ -848,7 +846,7 @@ StorageClass Parser::parseTypeCtor() * Parse declarations after an align, protection, or extern decl. */ -Dsymbols *Parser::parseBlock() +Dsymbols *Parser::parseBlock(Dsymbol **pLastDecl) { Dsymbols *a = NULL; @@ -867,10 +865,10 @@ Dsymbols *Parser::parseBlock() case TOKlcurly: { Loc lookingForElseSave = lookingForElse; - lookingForElse = 0; + lookingForElse = Loc(); nextToken(); - a = parseDeclDefs(0); + a = parseDeclDefs(0, pLastDecl); if (token.value != TOKrcurly) { /* { */ error("matching '}' expected, not %s", token.toChars()); @@ -886,12 +884,12 @@ Dsymbols *Parser::parseBlock() #if 0 a = NULL; #else - a = parseDeclDefs(0); // grab declarations up to closing curly bracket + a = parseDeclDefs(0, pLastDecl); // grab declarations up to closing curly bracket #endif break; default: - a = parseDeclDefs(1); + a = parseDeclDefs(1, pLastDecl); break; } return a; @@ -1135,13 +1133,13 @@ Dsymbol *Parser::parseCtor() Loc loc = this->loc; nextToken(); - if (token.value == TOKlparen && peek(&token)->value == TOKthis) + if (token.value == TOKlparen && peekNext() == TOKthis && peekNext2() == TOKrparen) { // this(this) { ... } nextToken(); nextToken(); check(TOKrparen); StorageClass stc = parsePostfix(); - PostBlitDeclaration *f = new PostBlitDeclaration(loc, 0, stc, Id::_postblit); + PostBlitDeclaration *f = new PostBlitDeclaration(loc, Loc(), stc, Id::_postblit); parseContracts(f); return f; } @@ -1163,7 +1161,7 @@ Dsymbol *Parser::parseCtor() Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto tf = tf->addSTC(stc); - CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf); + CtorDeclaration *f = new CtorDeclaration(loc, Loc(), stc, tf); parseContracts(f); // Wrap a template around it @@ -1182,7 +1180,7 @@ Dsymbol *Parser::parseCtor() Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto tf = tf->addSTC(stc); - CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf); + CtorDeclaration *f = new CtorDeclaration(loc, Loc(), stc, tf); parseContracts(f); return f; } @@ -1203,7 +1201,8 @@ DtorDeclaration *Parser::parseDtor() check(TOKlparen); check(TOKrparen); - f = new DtorDeclaration(loc, 0); + StorageClass stc = parsePostfix(); + f = new DtorDeclaration(loc, Loc(), stc, Id::dtor); parseContracts(f); return f; } @@ -1222,7 +1221,7 @@ StaticCtorDeclaration *Parser::parseStaticCtor() check(TOKlparen); check(TOKrparen); - StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, 0); + StaticCtorDeclaration *f = new StaticCtorDeclaration(loc, Loc()); parseContracts(f); return f; } @@ -1243,7 +1242,7 @@ SharedStaticCtorDeclaration *Parser::parseSharedStaticCtor() check(TOKlparen); check(TOKrparen); - SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, 0); + SharedStaticCtorDeclaration *f = new SharedStaticCtorDeclaration(loc, Loc()); parseContracts(f); return f; } @@ -1263,7 +1262,7 @@ StaticDtorDeclaration *Parser::parseStaticDtor() check(TOKlparen); check(TOKrparen); - StaticDtorDeclaration *f = new StaticDtorDeclaration(loc, 0); + StaticDtorDeclaration *f = new StaticDtorDeclaration(loc, Loc()); parseContracts(f); return f; } @@ -1285,7 +1284,7 @@ SharedStaticDtorDeclaration *Parser::parseSharedStaticDtor() check(TOKlparen); check(TOKrparen); - SharedStaticDtorDeclaration *f = new SharedStaticDtorDeclaration(loc, 0); + SharedStaticDtorDeclaration *f = new SharedStaticDtorDeclaration(loc, Loc()); parseContracts(f); return f; } @@ -1308,7 +1307,7 @@ InvariantDeclaration *Parser::parseInvariant() check(TOKrparen); } - f = new InvariantDeclaration(loc, 0); + f = new InvariantDeclaration(loc, Loc(), STCundefined); f->fbody = parseStatement(PScurly); return f; } @@ -1326,10 +1325,33 @@ UnitTestDeclaration *Parser::parseUnitTest() Loc loc = this->loc; nextToken(); + unsigned char *begPtr = token.ptr + 1; // skip '{' + unsigned char *endPtr = NULL; + body = parseStatement(PScurly, &endPtr); - body = parseStatement(PScurly); + /** Extract unittest body as a string. Must be done eagerly since memory + will be released by the lexer before doc gen. */ + char *docline = NULL; + if (global.params.doDocComments && endPtr > begPtr) + { + /* Remove trailing whitespaces */ + for (unsigned char *p = endPtr - 1; + begPtr <= p && (*p == ' ' || *p == '\n' || *p == '\t'); --p) + { + endPtr = p; + } - f = new UnitTestDeclaration(loc, this->loc); + size_t len = endPtr - begPtr; + if (len > 0) + { + docline = (char *)mem.malloc(len + 2); + memcpy(docline, begPtr, len); + docline[len ] = '\n'; // Terminate all lines by LF + docline[len+1] = '\0'; + } + } + + f = new UnitTestDeclaration(loc, this->loc, docline); f->fbody = body; return f; } @@ -1349,7 +1371,7 @@ NewDeclaration *Parser::parseNew() nextToken(); arguments = parseParameters(&varargs); - f = new NewDeclaration(loc, 0, arguments, varargs); + f = new NewDeclaration(loc, Loc(), arguments, varargs); parseContracts(f); return f; } @@ -1371,7 +1393,7 @@ DeleteDeclaration *Parser::parseDelete() arguments = parseParameters(&varargs); if (varargs) error("... not allowed in delete function parameter list"); - f = new DeleteDeclaration(loc, 0, arguments); + f = new DeleteDeclaration(loc, Loc(), arguments); parseContracts(f); return f; } @@ -1450,7 +1472,7 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) (storageClass & STCin && stc & (STCconst | STCscope)) || (stc & STCin && storageClass & (STCconst | STCscope)) ) - error("redundant storage class %s", Token::toChars(token.value)); + error("redundant storage class '%s'", Token::toChars(token.value)); storageClass |= stc; composeStorageClass(storageClass); continue; @@ -1712,6 +1734,18 @@ Dsymbol *Parser::parseAggregate() nextToken(); baseclasses = parseBaseClasses(); + if (tpl) + { + Expression *tempCons = parseConstraint(); + if (tempCons) + { + if (constraint) + error("members expected"); + else + constraint = tempCons; + } + } + if (token.value != TOKlcurly) error("members expected"); } @@ -2064,9 +2098,8 @@ Dsymbol *Parser::parseMixin() { TemplateMixin *tm; Identifier *id; - Type *tqual; + TypeQualified *tqual; Objects *tiargs; - Identifiers *idents; //printf("parseMixin()\n"); nextToken(); @@ -2082,11 +2115,6 @@ Dsymbol *Parser::parseMixin() tqual = parseTypeof(); check(TOKdot); } - else if (token.value == TOKvector) - { - tqual = parseVector(); - check(TOKdot); - } if (token.value != TOKidentifier) { error("identifier expected, not %s", token.toChars()); @@ -2097,7 +2125,6 @@ Dsymbol *Parser::parseMixin() nextToken(); } - idents = new Identifiers(); while (1) { tiargs = NULL; @@ -2110,16 +2137,25 @@ Dsymbol *Parser::parseMixin() tiargs = parseTemplateArgument(); } - if (token.value != TOKdot) - break; - - if (tiargs) + if (tiargs && token.value == TOKdot) { TemplateInstance *tempinst = new TemplateInstance(loc, id); tempinst->tiargs = tiargs; - id = (Identifier *)tempinst; + if (!tqual) + tqual = new TypeInstance(loc, tempinst); + else + tqual->addInst(tempinst); tiargs = NULL; } - idents->push(id); + else + { + if (!tqual) + tqual = new TypeIdentifier(loc, id); + else + tqual->addIdent(id); + } + + if (token.value != TOKdot) + break; nextToken(); if (token.value != TOKidentifier) @@ -2129,7 +2165,6 @@ Dsymbol *Parser::parseMixin() id = token.ident; nextToken(); } - idents->push(id); if (token.value == TOKidentifier) { @@ -2139,7 +2174,7 @@ Dsymbol *Parser::parseMixin() else id = NULL; - tm = new TemplateMixin(loc, id, tqual, idents, tiargs); + tm = new TemplateMixin(loc, id, tqual, tiargs); if (token.value != TOKsemicolon) error("';' expected after mixin"); nextToken(); @@ -2240,6 +2275,9 @@ Objects *Parser::parseTemplateArgument() case TOKstring: case TOKfile: case TOKline: + case TOKmodulestring: + case TOKfuncstring: + case TOKprettyfunc: case TOKthis: { // Template argument is an expression Expression *ea = parsePrimaryExp(); @@ -2477,7 +2515,7 @@ Type *Parser::parseBasicType() else // ident!template_argument tempinst->tiargs = parseTemplateArgument(); - tid->addIdent((Identifier *)tempinst); + tid->addInst(tempinst); } else tid->addIdent(id); @@ -2972,7 +3010,6 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c case TOKnothrow: stc = STCnothrow; goto L1; case TOKpure: stc = STCpure; goto L1; case TOKref: stc = STCref; goto L1; - case TOKtls: stc = STCtls; goto L1; case TOKgshared: stc = STCgshared; goto L1; case TOKenum: stc = STCmanifest; goto L1; case TOKat: @@ -3016,7 +3053,7 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c check(TOKrparen); } else - structalign = global.structalign; // default + structalign = STRUCTALIGN_DEFAULT; // default continue; } default: @@ -3122,7 +3159,8 @@ L2: else if (t != tfirst) error("multiple declarations must have the same type, not %s and %s", tfirst->toChars(), t->toChars()); - if (!ident) + bool isThis = (t->ty == Tident && ((TypeIdentifier *)t)->ident == Id::This); + if (!isThis && !ident) error("no identifier for declarator %s", t->toChars()); if (tok == TOKtypedef || tok == TOKalias) @@ -3147,8 +3185,16 @@ L2: deprecation("use of typedef is deprecated; use alias instead"); } else - { if (init) - error("alias cannot have initializer"); + { + if (init) + { + if (isThis) + error("Cannot use syntax 'alias this = %s', use 'alias %s this' instead", + init->toChars(), init->toChars()); + else + error("alias cannot have initializer"); + } + v = new AliasDeclaration(loc, ident, t); } v->storage_class = storage_class; @@ -3192,7 +3238,7 @@ L2: //printf("%s funcdecl t = %s, storage_class = x%lx\n", loc.toChars(), t->toChars(), storage_class); FuncDeclaration *f = - new FuncDeclaration(loc, 0, ident, storage_class | (disable ? STCdisable : 0), t); + new FuncDeclaration(loc, Loc(), ident, storage_class | (disable ? STCdisable : 0), t); addComment(f, comment); if (tpl) constraint = parseConstraint(); @@ -3637,14 +3683,17 @@ Initializer *Parser::parseInitializer() /***************************************** * Parses default argument initializer expression that is an assign expression, - * with special handling for __FILE__ and __LINE__. + * with special handling for __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__. */ #if DMDV2 Expression *Parser::parseDefaultInitExp() { if (token.value == TOKfile || - token.value == TOKline) + token.value == TOKline || + token.value == TOKmodulestring || + token.value == TOKfuncstring || + token.value == TOKprettyfunc) { Token *t = peek(&token); if (t->value == TOKcomma || t->value == TOKrparen) @@ -3652,8 +3701,14 @@ Expression *Parser::parseDefaultInitExp() if (token.value == TOKfile) e = new FileInitExp(loc); - else + else if (token.value == TOKline) e = new LineInitExp(loc); + else if (token.value == TOKmodulestring) + e = new ModuleInitExp(loc); + else if (token.value == TOKfuncstring) + e = new FuncInitExp(loc); + else if (token.value == TOKprettyfunc) + e = new PrettyFuncInitExp(loc); nextToken(); return e; } @@ -3683,7 +3738,7 @@ void Parser::checkDanglingElse(Loc elseloc) * flags PSxxxx */ -Statement *Parser::parseStatement(int flags) +Statement *Parser::parseStatement(int flags, unsigned char** endPtr) { Statement *s; Condition *condition; Statement *ifbody; @@ -3764,6 +3819,9 @@ Statement *Parser::parseStatement(int flags) case TOKtraits: case TOKfile: case TOKline: + case TOKmodulestring: + case TOKfuncstring: + case TOKprettyfunc: #endif Lexp: { @@ -3829,7 +3887,6 @@ Statement *Parser::parseStatement(int flags) case TOKnothrow: case TOKpure: case TOKref: - case TOKtls: case TOKgshared: case TOKat: #endif @@ -3917,7 +3974,7 @@ Statement *Parser::parseStatement(int flags) case TOKlcurly: { Loc lookingForElseSave = lookingForElse; - lookingForElse = 0; + lookingForElse = Loc(); nextToken(); //if (token.value == TOKsemicolon) @@ -3927,6 +3984,7 @@ Statement *Parser::parseStatement(int flags) { statements->push(parseStatement(PSsemi | PScurlyscope)); } + if (endPtr) *endPtr = token.ptr; endloc = this->loc; s = new CompoundStatement(loc, statements); if (flags & (PSscope | PScurlyscope)) @@ -3967,7 +4025,7 @@ Statement *Parser::parseStatement(int flags) nextToken(); Loc lookingForElseSave = lookingForElse; - lookingForElse = 0; + lookingForElse = Loc(); body = parseStatement(PSscope); lookingForElse = lookingForElseSave; check(TOKwhile); @@ -3998,7 +4056,7 @@ Statement *Parser::parseStatement(int flags) else { Loc lookingForElseSave = lookingForElse; - lookingForElse = 0; + lookingForElse = Loc(); init = parseStatement(0); lookingForElse = lookingForElseSave; } @@ -4043,22 +4101,29 @@ Statement *Parser::parseStatement(int flags) Type *at; StorageClass storageClass = 0; + StorageClass stc = 0; Lagain: + if (stc) + { + if (storageClass & stc) + error("redundant storage class '%s'", Token::toChars(token.value)); + storageClass |= stc; + composeStorageClass(storageClass); + nextToken(); + } switch (token.value) { case TOKref: #if D1INOUT case TOKinout: #endif - storageClass |= STCref; - nextToken(); + stc = STCref; goto Lagain; case TOKconst: if (peekNext() != TOKlparen) { - storageClass |= STCconst; - nextToken(); + stc = STCconst; goto Lagain; } break; @@ -4066,26 +4131,23 @@ Statement *Parser::parseStatement(int flags) case TOKimmutable: if (peekNext() != TOKlparen) { - storageClass |= STCimmutable; + stc = STCimmutable; if (token.value == TOKinvariant) deprecation("use of 'invariant' rather than 'immutable' is deprecated"); - nextToken(); goto Lagain; } break; case TOKshared: if (peekNext() != TOKlparen) { - storageClass |= STCshared; - nextToken(); + stc = STCshared; goto Lagain; } break; case TOKwild: if (peekNext() != TOKlparen) { - storageClass |= STCwild; - nextToken(); + stc = STCwild; goto Lagain; } break; @@ -4145,49 +4207,86 @@ Statement *Parser::parseStatement(int flags) nextToken(); check(TOKlparen); - if (token.value == TOKauto) + StorageClass storageClass = 0; + StorageClass stc = 0; + LagainStc: + if (stc) { + if (storageClass & stc) + error("redundant storage class '%s'", Token::toChars(token.value)); + storageClass |= stc; + composeStorageClass(storageClass); nextToken(); - if (token.value == TOKidentifier) - { - Token *t = peek(&token); - if (t->value == TOKassign) + } + switch (token.value) + { + case TOKref: + stc = STCref; + goto LagainStc; + case TOKauto: + stc = STCauto; + goto LagainStc; + case TOKconst: + if (peekNext() != TOKlparen) { - arg = new Parameter(0, NULL, token.ident, NULL); - nextToken(); - nextToken(); + stc = STCconst; + goto LagainStc; } - else - { error("= expected following auto identifier"); - goto Lerror; + break; + case TOKinvariant: + case TOKimmutable: + if (peekNext() != TOKlparen) + { + stc = STCimmutable; + if (token.value == TOKinvariant) + deprecation("use of 'invariant' rather than 'immutable' is deprecated"); + goto LagainStc; } - } - else - { error("identifier expected following auto"); - goto Lerror; - } + break; + case TOKshared: + if (peekNext() != TOKlparen) + { + stc = STCshared; + goto LagainStc; + } + break; + case TOKwild: + if (peekNext() != TOKlparen) + { + stc = STCwild; + goto LagainStc; + } + break; + default: + break; + } + + if (storageClass != 0 && + token.value == TOKidentifier && + peek(&token)->value == TOKassign) + { + Identifier *ai = token.ident; + Type *at = NULL; // infer argument type + nextToken(); + check(TOKassign); + arg = new Parameter(storageClass, at, ai, NULL); + } + // Check for " ident;" + else if (storageClass == 0 && + token.value == TOKidentifier && + peek(&token)->value == TOKsemicolon) + { + arg = new Parameter(0, NULL, token.ident, NULL); + nextToken(); + nextToken(); + error("if (v; e) is deprecated, use if (auto v = e)"); } else if (isDeclaration(&token, 2, TOKassign, NULL)) { - Type *at; Identifier *ai; - - at = parseType(&ai); + Type *at = parseType(&ai); check(TOKassign); - arg = new Parameter(0, at, ai, NULL); - } - - // Check for " ident;" - else if (token.value == TOKidentifier) - { - Token *t = peek(&token); - if (t->value == TOKsemicolon) - { - arg = new Parameter(0, NULL, token.ident, NULL); - nextToken(); - nextToken(); - error("if (v; e) is deprecated, use if (auto v = e)"); - } + arg = new Parameter(storageClass, at, ai, NULL); } condition = parseExpression(); @@ -4520,7 +4619,7 @@ Statement *Parser::parseStatement(int flags) nextToken(); Loc lookingForElseSave = lookingForElse; - lookingForElse = 0; + lookingForElse = Loc(); body = parseStatement(PSscope); lookingForElse = lookingForElseSave; while (token.value == TOKcatch) @@ -4584,7 +4683,7 @@ Statement *Parser::parseStatement(int flags) #if DMDV2 deprecation("volatile statements deprecated; use synchronized statements instead"); #endif - s = new VolatileStatement(loc, s); + s = new SynchronizedStatement(loc, (Expression *)NULL, s); break; case TOKasm: @@ -4691,8 +4790,10 @@ Statement *Parser::parseStatement(int flags) } case TOKtemplate: - error("template definitions aren't allowed inside functions"); - goto Lerror; + { Dsymbol *d = parseTemplateDeclaration(0); + s = new ExpStatement(loc, d); + break; + } default: error("found '%s' instead of statement", token.toChars()); @@ -4752,6 +4853,7 @@ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) { //printf("isDeclaration(needId = %d)\n", needId); int haveId = 0; + int haveTpl = 0; #if DMDV2 while (1) @@ -4778,7 +4880,7 @@ int Parser::isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt) { goto Lisnot; } - if (!isDeclarator(&t, &haveId, endtok)) + if (!isDeclarator(&t, &haveId, &haveTpl, endtok)) goto Lisnot; if ( needId == 1 || (needId == 0 && !haveId) || @@ -4866,6 +4968,9 @@ int Parser::isBasicType(Token **pt) case TOKstring: case TOKfile: case TOKline: + case TOKmodulestring: + case TOKfuncstring: + case TOKprettyfunc: goto L2; default: goto Lfalse; @@ -4919,7 +5024,7 @@ Lfalse: return FALSE; } -int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) +int Parser::isDeclarator(Token **pt, int *haveId, int *haveTpl, enum TOK endtok) { // This code parallels parseDeclarator() Token *t = *pt; int parens; @@ -4992,7 +5097,7 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) } - if (!isDeclarator(&t, haveId, TOKrparen)) + if (!isDeclarator(&t, haveId, NULL, TOKrparen)) return FALSE; t = peek(t); parens = TRUE; @@ -5040,6 +5145,13 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) case TOKlparen: parens = FALSE; + if (Token *tk = peekPastParen(t)) + { if (tk->value == TOKlparen) + { if (!haveTpl) return FALSE; + *haveTpl = 1; + t = tk; + } + } if (!isParameters(&t)) return FALSE; #if DMDV2 @@ -5085,6 +5197,8 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok) return TRUE; } return FALSE; + case TOKif: + return haveTpl ? TRUE : FALSE; default: return FALSE; @@ -5163,7 +5277,7 @@ int Parser::isParameters(Token **pt) L2: int tmp = FALSE; if (t->value != TOKdotdotdot && - !isDeclarator(&t, &tmp, TOKreserved)) + !isDeclarator(&t, &tmp, NULL, TOKreserved)) return FALSE; if (t->value == TOKassign) { t = peek(t); @@ -5342,7 +5456,6 @@ int Parser::skipAttributes(Token *t, Token **pt) case TOKnothrow: case TOKpure: case TOKref: - case TOKtls: case TOKgshared: //case TOKmanifest: break; @@ -5543,6 +5656,23 @@ Expression *Parser::parsePrimaryExp() e = new IntegerExp(loc, loc.linnum, Type::tint32); nextToken(); break; + + case TOKmodulestring: + { const char *s = md->toChars(); + e = new StringExp(loc, (char *)s, strlen(s), 0); + nextToken(); + break; + } + + case TOKfuncstring: + e = new FuncInitExp(loc); + nextToken(); + break; + + case TOKprettyfunc: + e = new PrettyFuncInitExp(loc); + nextToken(); + break; #endif case TOKtrue: @@ -5719,7 +5849,7 @@ Expression *Parser::parsePrimaryExp() tspec = parseType(); } } - if (ident && tspec) + if (tspec) { if (token.value == TOKcomma) tpl = parseTemplateParameterList(1); @@ -5727,8 +5857,6 @@ Expression *Parser::parsePrimaryExp() { tpl = new TemplateParameters(); check(TOKrparen); } - TemplateParameter *tp = new TemplateTypeParameter(loc, ident, NULL, NULL); - tpl->insert(0, tp); } else check(TOKrparen); @@ -5908,7 +6036,7 @@ Expression *Parser::parsePrimaryExp() if (!parameters) parameters = new Parameters(); TypeFunction *tf = new TypeFunction(parameters, tret, varargs, linkage, stc); - FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL); + FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, save, NULL); if (token.value == TOKgoesto) { @@ -6190,13 +6318,25 @@ Expression *Parser::parseUnaryExp() case TOKshared: case TOKconst: case TOKinvariant: - case TOKimmutable: // immutable(type)(arguments) + case TOKimmutable: // immutable(type)(arguments) / immutable(type).init { StorageClass stc = parseTypeCtor(); Type *t = parseBasicType(); t = t->addSTC(stc); e = new TypeExp(loc, t); - if (token.value != TOKlparen) + if (stc == 0 && token.value == TOKdot) + { + nextToken(); + if (token.value != TOKidentifier) + { error("Identifier expected following (type)."); + return NULL; + } + e = typeDotIdExp(loc, t, token.ident); + nextToken(); + e = parsePostExp(e); + break; + } + else if (token.value != TOKlparen) { error("(arguments) expected following %s", t->toChars()); return e; @@ -6261,6 +6401,9 @@ Expression *Parser::parseUnaryExp() #if DMDV2 case TOKfile: case TOKline: + case TOKmodulestring: + case TOKfuncstring: + case TOKprettyfunc: #endif case BASIC_TYPES: // (type)int.size { // (type) una_exp @@ -6271,15 +6414,14 @@ Expression *Parser::parseUnaryExp() check(TOKrparen); // if .identifier + // or .identifier!( ... ) if (token.value == TOKdot) { - nextToken(); - if (token.value != TOKidentifier) + if (peekNext() != TOKidentifier) { error("Identifier expected following (type)."); return NULL; } - e = typeDotIdExp(loc, t, token.ident); - nextToken(); + e = new TypeExp(loc, t); e = parsePostExp(e); } else @@ -6290,6 +6432,8 @@ Expression *Parser::parseUnaryExp() } return e; } + default: + break; } } #endif @@ -6883,6 +7027,9 @@ void initPrecedence() #if DMDV2 precedence[TOKfile] = PREC_primary; precedence[TOKline] = PREC_primary; + precedence[TOKmodulestring] = PREC_primary; + precedence[TOKfuncstring] = PREC_primary; + precedence[TOKprettyfunc] = PREC_primary; #endif precedence[TOKtypeid] = PREC_primary; precedence[TOKis] = PREC_primary; diff --git a/dmd2/parse.h b/dmd2/parse.h index 7cce6c0887..946b9570ca 100644 --- a/dmd2/parse.h +++ b/dmd2/parse.h @@ -71,9 +71,9 @@ struct Parser : Lexer Parser(Module *module, unsigned char *base, size_t length, int doDocComment); Dsymbols *parseModule(); - Dsymbols *parseDeclDefs(int once); + Dsymbols *parseDeclDefs(int once, Dsymbol **pLastDecl = NULL); Dsymbols *parseAutoDeclarations(StorageClass storageClass, unsigned char *comment); - Dsymbols *parseBlock(); + Dsymbols *parseBlock(Dsymbol **pLastDecl); void composeStorageClass(StorageClass stc); StorageClass parseAttribute(Expressions **pexps); StorageClass parsePostfix(); @@ -114,7 +114,8 @@ struct Parser : Lexer Dsymbols *parseDeclarations(StorageClass storage_class, unsigned char *comment); void parseContracts(FuncDeclaration *f); void checkDanglingElse(Loc elseloc); - Statement *parseStatement(int flags); + /** endPtr used for documented unittests */ + Statement *parseStatement(int flags, unsigned char** endPtr = NULL); Initializer *parseInitializer(); Expression *parseDefaultInitExp(); void check(Loc loc, enum TOK value); @@ -123,7 +124,7 @@ struct Parser : Lexer void checkParens(enum TOK value, Expression *e); int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt); int isBasicType(Token **pt); - int isDeclarator(Token **pt, int *haveId, enum TOK endtok); + int isDeclarator(Token **pt, int *haveId, int *haveTpl, enum TOK endtok); int isParameters(Token **pt); int isExpression(Token **pt); int skipParens(Token *t, Token **pt); diff --git a/dmd2/readme.txt b/dmd2/readme.txt index 0d72c9be6e..2b79949ddb 100644 --- a/dmd2/readme.txt +++ b/dmd2/readme.txt @@ -1,15 +1,15 @@ The D Programming Language Compiler Front End Source - Copyright (c) 1999-2009, by Digital Mars - http://www.digitalmars.com + Copyright (c) 1999-2013, by Digital Mars + http://www.digitalmars.com/ All Rights Reserved This is the source code to the front end Digital Mars D compiler. It covers the lexical analysis, parsing, and semantic analysis of the D Programming Language defined in the documents at -http://www.digitalmars.com/d/ +http://dlang.org/ These sources are free, they are redistributable and modifiable under the terms of the GNU General Public License as published by diff --git a/dmd2/root/longdouble.c b/dmd2/root/longdouble.c index 8852a83574..6244c6cbb7 100644 --- a/dmd2/root/longdouble.c +++ b/dmd2/root/longdouble.c @@ -51,14 +51,15 @@ bool initFPU() int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR, _MCW_EM | _MCW_PC | _MCW_RC); #endif + _set_output_format(_TWO_DIGIT_EXPONENT); return true; } static bool doInitFPU = initFPU(); -#ifndef _WIN64 extern "C" { +#ifndef _WIN64 double ld_read(const longdouble* pthis) { double res; @@ -70,6 +71,8 @@ double ld_read(const longdouble* pthis) } return res; } +#endif // !_WIN64 + long long ld_readll(const longdouble* pthis) { #if 1 @@ -126,6 +129,7 @@ unsigned long long ld_readull(const longdouble* pthis) #endif } +#ifndef _WIN64 void ld_set(longdouble* pthis, double d) { __asm @@ -157,9 +161,9 @@ void ld_setull(longdouble* pthis, unsigned long long d) fstp tbyte ptr [eax] } } +#endif // !_WIN64 } // extern "C" -#endif // !_WIN64 longdouble ldexpl(longdouble ld, int exp) { @@ -519,6 +523,13 @@ size_t ld_sprint(char* str, int fmt, longdouble x) // fmt is 'a','A','f' or 'g' if(fmt != 'a' && fmt != 'A') { + if (ldouble((unsigned long long)x) == x) + { // ((1.5 -> 1 -> 1.0) == 1.5) is false + // ((1.0 -> 1 -> 1.0) == 1.0) is true + // see http://en.cppreference.com/w/cpp/io/c/fprintf + char format[] = {'%', '#', 'L', fmt, 0}; + return sprintf(str, format, ld_read(&x)); + } char format[] = { '%', fmt, 0 }; return sprintf(str, format, ld_read(&x)); } @@ -580,6 +591,12 @@ static bool unittest() ld_sprint(buffer, 'a', ld_pi); assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0); + ld_sprint(buffer, 'g', ldouble(2.0)); + assert(strcmp(buffer, "2.00000") == 0); + + ld_sprint(buffer, 'g', ldouble(1234567.89)); + assert(strcmp(buffer, "1.23457e+06") == 0); + longdouble ldb = ldouble(0.4); long long b = ldb; assert(b == 0); diff --git a/dmd2/root/longdouble.h b/dmd2/root/longdouble.h index 0e8e449868..8add278749 100644 --- a/dmd2/root/longdouble.h +++ b/dmd2/root/longdouble.h @@ -42,9 +42,20 @@ typedef volatile long double volatile_longdouble; inline size_t ld_sprint(char* str, int fmt, longdouble x) { - char sfmt[4] = "%Lg"; - sfmt[2] = fmt; - return sprintf(str, sfmt, x); + if (((longdouble)(unsigned long long)x) == x) + { // ((1.5 -> 1 -> 1.0) == 1.5) is false + // ((1.0 -> 1 -> 1.0) == 1.0) is true + // see http://en.cppreference.com/w/cpp/io/c/fprintf + char sfmt[5] = "%#Lg"; + sfmt[3] = fmt; + return sprintf(str, sfmt, x); + } + else + { + char sfmt[4] = "%Lg"; + sfmt[2] = fmt; + return sprintf(str, sfmt, x); + } } #if __MINGW32__ diff --git a/dmd2/root/root.c b/dmd2/root/root.c index 8a16e83fe9..900a3e6553 100644 --- a/dmd2/root/root.c +++ b/dmd2/root/root.c @@ -987,6 +987,8 @@ void File::mark() int File::read() { + if (len) + return 0; // already read the file #if POSIX off_t size; ssize_t numread; @@ -1064,7 +1066,7 @@ err1: name = this->name->toChars(); h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0); + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (h == INVALID_HANDLE_VALUE) goto err1; @@ -1642,6 +1644,15 @@ void OutBuffer::prependbyte(unsigned b) offset++; } +void OutBuffer::writewchar(unsigned w) +{ +#if _WIN32 + writeword(w); +#else + write4(w); +#endif +} + void OutBuffer::writeword(unsigned w) { if (doindent && linehead @@ -1740,36 +1751,6 @@ void OutBuffer::align(size_t size) fill0(nbytes); } - -//////////////////////////////////////////////////////////////// -// The compiler shipped with Visual Studio 2005 (and possible -// other versions) does not support C99 printf format specfiers -// such as %z and %j -#if 0 && _MSC_VER -using std::string; -using std::wstring; - -template -inline void -search_and_replace(S& str, const S& what, const S& replacement) -{ - assert(!what.empty()); - size_t pos = str.find(what); - while (pos != S::npos) - { - str.replace(pos, what.size(), replacement); - pos = str.find(what, pos + replacement.size()); - } -} -#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ - S tmp = f; \ - search_and_replace(fmt, S("%z"), S("%l")); \ - search_and_replace(fmt, S("%j"), S("%l")); \ - f = tmp.c_str(); -#else -#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) -#endif - void OutBuffer::vprintf(const char *format, va_list args) { char buffer[128]; @@ -1777,8 +1758,6 @@ void OutBuffer::vprintf(const char *format, va_list args) unsigned psize; int count; - WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format); - p = buffer; psize = sizeof(buffer); for (;;) diff --git a/dmd2/root/root.h b/dmd2/root/root.h index 6cb36d69a6..5935d4b5ca 100644 --- a/dmd2/root/root.h +++ b/dmd2/root/root.h @@ -258,6 +258,7 @@ struct OutBuffer : Object void writebyte(unsigned b) { writeByte(b); } void writeUTF8(unsigned b); void prependbyte(unsigned b); + void writewchar(unsigned w); void writeword(unsigned w); void writeUTF16(unsigned w); void write4(unsigned w); diff --git a/dmd2/root/stringtable.c b/dmd2/root/stringtable.c index f1ea45d363..dcde89f474 100644 --- a/dmd2/root/stringtable.c +++ b/dmd2/root/stringtable.c @@ -99,7 +99,7 @@ void StringValue::ctor(const char *p, size_t length) memcpy(this->lstring, p, length * sizeof(char)); } -void StringTable::init(size_t size) +void StringTable::_init(size_t size) { table = (void **)mem.calloc(size, sizeof(void *)); tabledim = size; diff --git a/dmd2/root/stringtable.h b/dmd2/root/stringtable.h index e4b13b3ac4..1645734cbd 100644 --- a/dmd2/root/stringtable.h +++ b/dmd2/root/stringtable.h @@ -24,11 +24,7 @@ struct StringEntry; // method because the only thing which should be creating these is StringTable. struct StringValue { - union - { - void *ptrvalue; - char *string; - }; + void *ptrvalue; private: size_t length; @@ -59,7 +55,7 @@ private: size_t tabledim; public: - void init(size_t size = 37); + void _init(size_t size = 37); ~StringTable(); StringValue *lookup(const char *s, size_t len); diff --git a/dmd2/sapply.c b/dmd2/sapply.c new file mode 100644 index 0000000000..4add707160 --- /dev/null +++ b/dmd2/sapply.c @@ -0,0 +1,210 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2013 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 "statement.h" + + +/************************************** + * A Statement tree walker that will visit each Statement s in the tree, + * in depth-first evaluation order, and call fp(s,param) on it. + * fp() signals whether the walking continues with its return value: + * Returns: + * 0 continue + * 1 done + * It's a bit slower than using virtual functions, but more encapsulated and less brittle. + * Creating an iterator for this would be much more complex. + */ + +typedef bool (*sapply_fp_t)(Statement *, void *); + +bool Statement::apply(sapply_fp_t fp, void *param) +{ + return (*fp)(this, param); +} + +/****************************** + * Perform apply() on an t if not null + */ +#define scondApply(t, fp, param) (t ? t->apply(fp, param) : 0) + + + +bool PeelStatement::apply(sapply_fp_t fp, void *param) +{ + return s->apply(fp, param) || + (*fp)(this, param); +} + +bool CompoundStatement::apply(sapply_fp_t fp, void *param) +{ + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; + + bool r = scondApply(s, fp, param); + if (r) + return r; + } + return (*fp)(this, param); +} + +bool UnrolledLoopStatement::apply(sapply_fp_t fp, void *param) +{ + for (size_t i = 0; i < statements->dim; i++) + { Statement *s = (*statements)[i]; + + bool r = scondApply(s, fp, param); + if (r) + return r; + } + return (*fp)(this, param); +} + +bool ScopeStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + +bool WhileStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool DoStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool ForStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(init, fp, param) || + scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool ForeachStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +#if DMDV2 +bool ForeachRangeStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} +#endif + +bool IfStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(ifbody, fp, param) || + scondApply(elsebody, fp, param) || + (*fp)(this, param); +} + +bool ConditionalStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(ifbody, fp, param) || + scondApply(elsebody, fp, param) || + (*fp)(this, param); +} + +bool PragmaStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool SwitchStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool CaseStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + +#if DMDV2 +bool CaseRangeStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} +#endif + +bool DefaultStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + +bool SynchronizedStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool WithStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + (*fp)(this, param); +} + +bool TryCatchStatement::apply(sapply_fp_t fp, void *param) +{ + bool r = scondApply(body, fp, param); + if (r) + return r; + + for (size_t i = 0; i < catches->dim; i++) + { Catch *c = (*catches)[i]; + + bool r = scondApply(c->handler, fp, param); + if (r) + return r; + } + return (*fp)(this, param); +} + +bool TryFinallyStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(body, fp, param) || + scondApply(finalbody, fp, param) || + (*fp)(this, param); +} + +bool OnScopeStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + +bool DebugStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + +bool LabelStatement::apply(sapply_fp_t fp, void *param) +{ + return scondApply(statement, fp, param) || + (*fp)(this, param); +} + diff --git a/dmd2/scope.c b/dmd2/scope.c index 09da8d9c5a..2bcc085ad7 100644 --- a/dmd2/scope.c +++ b/dmd2/scope.c @@ -61,7 +61,8 @@ Scope::Scope() this->sbreak = NULL; this->scontinue = NULL; this->fes = NULL; - this->structalign = global.structalign; + this->callsc = NULL; + this->structalign = STRUCTALIGN_DEFAULT; this->func = NULL; this->slabel = NULL; this->linkage = LINKd; @@ -74,7 +75,7 @@ Scope::Scope() this->nofree = 0; this->noctor = 0; this->noaccesscheck = 0; - this->mustsemantic = 0; + this->needctfe = 0; this->intypeof = 0; this->speculative = 0; this->parameterSpecialization = 0; @@ -103,6 +104,7 @@ Scope::Scope(Scope *enclosing) this->sbreak = enclosing->sbreak; this->scontinue = enclosing->scontinue; this->fes = enclosing->fes; + this->callsc = enclosing->callsc; this->structalign = enclosing->structalign; this->enclosing = enclosing; #ifdef DEBUG @@ -125,7 +127,7 @@ Scope::Scope(Scope *enclosing) this->nofree = 0; this->noctor = enclosing->noctor; this->noaccesscheck = enclosing->noaccesscheck; - this->mustsemantic = enclosing->mustsemantic; + this->needctfe = enclosing->needctfe; this->intypeof = enclosing->intypeof; this->speculative = enclosing->speculative; this->parameterSpecialization = enclosing->parameterSpecialization; @@ -415,7 +417,7 @@ void *scope_search_fp(void *arg, const char *seed) Scope *sc = (Scope *)arg; Module::clearCache(); - Dsymbol *s = sc->search(0, id, NULL); + Dsymbol *s = sc->search(Loc(), id, NULL); return s; } diff --git a/dmd2/scope.h b/dmd2/scope.h index a3b7725bd3..de5f63f0bc 100644 --- a/dmd2/scope.h +++ b/dmd2/scope.h @@ -43,6 +43,25 @@ enum LINK; enum PROT; #endif +#define CSXthis_ctor 1 // called this() +#define CSXsuper_ctor 2 // called super() +#define CSXthis 4 // referenced this +#define CSXsuper 8 // referenced super +#define CSXlabel 0x10 // seen a label +#define CSXreturn 0x20 // seen a return statement +#define CSXany_ctor 0x40 // either this() or super() was called + +#define SCOPEctor 1 // constructor type +#define SCOPEstaticif 2 // inside static if +#define SCOPEfree 4 // is on free list +#define SCOPEstaticassert 8 // inside static assert +#define SCOPEdebug 0x10 // inside debug conditional + +#define SCOPEinvariant 0x20 // inside invariant code +#define SCOPErequire 0x40 // inside in contract code +#define SCOPEensure 0x60 // inside out contract code +#define SCOPEcontract 0x60 // [mask] we're inside contract code + struct Scope { Scope *enclosing; // enclosing Scope @@ -61,6 +80,7 @@ struct Scope Statement *sbreak; // enclosing statement that supports "break" Statement *scontinue; // enclosing statement that supports "continue" ForeachStatement *fes; // if nested function for ForeachStatement, this is it + Scope *callsc; // used for __FUNCTION__, __PRETTY_FUNCTION__ and __MODULE__ unsigned offset; // next offset to use in aggregate // This really shouldn't be a part of Scope, because it requires // semantic() to be done in the lexical field order. It should be @@ -73,17 +93,13 @@ struct Scope bool speculative; // in __traits(compiles) or typeof(exp) int parameterSpecialization; // if in template parameter specialization int noaccesscheck; // don't do access checks - int mustsemantic; // cannot defer semantic() + int needctfe; // inside a ctfe-only expression + +#if IN_LLVM int ignoreTemplates; // set if newly instantiated templates should be ignored when codegen'ing +#endif unsigned callSuper; // primitive flow analysis for constructors -#define CSXthis_ctor 1 // called this() -#define CSXsuper_ctor 2 // called super() -#define CSXthis 4 // referenced this -#define CSXsuper 8 // referenced super -#define CSXlabel 0x10 // seen a label -#define CSXreturn 0x20 // seen a return statement -#define CSXany_ctor 0x40 // either this() or super() was called structalign_t structalign; // alignment for struct members enum LINK linkage; // linkage for external functions @@ -95,20 +111,7 @@ struct Scope char *depmsg; // customized deprecation message unsigned flags; -#define SCOPEctor 1 // constructor type -#define SCOPEstaticif 2 // inside static if -#define SCOPEfree 4 // is on free list -#define SCOPEstaticassert 8 // inside static assert -#define SCOPEdebug 0x10 // inside debug conditional -#define SCOPEinvariant 0x20 // inside invariant code -#define SCOPErequire 0x40 // inside in contract code -#define SCOPEensure 0x60 // inside out contract code -#define SCOPEcontract 0x60 // [mask] we're inside contract code - -#ifdef IN_GCC - Expressions *attributes; // GCC decl/type attributes -#endif Expressions *userAttributes; // user defined attributes DocComment *lastdc; // documentation comment for last symbol at this scope @@ -120,7 +123,6 @@ struct Scope static Scope *createGlobal(Module *module); Scope(); - Scope(Module *module); Scope(Scope *enclosing); Scope *push(); diff --git a/dmd2/statement.c b/dmd2/statement.c index 96034062cd..9d9c5454e0 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -13,6 +13,7 @@ #include #include "rmem.h" +#include "target.h" #include "statement.h" #include "expression.h" @@ -100,8 +101,8 @@ Statement *Statement::syntaxCopy() void Statement::print() { - fprintf(stdmsg, "%s\n", toChars()); - fflush(stdmsg); + fprintf(stderr, "%s\n", toChars()); + fflush(stderr); } char *Statement::toChars() @@ -185,13 +186,78 @@ bool Statement::hasContinue() return FALSE; } +/* ============================================== */ // TRUE if statement uses exception handling bool Statement::usesEH() { - return FALSE; + struct UsesEH + { + static bool lambdaUsesEH(Statement *s, void *param) + { + return s->usesEHimpl(); + } + }; + + UsesEH ueh; + return apply(&UsesEH::lambdaUsesEH, &ueh); } +bool Statement::usesEHimpl() { return false; } +bool TryCatchStatement::usesEHimpl() { return true; } +bool TryFinallyStatement::usesEHimpl() { return true; } +bool OnScopeStatement::usesEHimpl() { return true; } +bool SynchronizedStatement::usesEHimpl() { return true; } + +/* ============================================== */ +// TRUE if statement 'comes from' somewhere else, like a goto + +bool Statement::comeFrom() +{ + struct ComeFrom + { + static bool lambdaComeFrom(Statement *s, void *param) + { + return s->comeFromImpl(); + } + }; + + ComeFrom cf; + return apply(&ComeFrom::lambdaComeFrom, &cf); +} + +bool Statement::comeFromImpl() { return false; } +bool CaseStatement::comeFromImpl() { return true; } +bool DefaultStatement::comeFromImpl() { return true; } +bool LabelStatement::comeFromImpl() { return true; } +bool AsmStatement::comeFromImpl() { return true; } + +/* ============================================== */ +// Return true if statement has executable code. + +bool Statement::hasCode() +{ + struct HasCode + { + static bool lambdaHasCode(Statement *s, void *param) + { + return s->hasCodeImpl(); + } + }; + + HasCode hc; + return apply(&HasCode::lambdaHasCode, &hc); +} + +bool Statement::hasCodeImpl() { return true; } +bool ExpStatement::hasCodeImpl() { return exp != NULL; } +bool CompoundStatement::hasCodeImpl() { return false; } +bool ScopeStatement::hasCodeImpl() { return false; } +bool ImportStatement::hasCodeImpl() { return false; } + + +/* ============================================== */ + /* Only valid after semantic analysis * If 'mustNotThrow' is true, generate an error if it throws */ @@ -203,21 +269,6 @@ int Statement::blockExit(bool mustNotThrow) return BEany; } -// TRUE if statement 'comes from' somewhere else, like a goto - -int Statement::comeFrom() -{ - //printf("Statement::comeFrom()\n"); - return FALSE; -} - -// Return TRUE if statement has no code in it -int Statement::isEmpty() -{ - //printf("Statement::isEmpty()\n"); - return FALSE; -} - Statement *Statement::last() { return this; @@ -359,11 +410,6 @@ int ExpStatement::blockExit(bool mustNotThrow) return result; } -int ExpStatement::isEmpty() -{ - return exp == NULL; -} - Statement *ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("ExpStatement::scopeCode()\n"); @@ -456,7 +502,7 @@ void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) Statements *CompileStatement::flatten(Scope *sc) { //printf("CompileStatement::flatten() %s\n", exp->toChars()); - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); exp = resolveProperties(sc, exp); exp = exp->ctfeInterpret(); if (exp->op == TOKerror) @@ -600,26 +646,26 @@ Statement *CompoundStatement::semantic(Scope *sc) { a->push((*statements)[j]); } - Statement *body = new CompoundStatement(0, a); - body = new ScopeStatement(0, body); + Statement *body = new CompoundStatement(Loc(), a); + body = new ScopeStatement(Loc(), body); Identifier *id = Lexer::uniqueId("__o"); Statement *handler = sexception; if (sexception->blockExit(FALSE) & BEfallthru) - { handler = new ThrowStatement(0, new IdentifierExp(0, id)); + { handler = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id)); ((ThrowStatement *)handler)->internalThrow = true; - handler = new CompoundStatement(0, sexception, handler); + handler = new CompoundStatement(Loc(), sexception, handler); } Catches *catches = new Catches(); - Catch *ctch = new Catch(0, NULL, id, handler); + Catch *ctch = new Catch(Loc(), NULL, id, handler); ctch->internalCatch = true; catches->push(ctch); - s = new TryCatchStatement(0, body, catches); + s = new TryCatchStatement(Loc(), body, catches); if (sfinally) - s = new TryFinallyStatement(0, s, sfinally); + s = new TryFinallyStatement(Loc(), s, sfinally); s = s->semantic(sc); statements->setDim(i + 1); statements->push(s); @@ -644,8 +690,8 @@ Statement *CompoundStatement::semantic(Scope *sc) { a->push((*statements)[j]); } - Statement *body = new CompoundStatement(0, a); - s = new TryFinallyStatement(0, body, sfinally); + Statement *body = new CompoundStatement(Loc(), a); + s = new TryFinallyStatement(Loc(), body, sfinally); s = s->semantic(sc); statements->setDim(i + 1); statements->push(s); @@ -709,16 +755,6 @@ void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } } -bool CompoundStatement::usesEH() -{ - 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) { //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); @@ -729,7 +765,7 @@ int CompoundStatement::blockExit(bool mustNotThrow) if (s) { //printf("result = x%x\n", result); - //printf("%s\n", s->toChars()); + //printf("s: %s\n", s->toChars()); if (global.params.warnings && result & BEfallthru && slast) { slast = slast->last(); @@ -739,9 +775,9 @@ int CompoundStatement::blockExit(bool mustNotThrow) // Allow if last case/default was empty CaseStatement *sc = slast->isCaseStatement(); DefaultStatement *sd = slast->isDefaultStatement(); - if (sc && sc->statement->isEmpty()) + if (sc && (!sc->statement->hasCode() || sc->statement->isCaseStatement())) ; - else if (sd && sd->statement->isEmpty()) + else if (sd && (!sd->statement->hasCode() || sd->statement->isCaseStatement())) ; else s->error("switch case fallthrough - use 'goto %s;' if intended", @@ -751,7 +787,7 @@ int CompoundStatement::blockExit(bool mustNotThrow) if (!(result & BEfallthru) && !s->comeFrom()) { - if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty()) + if (s->blockExit(mustNotThrow) != BEhalt && s->hasCode()) s->warning("statement is not reachable"); } else @@ -765,31 +801,6 @@ int CompoundStatement::blockExit(bool mustNotThrow) return result; } -int CompoundStatement::comeFrom() -{ int comefrom = FALSE; - - //printf("CompoundStatement::comeFrom()\n"); - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - - if (!s) - continue; - - comefrom |= s->comeFrom(); - } - return comefrom; -} - -int CompoundStatement::isEmpty() -{ - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - if (s && !s->isEmpty()) - return FALSE; - } - return TRUE; -} - /******************************** CompoundDeclarationStatement ***************************/ @@ -835,7 +846,7 @@ void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) */ if (anywritten) { - buf->writeByte(','); + buf->writestring(", "); buf->writestring(v->ident->toChars()); } else @@ -946,16 +957,6 @@ bool UnrolledLoopStatement::hasContinue() return TRUE; } -bool UnrolledLoopStatement::usesEH() -{ - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - if (s && s->usesEH()) - return TRUE; - } - return FALSE; -} - int UnrolledLoopStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; @@ -971,22 +972,6 @@ int UnrolledLoopStatement::blockExit(bool mustNotThrow) } -int UnrolledLoopStatement::comeFrom() -{ int comefrom = FALSE; - - //printf("UnrolledLoopStatement::comeFrom()\n"); - for (size_t i = 0; i < statements->dim; i++) - { Statement *s = (*statements)[i]; - - if (!s) - continue; - - comefrom |= s->comeFrom(); - } - return comefrom; -} - - /******************************** ScopeStatement ***************************/ ScopeStatement::ScopeStatement(Loc loc, Statement *s) @@ -1056,11 +1041,6 @@ bool ScopeStatement::hasContinue() return statement ? statement->hasContinue() : FALSE; } -bool ScopeStatement::usesEH() -{ - return statement ? statement->usesEH() : FALSE; -} - int ScopeStatement::blockExit(bool mustNotThrow) { //printf("ScopeStatement::blockExit(%p)\n", statement); @@ -1068,18 +1048,6 @@ int ScopeStatement::blockExit(bool mustNotThrow) } -int ScopeStatement::comeFrom() -{ - //printf("ScopeStatement::comeFrom()\n"); - return statement ? statement->comeFrom() : FALSE; -} - -int ScopeStatement::isEmpty() -{ - //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE); - return statement ? statement->isEmpty() : TRUE; -} - void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('{'); @@ -1130,12 +1098,6 @@ bool WhileStatement::hasContinue() return TRUE; } -bool WhileStatement::usesEH() -{ - assert(global.errors); - return 0; -} - int WhileStatement::blockExit(bool mustNotThrow) { assert(global.errors); @@ -1143,12 +1105,6 @@ int WhileStatement::blockExit(bool mustNotThrow) } -int WhileStatement::comeFrom() -{ - assert(global.errors); - return FALSE; -} - void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("while ("); @@ -1200,11 +1156,6 @@ bool DoStatement::hasContinue() return TRUE; } -bool DoStatement::usesEH() -{ - return body ? body->usesEH() : 0; -} - int DoStatement::blockExit(bool mustNotThrow) { int result; @@ -1229,13 +1180,6 @@ int DoStatement::blockExit(bool mustNotThrow) } -int DoStatement::comeFrom() -{ - if (body) - return body->comeFrom(); - return FALSE; -} - void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("do"); @@ -1289,131 +1233,98 @@ Statement *ForStatement::syntaxCopy() * } * finally { x.~this(); } */ -Statement *ForStatement::semanticInit(Scope *sc) +Statement *ForStatement::semanticInit(Scope *sc, Statements *ainit, size_t i) { - assert(init); - ++nest; - - Loc locinit = init->loc; - Statements *ainit = init->flatten(sc); - if (!ainit) - (ainit = new Statements())->push(init); - init = NULL; - Statement *statement = this; + if (i < ainit->dim) + { + Statement *s = (*ainit)[i]; + (*ainit)[i] = s = s->semantic(sc); + if (!s) + return semanticInit(sc, ainit, i + 1); - for (size_t i = 0; i < ainit->dim; i++) - { Statement *s = (*ainit)[i]; - s = s->semantic(sc); - (*ainit)[i] = s; - if (s) - { - Statement *sentry; - Statement *sexception; - Statement *sfinally; - - (*ainit)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally); + Statement *sentry; + Statement *sexception; + Statement *sfinally; + (*ainit)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally); + /* Rewrite to: + * ainit = + * [ ..., sentry, ainit[i], ... ] + * statement = + * try { // sfinally != NULL + * try { // sexception != NULL + * statement; + * } catch (__o) { // sexception != NULL + * sexception; // sexception != NULL + * throw __o; // sexception != NULL (internalThrow = true) + * } // sexception != NULL + * } finally { sfinally; } // sfinally != NULL + */ + if (sentry) + { sentry = sentry->semantic(sc); if (sentry) - { sentry = sentry->semantic(sc); - if (sentry) - ainit->insert(i++, sentry); - } - if (sexception) - sexception = sexception->semantic(sc); - if (sexception) - { // Re-initialize this->init - if (i + 1 < ainit->dim) - { - Statements *a = new Statements(); - for (size_t j = i + 1; j < ainit->dim; j++) - a->push((*ainit)[j]); - init = new CompoundStatement(0, a); - } - - Identifier *id = Lexer::uniqueId("__o"); - Statement *handler = sexception; - if (sexception->blockExit(FALSE) & BEfallthru) - { handler = new ThrowStatement(0, new IdentifierExp(0, id)); - ((ThrowStatement *)handler)->internalThrow = true; - handler = new CompoundStatement(0, sexception, handler); - } - Catches *catches = new Catches(); - Catch *ctch = new Catch(0, NULL, id, handler); - catches->push(ctch); - s = new TryCatchStatement(0, this, catches); - - if (sfinally) - s = new TryFinallyStatement(0, s, sfinally); - //printf("ex {{{\n"); - s = s->semantic(sc); - //printf("}}}\n"); - this->relatedLabeled = s; - statement = s; - - if (init) - { Statements *a = init->flatten(sc); - if (!a) - (a = new Statements())->push(init); - for (size_t j = 0; j < i + 1; j++) - a->insert(j, (*ainit)[j]); - init = new CompoundStatement(locinit, a); - } - break; - } - else if (sfinally) - { // Re-initialize this->init - if (i + 1 < ainit->dim) - { - Statements *a = new Statements(); - for (size_t j = i + 1; j < ainit->dim; j++) - a->push((*ainit)[j]); - init = new CompoundStatement(0, a); - } - - s = new TryFinallyStatement(0, this, sfinally); - //printf("fi {{{\n"); - s = s->semantic(sc); - //printf("}}} fi\n"); - this->relatedLabeled = s; - statement = s; - - if (init) - { Statements *a = init->flatten(sc); - if (!a) - (a = new Statements())->push(init); - for (size_t j = 0; j < i + 1; j++) - a->insert(j, (*ainit)[j]); - init = new CompoundStatement(locinit, a); - } - break; - } + ainit->insert(i++, sentry); } - } - if (!init) - { // whole init semantic is completely done. - init = new CompoundStatement(locinit, ainit); + if (sexception) + sexception = sexception->semantic(sc); + + statement = semanticInit(sc, ainit, i + 1); + + if (sexception) + { + Identifier *id = Lexer::uniqueId("__o"); + Statement *handler; + if (sexception->blockExit(FALSE) & BEfallthru) + { handler = new ThrowStatement(Loc(), new IdentifierExp(Loc(), id)); + ((ThrowStatement *)handler)->internalThrow = true; + handler = new CompoundStatement(Loc(), sexception, handler); + } + else + handler = sexception; + Catches *catches = new Catches(); + Catch *ctch = new Catch(Loc(), NULL, id, handler); + catches->push(ctch); + statement = new TryCatchStatement(Loc(), statement, catches); + } + if (sfinally) + statement = new TryFinallyStatement(Loc(), statement, sfinally); } - --nest; + //printf("-ForStatement::semanticInit %s\n", statement->toChars()); return statement; } Statement *ForStatement::semantic(Scope *sc) { + //printf("ForStatement::semantic %s\n", toChars()); + if (!nest) - { ScopeDsymbol *sym = new ScopeDsymbol(); + { + ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc->scopesym; sc = sc->push(sym); } - else if (init) - { // Process this->init recursively - return semanticInit(sc); - } + if (!nest && init) + { + Loc loc = init->loc; + Statements *ainit = init->flatten(sc); + if (!ainit) + (ainit = new Statements())->push(init); + init = NULL; - Statement *statement = this; - if (init) - statement = semanticInit(sc); + Statement *s = semanticInit(sc, ainit, 0); + ++nest; + s = s->semantic(sc); + --nest; + + init = new CompoundStatement(loc, ainit); + relatedLabeled = s; + + sc->pop(); + return s; + } + assert(init == NULL); sc->noctor++; if (condition) @@ -1436,8 +1347,8 @@ Statement *ForStatement::semantic(Scope *sc) if (!nest) sc->pop(); - //if (!nest) statement->print(); - return statement; + + return this; } Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) @@ -1458,11 +1369,6 @@ bool ForStatement::hasContinue() return TRUE; } -bool ForStatement::usesEH() -{ - return (init && init->usesEH()) || body->usesEH(); -} - int ForStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; @@ -1493,17 +1399,6 @@ int ForStatement::blockExit(bool mustNotThrow) } -int ForStatement::comeFrom() -{ - //printf("ForStatement::comeFrom()\n"); - if (body) - { int result = body->comeFrom(); - //printf("result = %d\n", result); - return result; - } - return FALSE; -} - void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("for ("); @@ -1614,18 +1509,9 @@ Statement *ForeachStatement::semantic(Scope *sc) //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars()); size_t n; TupleExp *te = NULL; - Expression *prelude = NULL; if (aggr->op == TOKtuple) // expression tuple { te = (TupleExp *)aggr; n = te->exps->dim; - - if (te->exps->dim > 0 && (*te->exps)[0]->op == TOKdotvar && - ((DotVarExp *)(*te->exps)[0])->e1->isTemp()) - { - CommaExp *ce = (CommaExp *)((DotVarExp *)(*te->exps)[0])->e1; - prelude = ce->e1; - ((DotVarExp *)(*te->exps)[0])->e1 = ce->e2; - } } else if (aggr->op == TOKtype) // type tuple { @@ -1660,7 +1546,7 @@ Statement *ForeachStatement::semantic(Scope *sc) else error("foreach: key type must be int or uint, not %s", arg->type->toChars()); } - Initializer *ie = new ExpInitializer(0, new IntegerExp(k)); + Initializer *ie = new ExpInitializer(Loc(), new IntegerExp(k)); VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie); var->storage_class |= STCmanifest; DeclarationExp *de = new DeclarationExp(loc, var); @@ -1701,7 +1587,7 @@ Statement *ForeachStatement::semantic(Scope *sc) arg->type = e->type; if (argtype && argtype->ty != Terror) arg->type = argtype; - Initializer *ie = new ExpInitializer(0, e); + Initializer *ie = new ExpInitializer(Loc(), e); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); if (arg->storageClass & STCref) v->storage_class |= STCref | STCforeach; @@ -1731,9 +1617,9 @@ Statement *ForeachStatement::semantic(Scope *sc) } s = new UnrolledLoopStatement(loc, statements); - if (prelude) + if (te && te->e0) s = new CompoundStatement(loc, - new ExpStatement(prelude->loc, prelude), s); + new ExpStatement(te->e0->loc, te->e0), s); s = s->semantic(sc); return s; } @@ -1867,7 +1753,7 @@ Lagain: if (op == TOKforeach_reverse) key->init = new ExpInitializer(loc, tmp_length); else - key->init = new ExpInitializer(loc, new IntegerExp(0)); + key->init = new ExpInitializer(loc, new IntegerExp(loc, 0, NULL)); Statements *cs = new Statements(); cs->push(new ExpStatement(loc, tmp)); @@ -1885,7 +1771,7 @@ Lagain: Expression *increment = NULL; if (op == TOKforeach) // key += 1 - increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); + increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(loc, 1, NULL)); // T value = tmp[key]; value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); @@ -1902,11 +1788,7 @@ Lagain: { ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); -#if (BUG6652 == 1 || BUG6652 == 2) - v->storage_class |= STCforeach | STCref | (arg->storageClass & STCref ? 0 : STCbug6652); -#else v->storage_class |= STCforeach | (arg->storageClass & STCref); -#endif body = new CompoundStatement(loc, new ExpStatement(loc, v), body); } } @@ -1995,7 +1877,7 @@ Lagain: { idfront = Id::Fback; idpopFront = Id::FpopBack; } - Dsymbol *sfront = ad->search(0, idfront, 0); + Dsymbol *sfront = ad->search(Loc(), idfront, 0); if (!sfront) goto Lapply; @@ -2193,17 +2075,18 @@ Lagain: if (dim == 2 && i == 0 && (tab->ty == Tarray || tab->ty == Tsarray)) { para_type = Type::tsize_t; - ie = new ExpInitializer(0, - new CastExp(0, - new IdentifierExp(0, id), arg->type)); + ie = new ExpInitializer(Loc(), + new CastExp(Loc(), + new IdentifierExp(Loc(), id), arg->type)); } else - ie = new ExpInitializer(0, new IdentifierExp(0, id)); + ie = new ExpInitializer(Loc(), new IdentifierExp(Loc(), id)); #else - Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); + Initializer *ie = new ExpInitializer(Loc(), new IdentifierExp(Loc(), id)); #endif - VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); - s = new ExpStatement(0, v); + VarDeclaration *v = new VarDeclaration(Loc(), arg->type, arg->ident, ie); + s = new ExpStatement(Loc(), v); + body = new CompoundStatement(loc, s, body); } #if IN_LLVM @@ -2215,7 +2098,7 @@ Lagain: tfld = new TypeFunction(args, Type::tint32, 0, LINKd); cases = new Statements(); gotos = new CompoundStatements(); - FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, tfld, TOKdelegate, this); + FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, Loc(), tfld, TOKdelegate, this); fld->fbody = body; Expression *flde = new FuncExp(loc, fld); flde = flde->semantic(sc); @@ -2229,7 +2112,7 @@ Lagain: 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)); + s = new ReturnStatement(Loc(), new IntegerExp(cases->dim + 1)); (*cs->statements)[0] = s; } } @@ -2293,12 +2176,12 @@ Lagain: fldeTy = aaApply_dg; } #endif - ec = new VarExp(0, fdapply); + ec = new VarExp(Loc(), fdapply); Expressions *exps = new Expressions(); exps->push(aggr); size_t keysize = taa->index->size(); - keysize = (keysize + ((size_t)PTRSIZE-1)) & ~((size_t)PTRSIZE-1); - exps->push(new IntegerExp(0, keysize, Type::tsize_t)); + keysize = (keysize + ((size_t)Target::ptrsize-1)) & ~((size_t)Target::ptrsize-1); + exps->push(new IntegerExp(Loc(), keysize, Type::tsize_t)); #if IN_LLVM // LDC paint delegate argument to the type runtime expects @@ -2345,7 +2228,7 @@ Lagain: } const char *r = (op == TOKforeach_reverse) ? "R" : ""; int j = sprintf(fdname, "_aApply%s%.*s%llu", r, 2, fntab[flag], (ulonglong)dim); - assert(j < sizeof(fdname)); + assert(j < sizeof(fdname) / sizeof(fdname[0])); #if IN_LLVM //LDC: Build arguments. Parameters* args = new Parameters; @@ -2368,7 +2251,7 @@ Lagain: FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); #endif - ec = new VarExp(0, fdapply); + ec = new VarExp(Loc(), fdapply); Expressions *exps = new Expressions(); if (tab->ty == Tsarray) aggr = aggr->castTo(sc, tn->arrayOf()); @@ -2446,15 +2329,15 @@ Lagain: Statements *a = new Statements(); // default: break; takes care of cases 0 and 1 - s = new BreakStatement(0, NULL); - s = new DefaultStatement(0, s); + s = new BreakStatement(Loc(), NULL); + s = new DefaultStatement(Loc(), s); a->push(s); // cases 2... for (size_t i = 0; i < cases->dim; i++) { s = (*cases)[i]; - s = new CaseStatement(0, new IntegerExp(i + 2), s); + s = new CaseStatement(Loc(), new IntegerExp(i + 2), s); a->push(s); } @@ -2503,11 +2386,6 @@ bool ForeachStatement::hasContinue() return TRUE; } -bool ForeachStatement::usesEH() -{ - return body->usesEH(); -} - int ForeachStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; @@ -2522,13 +2400,6 @@ int ForeachStatement::blockExit(bool mustNotThrow) } -int ForeachStatement::comeFrom() -{ - if (body) - return body->comeFrom(); - return FALSE; -} - void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(Token::toChars(op)); @@ -2705,11 +2576,7 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) { ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); -#if (BUG6652 == 1 || BUG6652 == 2) - v->storage_class |= STCforeach | STCref | (arg->storageClass & STCref ? 0 : STCbug6652); -#else v->storage_class |= STCforeach | (arg->storageClass & STCref); -#endif body = new CompoundStatement(loc, new ExpStatement(loc, v), body); } if (arg->storageClass & STCref) @@ -2762,12 +2629,6 @@ bool ForeachRangeStatement::hasContinue() return TRUE; } -bool ForeachRangeStatement::usesEH() -{ - assert(global.errors); - return body->usesEH(); -} - int ForeachRangeStatement::blockExit(bool mustNotThrow) { assert(global.errors); @@ -2775,12 +2636,6 @@ int ForeachRangeStatement::blockExit(bool mustNotThrow) } -int ForeachRangeStatement::comeFrom() -{ - assert(global.errors); - return FALSE; -} - void ForeachRangeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(Token::toChars(op)); @@ -2853,9 +2708,10 @@ Statement *IfStatement::semantic(Scope *sc) match = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, condition)); match->parent = sc->func; + match->storage_class |= arg->storageClass; DeclarationExp *de = new DeclarationExp(loc, match); - VarExp *ve = new VarExp(0, match); + VarExp *ve = new VarExp(Loc(), match); condition = new CommaExp(loc, de, ve); condition = condition->semantic(scd); @@ -2896,11 +2752,6 @@ Statement *IfStatement::semantic(Scope *sc) return this; } -bool IfStatement::usesEH() -{ - return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); -} - int IfStatement::blockExit(bool mustNotThrow) { //printf("IfStatement::blockExit(%p)\n", this); @@ -3042,11 +2893,6 @@ Statements *ConditionalStatement::flatten(Scope *sc) return a; } -bool ConditionalStatement::usesEH() -{ - return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); -} - int ConditionalStatement::blockExit(bool mustNotThrow) { int result = ifbody->blockExit(mustNotThrow); @@ -3115,7 +2961,7 @@ Statement *PragmaStatement::semantic(Scope *sc) { Expression *e = (*args)[i]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); if (e->op != TOKerror && e->op != TOKtype) e = e->ctfeInterpret(); @@ -3126,12 +2972,12 @@ Statement *PragmaStatement::semantic(Scope *sc) StringExp *se = e->toString(); if (se) { - fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string); + fprintf(stderr, "%.*s", (int)se->len, (char *)se->string); } else - fprintf(stdmsg, "%s", e->toChars()); + fprintf(stderr, "%s", e->toChars()); } - fprintf(stdmsg, "\n"); + fprintf(stderr, "\n"); } } else if (ident == Id::lib) @@ -3147,7 +2993,7 @@ Statement *PragmaStatement::semantic(Scope *sc) { Expression *e = (*args)[0]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); (*args)[0] = e; @@ -3184,7 +3030,7 @@ Statement *PragmaStatement::semantic(Scope *sc) else { Expression *e = (*args)[0]; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->ctfeInterpret(); (*args)[0] = e; @@ -3209,11 +3055,6 @@ Lerror: return body; } -bool PragmaStatement::usesEH() -{ - return body && body->usesEH(); -} - int PragmaStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; @@ -3449,7 +3290,7 @@ Statement *SwitchStatement::semantic(Scope *sc) sc->sw->sdefault = new DefaultStatement(loc, s); a->push(body); if (body->blockExit(FALSE) & BEfallthru) - a->push(new BreakStatement(0, NULL)); + a->push(new BreakStatement(Loc(), NULL)); a->push(sc->sw->sdefault); cs = new CompoundStatement(loc, a); body = cs; @@ -3464,11 +3305,6 @@ bool SwitchStatement::hasBreak() return TRUE; } -bool SwitchStatement::usesEH() -{ - return body ? body->usesEH() : 0; -} - int SwitchStatement::blockExit(bool mustNotThrow) { int result = BEnone; if (condition->canThrow(mustNotThrow)) @@ -3539,7 +3375,7 @@ Statement *CaseStatement::semantic(Scope *sc) { SwitchStatement *sw = sc->sw; //printf("CaseStatement::semantic() %s\n", toChars()); - exp = exp->semantic(sc); + exp = exp->ctfeSemantic(sc); exp = resolveProperties(sc, exp); if (sw) { @@ -3622,22 +3458,12 @@ int CaseStatement::compare(Object *obj) return exp->compare(cs2->exp); } -bool CaseStatement::usesEH() -{ - return statement->usesEH(); -} - int CaseStatement::blockExit(bool mustNotThrow) { return statement->blockExit(mustNotThrow); } -int CaseStatement::comeFrom() -{ - return TRUE; -} - void CaseStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("case "); @@ -3674,12 +3500,12 @@ Statement *CaseRangeStatement::semantic(Scope *sc) if (sw->isFinal) error("case ranges not allowed in final switch"); - first = first->semantic(sc); + first = first->ctfeSemantic(sc); first = resolveProperties(sc, first); first = first->implicitCastTo(sc, sw->condition->type); first = first->ctfeInterpret(); - last = last->semantic(sc); + last = last->ctfeSemantic(sc); last = resolveProperties(sc, last); last = last->implicitCastTo(sc, sw->condition->type); last = last->ctfeInterpret(); @@ -3788,22 +3614,12 @@ Statement *DefaultStatement::semantic(Scope *sc) return this; } -bool DefaultStatement::usesEH() -{ - return statement->usesEH(); -} - int DefaultStatement::blockExit(bool mustNotThrow) { return statement->blockExit(mustNotThrow); } -int DefaultStatement::comeFrom() -{ - return TRUE; -} - void DefaultStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("default:"); @@ -3952,7 +3768,12 @@ Statement *ReturnStatement::semantic(Scope *sc) if (fd->fes) fd = fd->fes->func; // fd is now function enclosing foreach - Type *tret = fd->type->nextOf(); + TypeFunction *tf = (TypeFunction *)fd->type; + assert(tf->ty == Tfunction); + bool isRefReturn = tf->isref && !(fd->storage_class & STCauto); + // Until 'ref' deduction finished, 'auto ref' is treated as a 'value return'. + + Type *tret = tf->next; if (fd->tintro) /* We'll be implicitly casting the return expression to tintro */ @@ -3983,7 +3804,7 @@ Statement *ReturnStatement::semantic(Scope *sc) // return this; if (exp && exp->op != TOKthis) error("cannot return expression from constructor"); - exp = new ThisExp(0); + exp = new ThisExp(Loc()); exp->type = tret; } @@ -4001,7 +3822,8 @@ Statement *ReturnStatement::semantic(Scope *sc) exp = exp->inferType(fld->treq->nextOf()->nextOf()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - if (!((TypeFunction *)fd->type)->isref) + // Until 'ref' deduction finished, don't invoke constant folding + if (!tf->isref) exp = exp->optimize(WANTvalue); if (exp->op == TOKcall) @@ -4017,7 +3839,7 @@ Statement *ReturnStatement::semantic(Scope *sc) { VarExp *ve = (VarExp *)exp; VarDeclaration *v = ve->var->isVarDeclaration(); - if (((TypeFunction *)fd->type)->isref) + if (isRefReturn) // Function returns a reference fd->nrvo_can = 0; else if (!v || v->isOut() || v->isRef()) @@ -4036,15 +3858,8 @@ Statement *ReturnStatement::semantic(Scope *sc) else fd->nrvo_can = 0; - if (!fd->nrvo_can && - exp->isLvalue() && !((TypeFunction *)fd->type)->isref) - { - exp = callCpCtor(exp->loc, sc, exp, 1); - } - if (fd->inferRetType) - { TypeFunction *tf = (TypeFunction *)fd->type; - assert(tf->ty == Tfunction); + { Type *tfret = tf->nextOf(); if (tfret) { @@ -4067,7 +3882,7 @@ Statement *ReturnStatement::semantic(Scope *sc) tf->next = exp->type; else if (m1 && !m2) ; - else + else if (exp->op != TOKerror) error("mismatched function return type inference of %s and %s", exp->type->toChars(), tfret->toChars()); } @@ -4094,21 +3909,29 @@ Statement *ReturnStatement::semantic(Scope *sc) unsigned errors = global.startGagging(); exp->checkEscapeRef(); if (global.endGagging(errors)) - tf->isref = FALSE; // return by value + tf->isref = false; // return by value } else - tf->isref = FALSE; // return by value + tf->isref = false; // return by value fd->storage_class &= ~STCauto; + + isRefReturn = tf->isref; // 'ref' deduction finished + if (!isRefReturn) + exp = exp->optimize(WANTvalue); } tf->next = exp->type; //fd->type = tf->semantic(loc, sc); // Removed with 6902 if (!fd->tintro) - { tret = fd->type->nextOf(); + { tret = tf->next; tbret = tret->toBasetype(); } } + if (!fd->nrvo_can && exp->isLvalue() && !isRefReturn) + { + exp = callCpCtor(exp->loc, sc, exp, 1); + } if (fd->returnLabel) - eorg = exp; + eorg = exp->copy(); if (!fd->returns) fd->returns = new ReturnStatements(); @@ -4116,38 +3939,42 @@ Statement *ReturnStatement::semantic(Scope *sc) } else if (tbret->ty != Tvoid) { - assert(fd->type->ty == Tfunction); - TypeFunction *tf = (TypeFunction *)fd->type; - if (fd->isPureBypassingInference() != PUREimpure && - !tf->hasMutableIndirectionParams() && - !exp->type->implicitConvTo(tret) && - exp->type->invariantOf()->implicitConvTo(tret)) + if (!fd->nrvo_can && exp->isLvalue() && !isRefReturn) { - exp = exp->castTo(sc, exp->type->invariantOf()); + exp = callCpCtor(exp->loc, sc, exp, 1); + } + + if (!exp->type->implicitConvTo(tret) && + fd->parametersIntersect(exp->type)) + { + if (exp->type->invariantOf()->implicitConvTo(tret)) + exp = exp->castTo(sc, exp->type->invariantOf()); + else if (exp->type->wildOf()->implicitConvTo(tret)) + exp = exp->castTo(sc, exp->type->wildOf()); } if (fd->tintro) - exp = exp->implicitCastTo(sc, fd->type->nextOf()); + exp = exp->implicitCastTo(sc, tf->next); // eorg isn't casted to tret (== fd->tintro->nextOf()) if (fd->returnLabel) eorg = exp->copy(); exp = exp->implicitCastTo(sc, tret); - if (!((TypeFunction *)fd->type)->isref) + if (!isRefReturn) exp = exp->optimize(WANTvalue); } } else if (fd->inferRetType) { - if (fd->type->nextOf()) + if (tf->next) { - if (fd->type->nextOf()->ty != Tvoid) + if (tf->next->ty != Tvoid) error("mismatched function return type inference of void and %s", - fd->type->nextOf()->toChars()); + tf->next->toChars()); } else { - ((TypeFunction *)fd->type)->next = Type::tvoid; + tf->next = Type::tvoid; //fd->type = fd->type->semantic(loc, sc); // Remove with7321, same as 6902 if (!fd->tintro) { tret = Type::tvoid; @@ -4173,16 +4000,16 @@ Statement *ReturnStatement::semantic(Scope *sc) { sc->fes->cases->push(this); // Construct: return cases->dim+1; - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); + s = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1)); } - else if (fd->type->nextOf()->toBasetype() == Type::tvoid) + else if (tf->next->toBasetype() == Type::tvoid) { - s = new ReturnStatement(0, NULL); + s = new ReturnStatement(Loc(), NULL); sc->fes->cases->push(s); // Construct: { exp; return cases->dim + 1; } Statement *s1 = new ExpStatement(loc, exp); - Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); + Statement *s2 = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1)); s = new CompoundStatement(loc, s1, s2); } else @@ -4196,7 +4023,7 @@ Statement *ReturnStatement::semantic(Scope *sc) VarDeclaration *v = new VarDeclaration(loc, tret, fd->outId, NULL); v->noscope = 1; v->storage_class |= STCresult; - if (((TypeFunction *)fd->type)->isref) + if (isRefReturn) v->storage_class |= STCref | STCforeach; v->semantic(sco); if (!sco->insert(v)) @@ -4205,14 +4032,14 @@ Statement *ReturnStatement::semantic(Scope *sc) fd->vresult = v; } - s = new ReturnStatement(0, new VarExp(0, fd->vresult)); + s = new ReturnStatement(Loc(), new VarExp(Loc(), fd->vresult)); sc->fes->cases->push(s); // Construct: { vresult = exp; return cases->dim + 1; } - exp = new ConstructExp(loc, new VarExp(0, fd->vresult), exp); + exp = new ConstructExp(loc, new VarExp(Loc(), fd->vresult), exp); exp = exp->semantic(sc); Statement *s1 = new ExpStatement(loc, exp); - Statement *s2 = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); + Statement *s2 = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1)); s = new CompoundStatement(loc, s1, s2); } return s; @@ -4220,7 +4047,7 @@ Statement *ReturnStatement::semantic(Scope *sc) if (exp) { - if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration()) + if (isRefReturn && !fd->isCtorDeclaration()) { // Function returns a reference exp = exp->toLvalue(sc, exp); exp->checkEscapeRef(); @@ -4235,7 +4062,7 @@ Statement *ReturnStatement::semantic(Scope *sc) if (fd->returnLabel && tbret->ty != Tvoid) { fd->buildResultVar(); - VarExp *v = new VarExp(0, fd->vresult); + VarExp *v = new VarExp(Loc(), fd->vresult); assert(eorg); exp = new ConstructExp(loc, v, eorg); @@ -4260,7 +4087,7 @@ Statement *ReturnStatement::semantic(Scope *sc) { /* Replace: return exp; * with: exp; goto returnLabel; */ - Statement *s = new ExpStatement(0, exp); + Statement *s = new ExpStatement(Loc(), exp); return new CompoundStatement(loc, s, gs); } return gs; @@ -4349,7 +4176,7 @@ Statement *BreakStatement::semantic(Scope *sc) */ Statement *s; sc->fes->cases->push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); + s = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1)); return s; } break; // can't break to it @@ -4383,7 +4210,7 @@ Statement *BreakStatement::semantic(Scope *sc) { Statement *s; // Replace break; with return 1; - s = new ReturnStatement(0, new IntegerExp(1)); + s = new ReturnStatement(Loc(), new IntegerExp(1)); return s; } error("break is not inside a loop or switch"); @@ -4447,7 +4274,7 @@ Statement *ContinueStatement::semantic(Scope *sc) if (ls && ls->ident == ident && ls->statement == sc->fes) { // Replace continue ident; with return 0; - return new ReturnStatement(0, new IntegerExp(0)); + return new ReturnStatement(Loc(), new IntegerExp(0)); } } @@ -4460,7 +4287,7 @@ Statement *ContinueStatement::semantic(Scope *sc) */ Statement *s; sc->fes->cases->push(this); - s = new ReturnStatement(0, new IntegerExp(sc->fes->cases->dim + 1)); + s = new ReturnStatement(Loc(), new IntegerExp(sc->fes->cases->dim + 1)); return s; } break; // can't continue to it @@ -4494,7 +4321,7 @@ Statement *ContinueStatement::semantic(Scope *sc) { Statement *s; // Replace continue; with return 0; - s = new ReturnStatement(0, new IntegerExp(0)); + s = new ReturnStatement(Loc(), new IntegerExp(0)); return s; } error("continue is not inside a loop"); @@ -4572,7 +4399,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) } Type *t = ClassDeclaration::object->type; - t = t->semantic(0, sc)->toBasetype(); + t = t->semantic(Loc(), sc)->toBasetype(); assert(t->ty == Tclass); exp = new CastExp(loc, exp, t); @@ -4628,9 +4455,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc) */ Identifier *id = Lexer::uniqueId("__critsec"); #if !IN_LLVM - Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32()))); + Type *t = new TypeSArray(Type::tint8, new IntegerExp(Target::ptrsize + (global.params.is64bit ? os_critsecsize64() : os_critsecsize32()))); #else - Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize())); + Type *t = new TypeSArray(Type::tint8, new IntegerExp(Target::ptrsize + os_critsecsize())); #endif VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL); tmp->storage_class |= STCgshared | STCstatic; @@ -4695,11 +4522,6 @@ bool SynchronizedStatement::hasContinue() return FALSE; //TRUE; } -bool SynchronizedStatement::usesEH() -{ - return TRUE; -} - int SynchronizedStatement::blockExit(bool mustNotThrow) { return body ? body->blockExit(mustNotThrow) : BEfallthru; @@ -4818,11 +4640,6 @@ void WithStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) body->toCBuffer(buf, hgs); } -bool WithStatement::usesEH() -{ - return body ? body->usesEH() : 0; -} - int WithStatement::blockExit(bool mustNotThrow) { int result = BEnone; @@ -4850,9 +4667,8 @@ Statement *TryCatchStatement::syntaxCopy() Catches *a = new Catches(); a->setDim(catches->dim); for (size_t i = 0; i < a->dim; i++) - { Catch *c; - - c = (*catches)[i]; + { + Catch *c = (*catches)[i]; c = c->syntaxCopy(); (*a)[i] = c; } @@ -4881,21 +4697,40 @@ Statement *TryCatchStatement::semantic(Scope *sc) } } - if (!body || body->isEmpty()) + if (!body || !body->hasCode()) { return NULL; } + + /* If the try body never throws, we can eliminate any catches + * of recoverable exceptions. + */ + + if (!(body->blockExit(false) & BEthrow) && ClassDeclaration::exception) + { + for (size_t i = 0; i < catches->dim; i++) + { Catch *c = (*catches)[i]; + + /* If catch exception type is derived from Exception + */ + if (c->type->toBasetype()->implicitConvTo(ClassDeclaration::exception->type) && + (!c->handler || !c->handler->comeFrom())) + { // Remove c from the array of catches + catches->remove(i); + --i; + } + } + } + + if (catches->dim == 0) + return body; + return this; } bool TryCatchStatement::hasBreak() { - return FALSE; //TRUE; -} - -bool TryCatchStatement::usesEH() -{ - return TRUE; + return FALSE; } int TryCatchStatement::blockExit(bool mustNotThrow) @@ -4993,7 +4828,7 @@ void Catch::semantic(Scope *sc) sc = sc->push(sym); if (!type) - type = new TypeIdentifier(0, Id::Throwable); + type = new TypeIdentifier(Loc(), Id::Throwable); type = type->semantic(loc, sc); ClassDeclaration *cd = type->toBasetype()->isClassHandle(); if (!cd || ((cd != ClassDeclaration::throwable) && !ClassDeclaration::throwable->isBaseOf(cd, NULL))) @@ -5128,11 +4963,6 @@ bool TryFinallyStatement::hasContinue() return FALSE; //TRUE; } -bool TryFinallyStatement::usesEH() -{ - return TRUE; -} - int TryFinallyStatement::blockExit(bool mustNotThrow) { int result = BEfallthru; @@ -5184,11 +5014,6 @@ void OnScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) statement->toCBuffer(buf, hgs); } -bool OnScopeStatement::usesEH() -{ - return 1; -} - Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("OnScopeStatement::scopeCode()\n"); @@ -5215,17 +5040,17 @@ Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement */ Identifier *id = Lexer::uniqueId("__os"); - ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(0, 0, Type::tbool)); + ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(Loc(), 0, Type::tbool)); VarDeclaration *v = new VarDeclaration(loc, Type::tbool, id, ie); *sentry = new ExpStatement(loc, v); - Expression *e = new IntegerExp(0, 1, Type::tbool); - e = new AssignExp(0, new VarExp(0, v), e); - *sexception = new ExpStatement(0, e); + Expression *e = new IntegerExp(Loc(), 1, Type::tbool); + e = new AssignExp(Loc(), new VarExp(Loc(), v), e); + *sexception = new ExpStatement(Loc(), e); - e = new VarExp(0, v); - e = new NotExp(0, e); - *sfinally = new IfStatement(0, NULL, e, statement, NULL); + e = new VarExp(Loc(), v); + e = new NotExp(Loc(), e); + *sfinally = new IfStatement(Loc(), NULL, e, statement, NULL); break; } @@ -5302,73 +5127,6 @@ void ThrowStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); } -/******************************** VolatileStatement **************************/ - -VolatileStatement::VolatileStatement(Loc loc, Statement *statement) - : Statement(loc) -{ - this->statement = statement; -} - -Statement *VolatileStatement::syntaxCopy() -{ - VolatileStatement *s = new VolatileStatement(loc, - statement ? statement->syntaxCopy() : NULL); - return s; -} - -Statement *VolatileStatement::semantic(Scope *sc) -{ - if (statement) -#if IN_LLVM - { - Statement* oldScopeExit = sc->enclosingScopeExit; - sc->enclosingScopeExit = this; -#endif - statement = statement->semantic(sc); -#if IN_LLVM - sc->enclosingScopeExit = oldScopeExit; - } -#endif - return this; -} - -Statements *VolatileStatement::flatten(Scope *sc) -{ - Statements *a; - - a = statement ? statement->flatten(sc) : NULL; - if (a) - { for (size_t i = 0; i < a->dim; i++) - { Statement *s = (*a)[i]; - - s = new VolatileStatement(loc, s); - (*a)[i] = s; - } - } - - return a; -} - -int VolatileStatement::blockExit(bool mustNotThrow) -{ - return statement ? statement->blockExit(mustNotThrow) : BEfallthru; -} - - -void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) -{ - buf->writestring("volatile"); - if (statement) - { if (statement->isScopeStatement()) - buf->writenl(); - else - buf->writebyte(' '); - statement->toCBuffer(buf, hgs); - } -} - - /******************************** DebugStatement **************************/ DebugStatement::DebugStatement(Loc loc, Statement *statement) @@ -5575,11 +5333,6 @@ Statements *LabelStatement::flatten(Scope *sc) } -bool LabelStatement::usesEH() -{ - return statement ? statement->usesEH() : FALSE; -} - int LabelStatement::blockExit(bool mustNotThrow) { //printf("LabelStatement::blockExit(%p)\n", this); @@ -5587,12 +5340,6 @@ int LabelStatement::blockExit(bool mustNotThrow) } -int LabelStatement::comeFrom() -{ - //printf("LabelStatement::comeFrom()\n"); - return TRUE; -} - void LabelStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(ident->toChars()); @@ -5637,12 +5384,6 @@ Statement *AsmStatement::syntaxCopy() } - -int AsmStatement::comeFrom() -{ - return TRUE; -} - int AsmStatement::blockExit(bool mustNotThrow) { if (mustNotThrow) @@ -5717,6 +5458,7 @@ Statement *ImportStatement::semantic(Scope *sc) TypeIdentifier *tname = new TypeIdentifier(s->loc, name); AliasDeclaration *ad = new AliasDeclaration(s->loc, alias, tname); + ad->import = s; s->aliasdecls.push(ad); } @@ -5738,11 +5480,6 @@ int ImportStatement::blockExit(bool mustNotThrow) return BEfallthru; } -int ImportStatement::isEmpty() -{ - return TRUE; -} - void ImportStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { for (size_t i = 0; i < imports->dim; i++) diff --git a/dmd2/statement.h b/dmd2/statement.h index ede1ee65e8..6a2edf4c0e 100644 --- a/dmd2/statement.h +++ b/dmd2/statement.h @@ -56,7 +56,6 @@ struct InterState; #if IN_LLVM struct CaseStatement; struct LabelStatement; -struct VolatileStatement; struct SynchronizedStatement; #endif @@ -71,6 +70,8 @@ namespace llvm } #endif +typedef bool (*sapply_fp_t)(Statement *, void *); + // Back end struct IRState; struct Blockx; @@ -125,13 +126,17 @@ struct Statement : Object virtual Statement *getRelatedLabeled() { return this; } virtual bool hasBreak(); virtual bool hasContinue(); - virtual bool usesEH(); + bool usesEH(); + virtual bool usesEHimpl(); virtual int blockExit(bool mustNotThrow); - virtual int comeFrom(); - virtual int isEmpty(); + bool comeFrom(); + virtual bool comeFromImpl(); + bool hasCode(); + virtual bool hasCodeImpl(); virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); virtual Statements *flatten(Scope *sc); virtual Expression *interpret(InterState *istate); + virtual bool apply(sapply_fp_t fp, void *param); virtual Statement *last(); virtual int inlineCost(InlineCostState *ics); @@ -164,6 +169,7 @@ struct PeelStatement : Statement PeelStatement(Statement *s); Statement *semantic(Scope *sc); + bool apply(sapply_fp_t fp, void *param); }; struct ExpStatement : Statement @@ -177,7 +183,7 @@ struct ExpStatement : Statement Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); int blockExit(bool mustNotThrow); - int isEmpty(); + bool hasCodeImpl(); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); int inlineCost(InlineCostState *ics); @@ -227,13 +233,12 @@ struct CompoundStatement : Statement Statement *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); - int isEmpty(); + bool hasCodeImpl(); Statements *flatten(Scope *sc); ReturnStatement *isReturnStatement(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); Statement *last(); int inlineCost(InlineCostState *ics); @@ -270,10 +275,9 @@ struct UnrolledLoopStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int inlineCost(InlineCostState *ics); @@ -295,11 +299,10 @@ struct ScopeStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); - int isEmpty(); + bool hasCodeImpl(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -319,10 +322,9 @@ struct WhileStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -340,10 +342,9 @@ struct DoStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -366,16 +367,15 @@ struct ForStatement : Statement ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); Statement *syntaxCopy(); - Statement *semanticInit(Scope *sc); + Statement *semanticInit(Scope *sc, Statements *ainit, size_t i); Statement *semantic(Scope *sc); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; } bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int inlineCost(InlineCostState *ics); @@ -408,10 +408,9 @@ struct ForeachStatement : Statement int inferApplyArgTypes(Scope *sc, Dsymbol *&sapply); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -436,10 +435,9 @@ struct ForeachRangeStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -461,8 +459,8 @@ struct IfStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - bool usesEH(); int blockExit(bool mustNotThrow); IfStatement *isIfStatement() { return this; } @@ -484,8 +482,8 @@ struct ConditionalStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); - bool usesEH(); int blockExit(bool mustNotThrow); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -499,8 +497,8 @@ struct PragmaStatement : Statement PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - bool usesEH(); int blockExit(bool mustNotThrow); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -542,9 +540,9 @@ struct SwitchStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); bool hasBreak(); - bool usesEH(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -568,10 +566,10 @@ struct CaseStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int compare(Object *obj); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); + bool comeFromImpl(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); CaseStatement *isCaseStatement() { return this; } @@ -596,6 +594,7 @@ struct CaseRangeStatement : Statement CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s); Statement *syntaxCopy(); Statement *semantic(Scope *sc); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -615,10 +614,10 @@ struct DefaultStatement : Statement DefaultStatement(Loc loc, Statement *s); Statement *syntaxCopy(); Statement *semantic(Scope *sc); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); + bool comeFromImpl(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); DefaultStatement *isDefaultStatement() { return this; } @@ -740,8 +739,9 @@ struct SynchronizedStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); + bool usesEHimpl(); int blockExit(bool mustNotThrow); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -765,9 +765,9 @@ struct WithStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - bool usesEH(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); Statement *inlineScan(InlineScanState *iss); @@ -783,9 +783,10 @@ struct TryCatchStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); bool hasBreak(); - bool usesEH(); + bool usesEHimpl(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); Statement *inlineScan(InlineScanState *iss); @@ -821,9 +822,10 @@ struct TryFinallyStatement : Statement Statement *semantic(Scope *sc); bool hasBreak(); bool hasContinue(); - bool usesEH(); + bool usesEHimpl(); int blockExit(bool mustNotThrow); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); Statement *inlineScan(InlineScanState *iss); @@ -840,9 +842,10 @@ struct OnScopeStatement : Statement int blockExit(bool mustNotThrow); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *semantic(Scope *sc); - bool usesEH(); + bool usesEHimpl(); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toIR(IRState *irs); }; @@ -865,22 +868,6 @@ struct ThrowStatement : Statement void toIR(IRState *irs); }; -struct VolatileStatement : Statement -{ - Statement *statement; - - VolatileStatement(Loc loc, Statement *statement); - Statement *syntaxCopy(); - Statement *semantic(Scope *sc); - Statements *flatten(Scope *sc); - int blockExit(bool mustNotThrow); - void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - - Statement *inlineScan(InlineScanState *iss); - - void toIR(IRState *irs); -}; - struct DebugStatement : Statement { Statement *statement; @@ -889,6 +876,7 @@ struct DebugStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; @@ -931,10 +919,10 @@ struct LabelStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); - bool usesEH(); int blockExit(bool mustNotThrow); - int comeFrom(); + bool comeFromImpl(); Expression *interpret(InterState *istate); + bool apply(sapply_fp_t fp, void *param); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Statement *inlineScan(InlineScanState *iss); @@ -968,7 +956,7 @@ struct AsmStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - int comeFrom(); + bool comeFromImpl(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -995,7 +983,7 @@ struct ImportStatement : Statement Statement *syntaxCopy(); Statement *semantic(Scope *sc); int blockExit(bool mustNotThrow); - int isEmpty(); + bool hasCodeImpl(); Expression *interpret(InterState *istate); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/dmd2/staticassert.c b/dmd2/staticassert.c index 3ce09b1df5..9d3c7b0209 100644 --- a/dmd2/staticassert.c +++ b/dmd2/staticassert.c @@ -56,7 +56,7 @@ void StaticAssert::semantic2(Scope *sc) sc = sc->push(sd); sc->flags |= SCOPEstaticassert; ++sc->ignoreTemplates; - Expression *e = exp->semantic(sc); + Expression *e = exp->ctfeSemantic(sc); e = resolveProperties(sc, e); sc = sc->pop(); if (!e->type->checkBoolean()) @@ -77,7 +77,7 @@ void StaticAssert::semantic2(Scope *sc) { HdrGenState hgs; OutBuffer buf; - msg = msg->semantic(sc); + msg = msg->ctfeSemantic(sc); msg = resolveProperties(sc, msg); msg = msg->ctfeInterpret(); hgs.console = 1; @@ -129,7 +129,7 @@ void StaticAssert::toCBuffer(OutBuffer *buf, HdrGenState *hgs) exp->toCBuffer(buf, hgs); if (msg) { - buf->writeByte(','); + buf->writestring(", "); msg->toCBuffer(buf, hgs); } buf->writestring(");"); diff --git a/dmd2/struct.c b/dmd2/struct.c index 29ba984fbe..39fe40bb84 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -49,7 +49,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) stag = NULL; sinit = NULL; #endif - isnested = false; + enclosing = NULL; vthis = NULL; #if DMDV2 @@ -88,6 +88,7 @@ void AggregateDeclaration::semantic2(Scope *sc) if (members) { sc = sc->push(this); + sc->parent = this; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; @@ -109,14 +110,25 @@ void AggregateDeclaration::semantic3(Scope *sc) if (members) { sc = sc->push(this); + sc->parent = this; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->semantic3(sc); } - sc->pop(); - if (!getRTInfo) + if (StructDeclaration *sd = isStructDeclaration()) + { + //if (sd->xeq != NULL) printf("sd = %s xeq @ [%s]\n", sd->toChars(), sd->loc.toChars()); + //assert(sd->xeq == NULL); + if (sd->xeq == NULL) + sd->xeq = sd->buildXopEquals(sc); + } + sc = sc->pop(); + + if (!getRTInfo && Type::rtinfo && + (!isDeprecated() || global.params.useDeprecated) && // don't do it for unused deprecated types + (type && type->ty != Terror)) // or error types { // Evaluate: gcinfo!type Objects *tiargs = new Objects(); tiargs->push(type); @@ -125,8 +137,8 @@ void AggregateDeclaration::semantic3(Scope *sc) ti->semantic2(sc); ti->semantic3(sc); Dsymbol *s = ti->toAlias(); - Expression *e = new DsymbolExp(0, s, 0); - e = e->semantic(ti->tempdecl->scope); + Expression *e = new DsymbolExp(Loc(), s, 0); + e = e->ctfeSemantic(ti->tempdecl->scope); e = e->ctfeInterpret(); getRTInfo = e; } @@ -178,7 +190,7 @@ unsigned AggregateDeclaration::size(Loc loc) v->semantic(NULL); if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter)) return 0; - if (v->storage_class & STCfield && v->sem >= SemanticDone) + if (v->isField() && v->sem >= SemanticDone) return 0; return 1; } @@ -209,7 +221,7 @@ Type *AggregateDeclaration::getType() return type; } -int AggregateDeclaration::isDeprecated() +bool AggregateDeclaration::isDeprecated() { return isdeprecated; } @@ -299,14 +311,68 @@ unsigned AggregateDeclaration::placeField( /**************************************** - * Returns !=0 if there's an extra member which is the 'this' + * Returns true if there's an extra member which is the 'this' * pointer to the enclosing context (enclosing aggregate or function) */ -int AggregateDeclaration::isNested() +bool AggregateDeclaration::isNested() { - assert((isnested & ~1) == 0); - return isnested; + return enclosing != NULL; +} + +void AggregateDeclaration::makeNested() +{ + if (!enclosing && sizeok != SIZEOKdone && !isUnionDeclaration() && !isInterfaceDeclaration()) + { + // If nested struct, add in hidden 'this' pointer to outer scope + if (!(storage_class & STCstatic)) + { + Dsymbol *s = toParent2(); + if (s) + { + AggregateDeclaration *ad = s->isAggregateDeclaration(); + FuncDeclaration *fd = s->isFuncDeclaration(); + + if (fd) + { + enclosing = fd; + } + else if (isClassDeclaration() && ad && ad->isClassDeclaration()) + { + enclosing = ad; + } + else if (isStructDeclaration() && ad) + { + if (TemplateInstance *ti = ad->parent->isTemplateInstance()) + { + enclosing = ti->enclosing; + } + } + if (enclosing) + { + //printf("makeNested %s, enclosing = %s\n", toChars(), enclosing->toChars()); + Type *t; + if (ad) + t = ad->handle; + else if (fd) + { AggregateDeclaration *ad2 = fd->isMember2(); + if (ad2) + t = ad2->handle; + else + t = Type::tvoidptr; + } + else + assert(0); + if (t->ty == Tstruct) + t = Type::tvoidptr; // t should not be a ref type + assert(!vthis); + vthis = new ThisDeclaration(loc, t); + //vthis->storage_class |= STCref; + members->push(vthis); + } + } + } + } } /**************************************** @@ -383,12 +449,16 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) type = new TypeStruct(this); #if MODULEINFO_IS_STRUCT + #ifdef DMDV2 + if (id == Id::ModuleInfo && !Module::moduleinfo) + Module::moduleinfo = this; + #else if (id == Id::ModuleInfo) - { - if (Module::moduleinfo) - Module::moduleinfo->error("only object.d can define this reserved class name"); + { if (Module::moduleinfo) + Module::moduleinfo->error("only object.d can define this reserved struct name"); Module::moduleinfo = this; } + #endif #endif } @@ -413,7 +483,7 @@ void StructDeclaration::semantic(Scope *sc) //static int count; if (++count == 20) halt(); assert(type); - if (!members) // if forward reference + if (!members) // if opaque declaration { return; } @@ -435,7 +505,7 @@ void StructDeclaration::semantic(Scope *sc) scope = NULL; } - int errors = global.gaggedErrors; + int errors = global.errors; unsigned dprogress_save = Module::dprogress; @@ -445,17 +515,6 @@ void StructDeclaration::semantic(Scope *sc) protection = sc->protection; alignment = sc->structalign; storage_class |= sc->stc; -#if IN_LLVM - // DMD allows nested unions with functions that access the outer scope, but - // generates invalid code for them (the context pointer is stored at the - // same offset as all the union fields, just as if it was a regular member). - // LDC would assert on this instead due to a type mismatch when trying to - // store the context pointer. This change mitigates the wrong-code/crash - // bug – see "[dmd-internals] Nested Unions?" for a discussion on whether - // this should be legal or not. - if (isUnionDeclaration()) - storage_class |= STCstatic; -#endif if (sc->stc & STCdeprecated) isdeprecated = true; assert(!isAnonymous()); @@ -594,7 +653,7 @@ void StructDeclaration::semantic(Scope *sc) arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc); + tfeqptr = (TypeFunction *)tfeqptr->semantic(Loc(), sc); } TypeFunction *tfeq; @@ -604,7 +663,7 @@ void StructDeclaration::semantic(Scope *sc) arguments->push(arg); tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(0, sc); + tfeq = (TypeFunction *)tfeq->semantic(Loc(), sc); } Identifier *id = Id::eq; @@ -643,22 +702,20 @@ void StructDeclaration::semantic(Scope *sc) postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); - hasIdentityAssign = (buildOpAssign(sc2) != NULL); - hasIdentityEquals = (buildOpEquals(sc2) != NULL); - - xeq = buildXopEquals(sc2); + buildOpAssign(sc2); + buildOpEquals(sc2); #endif + inv = buildInv(sc2); sc2->pop(); /* Look for special member functions. */ #if DMDV2 - ctor = search(0, Id::ctor, 0); + ctor = search(Loc(), Id::ctor, 0); #endif - inv = (InvariantDeclaration *)search(0, Id::classInvariant, 0); - aggNew = (NewDeclaration *)search(0, Id::classNew, 0); - aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); + aggNew = (NewDeclaration *)search(Loc(), Id::classNew, 0); + aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete, 0); TypeTuple *tup = type->toArgTypes(); size_t dim = tup->arguments->dim; @@ -675,8 +732,8 @@ void StructDeclaration::semantic(Scope *sc) semantic3(sc); } - if (global.gag && global.gaggedErrors != errors) - { // The type is no good, yet the error messages were gagged. + if (global.errors != errors) + { // The type is no good. type = Type::terror; } @@ -685,6 +742,15 @@ void StructDeclaration::semantic(Scope *sc) deferred->semantic2(sc); deferred->semantic3(sc); } + +#if 0 + if (type->ty == Tstruct && ((TypeStruct *)type)->sym != this) + { + printf("this = %p %s\n", this, this->toChars()); + printf("type = %d sym = %p\n", type->ty, ((TypeStruct *)type)->sym); + } +#endif + assert(type->ty != Tstruct || ((TypeStruct *)type)->sym == this); } Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) @@ -694,7 +760,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) if (scope && !symtab) semantic(scope); - if (!members || !symtab) + if (!members || !symtab) // opaque or semantic() is not yet called { error("is forward referenced when looking for '%s'", ident->toChars()); return NULL; @@ -737,45 +803,6 @@ void StructDeclaration::finalizeSize(Scope *sc) sizeok = SIZEOKdone; } -void StructDeclaration::makeNested() -{ - if (!isnested && sizeok != SIZEOKdone && !isUnionDeclaration()) - { - // If nested struct, add in hidden 'this' pointer to outer scope - if (!(storage_class & STCstatic)) - { Dsymbol *s = toParent2(); - if (s) - { - AggregateDeclaration *ad = s->isAggregateDeclaration(); - FuncDeclaration *fd = s->isFuncDeclaration(); - - TemplateInstance *ti; - if (ad && (ti = ad->parent->isTemplateInstance()) != NULL && ti->isnested || fd) - { isnested = true; - Type *t; - if (ad) - t = ad->handle; - else if (fd) - { AggregateDeclaration *ad = fd->isMember2(); - if (ad) - t = ad->handle; - else - t = Type::tvoidptr; - } - else - assert(0); - if (t->ty == Tstruct) - t = Type::tvoidptr; // t should not be a ref type - assert(!vthis); - vthis = new ThisDeclaration(loc, t); - //vthis->storage_class |= STCref; - members->push(vthis); - } - } - } - } -} - /*************************************** * Return true if struct is POD (Plain Old Data). * This is defined as: @@ -790,7 +817,7 @@ void StructDeclaration::makeNested() */ bool StructDeclaration::isPOD() { - if (isnested || cpctor || postblit || ctor || dtor) + if (enclosing || cpctor || postblit || ctor || dtor) return false; /* Recursively check any fields have a constructor. @@ -800,7 +827,7 @@ bool StructDeclaration::isPOD() { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); - assert(v && v->storage_class & STCfield); + assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); diff --git a/dmd2/target.c b/dmd2/target.c new file mode 100644 index 0000000000..8420547101 --- /dev/null +++ b/dmd2/target.c @@ -0,0 +1,125 @@ + +// Copyright (c) 2013 by Digital Mars +// All Rights Reserved +// written by Iain Buclaw +// 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 "target.h" +#include "mars.h" +#include "mtype.h" + +#if IN_LLVM +unsigned GetTypeAlignment(Type* t); +unsigned GetPointerSize(); +unsigned GetTypeStoreSize(Type* t); +unsigned GetTypeAllocSize(Type* t); +#endif + +int Target::ptrsize; +int Target::realsize; +int Target::realpad; +int Target::realalignsize; + +void Target::init() +{ +#if IN_LLVM + ptrsize = GetPointerSize(); + realsize = GetTypeAllocSize(Type::basic[Tfloat80]); + realpad = realsize - GetTypeStoreSize(Type::basic[Tfloat80]); + realalignsize = GetTypeAlignment(Type::basic[Tfloat80]); +#else + // These have default values for 32 bit code, they get + // adjusted for 64 bit code. + ptrsize = 4; + + if (global.params.isLinux || global.params.isFreeBSD + || global.params.isOpenBSD || global.params.isSolaris) + { + realsize = 12; + realpad = 2; + realalignsize = 4; + } + else if (global.params.isOSX) + { + realsize = 16; + realpad = 6; + realalignsize = 16; + } + else if (global.params.isWindows) + { + realsize = 10; + realpad = 0; + realalignsize = 2; + } + else + assert(0); + + if (global.params.is64bit) + { + ptrsize = 8; + if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris) + { + realsize = 16; + realpad = 6; + realalignsize = 16; + } + } +#endif +} + +/****************************** + * Return memory alignment size of type. + */ + +unsigned Target::alignsize (Type* type) +{ + assert (type->isTypeBasic()); + +#if IN_LLVM + if (type->ty == Tvoid) return 1; + return GetTypeAlignment(type); +#else + switch (type->ty) + { + case Tfloat80: + case Timaginary80: + case Tcomplex80: + return Target::realalignsize; + + case Tcomplex32: + if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD + || global.params.isOpenBSD || global.params.isSolaris) + return 4; + break; + + case Tint64: + case Tuns64: + case Tfloat64: + case Timaginary64: + case Tcomplex64: + if (global.params.isLinux || global.params.isOSX || global.params.isFreeBSD + || global.params.isOpenBSD || global.params.isSolaris) + return global.params.is64bit ? 8 : 4; + break; + + default: + break; + } + return type->size(Loc()); +#endif +} + +/****************************** + * Return field alignment size of type. + */ + +unsigned Target::fieldalign (Type* type) +{ + // LDC_FIXME: Verify this. + return type->alignsize(); +} diff --git a/dmd2/target.h b/dmd2/target.h new file mode 100644 index 0000000000..ad3d956d0a --- /dev/null +++ b/dmd2/target.h @@ -0,0 +1,31 @@ + +// Copyright (c) 2013 by Digital Mars +// All Rights Reserved +// written by Iain Buclaw +// 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 TARGET_H +#define TARGET_H + +// This file contains a data structure that describes a back-end target. +// At present it is incomplete, but in future it should grow to contain +// most or all target machine and target O/S specific information. + +struct Type; + +struct Target +{ + static int ptrsize; + static int realsize; // size a real consumes in memory + static int realpad; // 'padding' added to the CPU real size to bring it up to realsize + static int realalignsize; // alignment for reals + + static void init(); + static unsigned alignsize(Type* type); + static unsigned fieldalign(Type* type); +}; + +#endif diff --git a/dmd2/template.c b/dmd2/template.c index 418f617d9c..2daed08d46 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -32,6 +32,7 @@ #include "identifier.h" #include "hdrgen.h" #include "id.h" +#include "attrib.h" #if WINDOWS_SEH #include @@ -103,6 +104,9 @@ int isError(Object *o) Tuple *v = isTuple(o); if (v) return arrayObjectIsError(&v->objects); + Dsymbol *s = isDsymbol(o); + if (s->errors) + return 1; return 0; } @@ -177,9 +181,8 @@ Expression *getValue(Expression *e) { VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration(); if (v && v->storage_class & STCmanifest) - { ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - e = ei->exp; + { + e = v->getConstInitializer(); } } return e; @@ -191,9 +194,8 @@ Expression *getValue(Dsymbol *&s) { VarDeclaration *v = s->isVarDeclaration(); if (v && v->storage_class & STCmanifest) - { ExpInitializer *ei = v->init->isExpInitializer(); - if (ei) - e = ei->exp, s = NULL; + { + e = v->getConstInitializer(); } } return e; @@ -353,7 +355,7 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) for (size_t i = 0; i < args->dim; i++) { if (i) - buf->writeByte(','); + buf->writestring(", "); Object *o = (*args)[i]; ObjectToCBuffer(buf, hgs, o); } @@ -598,29 +600,28 @@ const char *TemplateDeclaration::kind() int TemplateDeclaration::overloadInsert(Dsymbol *s) { - TemplateDeclaration **pf; - TemplateDeclaration *f; - #if LOG printf("TemplateDeclaration::overloadInsert('%s')\n", s->toChars()); #endif - f = s->isTemplateDeclaration(); - if (!f) + TemplateDeclaration *td = s->isTemplateDeclaration(); + if (!td) return FALSE; + TemplateDeclaration *pthis = this; - for (pf = &pthis; *pf; pf = &(*pf)->overnext) + TemplateDeclaration **ptd; + for (ptd = &pthis; *ptd; ptd = &(*ptd)->overnext) { #if 0 // Conflict if TemplateParameter's match // Will get caught anyway later with TemplateInstance, but // should check it now. - TemplateDeclaration *f2 = *pf; + TemplateDeclaration *f2 = *ptd; - if (f->parameters->dim != f2->parameters->dim) + if (td->parameters->dim != f2->parameters->dim) goto Lcontinue; - for (size_t i = 0; i < f->parameters->dim; i++) - { TemplateParameter *p1 = (*f->parameters)[i]; + for (size_t i = 0; i < td->parameters->dim; i++) + { TemplateParameter *p1 = (*td->parameters)[i]; TemplateParameter *p2 = (*f2->parameters)[i]; if (!p1->overloadMatch(p2)) @@ -637,8 +638,8 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s) #endif } - f->overroot = this; - *pf = f; + td->overroot = this; + *ptd = td; #if LOG printf("\ttrue: no conflict\n"); #endif @@ -681,9 +682,6 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E { Parameter *fparam = Parameter::getNth(fparameters, i); // Remove addMod same as func.d L1065 of FuncDeclaration::semantic3 - //Type *vtype = fparam->type; - //if (fd->type && fd->isPure()) - // vtype = vtype->addMod(MODconst); fparam->storageClass &= (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); fparam->storageClass |= STCparameter; if (fvarargs == 2 && i + 1 == nfparams) @@ -755,7 +753,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, assert(dedtypes_dim >= ti->tiargs->dim || variadic); // Set up scope for parameters - assert((size_t)scope > 0x10000); + assert(scope); ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); @@ -819,7 +817,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, Scope *sc = paramscope->push(); /* There's a chicken-and-egg problem here. We don't know yet if this template - * instantiation will be a local one (isnested is set), and we won't know until + * instantiation will be a local one (enclosing is set), and we won't know until * after selecting the correct template. Thus, function we're nesting inside * is not on the sc scope chain, and this can cause errors in FuncDeclaration::getLevel(). * Workaround the problem by setting a flag to relax the checking on frame errors. @@ -839,7 +837,8 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, fd->vthis = fd->declareThis(paramscope, ad); } - e = e->semantic(sc); + e = e->ctfeSemantic(sc); + e = resolveProperties(sc, e); if (e->op == TOKerror) goto Lnomatch; @@ -919,7 +918,7 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi * as td2. */ - TemplateInstance ti(0, ident); // create dummy template instance + TemplateInstance ti(Loc(), ident); // create dummy template instance Objects dedtypes; #define LOG_LEASTAS 0 @@ -974,8 +973,9 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi * Match function arguments against a specific template function. * Input: * loc instantiation location - * targsi Expression/Type initial list of template arguments - * ethis 'this' argument if !NULL + * sc instantiation scope + * tiargs Expression/Type initial list of template arguments + * tthis 'this' argument if !NULL * fargs arguments to function * Output: * dedargs Expression/Type deduced template arguments @@ -985,17 +985,17 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi * bit 4-7 Match template parameters by initial template arguments */ -MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, - Expression *ethis, Expressions *fargs, +MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objects *tiargs, + Type *tthis, Expressions *fargs, Objects *dedargs) { size_t nfparams; size_t nfargs; - size_t nargsi; // array size of targsi + size_t ntargs; // array size of tiargs size_t fptupindex = IDX_NOTFOUND; size_t tuple_dim = 0; MATCH match = MATCHexact; - MATCH matchTargsi = MATCHexact; + MATCH matchTiargs = MATCHexact; FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); Parameters *fparameters; // function parameter list int fvarargs; // function varargs @@ -1007,17 +1007,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec #if 0 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); - for (size_t i = 0; i < fargs->dim; i++) + for (size_t i = 0; i < (fargs ? fargs->dim : 0); i++) { Expression *e = (*fargs)[i]; printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars()); } printf("fd = %s\n", fd->toChars()); printf("fd->type = %s\n", fd->type->toChars()); - if (ethis) - printf("ethis->type = %s\n", ethis->type->toChars()); + if (tthis) + printf("tthis = %s\n", tthis->toChars()); #endif - assert((size_t)scope > 0x10000); + assert(scope); dedargs->setDim(parameters->dim); dedargs->zero(); @@ -1032,10 +1032,11 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; Scope *paramscope = scope->push(paramsym); + paramscope->callsc = sc; paramscope->stc = 0; TemplateTupleParameter *tp = isVariadic(); - int tp_is_declared = 0; + bool tp_is_declared = false; #if 0 for (size_t i = 0; i < dedargs->dim; i++) @@ -1048,15 +1049,15 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec #endif - nargsi = 0; - if (targsi) + ntargs = 0; + if (tiargs) { // Set initial template arguments - nargsi = targsi->dim; + ntargs = tiargs->dim; size_t n = parameters->dim; if (tp) n--; - if (nargsi > n) + if (ntargs > n) { if (!tp) goto Lnomatch; @@ -1067,19 +1068,19 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec assert(parameters->dim); (*dedargs)[parameters->dim - 1] = t; - tuple_dim = nargsi - n; + tuple_dim = ntargs - n; t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { - t->objects[i] = (*targsi)[n + i]; + t->objects[i] = (*tiargs)[n + i]; } declareParameter(paramscope, tp, t); - tp_is_declared = 1; + tp_is_declared = true; } else - n = nargsi; + n = ntargs; - memcpy(dedargs->tdata(), targsi->tdata(), n * sizeof(*dedargs->tdata())); + memcpy(dedargs->tdata(), tiargs->tdata(), n * sizeof(*dedargs->tdata())); for (size_t i = 0; i < n; i++) { assert(i < parameters->dim); @@ -1091,8 +1092,8 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec //printf("\tdeduceType m = %d\n", m); if (m == MATCHnomatch) goto Lnomatch; - if (m < matchTargsi) - matchTargsi = m; + if (m < matchTiargs) + matchTiargs = m; sparam->semantic(paramscope); if (!paramscope->insert(sparam)) @@ -1126,23 +1127,22 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec /* Check for match of function arguments with variadic template * parameter, such as: * - * template Foo(T, A...) { void Foo(T t, A a); } - * void main() { Foo(1,2,3); } + * void foo(T, A...)(T t, A a); + * void main() { foo(1,2,3); } */ if (tp) // if variadic { if (nfparams == 0 && nfargs != 0) // if no function parameters { - if (tp_is_declared) - goto L2; - Tuple *t = new Tuple(); - //printf("t = %p\n", t); - (*dedargs)[parameters->dim - 1] = t; - declareParameter(paramscope, tp, t); - goto L2; + if (!tp_is_declared) + { + Tuple *t = new Tuple(); + //printf("t = %p\n", t); + (*dedargs)[parameters->dim - 1] = t; + declareParameter(paramscope, tp, t); + tp_is_declared = true; + } } - else if (nfargs < nfparams - 1) - goto L1; else { /* Figure out which of the function parameters matches @@ -1162,22 +1162,125 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec if (fvarargs) // variadic function doesn't goto Lnomatch; // go with variadic template - if (tp_is_declared) - goto L2; + goto L1; + } + fptupindex = IDX_NOTFOUND; + L1: + ; + } + } - // Apply function parameter storage classes to parameter type - tid = (TypeIdentifier *)tid->addStorageClass(fparam->storageClass); +#if DMDV2 + if (tthis) + { + bool hasttp = false; + // Match 'tthis' to any TemplateThisParameter's + for (size_t i = 0; i < parameters->dim; i++) + { TemplateParameter *tp = (*parameters)[i]; + TemplateThisParameter *ttp = tp->isTemplateThisParameter(); + if (ttp) + { hasttp = true; + + Type *t = new TypeIdentifier(Loc(), ttp->ident); + MATCH m = tthis->deduceType(paramscope, t, parameters, &dedtypes); + if (!m) + goto Lnomatch; + if (m < match) + match = m; // pick worst match + } + } + + // Match attributes of tthis against attributes of fd + if (fd->type && !fd->isCtorDeclaration()) + { + unsigned mod = fd->type->mod; + StorageClass stc = scope->stc | fd->storage_class2; + // Propagate parent storage class (see bug 5504) + Dsymbol *p = parent; + while (p->isTemplateDeclaration() || p->isTemplateInstance()) + p = p->parent; + AggregateDeclaration *ad = p->isAggregateDeclaration(); + if (ad) + stc |= ad->storage_class; + + if (stc & (STCshared | STCsynchronized)) + mod |= MODshared; + if (stc & STCimmutable) + mod |= MODimmutable; + if (stc & STCconst) + mod |= MODconst; + if (stc & STCwild) + mod |= MODwild; + // Fix mod + if (mod & MODimmutable) + mod = MODimmutable; + if (mod & MODconst) + mod &= ~STCwild; + + unsigned thismod = tthis->mod; + if (hasttp) + mod = MODmerge(thismod, mod); + if (thismod != mod) + { + if (!MODmethodConv(thismod, mod)) + goto Lnomatch; + if (MATCHconst < match) + match = MATCHconst; + } + } + } +#endif + + // Loop through the function parameters + { + //printf("%s nfargs=%d, nfparams=%d, tuple_dim = %d\n", toChars(), nfargs, nfparams, tuple_dim); + //printf("\ttp = %p, fptupindex = %d, found = %d, tp_is_declared = %d\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, tp_is_declared); + size_t argi = 0; + for (size_t parami = 0; parami < nfparams; parami++) + { + Parameter *fparam = Parameter::getNth(fparameters, parami); + + // Apply function parameter storage classes to parameter types + Type *prmtype = fparam->type->addStorageClass(fparam->storageClass); + + /* See function parameters which wound up + * as part of a template tuple parameter. + */ + if (fptupindex != IDX_NOTFOUND && parami == fptupindex) + { + assert(prmtype->ty == Tident); + TypeIdentifier *tid = (TypeIdentifier *)prmtype; + if (!tp_is_declared) + { /* The types of the function arguments * now form the tuple argument. */ Tuple *t = new Tuple(); (*dedargs)[parameters->dim - 1] = t; - tuple_dim = nfargs - (nfparams - 1); + /* Count function parameters following a tuple parameter. + * void foo(U, T...)(int y, T, U, int) {} // rem == 2 (U, int) + */ + size_t rem = 0; + for (size_t j = parami + 1; j < nfparams; j++) + { + Parameter *p = Parameter::getNth(fparameters, j); + if (!inferparams || !p->type->reliesOnTident(inferparams)) + { + Type *pt = p->type->syntaxCopy()->semantic(fd->loc, paramscope); + rem += pt->ty == Ttuple ? ((TypeTuple *)pt)->arguments->dim : 1; + } + else + { + ++rem; + } + } + + tuple_dim = nfargs - argi - rem; t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) - { Expression *farg = (*fargs)[fptupindex + i]; + { Expression *farg = (*fargs)[argi + i]; // Check invalid arguments to detect errors early. if (farg->op == TOKerror || farg->type->ty == Terror) @@ -1202,7 +1305,6 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(MODwild, MODimmutable): case X(MODwild | MODshared, MODshared): case X(MODwild | MODshared, MODconst | MODshared): - if (mod & MODwild) wildmatch |= MODwild; else if (mod == 0) @@ -1227,14 +1329,13 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(0, MODconst | MODshared): case X(0, MODwild): case X(0, MODwild | MODshared): - // foo(U:U) T => T - // foo(U:U) const(T) => const(T) - // foo(U:U) immutable(T) => immutable(T) - // foo(U:U) shared(T) => shared(T) - // foo(U:U) const(shared(T)) => const(shared(T)) - // foo(U:U) wild(T) => wild(T) - // foo(U:U) wild(shared(T)) => wild(shared(T)) - + // foo(U:U) T => T + // foo(U:U) const(T) => const(T) + // foo(U:U) immutable(T) => immutable(T) + // foo(U:U) shared(T) => shared(T) + // foo(U:U) const(shared(T)) => const(shared(T)) + // foo(U:U) wild(T) => wild(T) + // foo(U:U) wild(shared(T)) => wild(shared(T)) tt = farg->type; m = MATCHexact; break; @@ -1245,13 +1346,12 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(MODconst | MODshared, MODconst | MODshared): case X(MODwild, MODwild): case X(MODwild | MODshared, MODwild | MODshared): - // foo(U:const(U)) const(T) => T - // foo(U:immutable(U)) immutable(T) => T - // foo(U:shared(U)) shared(T) => T - // foo(U:const(shared(U)) const(shared(T)) => T - // foo(U:wild(U)) wild(T) => T - // foo(U:wild(shared(U)) wild(shared(T)) => T - + // foo(U:const(U)) const(T) => T + // foo(U:immutable(U)) immutable(T) => T + // foo(U:shared(U)) shared(T) => T + // foo(U:const(shared(U))) const(shared(T)) => T + // foo(U:wild(U)) wild(T) => T + // foo(U:wild(shared(U))) wild(shared(T)) => T tt = farg->type->mutableOf()->unSharedOf(); m = MATCHexact; break; @@ -1262,12 +1362,11 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(MODconst | MODshared, MODimmutable): case X(MODconst, MODwild): case X(MODconst, MODwild | MODshared): - // foo(U:const(U)) T => T - // foo(U:const(U)) immutable(T) => T - // foo(U:const(U)) const(shared(T)) => shared(T) - // foo(U:const(shared(U)) immutable(T) => T - // foo(U:const(U)) wild(shared(T)) => shared(T) - + // foo(U:const(U)) T => T + // foo(U:const(U)) immutable(T) => T + // foo(U:const(U)) const(shared(T)) => shared(T) + // foo(U:const(shared(U))) immutable(T) => T + // foo(U:const(U)) wild(shared(T)) => shared(T) tt = farg->type->mutableOf(); m = MATCHconst; break; @@ -1275,9 +1374,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(MODshared, MODconst | MODshared): case X(MODconst | MODshared, MODshared): case X(MODshared, MODwild | MODshared): - // foo(U:shared(U)) const(shared(T)) => const(T) - // foo(U:const(shared(U)) shared(T) => T - // foo(U:shared(U)) wild(shared(T)) => wild(T) + // foo(U:shared(U)) const(shared(T)) => const(T) + // foo(U:const(shared(U))) shared(T) => T + // foo(U:shared(U)) wild(shared(T)) => wild(T) tt = farg->type->unSharedOf(); m = MATCHconst; break; @@ -1309,34 +1408,33 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec case X(MODimmutable, MODwild | MODshared): case X(MODconst | MODshared, MODwild | MODshared): case X(MODwild, MODwild | MODshared): - - // foo(U:immutable(U)) T => nomatch - // foo(U:immutable(U)) const(T) => nomatch - // foo(U:immutable(U)) shared(T) => nomatch - // foo(U:immutable(U)) const(shared(T)) => nomatch - // foo(U:const(U)) shared(T) => nomatch - // foo(U:shared(U)) T => nomatch - // foo(U:shared(U)) const(T) => nomatch - // foo(U:shared(U)) immutable(T) => nomatch - // foo(U:const(shared(U)) T => nomatch - // foo(U:const(shared(U)) const(T) => nomatch - // foo(U:immutable(U)) wild(T) => nomatch - // foo(U:shared(U)) wild(T) => nomatch - // foo(U:const(shared(U)) wild(T) => nomatch - // foo(U:wild(U)) T => nomatch - // foo(U:wild(U)) const(T) => nomatch - // foo(U:wild(U)) immutable(T) => nomatch - // foo(U:wild(U)) shared(T) => nomatch - // foo(U:wild(U)) const(shared(T)) => nomatch - // foo(U:wild(shared(U)) T => nomatch - // foo(U:wild(shared(U)) const(T) => nomatch - // foo(U:wild(shared(U)) immutable(T) => nomatch - // foo(U:wild(shared(U)) shared(T) => nomatch - // foo(U:wild(shared(U)) const(shared(T)) => nomatch - // foo(U:wild(shared(U)) wild(T) => nomatch - // foo(U:immutable(U)) wild(shared(T)) => nomatch - // foo(U:const(shared(U))) wild(shared(T)) => nomatch - // foo(U:wild(U)) wild(shared(T)) => nomatch + // foo(U:immutable(U)) T => nomatch + // foo(U:immutable(U)) const(T) => nomatch + // foo(U:immutable(U)) shared(T) => nomatch + // foo(U:immutable(U)) const(shared(T)) => nomatch + // foo(U:const(U)) shared(T) => nomatch + // foo(U:shared(U)) T => nomatch + // foo(U:shared(U)) const(T) => nomatch + // foo(U:shared(U)) immutable(T) => nomatch + // foo(U:const(shared(U))) T => nomatch + // foo(U:const(shared(U))) const(T) => nomatch + // foo(U:immutable(U)) wild(T) => nomatch + // foo(U:shared(U)) wild(T) => nomatch + // foo(U:const(shared(U))) wild(T) => nomatch + // foo(U:wild(U)) T => nomatch + // foo(U:wild(U)) const(T) => nomatch + // foo(U:wild(U)) immutable(T) => nomatch + // foo(U:wild(U)) shared(T) => nomatch + // foo(U:wild(U)) const(shared(T)) => nomatch + // foo(U:wild(shared(U))) T => nomatch + // foo(U:wild(shared(U))) const(T) => nomatch + // foo(U:wild(shared(U))) immutable(T) => nomatch + // foo(U:wild(shared(U))) shared(T) => nomatch + // foo(U:wild(shared(U))) const(shared(T)) => nomatch + // foo(U:wild(shared(U))) wild(T) => nomatch + // foo(U:immutable(U)) wild(shared(T)) => nomatch + // foo(U:const(shared(U))) wild(shared(T)) => nomatch + // foo(U:wild(U)) wild(shared(T)) => nomatch m = MATCHnomatch; break; @@ -1363,104 +1461,45 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec t->objects[i] = tt; } declareParameter(paramscope, tp, t); - goto L2; } - fptupindex = IDX_NOTFOUND; - } - } - -L1: - if (nfparams == nfargs) - ; - else if (nfargs > nfparams) - { - if (fvarargs == 0) - goto Lnomatch; // too many args, no match - match = MATCHconvert; // match ... with a conversion - } - -L2: -#if DMDV2 - if (ethis) - { - // Match 'ethis' to any TemplateThisParameter's - for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = (*parameters)[i]; - TemplateThisParameter *ttp = tp->isTemplateThisParameter(); - if (ttp) - { MATCH m; - - Type *t = new TypeIdentifier(0, ttp->ident); - m = ethis->type->deduceType(paramscope, t, parameters, &dedtypes); - if (!m) - goto Lnomatch; - if (m < match) - match = m; // pick worst match - } - } - - // Match attributes of ethis against attributes of fd - if (fd->type && !fd->isCtorDeclaration()) - { - Type *tthis = ethis->type; - unsigned mod = fd->type->mod; - StorageClass stc = scope->stc | fd->storage_class2; - // Propagate parent storage class (see bug 5504) - Dsymbol *p = parent; - while (p->isTemplateDeclaration() || p->isTemplateInstance()) - p = p->parent; - AggregateDeclaration *ad = p->isAggregateDeclaration(); - if (ad) - stc |= ad->storage_class; - - if (stc & (STCshared | STCsynchronized)) - mod |= MODshared; - if (stc & STCimmutable) - mod |= MODimmutable; - if (stc & STCconst) - mod |= MODconst; - if (stc & STCwild) - mod |= MODwild; - // Fix mod - if (mod & MODimmutable) - mod = MODimmutable; - if (mod & MODconst) - mod &= ~STCwild; - if (tthis->mod != mod) - { - if (!MODmethodConv(tthis->mod, mod)) - goto Lnomatch; - if (MATCHconst < match) - match = MATCHconst; - } - } - } -#endif - - // Loop through the function parameters - for (size_t parami = 0; parami < nfparams; parami++) - { - /* Skip over function parameters which wound up - * as part of a template tuple parameter. - */ - if (parami == fptupindex) + argi += tuple_dim; continue; - /* Set i = index into function arguments - * Function parameters correspond to function arguments as follows. - * Note that tuple_dim may be zero, and there may be default or - * variadic arguments at the end. - * arg [0..fptupindex] == param[0..fptupindex] - * arg [fptupindex..fptupindex+tuple_dim] == param[fptupindex] - * arg[fputupindex+dim.. ] == param[fptupindex+1.. ] - */ - size_t i = parami; - if (fptupindex != IDX_NOTFOUND && parami > fptupindex) - i += tuple_dim - 1; + } - Parameter *fparam = Parameter::getNth(fparameters, parami); - Type *prmtype = fparam->type; + // If parameter type doesn't depend on inferred template parameters, + // semantic it to get actual type. + if (!inferparams || !prmtype->reliesOnTident(inferparams)) + { + // should copy prmtype to avoid affecting semantic result + prmtype = prmtype->syntaxCopy()->semantic(fd->loc, paramscope); - if (i >= nfargs) // if not enough arguments + if (prmtype->ty == Ttuple) + { + TypeTuple *tt = (TypeTuple *)prmtype; + size_t tt_dim = tt->arguments->dim; + for (size_t j = 0; j < tt_dim; j++, ++argi) + { + Parameter *p = (*tt->arguments)[j]; + if (j == tt_dim - 1 && fvarargs == 2 && parami + 1 == nfparams && argi < nfargs) + { + prmtype = p->type; + goto Lvarargs; + } + if (argi >= nfargs) + { + if (p->defaultArg) + continue; + goto Lnomatch; + } + Expression *farg = (*fargs)[argi]; + if (!farg->implicitConvTo(p->type)) + goto Lnomatch; + } + continue; + } + } + + if (argi >= nfargs) // if not enough arguments { if (fparam->defaultArg) { /* Default arguments do not participate in template argument @@ -1471,7 +1510,7 @@ L2: } else { - Expression *farg = (*fargs)[i]; + Expression *farg = (*fargs)[argi]; // Check invalid arguments to detect errors early. if (farg->op == TOKerror || farg->type->ty == Terror) @@ -1484,28 +1523,30 @@ Lretry: #endif Type *argtype = farg->type; - // Apply function parameter storage classes to parameter types - prmtype = prmtype->addStorageClass(fparam->storageClass); - - // If parameter type doesn't depend on inferred template parameters, - // semantic it to get actual type. - if (!inferparams || !prmtype->reliesOnTident(inferparams)) - { - // should copy prmtype to avoid affecting semantic result - prmtype = prmtype->syntaxCopy()->semantic(fd->loc, paramscope); - } - #if DMDV2 - /* Allow string literals which are type [] to match with [dim] + /* Allow expressions that have CT-known boundaries and type [] to match with [dim] */ - if (farg->op == TOKstring) - { StringExp *se = (StringExp *)farg; - if (!se->committed && argtype->ty == Tarray && - prmtype->toBasetype()->ty == Tsarray) - { + Type *taai; + if ( argtype->ty == Tarray && + (prmtype->ty == Tsarray || + prmtype->ty == Taarray && (taai = ((TypeAArray *)prmtype)->index)->ty == Tident && + ((TypeIdentifier *)taai)->idents.dim == 0)) + { + if (farg->op == TOKstring) + { StringExp *se = (StringExp *)farg; argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex)); argtype = argtype->semantic(se->loc, NULL); - argtype = argtype->invariantOf(); + } + else if (farg->op == TOKslice) + { SliceExp *se = (SliceExp *)farg; + Type *tsa = se->toStaticArrayType(); + if (tsa) + argtype = tsa; + } + else if (farg->op == TOKarrayliteral) + { ArrayLiteralExp *ae = (ArrayLiteralExp *)farg; + argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(ae->loc, ae->elements->dim, Type::tindex)); + argtype = argtype->semantic(ae->loc, NULL); } } @@ -1514,7 +1555,7 @@ Lretry: if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; Type *tp = prmtype; - Expression *e = fe->inferType(tp, 1, parameters); + Expression *e = fe->inferType(tp, 1, paramscope, inferparams); if (!e) goto Lvarargs; farg = e; @@ -1535,7 +1576,7 @@ Lretry: } #endif - if (fvarargs == 2 && i + 1 == nfparams && i + 1 < nfargs) + if (fvarargs == 2 && parami + 1 == nfparams && argi + 1 < nfargs) goto Lvarargs; unsigned wm = 0; @@ -1593,9 +1634,17 @@ Lretry: } if (m && (fparam->storageClass & (STCref | STCauto)) == STCref) - { if (!farg->isLvalue()) + { + if (!farg->isLvalue()) { - goto Lnomatch; + if (farg->op == TOKstring && argtype->ty == Tsarray) + { + } + else if (farg->op == TOKslice && argtype->ty == Tsarray) + { // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] + } + else + goto Lnomatch; } } if (m && (fparam->storageClass & STCout)) @@ -1609,6 +1658,7 @@ Lretry: if (m) { if (m < match) match = m; // pick worst match + argi++; continue; } } @@ -1617,7 +1667,7 @@ Lretry: /* The following code for variadic arguments closely * matches TypeFunction::callMatch() */ - if (!(fvarargs == 2 && i + 1 == nfparams)) + if (!(fvarargs == 2 && parami + 1 == nfparams)) goto Lnomatch; /* Check for match with function parameter T... @@ -1632,12 +1682,12 @@ Lretry: if (tb->ty == Tsarray) { TypeSArray *tsa = (TypeSArray *)tb; dinteger_t sz = tsa->dim->toInteger(); - if (sz != nfargs - i) + if (sz != nfargs - argi) goto Lnomatch; } else if (tb->ty == Taarray) { TypeAArray *taa = (TypeAArray *)tb; - Expression *dim = new IntegerExp(loc, nfargs - i, Type::tsize_t); + Expression *dim = new IntegerExp(loc, nfargs - argi, Type::tsize_t); size_t i = templateParameterLookup(taa->index, parameters); if (i == IDX_NOTFOUND) @@ -1647,7 +1697,7 @@ Lretry: taa->index->resolve(loc, sc, &e, &t, &s); if (!e) goto Lnomatch; - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); e = e->implicitCastTo(sc, Type::tsize_t); e = e->optimize(WANTvalue); if (!dim->equals(e)) @@ -1667,7 +1717,7 @@ Lretry: } else { - Type *vt = tvp->valType->semantic(0, sc); + Type *vt = tvp->valType->semantic(Loc(), sc); MATCH m = (MATCH)dim->implicitConvTo(vt); if (!m) goto Lnomatch; @@ -1679,16 +1729,16 @@ Lretry: } case Tarray: { TypeArray *ta = (TypeArray *)tb; - for (; i < nfargs; i++) + for (; argi < nfargs; argi++) { - Expression *arg = (*fargs)[i]; + Expression *arg = (*fargs)[argi]; assert(arg); if (arg->op == TOKfunction) { FuncExp *fe = (FuncExp *)arg; Type *tp = tb->nextOf(); - Expression *e = fe->inferType(tp, 1, parameters); + Expression *e = fe->inferType(tp, 1, paramscope, inferparams); if (!e) goto Lnomatch; arg = e; @@ -1733,11 +1783,16 @@ Lretry: default: goto Lnomatch; } + ++argi; + } + //printf("-> argi = %d, nfargs = %d\n", argi, nfargs); + if (argi != nfargs && !fvarargs) + goto Lnomatch; } Lmatch: - for (size_t i = nargsi; i < dedargs->dim; i++) + for (size_t i = ntargs; i < dedargs->dim; i++) { TemplateParameter *tparam = (*parameters)[i]; //printf("tparam[%d] = %s\n", i, tparam->ident->toChars()); @@ -1775,7 +1830,7 @@ Lmatch: { if (tp && // if tuple parameter and fptupindex == IDX_NOTFOUND && // tuple parameter was not in function parameter list and - nargsi == dedargs->dim - 1) // we're one argument short (i.e. no tuple argument) + ntargs == dedargs->dim - 1) // we're one argument short (i.e. no tuple argument) { // make tuple argument an empty tuple oded = (Object *)new Tuple(); } @@ -1844,7 +1899,8 @@ Lmatch: fd->vthis = fd->declareThis(paramscope, ad); } - e = e->semantic(paramscope); + e = e->ctfeSemantic(paramscope); + e = resolveProperties(sc, e); if (fd && fd->vthis) fd->vthis = vthissave; @@ -1877,7 +1933,7 @@ Lmatch: paramscope->pop(); //printf("\tmatch %d\n", match); - return (MATCH)(match | (matchTargsi<<4)); + return (MATCH)(match | (matchTiargs<<4)); Lnomatch: paramscope->pop(); @@ -1926,12 +1982,12 @@ Object *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, if (targ) { //printf("type %s\n", targ->toChars()); - s = new AliasDeclaration(0, tp->ident, targ); + s = new AliasDeclaration(Loc(), tp->ident, targ); } else if (sa) { //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars()); - s = new AliasDeclaration(0, tp->ident, sa); + s = new AliasDeclaration(Loc(), tp->ident, sa); } else if (ea && ea->op == TOKfunction) { @@ -1939,8 +1995,7 @@ Object *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, sa = ((FuncExp *)ea)->td; else sa = ((FuncExp *)ea)->fd; - - s = new AliasDeclaration(0, tp->ident, sa); + s = new AliasDeclaration(Loc(), tp->ident, sa); } else if (ea) { @@ -1951,7 +2006,7 @@ Object *TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Type *t = tvp ? tvp->valType : NULL; v = new VarDeclaration(loc, t, tp->ident, init); - v->storage_class = STCmanifest; + v->storage_class = STCmanifest | STCtemplateparameter; s = v; } else if (va) @@ -2008,16 +2063,16 @@ int TemplateDeclaration::isOverloadable() * to expand, and return that function. * If no match, give error message and return NULL. * Input: - * sc instantiation scope * loc instantiation location - * targsi initial list of template arguments - * ethis if !NULL, the 'this' pointer argument + * sc instantiation scope + * tiargs initial list of template arguments + * tthis if !NULL, the 'this' pointer argument * fargs arguments to function * flags 1: do not issue error message on no match, just return NULL */ -FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, - Objects *targsi, Expression *ethis, Expressions *fargs, int flags) +FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Loc loc, Scope *sc, + Objects *tiargs, Type *tthis, Expressions *fargs, int flags) { MATCH m_best = MATCHnomatch; MATCH m_best2 = MATCHnomatch; @@ -2026,18 +2081,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, Objects *tdargs = new Objects(); TemplateInstance *ti; FuncDeclaration *fd_best; + Type *tthis_best = NULL; #if 0 printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars()); - printf(" targsi:\n"); - if (targsi) - { for (size_t i = 0; i < targsi->dim; i++) - { Object *arg = (*targsi)[i]; + printf(" tiargs:\n"); + if (tiargs) + { for (size_t i = 0; i < tiargs->dim; i++) + { Object *arg = (*tiargs)[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 ? fargs->dim : 0); i++) { Expression *arg = (*fargs)[i]; printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); //printf("\tty = %d\n", arg->type->ty); @@ -2054,9 +2110,9 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, } if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration()) { - if (!targsi) - targsi = new Objects(); - TemplateInstance *ti = new TemplateInstance(loc, td, targsi); + if (!tiargs) + tiargs = new Objects(); + TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); Objects dedtypes; dedtypes.setDim(td->parameters->dim); @@ -2077,18 +2133,18 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, td->error("is not a function template"); goto Lerror; } - fd = fd->overloadResolve(loc, ethis, fargs, flags); + fd = resolveFuncCall(loc, sc, fd, NULL, tthis, fargs, flags); if (!fd) continue; TypeFunction *tf = (TypeFunction *)fd->type; - MATCH m = (MATCH) tf->callMatch(fd->needThis() && !fd->isCtorDeclaration() ? ethis : NULL, fargs); + MATCH m = (MATCH) tf->callMatch(fd->needThis() && !fd->isCtorDeclaration() ? tthis : NULL, fargs); if (m < m_best) continue; // td is the new best match td_ambig = NULL; - assert((size_t)td->scope > 0x10000); + assert(td->scope); td_best = td; fd_best = fd; m_best = m; @@ -2102,13 +2158,38 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, Objects dedargs; FuncDeclaration *fd = NULL; - m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); + m = td->deduceFunctionTemplateMatch(loc, sc, tiargs, tthis, fargs, &dedargs); m2 = (MATCH)(m >> 4); m = (MATCH)(m & 0xF); //printf("deduceFunctionTemplateMatch = %d, m2 = %d\n", m, m2); if (!m) // if no match continue; + Type *tthis_fd = NULL; + if (td->onemember->toAlias()->isFuncDeclaration()->isCtorDeclaration()) + { + // Constructor call requires additional check. + // For that, do instantiate in early stage. + fd = td->doHeaderInstantiation(sc, &dedargs, tthis, fargs); + if (!fd) + goto Lerror; + + TypeFunction *tf = (TypeFunction *)fd->type; + tthis_fd = fd->needThis() ? tthis : NULL; + if (tthis_fd) + { + assert(tf->next); + if (MODimplicitConv(tf->mod, tthis_fd->mod) || + tf->isWild() && tf->isShared() == tthis_fd->isShared() || + fd->isolateReturn()) + { + tthis_fd = NULL; + } + else + continue; // MATCHnomatch + } + } + if (m2 < m_best2) goto Ltd_best; if (m2 > m_best2) @@ -2133,14 +2214,17 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, if (!fd_best) { - fd_best = td_best->doHeaderInstantiation(sc, tdargs, fargs); + fd_best = td_best->doHeaderInstantiation(sc, tdargs, tthis, fargs); if (!fd_best) goto Lerror; + tthis_best = fd_best->needThis() ? tthis : NULL; } + if (!fd) { - fd = td->doHeaderInstantiation(sc, &dedargs, fargs); + fd = td->doHeaderInstantiation(sc, &dedargs, tthis, fargs); if (!fd) goto Lerror; + tthis_fd = fd->needThis() ? tthis : NULL; } assert(fd && fd_best); @@ -2148,8 +2232,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, // Disambiguate by tf->callMatch TypeFunction *tf1 = (TypeFunction *)fd->type; TypeFunction *tf2 = (TypeFunction *)fd_best->type; - MATCH c1 = (MATCH) tf1->callMatch(fd->needThis() && !fd->isCtorDeclaration() ? ethis : NULL, fargs); - MATCH c2 = (MATCH) tf2->callMatch(fd_best->needThis() && !fd_best->isCtorDeclaration() ? ethis : NULL, fargs); + MATCH c1 = tf1->callMatch(tthis_fd, fargs); + MATCH c2 = tf2->callMatch(tthis_best, fargs); //printf("2: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -2180,9 +2264,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, Ltd: // td is the new best match td_ambig = NULL; - assert((size_t)td->scope > 0x10000); + assert(td->scope); td_best = td; fd_best = fd; + tthis_best = tthis_fd; m_best = m; m_best2 = m2; tdargs->setDim(dedargs.dim); @@ -2230,12 +2315,14 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, /* The best match is td_best with arguments tdargs. * Now instantiate the template. */ - assert((size_t)td_best->scope > 0x10000); + assert(td_best->scope); ti = new TemplateInstance(loc, td_best, tdargs); ti->semantic(sc, fargs); fd_best = ti->toAlias()->isFuncDeclaration(); if (!fd_best) goto Lerror; + if (!((TypeFunction*)fd_best->type)->callMatch(fd_best->needThis() && !fd_best->isCtorDeclaration() ? tthis : NULL, fargs)) + goto Lerror; if (FuncLiteralDeclaration *fld = fd_best->isFuncLiteralDeclaration()) { @@ -2261,7 +2348,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, } } - fd_best->functionSemantic(); + if (!(flags & 1)) + fd_best->functionSemantic(); return fd_best; @@ -2273,12 +2361,12 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, HdrGenState hgs; OutBuffer bufa; - Objects *args = targsi; + Objects *args = tiargs; if (args) { for (size_t i = 0; i < args->dim; i++) { if (i) - bufa.writeByte(','); + bufa.writestring(", "); Object *oarg = (*args)[i]; ObjectToCBuffer(&bufa, &hgs, oarg); } @@ -2301,7 +2389,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, * Limited function template instantiation for using fd->leastAsSpecialized() */ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, - Objects *tdargs, Expressions *fargs) + Objects *tdargs, Type *tthis, Expressions *fargs) { FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); if (!fd) @@ -2313,7 +2401,7 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, printf("\ttdargs[%d] = %s\n", i, ((Object *)tdargs->data[i])->toChars()); #endif - assert((size_t)scope > 0x10000); + assert(scope); TemplateInstance *ti = new TemplateInstance(loc, this, tdargs); ti->tinst = sc->tinst; { @@ -2326,7 +2414,10 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, // function body and contracts are not need //fd = fd->syntaxCopy(NULL)->isFuncDeclaration(); - fd = new FuncDeclaration(fd->loc, fd->endloc, fd->ident, fd->storage_class, fd->type->syntaxCopy()); + if (fd->isCtorDeclaration()) + fd = new CtorDeclaration(fd->loc, fd->endloc, fd->storage_class, fd->type->syntaxCopy()); + else + fd = new FuncDeclaration(fd->loc, fd->endloc, fd->ident, fd->storage_class, fd->type->syntaxCopy()); fd->parent = ti; Scope *scope = this->scope; @@ -2335,11 +2426,23 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, ti->argsym->parent = scope->parent; scope = scope->push(ti->argsym); + bool hasttp = false; + Scope *paramscope = scope->push(); paramscope->stc = 0; ti->declareParameters(paramscope); paramscope->pop(); + if (tthis) + { + // Match 'tthis' to any TemplateThisParameter's + for (size_t i = 0; i < parameters->dim; i++) + { TemplateParameter *tp = (*parameters)[i]; + TemplateThisParameter *ttp = tp->isTemplateThisParameter(); + if (ttp) + hasttp = true; + } + } { TypeFunction *tf = (TypeFunction *)fd->type; if (tf && tf->ty == Tfunction) @@ -2348,15 +2451,39 @@ FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc, Scope *sc2; sc2 = scope->push(ti); - sc2->parent = /*isnested ? sc->parent :*/ ti; + sc2->parent = /*enclosing ? sc->parent :*/ ti; sc2->tinst = ti; { Scope *sc = sc2; sc = sc->push(); + if (hasttp) + fd->type = fd->type->addMod(tthis->mod); + //printf("tthis = %s, fdtype = %s\n", tthis->toChars(), fd->type->toChars()); if (fd->isCtorDeclaration()) + { sc->flags |= SCOPEctor; + + Dsymbol *parent = toParent2(); + Type *tret; + AggregateDeclaration *ad = parent->isAggregateDeclaration(); + if (!ad || parent->isUnionDeclaration()) + { + tret = Type::tvoid; + } + else + { tret = ad->handle; + assert(tret); + tret = tret->addStorageClass(fd->storage_class | sc->stc); + tret = tret->addMod(fd->type->mod); + } + ((TypeFunction *)fd->type)->next = tret; + if (ad && ad->isStructDeclaration()) + ((TypeFunction *)fd->type)->isref = 1; + //printf("fd->type = %s\n", fd->type->toChars()); + } + fd->type = fd->type->addSTC(sc->stc); fd->type = fd->type->semantic(fd->loc, sc); sc = sc->pop(); } @@ -2465,6 +2592,11 @@ char *TemplateDeclaration::toChars() return (char *)buf.extractData(); } +enum PROT TemplateDeclaration::prot() +{ + return protection; +} + /* ======================== Type ============================================ */ /**** @@ -2629,31 +2761,31 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, case X(0, MODconst | MODshared): case X(0, MODwild): case X(0, MODwild | MODshared): - // foo(U:U) T => T - // foo(U:U) const(T) => const(T) - // foo(U:U) immutable(T) => immutable(T) - // foo(U:U) shared(T) => shared(T) - // foo(U:U) const(shared(T)) => const(shared(T)) - // foo(U:U) wild(T) => wild(T) - // foo(U:U) wild(shared(T)) => wild(shared(T)) + // foo(U:U) T => T + // foo(U:U) const(T) => const(T) + // foo(U:U) immutable(T) => immutable(T) + // foo(U:U) shared(T) => shared(T) + // foo(U:U) const(shared(T)) => const(shared(T)) + // foo(U:U) wild(T) => wild(T) + // foo(U:U) wild(shared(T)) => wild(shared(T)) if (!at) { (*dedtypes)[i] = tt; goto Lexact; } break; - case X(MODconst, MODconst): - case X(MODimmutable, MODimmutable): - case X(MODshared, MODshared): + case X(MODconst, MODconst): + case X(MODimmutable, MODimmutable): + case X(MODshared, MODshared): case X(MODconst | MODshared, MODconst | MODshared): - case X(MODwild, MODwild): - case X(MODwild | MODshared, MODwild | MODshared): - // foo(U:const(U)) const(T) => T - // foo(U:immutable(U)) immutable(T) => T - // foo(U:shared(U)) shared(T) => T - // foo(U:const(shared(U)) const(shared(T)) => T - // foo(U:wild(U)) wild(T) => T - // foo(U:wild(shared(U)) wild(shared(T)) => T + case X(MODwild, MODwild): + case X(MODwild | MODshared, MODwild | MODshared): + // foo(U:const(U)) const(T) => T + // foo(U:immutable(U)) immutable(T) => T + // foo(U:shared(U)) shared(T) => T + // foo(U:const(shared(U))) const(shared(T)) => T + // foo(U:wild(U)) wild(T) => T + // foo(U:wild(shared(U))) wild(shared(T)) => T tt = mutableOf()->unSharedOf(); if (!at) { (*dedtypes)[i] = tt; @@ -2661,17 +2793,17 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, } break; - case X(MODconst, 0): - case X(MODconst, MODimmutable): - case X(MODconst, MODconst | MODshared): + case X(MODconst, 0): + case X(MODconst, MODimmutable): + case X(MODconst, MODconst | MODshared): case X(MODconst | MODshared, MODimmutable): - case X(MODconst, MODwild): - case X(MODconst, MODwild | MODshared): - // foo(U:const(U)) T => T - // foo(U:const(U)) immutable(T) => T - // foo(U:const(U)) const(shared(T)) => shared(T) - // foo(U:const(shared(U)) immutable(T) => T - // foo(U:const(U)) wild(shared(T)) => shared(T) + case X(MODconst, MODwild): + case X(MODconst, MODwild | MODshared): + // foo(U:const(U)) T => T + // foo(U:const(U)) immutable(T) => T + // foo(U:const(U)) const(shared(T)) => shared(T) + // foo(U:const(shared(U))) immutable(T) => T + // foo(U:const(U)) wild(shared(T)) => shared(T) tt = mutableOf(); if (!at) { (*dedtypes)[i] = tt; @@ -2679,12 +2811,12 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, } break; - case X(MODshared, MODconst | MODshared): + case X(MODshared, MODconst | MODshared): case X(MODconst | MODshared, MODshared): - case X(MODshared, MODwild | MODshared): - // foo(U:shared(U)) const(shared(T)) => const(T) - // foo(U:const(shared(U)) shared(T) => T - // foo(U:shared(U)) wild(shared(T)) => wild(T) + case X(MODshared, MODwild | MODshared): + // foo(U:shared(U)) const(shared(T)) => const(T) + // foo(U:const(shared(U))) shared(T) => T + // foo(U:shared(U)) wild(shared(T)) => wild(T) tt = unSharedOf(); if (!at) { (*dedtypes)[i] = tt; @@ -2693,7 +2825,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, break; case X(MODconst, MODshared): - // foo(U:const(U)) shared(T) => shared(T) + // foo(U:const(U)) shared(T) => shared(T) if (!at) { (*dedtypes)[i] = tt; goto Lconst; @@ -2726,34 +2858,33 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, case X(MODimmutable, MODwild | MODshared): case X(MODconst | MODshared, MODwild | MODshared): case X(MODwild, MODwild | MODshared): - - // foo(U:immutable(U)) T => nomatch - // foo(U:immutable(U)) const(T) => nomatch - // foo(U:immutable(U)) shared(T) => nomatch - // foo(U:immutable(U)) const(shared(T)) => nomatch - // foo(U:const(U)) shared(T) => nomatch - // foo(U:shared(U)) T => nomatch - // foo(U:shared(U)) const(T) => nomatch - // foo(U:shared(U)) immutable(T) => nomatch - // foo(U:const(shared(U)) T => nomatch - // foo(U:const(shared(U)) const(T) => nomatch - // foo(U:immutable(U)) wild(T) => nomatch - // foo(U:shared(U)) wild(T) => nomatch - // foo(U:const(shared(U)) wild(T) => nomatch - // foo(U:wild(U)) T => nomatch - // foo(U:wild(U)) const(T) => nomatch - // foo(U:wild(U)) immutable(T) => nomatch - // foo(U:wild(U)) shared(T) => nomatch - // foo(U:wild(U)) const(shared(T)) => nomatch - // foo(U:wild(shared(U)) T => nomatch - // foo(U:wild(shared(U)) const(T) => nomatch - // foo(U:wild(shared(U)) immutable(T) => nomatch - // foo(U:wild(shared(U)) shared(T) => nomatch - // foo(U:wild(shared(U)) const(shared(T)) => nomatch - // foo(U:wild(shared(U)) wild(T) => nomatch - // foo(U:immutable(U)) wild(shared(T)) => nomatch - // foo(U:const(shared(U))) wild(shared(T)) => nomatch - // foo(U:wild(U)) wild(shared(T)) => nomatch + // foo(U:immutable(U)) T => nomatch + // foo(U:immutable(U)) const(T) => nomatch + // foo(U:immutable(U)) shared(T) => nomatch + // foo(U:immutable(U)) const(shared(T)) => nomatch + // foo(U:const(U)) shared(T) => nomatch + // foo(U:shared(U)) T => nomatch + // foo(U:shared(U)) const(T) => nomatch + // foo(U:shared(U)) immutable(T) => nomatch + // foo(U:const(shared(U))) T => nomatch + // foo(U:const(shared(U))) const(T) => nomatch + // foo(U:immutable(U)) wild(T) => nomatch + // foo(U:shared(U)) wild(T) => nomatch + // foo(U:const(shared(U))) wild(T) => nomatch + // foo(U:wild(U)) T => nomatch + // foo(U:wild(U)) const(T) => nomatch + // foo(U:wild(U)) immutable(T) => nomatch + // foo(U:wild(U)) shared(T) => nomatch + // foo(U:wild(U)) const(shared(T)) => nomatch + // foo(U:wild(shared(U))) T => nomatch + // foo(U:wild(shared(U))) const(T) => nomatch + // foo(U:wild(shared(U))) immutable(T) => nomatch + // foo(U:wild(shared(U))) shared(T) => nomatch + // foo(U:wild(shared(U))) const(shared(T)) => nomatch + // foo(U:wild(shared(U))) wild(T) => nomatch + // foo(U:immutable(U)) wild(shared(T)) => nomatch + // foo(U:const(shared(U))) wild(shared(T)) => nomatch + // foo(U:wild(U)) wild(shared(T)) => nomatch //if (!at) goto Lnomatch; break; @@ -2916,7 +3047,7 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame } else { - Type *vt = tvp->valType->semantic(0, sc); + Type *vt = tvp->valType->semantic(Loc(), sc); MATCH m = (MATCH)dim->implicitConvTo(vt); if (!m) goto Lnomatch; @@ -3064,8 +3195,8 @@ MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *pa for (size_t i = 0; i < idents.dim; i++) { - Identifier *id1 = idents[i]; - Identifier *id2 = tp->idents[i]; + Object *id1 = idents[i]; + Object *id2 = tp->idents[i]; if (!id1->equals(id2)) return MATCHnomatch; @@ -3103,11 +3234,11 @@ MATCH TypeInstance::deduceType(Scope *sc, { /* Didn't find it as a parameter identifier. Try looking * it up and seeing if is an alias. See Bugzilla 1454 */ - TypeIdentifier *tid = new TypeIdentifier(0, tp->tempinst->name); + TypeIdentifier *tid = new TypeIdentifier(Loc(), tp->tempinst->name); Type *t; Expression *e; Dsymbol *s; - tid->resolve(0, sc, &e, &t, &s); + tid->resolve(Loc(), sc, &e, &t, &s); if (t) { s = t->toDsymbol(sc); @@ -3285,7 +3416,7 @@ MATCH TypeInstance::deduceType(Scope *sc, goto Lnomatch; } else - { Type *vt = tv->valType->semantic(0, sc); + { Type *vt = tv->valType->semantic(Loc(), sc); MATCH m = (MATCH)e1->implicitConvTo(vt); if (!m) goto Lnomatch; @@ -3363,7 +3494,7 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame { if (ti && ti->toAlias() == sym) { - TypeInstance *t = new TypeInstance(0, ti); + TypeInstance *t = new TypeInstance(Loc(), ti); return t->deduceType(sc, tparam, parameters, dedtypes, wildmatch); } @@ -3372,8 +3503,8 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame */ TypeInstance *tpi = (TypeInstance *)tparam; if (tpi->idents.dim) - { Identifier *id = tpi->idents[tpi->idents.dim - 1]; - if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) + { Object *id = tpi->idents[tpi->idents.dim - 1]; + if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals((Identifier *)id)) { Type *tparent = sym->parent->getType(); if (tparent) @@ -3410,6 +3541,12 @@ MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramete if (sym != tp->sym) return MATCHnomatch; } + Type *tb = toBasetype(); + if (tb->ty == tparam->ty || + tb->ty == Tsarray && tparam->ty == Taarray) + { + return tb->deduceType(sc, tparam, parameters, dedtypes, wildmatch); + } return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); } @@ -3456,7 +3593,7 @@ void deduceBaseClassParameters(BaseClass *b, tmpdedtypes->setDim(dedtypes->dim); memcpy(tmpdedtypes->tdata(), dedtypes->tdata(), dedtypes->dim * sizeof(void *)); - TypeInstance *t = new TypeInstance(0, parti); + TypeInstance *t = new TypeInstance(Loc(), parti); MATCH m = t->deduceType(sc, tparam, parameters, tmpdedtypes); if (m != MATCHnomatch) { @@ -3497,7 +3634,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet { if (ti && ti->toAlias() == sym) { - TypeInstance *t = new TypeInstance(0, ti); + TypeInstance *t = new TypeInstance(Loc(), ti); MATCH m = t->deduceType(sc, tparam, parameters, dedtypes, wildmatch); // Even if the match fails, there is still a chance it could match // a base class. @@ -3510,8 +3647,8 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet */ TypeInstance *tpi = (TypeInstance *)tparam; if (tpi->idents.dim) - { Identifier *id = tpi->idents[tpi->idents.dim - 1]; - if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) + { Object *id = tpi->idents[tpi->idents.dim - 1]; + if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals((Identifier *)id)) { Type *tparent = sym->parent->getType(); if (tparent) @@ -3942,7 +4079,7 @@ Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o) } else if (ea) { - ea = ea->semantic(sc); + ea = ea->ctfeSemantic(sc); o = ea->ctfeInterpret(); } } @@ -4085,7 +4222,7 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs, Type *ta = isType(specAlias); if (!ti || !ta) goto Lnomatch; - Type *t = new TypeInstance(0, ti); + Type *t = new TypeInstance(Loc(), ti); MATCH m = t->deduceType(sc, ta, parameters, dedtypes); if (m == MATCHnomatch) goto Lnomatch; @@ -4258,7 +4395,7 @@ void TemplateValueParameter::semantic(Scope *sc) if (specValue) { Expression *e = specValue; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = e->implicitCastTo(sc, valType); e = e->ctfeInterpret(); if (e->op == TOKint64 || e->op == TOKfloat64 || @@ -4270,7 +4407,7 @@ void TemplateValueParameter::semantic(Scope *sc) if (defaultValue) { Expression *e = defaultValue; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = e->implicitCastTo(sc, valType); e = e->ctfeInterpret(); if (e->op == TOKint64) @@ -4354,7 +4491,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, } //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty); - vt = valType->semantic(0, sc); + vt = valType->semantic(Loc(), sc); //printf("ei: %s, ei->type: %s\n", ei->toChars(), ei->type->toChars()); //printf("vt = %s\n", vt->toChars()); @@ -4373,13 +4510,13 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Expression *e = specValue; - e = e->semantic(sc); + e = e->ctfeSemantic(sc); e = resolveProperties(sc, e); e = e->implicitCastTo(sc, vt); e = e->ctfeInterpret(); ei = ei->syntaxCopy(); - ei = ei->semantic(sc); + ei = ei->ctfeSemantic(sc); ei = ei->implicitCastTo(sc, vt); ei = ei->ctfeInterpret(); //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars()); @@ -4639,13 +4776,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->withsym = NULL; this->nest = 0; this->havetempdecl = 0; - this->isnested = NULL; + this->enclosing = NULL; this->speculative = 0; - this->ignore = true; #if IN_LLVM + this->ignore = true; this->emittedInModule = NULL; - this->tmodule = NULL; #endif } @@ -4673,17 +4809,15 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->withsym = NULL; this->nest = 0; this->havetempdecl = 1; - this->isnested = NULL; + this->enclosing = NULL; this->speculative = 0; - this->ignore = true; #if IN_LLVM - this->tinst = NULL; + this->ignore = true; this->emittedInModule = NULL; - this->tmodule = NULL; #endif - assert((size_t)tempdecl->scope > 0x10000); + assert(tempdecl->scope); } @@ -4735,12 +4869,12 @@ void TemplateInstance::expandMembers(Scope *sc2) { Dsymbol *s = (*members)[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) + //printf("test: enclosing = %d, sc2->parent = %s\n", enclosing, sc2->parent->toChars()); +// if (enclosing) // s->parent = sc->parent; - //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); + //printf("test3: enclosing = %d, s->parent = %s\n", enclosing, s->parent->toChars()); s->semantic(sc2); - //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); + //printf("test4: enclosing = %d, s->parent = %s\n", enclosing, s->parent->toChars()); sc2->module->runDeferredSemantic(); } } @@ -4825,10 +4959,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #endif return; } - + +#if IN_LLVM if (!sc->ignoreTemplates) ignore = false; - +#endif // get the enclosing template instance from the scope tinst tinst = sc->tinst; @@ -4843,24 +4978,13 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) return; } semanticRun = PASSsemantic; -#if IN_LLVM - // get the enclosing template instance from the scope tinst - tinst = sc->tinst; - - // get the module of the outermost enclosing instantiation - if (tinst) - tmodule = tinst->tmodule; - else - tmodule = sc->module; - //printf("%s in %s\n", toChars(), tmodule->toChars()); -#endif #if LOG printf("\tdo semantic\n"); #endif if (havetempdecl) { - assert((size_t)tempdecl->scope > 0x10000); + assert(tempdecl->scope); // Deduce tdtypes tdtypes.setDim(tempdecl->parameters->dim); if (!tempdecl->matchWithInstance(this, &tdtypes, fargs, 2)) @@ -4872,37 +4996,21 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } else { - /* Find template declaration first. + /* Find template declaration first, + * then run semantic on each argument (place results in tiargs[]), + * last find most specialized template from overload list/set. */ - tempdecl = findTemplateDeclaration(sc); - if (!tempdecl) - { if (!sc->parameterSpecialization) - inst = this; - //printf("error return %p, %d\n", tempdecl, global.errors); - return; // error recovery - } - - /* Run semantic on each argument, place results in tiargs[] - * (if we have tempdecl, then tiargs is already evaluated) - */ - semanticTiargs(sc); - if (arrayObjectIsError(tiargs)) - { if (!sc->parameterSpecialization) + if (!findTemplateDeclaration(sc) || + !semanticTiargs(sc) || + !findBestMatch(sc, fargs)) + { + if (!sc->parameterSpecialization) inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); if (inst) inst->errors = true; return; // error recovery } - - unsigned errs = global.errors; - tempdecl = findBestMatch(sc, fargs); - if (!tempdecl || (errs != global.errors)) - { if (!sc->parameterSpecialization) - inst = this; - //printf("error return %p, %d\n", tempdecl, global.errors); - return; // error recovery - } } // If tempdecl is a mixin, disallow it @@ -4924,9 +5032,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) assert(tdtypes.dim == ti->tdtypes.dim); // Nesting must match - if (isnested != ti->isnested) + if (enclosing != ti->enclosing) { - //printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : ""); + //printf("test2 enclosing %s ti->enclosing %s\n", enclosing ? enclosing->toChars() : "", ti->enclosing ? ti->enclosing->toChars() : ""); continue; } //printf("parent = %s, ti->parent = %s\n", tempdecl->parent->toPrettyChars(), ti->parent->toPrettyChars()); @@ -5015,8 +5123,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) ident = genIdent(tiargs); // need an identifier for name mangling purposes. #if 1 - if (isnested) - parent = isnested; + if (enclosing) + parent = enclosing; #endif //printf("parent = '%s'\n", parent->kind()); @@ -5058,7 +5166,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } else { - Module *m = (isnested ? sc : tempdecl->scope)->module->importedFrom; + Module *m = (enclosing ? sc : tempdecl->scope)->module->importedFrom; //printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars()); a = m->members; if (m->semanticRun >= 3) @@ -5082,12 +5190,41 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #endif // Copy the syntax trees from the TemplateDeclaration -#if IN_LLVM // Backport of DMD pull request #1760. if (members && speculative) - {} // Don't copy again so they were previously created. + {} // Don't copy again so they were previously created. else -#endif - members = Dsymbol::arraySyntaxCopy(tempdecl->members); + members = Dsymbol::arraySyntaxCopy(tempdecl->members); + + // todo for TemplateThisParameter + for (size_t i = 0; i < tempdecl->parameters->dim; i++) + { + if ((*tempdecl->parameters)[i]->isTemplateThisParameter() == NULL) + continue; + Type *t = isType((*tiargs)[i]); + assert(t); + + StorageClass stc = 0; + if (t->mod & MODimmutable) + stc |= STCimmutable; + else + { + if (t->mod & MODconst) + stc |= STCconst; + else if (t->mod & MODwild) + stc |= STCwild; + + if (t->mod & MODshared) + stc |= STCshared; + } + if (stc != 0) + { + //printf("t = %s, stc = x%llx\n", t->toChars(), stc); + Dsymbols *s = new Dsymbols(); + s->push(new StorageClassDeclaration(stc, members)); + members = s; + } + break; + } // Create our own scope for the template parameters Scope *scope = tempdecl->scope; @@ -5177,8 +5314,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #endif Scope *sc2; sc2 = scope->push(this); - //printf("isnested = %d, sc->parent = %s\n", isnested, sc->parent->toChars()); - sc2->parent = /*isnested ? sc->parent :*/ this; + //printf("enclosing = %d, sc->parent = %s\n", enclosing, sc->parent->toChars()); + sc2->parent = /*enclosing ? sc->parent :*/ this; sc2->tinst = this; sc2->speculative = speculative; @@ -5286,13 +5423,14 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } -void TemplateInstance::semanticTiargs(Scope *sc) +bool TemplateInstance::semanticTiargs(Scope *sc) { //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); if (semantictiargsdone) - return; + return true; semantictiargsdone = 1; semanticTiargs(loc, sc, tiargs, 0); + return arrayObjectIsError(tiargs) == 0; } /********************************** @@ -5353,9 +5491,25 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { Lexpr: //printf("+[%d] ea = %s %s\n", j, Token::toChars(ea->op), ea->toChars()); - ea = ea->semantic(sc); + if (flags & 1) + ea = ea->semantic(sc); + else + ea = ea->ctfeSemantic(sc); if (flags & 1) // only used by __traits, must not interpret the args - ea = ea->optimize(WANTvalue); + { + VarDeclaration *v; + if (ea->op == TOKvar && (v = ((VarExp *)ea)->var->isVarDeclaration()) != NULL && + v->storage_class & STCmanifest && !(v->storage_class & STCtemplateparameter)) + { + if (v->sem < SemanticDone) + v->semantic(sc); + // skip optimization for manifest constant + } + else + { + ea = ea->optimize(WANTvalue); + } + } else if (ea->op == TOKvar) { /* This test is to skip substituting a const var with * its initializer. The problem is the initializer won't @@ -5458,6 +5612,9 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { td->semantic(sc); } + FuncDeclaration *fd = sa->isFuncDeclaration(); + if (fd) + fd->functionSemantic(); } else if (isParameter(o)) { @@ -5487,7 +5644,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f * Find template declaration corresponding to template instance. */ -TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) +bool TemplateInstance::findTemplateDeclaration(Scope *sc) { //printf("TemplateInstance::findTemplateDeclaration() %s\n", toChars()); if (!tempdecl) @@ -5509,7 +5666,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) error("template '%s' is not defined, did you mean %s?", id->toChars(), s->toChars()); else error("template '%s' is not defined", id->toChars()); - return NULL; + return false; } /* If an OverloadSet, look for a unique member that is a template declaration @@ -5528,7 +5685,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) } if (!s) { error("template '%s' is not defined", id->toChars()); - return NULL; + return false; } } @@ -5567,13 +5724,13 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) if (!tempdecl) { if (!s->parent && global.errors) - return NULL; + return false; if (!s->parent && s->getType()) { Dsymbol *s2 = s->getType()->toDsymbol(sc); if (!s2) { error("%s is not a template declaration, it is a %s", id->toChars(), s->kind()); - return NULL; + return false; } s = s2; } @@ -5599,16 +5756,16 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) else { error("%s is not a template declaration, it is a %s", id->toChars(), s->kind()); - return NULL; + return false; } } } else assert(tempdecl->isTemplateDeclaration()); - return tempdecl; + return (tempdecl != NULL); } -TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) +bool TemplateInstance::findBestMatch(Scope *sc, Expressions *fargs) { /* Since there can be multiple TemplateDeclaration's with the same * name, look for the best match. @@ -5617,6 +5774,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far TemplateDeclaration *td_best = NULL; MATCH m_best = MATCHnomatch; Objects dedtypes; + unsigned errs = global.errors; #if LOG printf("TemplateInstance::findBestMatch()\n"); @@ -5639,7 +5797,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far if (!td->semanticRun) { error("%s forward references template declaration %s", toChars(), td->toChars()); - return NULL; + return false; } } } @@ -5704,13 +5862,15 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far if (!td_best) { - if (tempdecl && !tempdecl->overnext) + if (errs != global.errors) + errorSupplemental(loc, "while looking for match for %s", toChars()); + else if (tempdecl && !tempdecl->overnext) // Only one template, so we can give better error message - error("%s does not match template declaration %s", toChars(), tempdecl->toChars()); + error("does not match template declaration %s", tempdecl->toChars()); else ::error(loc, "%s %s.%s does not match any template declaration", tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars()); - return NULL; + return false; } if (td_ambig) { @@ -5746,14 +5906,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far #if LOG printf("\tIt's a match with template declaration '%s'\n", tempdecl->toChars()); #endif - return tempdecl; + return (errs == global.errors) && tempdecl; } /***************************************** * Determines if a TemplateInstance will need a nested * generation of the TemplateDeclaration. - * Sets isnested property if so, and returns != 0; + * Sets enclosing property if so, and returns != 0; */ int TemplateInstance::hasNestedArgs(Objects *args) @@ -5810,6 +5970,7 @@ int TemplateInstance::hasNestedArgs(Objects *args) else if (sa) { Lsa: + sa = sa->toAlias(); TemplateDeclaration *td = sa->isTemplateDeclaration(); AggregateDeclaration *ad = sa->isAggregateDeclaration(); Declaration *d = sa->isDeclaration(); @@ -5827,31 +5988,31 @@ int TemplateInstance::hasNestedArgs(Objects *args) { // if module level template if (tempdecl->toParent()->isModule()) - { Dsymbol *dparent = sa->toParent(); - if (!isnested) - isnested = dparent; - else if (isnested != dparent) + { Dsymbol *dparent = sa->toParent2(); + if (!enclosing) + enclosing = dparent; + else if (enclosing != dparent) { /* Select the more deeply nested of the two. * Error if one is not nested inside the other. */ - for (Dsymbol *p = isnested; p; p = p->parent) + for (Dsymbol *p = enclosing; p; p = p->parent) { if (p == dparent) - goto L1; // isnested is most nested + goto L1; // enclosing is most nested } for (Dsymbol *p = dparent; p; p = p->parent) { - if (p == isnested) - { isnested = dparent; + if (p == enclosing) + { enclosing = dparent; goto L1; // dparent is most nested } } error("%s is nested in both %s and %s", - toChars(), isnested->toChars(), dparent->toChars()); + toChars(), enclosing->toChars(), dparent->toChars()); } L1: - //printf("\tnested inside %s\n", isnested->toChars()); + //printf("\tnested inside %s\n", enclosing->toChars()); nested |= 1; } else @@ -5953,6 +6114,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) { Lsa: buf.writeByte('S'); + sa = sa->toAlias(); Declaration *d = sa->isDeclaration(); Lsa2: if (d && (!d->type || !d->type->deco)) @@ -6037,8 +6199,9 @@ void TemplateInstance::declareParameters(Scope *sc) int TemplateInstance::needsTypeInference(Scope *sc) { //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); - if (!tempdecl) - tempdecl = findTemplateDeclaration(sc); + if (!findTemplateDeclaration(sc)) + return FALSE; + int multipleMatches = FALSE; for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { @@ -6174,8 +6337,6 @@ void TemplateInstance::semantic3(Scope *sc) } } -#if IN_DMD - /************************************** * Given an error instantiating the TemplateInstance, * give the nested TemplateInstance instantiations that got @@ -6253,29 +6414,6 @@ void TemplateInstance::printInstantiationTrace() } } -void TemplateInstance::toObjFile(int multiobj) -{ -#if LOG - printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this); -#endif - if (!errors && members) - { - if (multiobj) - // Append to list of object files to be written later - obj_append(this); - else - { - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = (*members)[i]; - s->toObjFile(multiobj); - } - } - } -} - -#endif - void TemplateInstance::inlineScan() { #if LOG @@ -6380,81 +6518,22 @@ char *TemplateInstance::toChars() return s; } -#if IN_LLVM - -void TemplateInstance::printInstantiationTrace() -{ - if(global.gag) - return; - - const int max_shown = 6; - - // determine instantiation depth - int n_instantiations = 1; - TemplateInstance* cur = this; - while(cur = cur->tinst) - ++n_instantiations; - - // show full trace only if it's short or verbose is on - if(n_instantiations <= max_shown || global.params.verbose) - { - cur = this; - while(cur) - { - fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); - cur = cur->tinst; - } - } - else - { - cur = this; - size_t i = 0; - for(; i < max_shown/2; ++i, cur = cur->tinst) - fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); - fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown); - for(; i < n_instantiations - max_shown + max_shown/2; ++i, cur = cur->tinst) - {} - for(; i < n_instantiations; ++i, cur = cur->tinst) - fprintf(stdmsg," instantiatied in %s: %s\n", cur->loc.toChars(), cur->toChars()); - } -} - -#endif - /* ======================== TemplateMixin ================================ */ -TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, - Identifiers *idents, Objects *tiargs) - : TemplateInstance(loc, (*idents)[idents->dim - 1]) +TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs) + : TemplateInstance(loc, tqual->idents.dim ? (Identifier *)tqual->idents[tqual->idents.dim - 1] + : ((TypeIdentifier *)tqual)->ident) { //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : ""); this->ident = ident; this->tqual = tqual; - this->idents = idents; this->tiargs = tiargs ? tiargs : new Objects(); } Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) -{ TemplateMixin *tm; - - Identifiers *ids = new Identifiers(); - ids->setDim(idents->dim); - for (size_t i = 0; i < idents->dim; i++) - { // Matches TypeQualified::syntaxCopyHelper() - Identifier *id = (*idents)[i]; - if (id->dyncast() == DYNCAST_DSYMBOL) - { - TemplateInstance *ti = (TemplateInstance *)id; - - ti = (TemplateInstance *)ti->syntaxCopy(NULL); - id = (Identifier *)ti; - } - (*ids)[i] = id; - } - - tm = new TemplateMixin(loc, ident, - (Type *)(tqual ? tqual->syntaxCopy() : NULL), - ids, tiargs); +{ + TemplateMixin *tm = new TemplateMixin(loc, ident, + (TypeQualified *)tqual->syntaxCopy(), tiargs); TemplateInstance::syntaxCopy(tm); return tm; } @@ -6503,43 +6582,11 @@ void TemplateMixin::semantic(Scope *sc) // Follow qualifications to find the TemplateDeclaration if (!tempdecl) - { Dsymbol *s; - size_t i; - Identifier *id; - - if (tqual) - { s = tqual->toDsymbol(sc); - i = 0; - } - else - { - i = 1; - id = (*idents)[0]; - switch (id->dyncast()) - { - case DYNCAST_IDENTIFIER: - s = sc->search(loc, id, NULL); - break; - - case DYNCAST_DSYMBOL: - { - TemplateInstance *ti = (TemplateInstance *)id; - ti->semantic(sc); - s = ti; - break; - } - default: - assert(0); - } - } - - for (; i < idents->dim; i++) - { - if (!s) - break; - id = (*idents)[i]; - s = s->searchX(loc, sc, id); - } + { + Expression *e; + Type *t; + Dsymbol *s; + tqual->resolve(loc, sc, &e, &t, &s); if (!s) { error("is not defined"); @@ -6561,36 +6608,41 @@ void TemplateMixin::semantic(Scope *sc) { if (!td->semanticRun) { - /* Cannot handle forward references if mixin is a struct member, - * because addField must happen during struct's semantic, not - * during the mixin semantic. - * runDeferred will re-run mixin's semantic outside of the struct's - * semantic. - */ - semanticRun = PASSinit; - AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); - if (ad) - ad->sizeok = SIZEOKfwd; + if (td->scope) + td->semantic(td->scope); else { - // Forward reference - //printf("forward reference - deferring\n"); - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); + /* Cannot handle forward references if mixin is a struct member, + * because addField must happen during struct's semantic, not + * during the mixin semantic. + * runDeferred will re-run mixin's semantic outside of the struct's + * semantic. + */ + semanticRun = PASSinit; + AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); + if (ad) + ad->sizeok = SIZEOKfwd; + else + { + // Forward reference + //printf("forward reference - deferring\n"); + scope = scx ? scx : new Scope(*sc); + scope->setNoFree(); + scope->module->addDeferredSemantic(this); + } + return; } - return; } } - // Run semantic on each argument, place results in tiargs[] - semanticTiargs(sc); - if (errors || arrayObjectIsError(tiargs)) - return; - - tempdecl = findBestMatch(sc, NULL); - if (!tempdecl) - { inst = this; + /* Run semantic on each argument, place results in tiargs[], + * then find best match template with tiargs + */ + if (!semanticTiargs(sc) || + !findBestMatch(sc, NULL)) + { + inst = this; + inst->errors = true; return; // error recovery } @@ -6650,12 +6702,10 @@ void TemplateMixin::semantic(Scope *sc) } // Copy the syntax trees from the TemplateDeclaration -#if IN_LLVM // Backport of DMD pull request #1760. if (scx && members) - {} // Don't copy again so they were previously created. + {} // Don't copy again so they were previously created. else -#endif - members = Dsymbol::arraySyntaxCopy(tempdecl->members); + members = Dsymbol::arraySyntaxCopy(tempdecl->members); if (!members) return; @@ -6754,16 +6804,10 @@ void TemplateMixin::semantic(Scope *sc) return; } - /* The problem is when to parse the initializer for a variable. - * Perhaps VarDeclaration::semantic() should do it like it does - * for initializers inside a function. - */ -// if (sc->parent->isFuncDeclaration()) - - semantic2(sc2); - - if (sc->func) + AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); + if (sc->func && !ad) { + semantic2(sc2); semantic3(sc2); } @@ -6916,19 +6960,13 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring("mixin "); - for (size_t i = 0; i < idents->dim; i++) - { Identifier *id = (*idents)[i]; - - if (i) - buf->writeByte('.'); - buf->writestring(id->toChars()); - } + tqual->toCBuffer(buf, NULL, hgs); buf->writestring("!("); if (tiargs) { for (size_t i = 0; i < tiargs->dim; i++) { if (i) - buf->writebyte(','); + buf->writestring(", "); Object *oarg = (*tiargs)[i]; Type *t = isType(oarg); Expression *e = isExpression(oarg); @@ -6961,13 +6999,3 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writebyte(';'); buf->writenl(); } - - -#if IN_DMD -void TemplateMixin::toObjFile(int multiobj) -{ - //printf("TemplateMixin::toObjFile('%s')\n", toChars()); - TemplateInstance::toObjFile(0); -} -#endif - diff --git a/dmd2/template.h b/dmd2/template.h index c01f6987ef..ddb2a5b5f6 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -14,15 +14,14 @@ #ifdef __DMC__ #pragma once #endif /* __DMC__ */ + #if IN_LLVM #include #endif #include "root.h" #include "arraytypes.h" #include "dsymbol.h" -#if IN_LLVM -#include "mtype.h" -#endif + struct OutBuffer; struct Identifier; @@ -34,6 +33,7 @@ struct TemplateValueParameter; struct TemplateAliasParameter; struct TemplateTupleParameter; struct Type; +struct TypeQualified; struct TypeTypeof; struct Scope; struct Expression; @@ -90,15 +90,17 @@ struct TemplateDeclaration : ScopeDsymbol void emitComment(Scope *sc); void toJson(JsonOut *json); + virtual void jsonProperties(JsonOut *json); + enum PROT prot(); // void toDocBuffer(OutBuffer *buf); MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs); - MATCH deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs); - FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0); + MATCH deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, Objects *dedargs); + FuncDeclaration *deduceFunctionTemplate(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, int flags = 0); Object *declareParameter(Scope *sc, TemplateParameter *tp, Object *o); - FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Expressions *fargs); + FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Type *tthis, Expressions *fargs); TemplateDeclaration *isTemplateDeclaration() { return this; } @@ -304,7 +306,7 @@ struct TemplateInstance : ScopeDsymbol int semantictiargsdone; // has semanticTiargs() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor - Dsymbol *isnested; // if referencing local symbols, this is the context + Dsymbol *enclosing; // if referencing local symbols, this is the context int speculative; // 1 if only instantiated with errors gagged #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol @@ -328,7 +330,7 @@ struct TemplateInstance : ScopeDsymbol int oneMember(Dsymbol **ps, Identifier *ident); int needsTypeInference(Scope *sc); char *toChars(); - char *mangle(bool isv = false); + const char *mangle(bool isv = false); void printInstantiationTrace(); #if IN_DMD @@ -337,9 +339,9 @@ struct TemplateInstance : ScopeDsymbol // Internal static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); - void semanticTiargs(Scope *sc); - TemplateDeclaration *findTemplateDeclaration(Scope *sc); - TemplateDeclaration *findBestMatch(Scope *sc, Expressions *fargs); + bool semanticTiargs(Scope *sc); + bool findTemplateDeclaration(Scope *sc); + bool findBestMatch(Scope *sc, Expressions *fargs); void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); Identifier *genIdent(Objects *args); @@ -352,7 +354,6 @@ struct TemplateInstance : ScopeDsymbol #if IN_LLVM bool ignore; // true if the instance must be ignored when codegen'ing - Module* tmodule; // module from outermost enclosing template instantiation Module* emittedInModule; // which module this template instance has been emitted in void codegen(Ir*); @@ -361,10 +362,9 @@ struct TemplateInstance : ScopeDsymbol struct TemplateMixin : TemplateInstance { - Identifiers *idents; - Type *tqual; + TypeQualified *tqual; - TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Identifiers *idents, Objects *tiargs); + TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); diff --git a/dmd2/traits.c b/dmd2/traits.c index 411bee0d82..3594a7c955 100644 --- a/dmd2/traits.c +++ b/dmd2/traits.c @@ -61,10 +61,12 @@ static int fptraits(void *param, FuncDeclaration *f) return 0; Expression *e; + FuncAliasDeclaration* alias = new FuncAliasDeclaration(f, 0); + alias->protection = f->protection; if (p->e1) - e = new DotVarExp(0, p->e1, new FuncAliasDeclaration(f, 0)); + e = new DotVarExp(Loc(), p->e1, alias); else - e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0)); + e = new DsymbolExp(Loc(), alias); p->exps->push(e); return 0; } @@ -168,6 +170,34 @@ Expression *TraitsExp::semantic(Scope *sc) } goto Ltrue; } + else if (ident == Id::isNested) + { + if (dim != 1) + goto Ldimerror; + Object *o = (*args)[0]; + Dsymbol *s = getDsymbol(o); + AggregateDeclaration *a; + FuncDeclaration *f; + + if (!s) { } + else if ((a = s->isAggregateDeclaration()) != NULL) + { + if (a->isNested()) + goto Ltrue; + else + goto Lfalse; + } + else if ((f = s->isFuncDeclaration()) != NULL) + { + if (f->isNested()) + goto Ltrue; + else + goto Lfalse; + } + + error("aggregate or function expected instead of '%s'", o->toChars()); + goto Lfalse; + } else if (ident == Id::isAbstractFunction) { FuncDeclaration *f; @@ -254,6 +284,7 @@ Expression *TraitsExp::semantic(Scope *sc) const char *protName = Pprotectionnames[protection]; + assert(protName); StringExp *se = new StringExp(loc, (char *) protName); return se->semantic(sc); } @@ -305,17 +336,17 @@ Expression *TraitsExp::semantic(Scope *sc) } Identifier *id = Lexer::idPool((char *)se->string); - Type *t = isType(o); - e = isExpression(o); - Dsymbol *s = isDsymbol(o); - if (t) - e = typeDotIdExp(loc, t, id); - else if (e) - e = new DotIdExp(loc, e, id); - else if (s) - { e = new DsymbolExp(loc, s); + /* Prefer dsymbol, because it might need some runtime contexts. + */ + Dsymbol *sym = getDsymbol(o); + if (sym) + { e = new DsymbolExp(loc, sym); e = new DotIdExp(loc, e, id); } + else if (Type *t = isType(o)) + e = typeDotIdExp(loc, t, id); + else if (Expression *ex = isExpression(o)) + e = new DotIdExp(loc, ex, id); else { error("invalid first argument"); goto Lfalse; @@ -323,21 +354,16 @@ Expression *TraitsExp::semantic(Scope *sc) if (ident == Id::hasMember) { - if (t) + if (sym) { - Dsymbol *sym = t->toDsymbol(sc); - if (sym) - { - Dsymbol *sm = sym->search(loc, id, 0); - if (sm) - goto Ltrue; - } + Dsymbol *sm = sym->search(loc, id, 0); + if (sm) + goto Ltrue; } /* Take any errors as meaning it wasn't found */ Scope *sc2 = sc->push(); - //sc2->inHasMember++; e = e->trySemantic(sc2); sc2->pop(); if (!e) @@ -384,7 +410,7 @@ Expression *TraitsExp::semantic(Scope *sc) p.exps = exps; p.e1 = e; p.ident = ident; - overloadApply(f, fptraits, &p); + overloadApply(f, &fptraits, &p); TupleExp *tup = new TupleExp(loc, exps); return tup->semantic(sc); @@ -435,7 +461,12 @@ Expression *TraitsExp::semantic(Scope *sc) error("argument has no members"); goto Lfalse; } - if ((sd = s->isScopeDsymbol()) == NULL) + Import *import; + if ((import = s->isImport()) != NULL) + { // Bugzilla 9692 + sd = import->mod; + } + else if ((sd = s->isScopeDsymbol()) == NULL) { error("%s %s has no members", s->kind(), s->toChars()); goto Lfalse; @@ -468,6 +499,14 @@ Expression *TraitsExp::semantic(Scope *sc) idents->push(sm->ident); } + else + { + EnumDeclaration *ed = sm->isEnumDeclaration(); + if (ed) + { + ScopeDsymbol::foreach(NULL, ed->members, &PushIdentsDg::dg, (Identifiers *)ctx); + } + } return 0; } }; diff --git a/dmd2/utf.c b/dmd2/utf.c index c05fc101f0..804dfcac50 100644 --- a/dmd2/utf.c +++ b/dmd2/utf.c @@ -19,9 +19,6 @@ #include "utf.h" -namespace -{ - /* The following encodings are valid, except for the 5 and 6 byte * combinations: * 0xxxxxxx @@ -51,11 +48,6 @@ const unsigned UTF8_STRIDE[256] = 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, }; -} // namespace - -namespace Unicode -{ - // UTF-8 decoding errors char const UTF8_DECODE_OUTSIDE_CODE_SPACE[] = "Outside Unicode code space"; char const UTF8_DECODE_TRUNCATED_SEQUENCE[] = "Truncated UTF-8 sequence"; @@ -69,10 +61,6 @@ char const UTF16_DECODE_INVALID_SURROGATE[] = "Invalid low surrogate"; char const UTF16_DECODE_UNPAIRED_SURROGATE[]= "Unpaired surrogate"; char const UTF16_DECODE_INVALID_CODE_POINT[]= "Invalid code point decoded"; -} // namespace Unicode - -using namespace Unicode; - /// The Unicode code space is the range of code points [0x000000,0x10FFFF] /// except the UTF-16 surrogate pairs in the range [0xD800,0xDFFF] /// and non-characters (which end in 0xFFFE or 0xFFFF). diff --git a/dmd2/utf.h b/dmd2/utf.h index 22e405bc27..cd279686a3 100644 --- a/dmd2/utf.h +++ b/dmd2/utf.h @@ -20,9 +20,6 @@ typedef unsigned short utf16_t; typedef unsigned int utf32_t; typedef utf32_t dchar_t; -namespace Unicode -{ - static utf16_t const ALPHA_TABLE[][2] = { { 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA }, @@ -102,8 +99,6 @@ extern char const UTF16_DECODE_INVALID_SURROGATE[]; extern char const UTF16_DECODE_UNPAIRED_SURROGATE[]; extern char const UTF16_DECODE_INVALID_CODE_POINT[]; -} // namespace Unicode - /// \return true if \a c is a valid, non-private UTF-32 code point bool utf_isValidDchar(dchar_t c); diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index c88a26337f..8b688953df 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "driver/cl_options.h" +#include "mars.h" #include "gen/cl_helpers.h" #include "gen/logger.h" #include "llvm/Support/CommandLine.h" @@ -204,6 +205,10 @@ static cl::list stringImportPaths("J", cl::location(strImpPathStore), cl::Prefix); +static cl::opt addMain("main", + cl::desc("add empty main() (e.g. for unittesting)"), + cl::ZeroOrMore, + cl::location(global.params.addMain)); // -d-debug is a bit messy, it has 3 modes: @@ -217,7 +222,7 @@ struct D_DebugStorage { if (str.empty()) { // Bare "-d-debug" has a special meaning. global.params.useAssert = true; - global.params.useArrayBounds = true; + global.params.useArrayBounds = 2; global.params.useInvariants = true; global.params.useIn = true; global.params.useOut = true; @@ -316,11 +321,8 @@ static cl::opt asserts("asserts", cl::location(global.params.useAssert), cl::init(true)); -static cl::opt boundsChecks("boundscheck", - cl::desc("(*) Enable array bounds checks"), - cl::value_desc("bool"), - cl::location(global.params.useArrayBounds), - cl::init(true)); +cl::opt boundsChecks("boundscheck", + cl::desc("(*) Enable array bounds checks")); static cl::opt invariants("invariants", cl::desc("(*) Enable invariants"), @@ -344,8 +346,9 @@ static cl::opt contracts("contracts", cl::desc("(*) Enable function pre- and post-conditions"), cl::location(ContractsSetter)); +bool nonSafeBoundsChecks = true; static MultiSetter ReleaseSetter(true, &global.params.useAssert, - &global.params.useArrayBounds, &global.params.useInvariants, + &nonSafeBoundsChecks, &global.params.useInvariants, &global.params.useOut, &global.params.useIn, NULL); static cl::opt > release("release", cl::desc("Disables asserts, invariants, contracts and boundscheck"), diff --git a/driver/cl_options.h b/driver/cl_options.h index d1320894fe..25afb5a69d 100644 --- a/driver/cl_options.h +++ b/driver/cl_options.h @@ -15,7 +15,7 @@ #ifndef LDC_DRIVER_CL_OPTIONS_H #define LDC_DRIVER_CL_OPTIONS_H -#include "mars.h" +#include "gen/cl_helpers.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include @@ -63,6 +63,9 @@ namespace opts { extern cl::opt singleObj; extern cl::opt linkonceTemplates; + extern cl::opt boundsChecks; + extern bool nonSafeBoundsChecks; + // Arguments to -d-debug extern std::vector debugArgs; // Arguments to -run diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index 1baf509878..82201b96c7 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -233,8 +233,12 @@ Usage:\n\ -quiet suppress unnecessary messages\n\ -release compile release version\n\ -run srcfile args... run resulting program, passing args\n\ - -shared generate shared library\n\ - -unittest compile in unit tests\n\ + -shared generate shared library\n" +#if 0 +" -transition=id show additional info about language change identified by 'id'\n\ + -transition=? list all language changes\n" +#endif +" -unittest compile in unit tests\n\ -v verbose\n\ -vdmd print the command used to invoke the underlying compiler\n\ -version=level compile in version code >= level\n\ @@ -529,6 +533,8 @@ Params parseArgs(size_t originalArgc, char** originalArgv, ls::Path ldcPath) result.targetModel = Model::m64; else if (strcmp(p + 1, "profile") == 0) result.profile = true; + else if (memcmp(p + 1, "transition", 10) == 0) + warning("-transition not yet supported by LDC."); else if (strcmp(p + 1, "v") == 0) result.verbose = true; else if (strcmp(p + 1, "vdmd") == 0) diff --git a/driver/main.cpp b/driver/main.cpp index c91b32f003..ddc06278b7 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -14,6 +14,7 @@ #include "mtype.h" #include "rmem.h" #include "root.h" +#include "dmd2/target.h" #include "driver/cl_options.h" #include "driver/configfile.h" #include "driver/linker.h" @@ -163,6 +164,8 @@ int main(int argc, char** argv) Module *m; int status = EXIT_SUCCESS; + global.init(); + // Set some default values #if _WIN32 char buf[MAX_PATH]; @@ -172,6 +175,7 @@ int main(int argc, char** argv) global.params.argv0 = argv[0]; #endif global.params.useSwitchError = 1; + global.params.useArrayBounds = 2; global.params.linkswitches = new Strings(); global.params.libfiles = new Strings(); @@ -366,6 +370,14 @@ int main(int argc, char** argv) if (global.params.useUnitTests) global.params.useAssert = 1; + // Bounds checking is a bit peculiar: -enable/disable-boundscheck is an + // absolute decision. Only if no explicit option is specified, -release + // downgrades useArrayBounds 2 to 1 (only for safe functions). + if (opts::boundsChecks == cl::BOU_UNSET) + global.params.useArrayBounds = opts::nonSafeBoundsChecks ? 2 : 1; + else + global.params.useArrayBounds = (opts::boundsChecks == cl::BOU_TRUE) ? 2 : 0; + // LDC output determination // if we don't link, autodetect target from extension @@ -648,6 +660,8 @@ int main(int argc, char** argv) Type::init(&ir); Id::initialize(); Module::init(); + Target::init(); + Expression::init(); initPrecedence(); backend_init(); @@ -688,6 +702,12 @@ int main(int argc, char** argv) } } + if (global.params.addMain) + { + // a dummy name, we never actually look up this file + files.push(const_cast(global.main_d)); + } + // Create Modules Modules modules; modules.reserve(files.dim); @@ -761,7 +781,8 @@ int main(int argc, char** argv) #endif if (Port::stricmp(ext, global.mars_ext) == 0 || - Port::stricmp(ext, global.hdr_ext) == 0) + Port::stricmp(ext, global.hdr_ext) == 0 || + FileName::equals(ext, "dd")) { ext--; // skip onto '.' assert(*ext == '.'); @@ -808,7 +829,18 @@ int main(int argc, char** argv) if (!Module::rootModule) Module::rootModule = m; m->importedFrom = m; - m->read(0); + + if (strcmp(m->srcfile->name->str, global.main_d) == 0) + { + static const char buf[] = "void main(){}"; + m->srcfile->setbuffer((void *)buf, sizeof(buf)); + m->srcfile->ref = 1; + } + else + { + m->read(Loc()); + } + m->parse(global.params.doDocComments); m->buildTargetFiles(singleObj); m->deleteObjFile(); @@ -924,6 +956,7 @@ int main(int argc, char** argv) if (global.errors) fatal(); } + global.inExtraInliningSemantic = false; } if (global.errors || global.warnings) fatal(); diff --git a/gen/aa.cpp b/gen/aa.cpp index 9ab363a259..bbebda5dcf 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -80,7 +80,7 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue) // Only check bounds for rvalues ('aa[key]'). // Lvalue use ('aa[key] = value') auto-adds an element. - if (!lvalue && global.params.useArrayBounds) { + if (!lvalue && gIR->emitArrayBoundsChecks()) { llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend); llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend); diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 278aa7628f..36c0c5191d 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -385,7 +385,7 @@ static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz) static void copySlice(LLValue* dstarr, LLValue* sz1, LLValue* srcarr, LLValue* sz2) { - if (global.params.useAssert || global.params.useArrayBounds) + if (global.params.useAssert || gIR->emitArrayBoundsChecks()) { LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy"); gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, sz2); diff --git a/gen/asm-x86.h b/gen/asm-x86.h index accec4d3b4..0d2384e9c7 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -1546,7 +1546,7 @@ namespace AsmParserx8664 for ( int i = 0; i < N_PtrNames; i++ ) ptrTypeIdentTable[i] = Lexer::idPool ( ptrTypeNameTable[i] ); - Handled = new Expression ( 0, TOKvoid, sizeof ( Expression ) ); + Handled = new Expression ( Loc(), TOKvoid, sizeof ( Expression ) ); ident_seg = Lexer::idPool ( "seg" ); @@ -1827,6 +1827,12 @@ namespace AsmParserx8664 break; case Arg_Memory: + // Peel off one layer of explicitly taking the address, if present. + if ( e->op == TOKaddress ) + { + e = static_cast(e)->e1; + } + if ( e->op == TOKvar ) { VarExp* v = ( VarExp* ) e; @@ -2474,7 +2480,7 @@ namespace AsmParserx8664 #endif { - e = new AddrExp ( 0, e ); + e = new AddrExp ( Loc(), e ); e->type = decl->type->pointerTo(); operand->constDisplacement = 0; @@ -2539,7 +2545,7 @@ namespace AsmParserx8664 if ( !sc->func->naked ) // no addrexp in naked asm please :) { Type* tt = e->type->pointerTo(); - e = new AddrExp ( 0, e ); + e = new AddrExp ( Loc(), e ); e->type = tt; } @@ -2580,15 +2586,7 @@ namespace AsmParserx8664 bool isIntExp ( Expression * exp ) { - if ( exp->op == TOKint64 ) - return 1; - if ( exp->op == TOKvar ) - { - Declaration * v = ( ( VarExp * ) exp )->var; - if ( v->isConst() && v->type->isintegral() ) - return 1; - } - return 0; + return exp->op == TOKint64; } bool isRegExp ( Expression * exp ) { return exp->op == TOKmod; } // ewww.%% bool isLocalSize ( Expression * exp ) @@ -2696,7 +2694,7 @@ namespace AsmParserx8664 // DMD doesn't check Tcomplex*, and counts Tcomplex32 as Tfloat64 TY ty = v->type->toBasetype()->ty; operand->dataSizeHint = ty == Tfloat80 || ty == Timaginary80 ? - Extended_Ptr : ( PtrType ) v->type->size ( 0 ); + Extended_Ptr : ( PtrType ) v->type->size ( Loc() ); } if ( ! operand->symbolDisplacement.dim ) @@ -3214,6 +3212,7 @@ namespace AsmParserx8664 } e = e->semantic ( sc ); + e = e->optimize (WANTvalue); // Special case for floating point constant declarations. if ( e->op == TOKfloat64 ) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 7e3e3a06b9..2108fa91b9 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -132,11 +132,6 @@ void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); } -int AsmStatement::comeFrom() -{ - return FALSE; -} - struct AsmParserCommon { virtual ~AsmParserCommon() {} @@ -577,7 +572,7 @@ void AsmBlockStatement::toIR(IRState* p) { FuncDeclaration* fd = gIR->func()->decl; - char* fdmangle = fd->mangle(); + const char* fdmangle = fd->mangle(); // we use a simple static counter to make sure the new end labels are unique static size_t uniqueLabelsId = 0; diff --git a/gen/classes.cpp b/gen/classes.cpp index efb8ac4948..f5d164ac74 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -12,6 +12,7 @@ #include "declaration.h" #include "init.h" #include "mtype.h" +#include "target.h" #include "gen/arrays.h" #include "gen/classes.h" #include "gen/dvalue.h" @@ -56,9 +57,9 @@ void DtoResolveClass(ClassDeclaration* cd) DtoType(cd->type); // create IrAggr - assert(cd->ir.irStruct == NULL); + assert(cd->ir.irAggr == NULL); IrAggr* irAggr = new IrAggr(cd); - cd->ir.irStruct = irAggr; + cd->ir.irAggr = irAggr; // make sure all fields really get their ir field ArrayIter it(cd->fields); @@ -151,7 +152,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp) else { llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, _d_allocclass); - LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->getClassInfoSymbol(), DtoType(ClassDeclaration::classinfo->type)); + LLConstant* ci = DtoBitCast(tc->sym->ir.irAggr->getClassInfoSymbol(), DtoType(ClassDeclaration::classinfo->type)); mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction(); mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc"); } @@ -198,11 +199,11 @@ void DtoInitClass(TypeClass* tc, LLValue* dst) { tc->sym->codegen(Type::sir); - uint64_t n = tc->sym->structsize - PTRSIZE * 2; + uint64_t n = tc->sym->structsize - Target::ptrsize * 2; // set vtable field seperately, this might give better optimization LLValue* tmp = DtoGEPi(dst,0,0,"vtbl"); - LLValue* val = DtoBitCast(tc->sym->ir.irStruct->getVtblSymbol(), tmp->getType()->getContainedType(0)); + LLValue* val = DtoBitCast(tc->sym->ir.irAggr->getVtblSymbol(), tmp->getType()->getContainedType(0)); DtoStore(val, tmp); // monitor always defaults to zero @@ -218,7 +219,7 @@ void DtoInitClass(TypeClass* tc, LLValue* dst) LLValue* dstarr = DtoGEPi(dst,0,2,"tmp"); // init symbols might not have valid types - LLValue* initsym = tc->sym->ir.irStruct->getInitSymbol(); + LLValue* initsym = tc->sym->ir.irAggr->getInitSymbol(); initsym = DtoBitCast(initsym, DtoType(tc)); LLValue* srcarr = DtoGEPi(initsym,0,2,"tmp"); @@ -379,7 +380,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to) TypeClass* to = static_cast(_to->toBasetype()); to->sym->codegen(Type::sir); - LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol(); + LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol(); // unfortunately this is needed as the implementation of object differs somehow from the declaration // this could happen in user code as well :/ cinfo = DtoBitCast(cinfo, funcTy->getParamType(1)); @@ -440,7 +441,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to) // ClassInfo c TypeClass* to = static_cast(_to->toBasetype()); to->sym->codegen(Type::sir); - LLValue* cinfo = to->sym->ir.irStruct->getClassInfoSymbol(); + LLValue* cinfo = to->sym->ir.irAggr->getClassInfoSymbol(); // unfortunately this is needed as the implementation of object differs somehow from the declaration // this could happen in user code as well :/ cinfo = DtoBitCast(cinfo, funcTy->getParamType(1)); @@ -579,14 +580,14 @@ static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd) static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT) { - IrStruct* irstruct = cd->ir.irStruct; + IrAggr* iraggr = cd->ir.irAggr; - size_t nvars = irstruct->varDecls.size(); + size_t nvars = iraggr->varDecls.size(); std::vector arrayInits(nvars); for (size_t i=0; ivarDecls[i]); + arrayInits[i] = build_offti_entry(cd, iraggr->varDecls[i]); } LLConstant* size = DtoConstSize_t(nvars); @@ -604,7 +605,8 @@ static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT) name.append("__OffsetTypeInfos"); // create symbol - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,DtoInternalLinkage(cd),arrInit,name,gIR->module); + llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, *gIR->module, arrTy, + true,DtoInternalLinkage(cd),arrInit,name); ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType())); return DtoConstSlice(size, ptr); @@ -689,7 +691,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd) assert(cd->type->ty == Tclass); TypeClass* cdty = static_cast(cd->type); - IrAggr* ir = cd->ir.irStruct; + IrAggr* ir = cd->ir.irAggr; assert(ir); ClassDeclaration* cinfo = ClassDeclaration::classinfo; diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 237bbc95e9..dcb710bbea 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -98,23 +98,6 @@ void TupleDeclaration::codegen(Ir* p) /* ================================================================== */ -static llvm::GlobalVariable* createGlobal(llvm::Type* type, bool isConst, - llvm::GlobalValue::LinkageTypes linkage, llvm::StringRef name, - bool isThreadLocal) -{ -#if LDC_LLVM_VER >= 302 - // FIXME: clang uses a command line option for the thread model - const llvm::GlobalVariable::ThreadLocalMode tlsModel = - isThreadLocal ? llvm::GlobalVariable::GeneralDynamicTLSModel - : llvm::GlobalVariable::NotThreadLocal; - return new llvm::GlobalVariable(*gIR->module, type, isConst, linkage, - NULL, name, 0, tlsModel); -#else - return new llvm::GlobalVariable(*gIR->module, type, isConst, linkage, - NULL, name, 0, isThreadLocal); -#endif -} - void VarDeclaration::codegen(Ir* p) { Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars()); @@ -171,8 +154,9 @@ void VarDeclaration::codegen(Ir* p) // this->ir.irGlobal->value!), and in case we also do an initializer // with a different type later, swap it out and replace any existing // uses with bitcasts to the previous type. - llvm::GlobalVariable* gvar = createGlobal(i1ToI8(DtoType(type)), isLLConst, - llLinkage, llName, isThreadlocal()); + llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module, + i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName, + isThreadlocal()); this->ir.irGlobal->value = gvar; // Check if we are defining or just declaring the global in this module. @@ -184,8 +168,8 @@ void VarDeclaration::codegen(Ir* p) // In case of type mismatch, swap out the variable. if (initVal->getType() != gvar->getType()->getElementType()) { - llvm::GlobalVariable* newGvar = createGlobal( - initVal->getType(), isLLConst, llLinkage, + llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc, + *gIR->module, initVal->getType(), isLLConst, llLinkage, 0, "", // We take on the name of the old global below. isThreadlocal()); diff --git a/gen/irstate.cpp b/gen/irstate.cpp index e260b7633f..be6f184051 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -165,6 +165,21 @@ LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue* return CreateCallOrInvoke(Callee, args, Name); } +bool IRState::emitArrayBoundsChecks() +{ + int p = global.params.useArrayBounds; + + // 0 or 2 are absolute decisions. + if (p != 1) return p != 0; + + // Safe functions only. + if (functions.empty()) return false; + + Type* t = func()->decl->type; + return t->ty == Tfunction && ((TypeFunction*)t)->trust == TRUSTsafe; +} + + ////////////////////////////////////////////////////////////////////////////////////////// IRBuilder<>* IRBuilderHelper::operator->() diff --git a/gen/irstate.h b/gen/irstate.h index 3d57918e18..456599887f 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -208,6 +208,9 @@ struct IRState // 'used' array solely for keeping a reference to globals std::vector usedArray; + + /// Whether to emit array bounds checking in the current function. + bool emitArrayBoundsChecks(); }; template diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 4097e199a5..8c01cd7b3a 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -252,7 +252,7 @@ void DtoGoto(Loc loc, Identifier* target, TryFinallyStatement* sourceFinally) /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// -// TRY-FINALLY, VOLATILE AND SYNCHRONIZED HELPER +// TRY-FINALLY AND SYNCHRONIZED HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ void EnclosingSynchro::emitCode(IRState * p) @@ -265,14 +265,6 @@ void EnclosingSynchro::emitCode(IRState * p) //////////////////////////////////////////////////////////////////////////////////////// -void EnclosingVolatile::emitCode(IRState * p) -{ - // store-load barrier - DtoMemoryBarrier(false, false, true, false); -} - -//////////////////////////////////////////////////////////////////////////////////////// - void EnclosingTryFinally::emitCode(IRState * p) { if (tf->finalbody) @@ -829,6 +821,13 @@ DValue* DtoCast(Loc& loc, DValue* val, Type* to) LLValue *rval = DtoBitCast(val->getRVal(), DtoType(to)); return new DImValue(to, rval); } + else if (totype->ty == Tbool) + { + IF_LOG Logger::println("Casting AA to bool."); + LLValue* rval = val->getRVal(); + LLValue* zero = LLConstant::getNullValue(rval->getType()); + return new DImValue(to, gIR->ir->CreateICmpNE(rval, zero)); + } // Else try dealing with the rewritten (struct) type. fromtype = static_cast(fromtype)->getImpl()->type; @@ -1138,18 +1137,6 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) Logger::println("FuncDeclaration"); f->codegen(Type::sir); } - // alias declaration - else if (declaration->isAliasDeclaration()) - { - Logger::println("AliasDeclaration - no work"); - // do nothing - } - // enum - else if (declaration->isEnumDeclaration()) - { - Logger::println("EnumDeclaration - no work"); - // do nothing - } // class else if (ClassDeclaration* e = declaration->isClassDeclaration()) { @@ -1196,15 +1183,12 @@ DValue* DtoDeclarationExp(Dsymbol* declaration) DtoDeclarationExp(exp->s); } } - // template - else if (declaration->isTemplateDeclaration()) - { - Logger::println("TemplateDeclaration"); - // do nothing - } else { - llvm_unreachable("Unimplemented Declaration type for DeclarationExp."); + // Do nothing for template/alias/enum declarations and static + // assertions. We cannot detect StaticAssert without RTTI, so don't + // even bother to check. + IF_LOG Logger::println("Ignoring Symbol: %s", declaration->kind()); } return 0; @@ -1295,7 +1279,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init) { Logger::println("const struct initializer"); si->ad->codegen(Type::sir); - return si->ad->ir.irStruct->createStructInitializer(si); + return si->ad->ir.irAggr->createStructInitializer(si); } else if (ArrayInitializer* ai = init->isArrayInitializer()) { @@ -1510,6 +1494,11 @@ bool mustDefineSymbol(Dsymbol* s) if (fd->semanticRun < PASSsemantic3) return false; + // If a function has no body, we cannot possibly emit it (and so it + // cannot be available_externally either). + if (!fd->fbody) + return false; + if (fd->isArrayOp == 1) return true; @@ -1542,6 +1531,13 @@ bool mustDefineSymbol(Dsymbol* s) } } + if (VarDeclaration* vd = s->isVarDeclaration()) + { + // Never define 'extern' variables. + if (vd->storage_class & STCextern) + return false; + } + // Inlining checks may create some variable and class declarations // we don't need to emit. if (global.inExtraInliningSemantic) @@ -1700,7 +1696,7 @@ LLValue* makeLValue(Loc& loc, DValue* value) if (needsMemory) { LLValue* tmp = DtoAlloca(valueType, ".makelvaluetmp"); - DtoStore(valuePointer, tmp); + DtoStoreZextI8(valuePointer, tmp); valuePointer = tmp; } @@ -1855,7 +1851,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) { Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars()); cid->cd->codegen(Type::sir);; - return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol()); + return new DVarValue(type, vd, cid->cd->ir.irAggr->getClassInfoSymbol()); } // typeinfo else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) @@ -1954,7 +1950,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) return new DFuncValue(fdecl, func); } - if (StaticStructInitDeclaration* sdecl = decl->isStaticStructInitDeclaration()) + if (SymbolDeclaration* sdecl = decl->isSymbolDeclaration()) { // this seems to be the static initialiser for structs Type* sdecltype = sdecl->type->toBasetype(); @@ -1964,7 +1960,7 @@ DValue* DtoSymbolAddress(const Loc& loc, Type* type, Declaration* decl) assert(ts->sym); ts->sym->codegen(Type::sir); - LLValue* initsym = ts->sym->ir.irStruct->getInitSymbol(); + LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol(); initsym = DtoBitCast(initsym, DtoType(ts->pointerTo())); return new DVarValue(type, initsym); } @@ -2013,3 +2009,32 @@ llvm::Constant* DtoConstSymbolAddress(const Loc& loc, Declaration* decl) llvm_unreachable("Taking constant address not implemented."); } + +llvm::GlobalVariable* getOrCreateGlobal(Loc loc, llvm::Module& module, + llvm::Type* type, bool isConstant, llvm::GlobalValue::LinkageTypes linkage, + llvm::Constant* init, llvm::StringRef name, bool isThreadLocal) +{ + llvm::GlobalVariable* existing = module.getGlobalVariable(name, true); + if (existing) + { + if (existing->getType()->getElementType() != type) + { + error(loc, "Global variable type does not match previous " + "declaration with same mangled name: %s", name.str().c_str()); + fatal(); + } + return existing; + } + +#if LDC_LLVM_VER >= 302 + // FIXME: clang uses a command line option for the thread model + const llvm::GlobalVariable::ThreadLocalMode tlsModel = + isThreadLocal ? llvm::GlobalVariable::GeneralDynamicTLSModel + : llvm::GlobalVariable::NotThreadLocal; + return new llvm::GlobalVariable(module, type, isConstant, linkage, + init, name, 0, tlsModel); +#else + return new llvm::GlobalVariable(module, type, isConstant, linkage, + init, name, 0, isThreadLocal); +#endif +} diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 7c5c4e69a4..a23b2a55eb 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -35,12 +35,6 @@ struct EnclosingTryFinally : EnclosingHandler EnclosingTryFinally(TryFinallyStatement* _tf, llvm::BasicBlock* _pad) : tf(_tf), landingPad(_pad) {} }; -struct EnclosingVolatile : EnclosingHandler -{ - VolatileStatement* v; - void emitCode(IRState* p); - EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {} -}; struct EnclosingSynchro : EnclosingHandler { SynchronizedStatement* s; @@ -232,4 +226,16 @@ LLConstant* toConstantArray(LLType* ct, LLArrayType* at, T* str, size_t len, boo return LLConstantArray::get(at, vals); } + +/// Tries to create an LLVM global with the given properties. If a variable with +/// the same mangled name already exists, checks if the types match and returns +/// it instead. +/// +/// Necessary to support multiple declarations with the same mangled name, as +/// can be the case due to pragma(mangle). +llvm::GlobalVariable* getOrCreateGlobal(Loc loc, llvm::Module& module, + llvm::Type* type, bool isConstant, llvm::GlobalValue::LinkageTypes linkage, + llvm::Constant* init, llvm::StringRef name, bool isThreadLocal = false); + + #endif diff --git a/gen/module.cpp b/gen/module.cpp index 5893de6572..7ff40101b9 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -19,6 +19,7 @@ #include "mtype.h" #include "scope.h" #include "statement.h" +#include "target.h" #include "template.h" #include "gen/abi.h" #include "gen/arrays.h" @@ -177,8 +178,9 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo) std::string thismrefname = "_D"; thismrefname += gIR->dmodule->mangle(); thismrefname += "11__moduleRefZ"; - LLGlobalVariable* thismref = new LLGlobalVariable(*gIR->module, modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, thismrefname); - + LLGlobalVariable* thismref = getOrCreateGlobal(Loc(), *gIR->module, + modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit, + thismrefname); // make sure _Dmodule_ref is declared LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref"); LLType *modulerefPtrTy = getPtrToType(modulerefTy); @@ -325,7 +327,7 @@ llvm::GlobalVariable* Module::moduleInfoSymbol() // create name std::string MIname("_D"); MIname.append(mangle()); - MIname.append("8__ModuleZ"); + MIname.append("12__ModuleInfoZ"); if (gIR->dmodule != this) { LLType* moduleinfoTy = DtoType(moduleinfo->type); @@ -340,7 +342,8 @@ llvm::GlobalVariable* Module::moduleInfoSymbol() // declare global // flags will be modified at runtime so can't make it constant - moduleInfoVar = new llvm::GlobalVariable(*gIR->module, moduleInfoType, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); + moduleInfoVar = getOrCreateGlobal(loc, *gIR->module, moduleInfoType, + false, llvm::GlobalValue::ExternalLinkage, NULL, MIname); return moduleInfoVar; } @@ -357,7 +360,7 @@ void Module::genmoduleinfo() // check for patch else { - unsigned sizeof_ModuleInfo = 16 * PTRSIZE; + unsigned sizeof_ModuleInfo = 16 * Target::ptrsize; if (sizeof_ModuleInfo != moduleinfo->structsize) { error("object.d ModuleInfo class is incorrect"); @@ -385,7 +388,7 @@ void Module::genmoduleinfo() // declare the imported module info std::string m_name("_D"); m_name.append(m->mangle()); - m_name.append("8__ModuleZ"); + m_name.append("12__ModuleInfoZ"); llvm::GlobalVariable* m_gvar = gIR->module->getGlobalVariable(m_name); if (!m_gvar) m_gvar = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name); importInits.push_back(m_gvar); @@ -428,7 +431,7 @@ void Module::genmoduleinfo() continue; } Logger::println("class: %s", cd->toPrettyChars()); - LLConstant *c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), classinfoTy); + LLConstant *c = DtoBitCast(cd->ir.irAggr->getClassInfoSymbol(), classinfoTy); classInits.push_back(c); } // has class array? diff --git a/gen/nested.cpp b/gen/nested.cpp index 45e548025f..2b7e778541 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "target.h" #include "gen/nested.h" #include "gen/dvalue.h" #include "gen/functions.h" @@ -95,18 +96,21 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd, bool byref) // get the nested context LLValue* ctx = 0; - if (irfunc->decl->isMember2()) - { + if (irfunc->nestedVar) { + // If this function has its own nested context struct, always load it. + ctx = irfunc->nestedVar; + dwarfValue = ctx; + } else if (irfunc->decl->isMember2()) { + // If this is a member function of a nested class without its own + // context, load the vthis member. AggregateDeclaration* cd = irfunc->decl->isMember2(); LLValue* val = irfunc->thisArg; if (cd->isClassDeclaration()) val = DtoLoad(val); ctx = DtoLoad(DtoGEPi(val, 0, cd->vthis->ir.irField->index, ".vthis")); - } - else if (irfunc->nestedVar) { - ctx = irfunc->nestedVar; - dwarfValue = ctx; } else { + // Otherwise, this is a simple nested function, load from the context + // argument. ctx = DtoLoad(irfunc->nestArg); dwarfValue = irfunc->nestArg; if (global.params.symdebug) @@ -444,7 +448,7 @@ void DtoCreateNestedContext(FuncDeclaration* fd) { if (depth > 1) { src = DtoBitCast(src, getVoidPtrType()); LLValue* dst = DtoBitCast(frame, getVoidPtrType()); - DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * PTRSIZE), + DtoMemCpy(dst, src, DtoConstSize_t((depth-1) * Target::ptrsize), getABITypeAlign(getVoidPtrType())); } // Copy nestArg into framelist; the outer frame is not in the list of pointers diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index bc182b5f5c..c1711d7037 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -26,7 +26,7 @@ RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class) base = base_class; basetype = static_cast(base->type); - baseir = base->ir.irStruct; + baseir = base->ir.irAggr; assert(baseir && "no IrStruct for TypeInfo base class"); if (base->isClassDeclaration()) { @@ -59,7 +59,7 @@ void RTTIBuilder::push_typeinfo(Type* t) void RTTIBuilder::push_classinfo(ClassDeclaration* cd) { - inits.push_back(cd->ir.irStruct->getClassInfoSymbol()); + inits.push_back(cd->ir.irAggr->getClassInfoSymbol()); } void RTTIBuilder::push_string(const char* str) @@ -86,7 +86,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma std::string initname(mangle_sym->mangle()); initname.append(".rtti.voidarr.data"); - LLGlobalVariable* G = new llvm::GlobalVariable( + LLGlobalVariable* G = new LLGlobalVariable( *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); @@ -105,7 +105,7 @@ void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, D initname.append(tmpStr); initname.append(".data"); - LLGlobalVariable* G = new llvm::GlobalVariable( + LLGlobalVariable* G = new LLGlobalVariable( *gIR->module, CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname); G->setAlignment(valtype->alignsize()); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 3b2f33717e..c6e4af3425 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -15,11 +15,14 @@ #include "module.h" #include "mtype.h" #include "root.h" +#include "gen/abi.h" #include "gen/irstate.h" #include "gen/llvm.h" +#include "gen/llvmhelpers.h" #include "gen/logger.h" #include "gen/tollvm.h" #include "ir/irtype.h" +#include "ir/irtypefunction.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" @@ -92,6 +95,7 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name LLFunctionType* fnty = fn->getFunctionType(); LLFunction* resfn = llvm::cast(target->getOrInsertFunction(name, fnty)); resfn->setAttributes(fn->getAttributes()); + resfn->setCallingConv(fn->getCallingConv()); return resfn; } @@ -121,8 +125,8 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* } LLPointerType* t = g->getType(); - return new LLGlobalVariable(*target, t->getElementType(), g->isConstant(), - g->getLinkage(), NULL, g->getName()); + return getOrCreateGlobal(Loc(), *target, t->getElementType(), g->isConstant(), + g->getLinkage(), NULL, g->getName()); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -898,12 +902,26 @@ static void LLVM_D_BuildRuntimeModule() ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// - // void _d_invariant(Object o) + // void invariant._d_invariant(Object o) { - llvm::StringRef fname("_d_invariant"); - LLType *types[] = { objectTy }; - LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false); - llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + // KLUDGE: _d_invariant is actually extern(D) in the upstream runtime, possibly + // for more efficient parameter passing on x86. This complicates our code here + // quite a bit, though. + llvm::StringRef fname("_D9invariant12_d_invariantFC6ObjectZv"); + Parameters* params = new Parameters(); + params->push(new Parameter(STCin, ClassDeclaration::object->type, NULL, NULL)); + TypeFunction* dty = new TypeFunction(params, Type::tvoid, 0, LINKd); + llvm::Function* fn = llvm::Function::Create(llvm::cast(DtoType(dty)), + llvm::GlobalValue::ExternalLinkage, fname, M); + gABI->newFunctionType(dty); + gABI->rewriteFunctionType(dty); + gABI->doneWithFunctionType(); +#if LDC_LLVM_VER < 303 + fn->addAttribute(1, dty->fty.args[0]->attrs); +#else + fn->addAttributes(1, llvm::AttributeSet::get(gIR->context(), 1, dty->fty.args[0]->attrs)); +#endif + fn->setCallingConv(gABI->callingConv(LINKd)); } // void _d_hidden_func() diff --git a/gen/statements.cpp b/gen/statements.cpp index 5c5d71652e..b2b0b80602 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1557,48 +1557,6 @@ void SynchronizedStatement::toIR(IRState* p) ////////////////////////////////////////////////////////////////////////////// -void VolatileStatement::toIR(IRState* p) -{ - Logger::println("VolatileStatement::toIR(): %s", loc.toChars()); - LOG_SCOPE; - - // emit dwarf stop point - DtoDwarfStopPoint(loc.linnum); - - // mark in-volatile - // FIXME - - // has statement - if (statement != NULL) - { - // load-store - DtoMemoryBarrier(false, true, false, false); - - // do statement - p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL)); - statement->toIR(p); - p->func()->gen->targetScopes.pop_back(); - - // no point in a unreachable barrier, terminating statements must insert this themselves. - if (statement->blockExit(false) & BEfallthru) - { - // store-load - DtoMemoryBarrier(false, false, true, false); - } - } - // barrier only - else - { - // load-store & store-load - DtoMemoryBarrier(false, true, true, false); - } - - // restore volatile state - // FIXME -} - -////////////////////////////////////////////////////////////////////////////// - void SwitchErrorStatement::toIR(IRState* p) { Logger::println("SwitchErrorStatement::toIR(): %s", loc.toChars()); @@ -1653,7 +1611,6 @@ STUBST(Statement); //STUBST(AsmStatement); //STUBST(TryCatchStatement); //STUBST(TryFinallyStatement); -//STUBST(VolatileStatement); //STUBST(LabelStatement); //STUBST(ThrowStatement); //STUBST(GotoCaseStatement); diff --git a/gen/structs.cpp b/gen/structs.cpp index 118e70d7de..190550369c 100644 --- a/gen/structs.cpp +++ b/gen/structs.cpp @@ -45,8 +45,8 @@ void DtoResolveStruct(StructDeclaration* sd) return; // create the IrAggr - IrAggr* irstruct = new IrAggr(sd); - sd->ir.irStruct = irstruct; + IrAggr* iraggr = new IrAggr(sd); + sd->ir.irAggr = iraggr; // Set up our field metadata. for (ArrayIter it(sd->fields); !it.done(); it.next()) @@ -61,10 +61,10 @@ void DtoResolveStruct(StructDeclaration* sd) if (emitGlobalData) { // emit the initZ symbol - LLGlobalVariable* initZ = irstruct->getInitSymbol(); + LLGlobalVariable* initZ = iraggr->getInitSymbol(); // set initZ initializer - initZ->setInitializer(irstruct->getDefaultInit()); + initZ->setInitializer(iraggr->getDefaultInit()); } // emit members diff --git a/gen/tocall.cpp b/gen/tocall.cpp index fb06fc090b..257d32c13d 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -10,6 +10,7 @@ #include "declaration.h" #include "id.h" #include "mtype.h" +#include "target.h" #include "gen/abi.h" #include "gen/dvalue.h" #include "gen/functions.h" @@ -211,24 +212,24 @@ void DtoBuildDVarArgList(std::vector& args, assert(argexp->type->ty != Ttuple); vtypes.push_back(DtoType(argexp->type)); size_t sz = getTypePaddedSize(vtypes.back()); - size_t asz = (sz + PTRSIZE - 1) & ~(PTRSIZE -1); + size_t asz = (sz + Target::ptrsize - 1) & ~(Target::ptrsize -1); if (sz != asz) { - if (sz < PTRSIZE) + if (sz < Target::ptrsize) { vtypes.back() = DtoSize_t(); } else { // ok then... so we build some type that is big enough - // and aligned to PTRSIZE + // and aligned to Target::ptrsize std::vector gah; - gah.reserve(asz/PTRSIZE); + gah.reserve(asz/Target::ptrsize); size_t gah_sz = 0; while (gah_sz < asz) { gah.push_back(DtoSize_t()); - gah_sz += PTRSIZE; + gah_sz += Target::ptrsize; } vtypes.back() = LLStructType::get(gIR->context(), gah, true); } @@ -512,7 +513,10 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* std::vector argvals; argvals.reserve(n); if (dfnval && dfnval->func->isArrayOp) { - // slightly different approach for array operators + // For array ops, the druntime implementation signatures are crafted + // specifically such that the evaluation order is as expected with + // the strange DMD reverse parameter passing order. Thus, we need + // to actually build the arguments right-to-left for them. for (int i=n-1; i>=0; --i) { Parameter* fnarg = Parameter::getNth(tf->parameters, i); assert(fnarg); diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 62c2e5df3d..26e29f9397 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -23,6 +23,7 @@ #include "gen/tollvm.h" #include "gen/utils.h" #include "ir/irmodule.h" +#include "ir/irtypeaggr.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/FileSystem.h" @@ -214,7 +215,7 @@ static llvm::DIType dwarfVectorType(Type* type) assert(t->ty == Tvector && "only vectors allowed for debug info in dwarfVectorType"); TypeVector *tv = static_cast(t); Type *te = tv->elementType(); - int64_t Dim = tv->size(Loc(0)) / te->size(Loc(0)); + int64_t Dim = tv->size(Loc()) / te->size(Loc()); llvm::Value *subscripts[] = { gIR->dibuilder.getOrCreateSubrange(0, Dim) @@ -281,9 +282,7 @@ static void add_base_fields( static llvm::DIType dwarfCompositeType(Type* type) { - LLType* T = DtoType(type); Type* t = type->toBasetype(); - assert((t->ty == Tstruct || t->ty == Tclass) && "unsupported type for dwarfCompositeType"); AggregateDeclaration* sd; @@ -299,19 +298,20 @@ static llvm::DIType dwarfCompositeType(Type* type) } assert(sd); - // make sure it's resolved - sd->codegen(Type::sir); + // Use the actual type associated with the declaration, ignoring any + // const/… wrappers. + LLType* T = DtoType(sd->type); + IrTypeAggr* ir = sd->type->irtype->isAggr(); + assert(ir); + + if (static_cast(ir->diCompositeType) != 0) + return ir->diCompositeType; // if we don't know the aggregate's size, we don't know enough about it // to provide debug info. probably a forward-declared struct? if (sd->sizeok == 0) return llvm::DICompositeType(NULL); - IrAggr* ir = sd->ir.irStruct; - assert(ir); - if (static_cast(ir->diCompositeType) != 0) - return ir->diCompositeType; - // elements std::vector elems; @@ -322,17 +322,15 @@ static llvm::DIType dwarfCompositeType(Type* type) llvm::DIType derivedFrom; // set diCompositeType to handle recursive types properly - if (!ir->diCompositeType) { - unsigned tag = (t->ty == Tstruct) ? llvm::dwarf::DW_TAG_structure_type - : llvm::dwarf::DW_TAG_class_type; - ir->diCompositeType = gIR->dibuilder.createForwardDecl(tag, name, + unsigned tag = (t->ty == Tstruct) ? llvm::dwarf::DW_TAG_structure_type + : llvm::dwarf::DW_TAG_class_type; + ir->diCompositeType = gIR->dibuilder.createForwardDecl(tag, name, #if LDC_LLVM_VER >= 302 - llvm::DIDescriptor(file), + llvm::DIDescriptor(file), #endif - file, linnum); - } + file, linnum); - if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one + if (!sd->isInterfaceDeclaration()) // plain interfaces don't have one { if (t->ty == Tstruct) { @@ -348,7 +346,7 @@ static llvm::DIType dwarfCompositeType(Type* type) } else { - ClassDeclaration *classDecl = ir->aggrdecl->isClassDeclaration(); + ClassDeclaration *classDecl = sd->isClassDeclaration(); add_base_fields(classDecl, file, elems); if (classDecl->baseClass) derivedFrom = dwarfCompositeType(classDecl->baseClass->getType()); diff --git a/gen/toir.cpp b/gen/toir.cpp index 8963d2f7f6..d1ee19fe18 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -36,13 +36,18 @@ #include "gen/typeinf.h" #include "gen/utils.h" #include "gen/warnings.h" +#include "ir/irtypeclass.h" #include "ir/irtypestruct.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include #include +#include #include +// Needs other includes. +#include "ctfe.h" + llvm::cl::opt checkPrintf("check-printf-calls", llvm::cl::desc("Validate printf call format strings against arguments"), llvm::cl::ZeroOrMore); @@ -120,7 +125,7 @@ LLConstant* VarExp::toConstElem(IRState* p) Logger::print("VarExp::toConstElem: %s @ %s\n", toChars(), type->toChars()); LOG_SCOPE; - if (StaticStructInitDeclaration* sdecl = var->isStaticStructInitDeclaration()) + if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) { // this seems to be the static initialiser for structs Type* sdecltype = sdecl->type->toBasetype(); @@ -129,7 +134,7 @@ LLConstant* VarExp::toConstElem(IRState* p) TypeStruct* ts = static_cast(sdecltype); ts->sym->codegen(Type::sir); - return ts->sym->ir.irStruct->getDefaultInit(); + return ts->sym->ir.irAggr->getDefaultInit(); } if (TypeInfoDeclaration* ti = var->isTypeInfoDeclaration()) @@ -419,7 +424,12 @@ DValue* AssignExp::toElem(IRState* p) DVarValue* lhs = e1->toElem(p)->isVar(); assert(lhs); DValue* rhs = e2->toElem(p); - DtoStore(rhs->getLVal(), lhs->getRefStorage()); + + // We shouldn't really need makeLValue() here, but the 2.063 + // frontend generates ref variables initialized from function + // calls. + DtoStore(makeLValue(loc, rhs), lhs->getRefStorage()); + return rhs; } } @@ -1094,6 +1104,25 @@ LLConstant* CastExp::toConstElem(IRState* p) } return DtoBitCast(value, DtoType(tb)); } + else if (tb->ty == Tclass && e1->type->ty == Tclass) { + assert(e1->op == TOKclassreference); + ClassDeclaration* cd = static_cast(e1)->originalClass(); + + llvm::Constant* instance = e1->toConstElem(p); + if (InterfaceDeclaration* it = static_cast(tb)->sym->isInterfaceDeclaration()) { + assert(it->isBaseOf(cd, NULL)); + + IrTypeClass* typeclass = cd->type->irtype->isClass(); + + // find interface impl + size_t i_index = typeclass->getInterfaceIndex(it); + assert(i_index != ~0UL); + + // offset pointer + instance = DtoGEPi(instance, 0, i_index); + } + return DtoBitCast(instance, DtoType(tb)); + } else { goto Lerr; } @@ -1101,7 +1130,7 @@ LLConstant* CastExp::toConstElem(IRState* p) return res; Lerr: - error("can not cast %s to %s at compile time", e1->type->toChars(), type->toChars()); + error("cannot cast %s to %s at compile time", e1->type->toChars(), type->toChars()); if (!global.gag) fatal(); return NULL; @@ -1200,8 +1229,26 @@ llvm::Constant* SymOffExp::toConstElem(IRState* p) DValue* AddrExp::toElem(IRState* p) { - Logger::println("AddrExp::toElem: %s @ %s", toChars(), type->toChars()); + IF_LOG Logger::println("AddrExp::toElem: %s @ %s", toChars(), type->toChars()); LOG_SCOPE; + + // The address of a StructLiteralExp can in fact be a global variable, check + // for that instead of re-codegening the literal. + if (e1->op == TOKstructliteral) + { + IF_LOG Logger::println("is struct literal"); + StructLiteralExp* se = static_cast(e1); + + // DMD uses origin here as well, necessary to handle messed-up AST on + // forward references. + if (se->origin->globalVar) + { + IF_LOG Logger::cout() << "returning address of global: " << + *se->globalVar << '\n'; + return new DImValue(type, DtoBitCast(se->origin->globalVar, DtoType(type))); + } + } + DValue* v = e1->toElem(p); if (v->isField()) { Logger::println("is field"); @@ -1241,6 +1288,8 @@ DValue* AddrExp::toElem(IRState* p) LLConstant* AddrExp::toConstElem(IRState* p) { + IF_LOG Logger::println("AddrExp::toConstElem: %s @ %s", toChars(), type->toChars()); + LOG_SCOPE; // FIXME: this should probably be generalized more so we don't // need to have a case for each thing we can take the address of @@ -1279,9 +1328,37 @@ LLConstant* AddrExp::toConstElem(IRState* p) assert(type->toBasetype()->ty == Tpointer); return DtoBitCast(gep, DtoType(type)); } - else if ( - e1->op == TOKstructliteral || - e1->op == TOKslice) + else if (e1->op == TOKstructliteral) + { + StructLiteralExp* se = static_cast(e1); + + if (se->globalVar) + { + Logger::cout() << "Returning existing global: " << *se->globalVar << '\n'; + return se->globalVar; + } + + se->globalVar = new llvm::GlobalVariable(*p->module, + DtoType(e1->type), false, llvm::GlobalValue::InternalLinkage, 0, + ".structliteral"); + + llvm::Constant* constValue = se->toConstElem(p); + if (constValue->getType() != se->globalVar->getType()->getContainedType(0)) + { + llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable( + *p->module, constValue->getType(), false, + llvm::GlobalValue::InternalLinkage, 0, ".structliteral"); + se->globalVar->replaceAllUsesWith( + DtoBitCast(finalGlobalVar, se->globalVar->getType())); + se->globalVar->eraseFromParent(); + se->globalVar = finalGlobalVar; + } + se->globalVar->setInitializer(constValue); + se->globalVar->setAlignment(e1->type->alignsize()); + + return se->globalVar; + } + else if (e1->op == TOKslice) { error("non-constant expression '%s'", toChars()); fatal(); @@ -1325,6 +1402,30 @@ DValue* PtrExp::toElem(IRState* p) { V = e1->toElem(p)->getRVal(); } + + // The frontend emits dereferences of class/interfaces types to access the + // first member, which is the .classinfo property. + Type* origType = e1->type->toBasetype(); + if (origType->ty == Tclass) + { + TypeClass* ct = static_cast(origType); + + Type* resultType; + if (ct->sym->isInterfaceDeclaration()) + { + // For interfaces, the first entry in the vtbl is actually a pointer + // to an Interface instance, which has the type info as its first + // member, so we have to add an extra layer of indirection. + resultType = Type::typeinfointerface->type->pointerTo(); + } + else + { + resultType = Type::typeinfointerface->type; + } + + V = DtoBitCast(V, DtoType(resultType->pointerTo()->pointerTo())); + } + return new DVarValue(type, V); } @@ -1508,12 +1609,12 @@ DValue* IndexExp::toElem(IRState* p) arrptr = DtoGEP1(l->getRVal(),r->getRVal()); } else if (e1type->ty == Tsarray) { - if(global.params.useArrayBounds) + if (gIR->emitArrayBoundsChecks()) DtoArrayBoundsCheck(loc, l, r); arrptr = DtoGEP(l->getRVal(), zero, r->getRVal()); } else if (e1type->ty == Tarray) { - if(global.params.useArrayBounds) + if (gIR->emitArrayBoundsChecks()) DtoArrayBoundsCheck(loc, l, r); arrptr = DtoArrayPtr(l); arrptr = DtoGEP1(arrptr,r->getRVal()); @@ -1540,7 +1641,7 @@ DValue* SliceExp::toElem(IRState* p) // now all slices have *both* the 'len' and 'ptr' fields set to != null. // value being sliced - LLValue* elen; + LLValue* elen = 0; LLValue* eptr; DValue* e = e1->toElem(p); @@ -1571,7 +1672,7 @@ DValue* SliceExp::toElem(IRState* p) LLValue* vlo = lo->getRVal(); LLValue* vup = up->getRVal(); - if(global.params.useArrayBounds) + if (gIR->emitArrayBoundsChecks()) DtoArrayBoundsCheck(loc, e, up, lo); // offset by lower @@ -1595,13 +1696,17 @@ DValue* SliceExp::toElem(IRState* p) // in this case, we also need to make sure the pointer is cast to the innermost element type eptr = DtoBitCast(eptr, DtoType(tsa->nextOf()->pointerTo())); } - // for normal code the actual array length is what we want! - else - { - elen = DtoArrayLen(e); - } } + // The frontend generates a SliceExp of static array type when assigning a + // fixed-width slice to a static array. + if (type->toBasetype()->ty == Tsarray) + { + return new DVarValue(type, + DtoBitCast(eptr, DtoType(type->pointerTo()))); + } + + if (!elen) elen = DtoArrayLen(e); return new DSliceValue(type, elen, eptr); } @@ -1933,7 +2038,7 @@ DValue* NewExp::toElem(IRState* p) else { assert(ts->sym); ts->sym->codegen(Type::sir); - DtoAggrCopy(mem, ts->sym->ir.irStruct->getInitSymbol()); + DtoAggrCopy(mem, ts->sym->ir.irAggr->getInitSymbol()); } if (ts->sym->isNested() && ts->sym->vthis) DtoResolveNestedContext(loc, ts->sym, mem); @@ -2086,7 +2191,7 @@ DValue* AssertExp::toElem(IRState* p) p->scope() = IRScope(endbb,oldend); - InvariantDeclaration* invdecl; + FuncDeclaration* invdecl; // class invariants if( global.params.useInvariants && @@ -2094,7 +2199,7 @@ DValue* AssertExp::toElem(IRState* p) !(static_cast(condty)->sym->isInterfaceDeclaration())) { Logger::println("calling class invariant"); - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_invariant"); + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_D9invariant12_d_invariantFC6ObjectZv"); LLValue* arg = DtoBitCast(cond->getRVal(), fn->getFunctionType()->getParamType(0)); gIR->CreateCallOrInvoke(fn, arg); } @@ -2819,7 +2924,7 @@ static LLValue* write_zeroes(LLValue* mem, unsigned start, unsigned end) { DValue* StructLiteralExp::toElem(IRState* p) { - Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars()); + IF_LOG Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars()); LOG_SCOPE; if (sinit) @@ -2832,16 +2937,18 @@ DValue* StructLiteralExp::toElem(IRState* p) assert(ts->sym); ts->sym->codegen(Type::sir); - LLValue* initsym = ts->sym->ir.irStruct->getInitSymbol(); + LLValue* initsym = ts->sym->ir.irAggr->getInitSymbol(); initsym = DtoBitCast(initsym, DtoType(ts->pointerTo())); return new DVarValue(type, initsym); } + if (inProgressMemory) return new DVarValue(type, inProgressMemory); + // make sure the struct is fully resolved sd->codegen(Type::sir); // alloca a stack slot - LLValue* mem = DtoRawAlloca(DtoType(type), 0, ".structliteral"); + inProgressMemory = DtoRawAlloca(DtoType(type), 0, ".structliteral"); // ready elements data assert(elements && "struct literal has null elements"); @@ -2849,7 +2956,7 @@ DValue* StructLiteralExp::toElem(IRState* p) Expression** exprs = (Expression**)elements->data; // might be reset to an actual i8* value so only a single bitcast is emitted. - LLValue* voidptr = mem; + LLValue* voidptr = inProgressMemory; unsigned offset = 0; // go through fields @@ -2897,10 +3004,10 @@ DValue* StructLiteralExp::toElem(IRState* p) } // get a pointer to this field - DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd)); + DVarValue field(vd->type, vd, DtoIndexStruct(inProgressMemory, sd, vd)); // store the initializer there - DtoAssign(loc, &field, val, TOKconstruct); + DtoAssign(loc, &field, val, TOKconstruct, true); if (expr) callPostblit(loc, expr, field.getLVal()); @@ -2921,14 +3028,18 @@ DValue* StructLiteralExp::toElem(IRState* p) voidptr = write_zeroes(voidptr, offset, sd->structsize); // return as a var - return new DVarValue(type, mem); + DValue* result = new DVarValue(type, inProgressMemory); + inProgressMemory = 0; + return result; } ////////////////////////////////////////////////////////////////////////////////////////// LLConstant* StructLiteralExp::toConstElem(IRState* p) { - Logger::print("StructLiteralExp::toConstElem: %s @ %s\n", toChars(), type->toChars()); + // type can legitimately be null for ClassReferenceExp::value. + IF_LOG Logger::print("StructLiteralExp::toConstElem: %s @ %s\n", + toChars(), type ? type->toChars() : "(null)"); LOG_SCOPE; if (sinit) @@ -2940,15 +3051,14 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) TypeStruct* ts = static_cast(sdecltype); ts->sym->codegen(Type::sir); - return ts->sym->ir.irStruct->getDefaultInit(); + return ts->sym->ir.irAggr->getDefaultInit(); } // make sure the struct is resolved sd->codegen(Type::sir); std::map varInits; - - size_t nexprs = elements->dim; + const size_t nexprs = elements->dim; for (size_t i = 0; i < nexprs; i++) { if ((*elements)[i]) @@ -2957,7 +3067,96 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) } } - return sd->ir.irStruct->createInitializerConstant(varInits); + return sd->ir.irAggr->createInitializerConstant(varInits); +} + +llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) +{ + IF_LOG Logger::print("ClassReferenceExp::toConstElem: %s @ %s\n", + toChars(), type->toChars()); + LOG_SCOPE; + + ClassDeclaration* origClass = originalClass(); + + origClass->codegen(Type::sir); + + if (value->globalVar) + { + IF_LOG Logger::cout() << "Using existing global: " << *value->globalVar << '\n'; + } + else + { + value->globalVar = new llvm::GlobalVariable(*p->module, + origClass->type->irtype->isClass()->getMemoryLLType(), + false, llvm::GlobalValue::InternalLinkage, 0, ".classref"); + + std::map varInits; + + // Unfortunately, ClassReferenceExp::getFieldAt is badly broken – it + // places the base class fields _after_ those of the subclass. + { + const size_t nexprs = value->elements->dim; + + std::stack classHierachy; + ClassDeclaration* cur = origClass; + while (cur) + { + classHierachy.push(cur); + cur = cur->baseClass; + } + size_t i = 0; + while (!classHierachy.empty()) + { + cur = classHierachy.top(); + classHierachy.pop(); + for (size_t j = 0; j < cur->fields.dim; ++j) + { + if ((*value->elements)[i]) + { + VarDeclaration* field = cur->fields[j]; + IF_LOG Logger::println("Getting initializer for: %s", field->toChars()); + LOG_SCOPE; + varInits[field] = (*value->elements)[i]->toConstElem(p); + } + ++i; + } + } + assert(i == nexprs); + } + + llvm::Constant* constValue = origClass->ir.irAggr->createInitializerConstant(varInits); + + if (constValue->getType() != value->globalVar->getType()->getContainedType(0)) + { + llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable( + *p->module, constValue->getType(), false, + llvm::GlobalValue::InternalLinkage, 0, ".classref"); + value->globalVar->replaceAllUsesWith( + DtoBitCast(finalGlobalVar, value->globalVar->getType())); + value->globalVar->eraseFromParent(); + value->globalVar = finalGlobalVar; + } + value->globalVar->setInitializer(constValue); + } + + llvm::Constant* result = value->globalVar; + + assert(type->ty == Tclass); + ClassDeclaration* targetClass = static_cast(type)->sym; + if (InterfaceDeclaration* it = targetClass->isInterfaceDeclaration()) { + assert(it->isBaseOf(origClass, NULL)); + + IrTypeClass* typeclass = origClass->type->irtype->isClass(); + + // find interface impl + size_t i_index = typeclass->getInterfaceIndex(it); + assert(i_index != ~0UL); + + // offset pointer + result = DtoGEPi(result, 0, i_index); + } + + return DtoBitCast(result, DtoType(type)); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -3132,7 +3331,12 @@ DValue* TypeExp::toElem(IRState *p) DValue* TupleExp::toElem(IRState *p) { - Logger::print("TupleExp::toElem() %s\n", toChars()); + IF_LOG Logger::print("TupleExp::toElem() %s\n", toChars()); + LOG_SCOPE; + + // If there are any side effects, evaluate them first. + if (e0) e0->toElem(p); + std::vector types; types.reserve(exps->dim); for (size_t i = 0; i < exps->dim; i++) @@ -3160,7 +3364,7 @@ DValue* TupleExp::toElem(IRState *p) DValue* VectorExp::toElem(IRState* p) { - Logger::print("VectorExp::toElem() %s\n", toChars()); + IF_LOG Logger::print("VectorExp::toElem() %s\n", toChars()); LOG_SCOPE; TypeVector *type = static_cast(to->toBasetype()); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 11fa2f1aa1..d960442cb7 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -342,20 +342,28 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) // intrinsics are always external if (fdecl->llvmInternal == LLVMintrinsic) return llvm::GlobalValue::ExternalLinkage; - // generated by inlining semantics run - if (fdecl->availableExternally && mustDefine) + + // Mark functions generated by an inlining semantic run as + // available_externally. Naked functions are turned into module-level + // inline asm and are thus declaration-only as far as the LLVM IR level + // is concerned. + if (fdecl->availableExternally && mustDefine && !fdecl->naked) return llvm::GlobalValue::AvailableExternallyLinkage; + // array operations are always template linkage if (fdecl->isArrayOp == 1) return templateLinkage; + // template instances should have weak linkage // but only if there's a body, and it's not naked // otherwise we make it external - else if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked) + if (needsTemplateLinkage(fdecl) && fdecl->fbody && !fdecl->naked) return templateLinkage; + // extern(C) functions are always external - else if (ft->linkage == LINKc) + if (ft->linkage == LINKc) return llvm::GlobalValue::ExternalLinkage; + // If a function without a body is nested in another // function, we cannot use internal linkage for that // function (see below about nested functions) @@ -427,7 +435,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) for (Dsymbol* parent = sym->parent; parent ; parent = parent->parent) { FuncDeclaration *fd = parent->isFuncDeclaration(); - if (fd && !fd->canInline(fd->needThis())) + if (fd && !fd->canInline(fd->needThis(), false, false)) { // We also cannot internalize nested functions which are // leaked to the outside via a templated return type, because diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 9e69d95128..bcdab26462 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -77,15 +77,15 @@ Expression *Type::getInternalTypeInfo(Scope *sc) break; case Tclass: - if (static_cast(t)->sym->isInterfaceDeclaration()) - break; + if (((TypeClass *)t)->sym->isInterfaceDeclaration()) + break; goto Linternal; case Tarray: // convert to corresponding dynamic array type t = t->nextOf()->mutableOf()->arrayOf(); if (t->nextOf()->ty != Tclass) - break; + break; goto Linternal; case Tfunction: @@ -95,11 +95,11 @@ Expression *Type::getInternalTypeInfo(Scope *sc) tid = internalTI[t->ty]; if (!tid) { tid = new TypeInfoDeclaration(t, 1); - internalTI[t->ty] = tid; + internalTI[t->ty] = tid; } - e = new VarExp(0, tid); + e = new VarExp(Loc(), tid); e = e->addressOf(sc); - e->type = tid->type; // do this so we don't get redundant dereference + e->type = tid->type; // do this so we don't get redundant dereference return e; default: @@ -118,16 +118,14 @@ Expression *Type::getTypeInfo(Scope *sc) //printf("Type::getTypeInfo() %p, %s\n", this, toChars()); if (!Type::typeinfo) { - error(0, "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); + error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch"); fatal(); } - Expression *e = 0; Type *t = merge2(); // do this since not all Type's are merge'd - if (!t->vtinfo) { - if (t->isShared()) + if (t->isShared()) // does both 'shared' and 'shared const' t->vtinfo = new TypeInfoSharedDeclaration(t); else if (t->isConst()) t->vtinfo = new TypeInfoConstDeclaration(t); @@ -138,30 +136,29 @@ Expression *Type::getTypeInfo(Scope *sc) else t->vtinfo = t->getTypeInfoDeclaration(); assert(t->vtinfo); + vtinfo = t->vtinfo; /* If this has a custom implementation in std/typeinfo, then * do not generate a COMDAT for it. */ if (!t->builtinTypeInfo()) { // Generate COMDAT - if (sc) // if in semantic() pass + if (sc) // if in semantic() pass { // Find module that will go all the way to an object file Module *m = sc->module->importedFrom; m->members->push(t->vtinfo); } - else // if in obj generation pass + else // if in obj generation pass { -#if IN_DMD - t->vtinfo->toObjFile(0); // TODO: multiobj -#else t->vtinfo->codegen(sir); -#endif } } } - e = new VarExp(0, t->vtinfo); + if (!vtinfo) + vtinfo = t->vtinfo; // Types aren't merged, but we can share the vtinfo's + Expression *e = new VarExp(Loc(), t->vtinfo); e = e->addressOf(sc); - e->type = t->vtinfo->type; // do this so we don't get redundant dereference + e->type = t->vtinfo->type; // do this so we don't get redundant dereference return e; } @@ -323,7 +320,7 @@ void DtoResolveTypeInfo(TypeInfoDeclaration* tid) // As those types cannot appear as LLVM values, they are not interesting for // the optimizer passes anyway. Type* t = tid->tinfo->toBasetype(); - if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction) { + if (t->ty < Terror && t->ty != Tvoid && t->ty != Tfunction && t->ty != Tident) { // Add some metadata for use by optimization passes. std::string metaname = std::string(TD_PREFIX) + mangle; llvm::NamedMDNode* meta = gIR->module->getNamedMetadata(metaname); @@ -409,7 +406,7 @@ void TypeInfoTypedefDeclaration::llvmDefine() // void[] init // emit null array if we should use the basetype, or if the basetype // uses default initialization. - if (tinfo->isZeroInit(0) || !sd->init) + if (tinfo->isZeroInit(Loc()) || !sd->init) { b.push_null_void_array(); } @@ -446,7 +443,7 @@ void TypeInfoEnumDeclaration::llvmDefine() // void[] init // emit void[] with the default initialier, the array is null if the default // initializer is zero - if (!sd->defaultval || tinfo->isZeroInit(0)) + if (!sd->defaultval || tinfo->isZeroInit(Loc())) { b.push_null_void_array(); } @@ -607,7 +604,7 @@ void TypeInfoStructDeclaration::llvmDefine() } sd->codegen(Type::sir); - IrAggr* irstruct = sd->ir.irStruct; + IrAggr* iraggr = sd->ir.irAggr; RTTIBuilder b(Type::typeinfostruct); @@ -618,10 +615,10 @@ void TypeInfoStructDeclaration::llvmDefine() // The protocol is to write a null pointer for zero-initialized arrays. The // length field is always needed for tsize(). llvm::Constant *initPtr; - if (tc->isZeroInit(0)) + if (tc->isZeroInit(Loc())) initPtr = getNullValue(getVoidPtrType()); else - initPtr = irstruct->getInitSymbol(); + initPtr = iraggr->getInitSymbol(); b.push_void_array(getTypeStoreSize(tc->irtype->getLLType()), initPtr); // toX functions ground work @@ -633,11 +630,11 @@ void TypeInfoStructDeclaration::llvmDefine() Scope sc; tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash ->mod = MODconst; - tftohash = static_cast(tftohash->semantic(0, &sc)); + tftohash = static_cast(tftohash->semantic(Loc(), &sc)); Type *retType = Type::tchar->invariantOf()->arrayOf(); tftostring = new TypeFunction(NULL, retType, 0, LINKd); - tftostring = static_cast(tftostring->semantic(0, &sc)); + tftostring = static_cast(tftostring->semantic(Loc(), &sc)); } // this one takes a parameter, so we need to build a new one each time @@ -652,7 +649,7 @@ void TypeInfoStructDeclaration::llvmDefine() arguments->push(arg); tfcmpptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfcmpptr->mod = MODconst; - tfcmpptr = static_cast(tfcmpptr->semantic(0, &sc)); + tfcmpptr = static_cast(tfcmpptr->semantic(Loc(), &sc)); } // well use this module for all overload lookups @@ -740,7 +737,7 @@ void TypeInfoClassDeclaration::codegen(Ir*i) assert(tinfo->ty == Tclass); TypeClass *tc = static_cast(tinfo); tc->sym->codegen(Type::sir); // make sure class is resolved - irg->value = tc->sym->ir.irStruct->getClassInfoSymbol(); + irg->value = tc->sym->ir.irAggr->getClassInfoSymbol(); } void TypeInfoClassDeclaration::llvmDefine() diff --git a/ir/ir.cpp b/ir/ir.cpp index e50246da5e..156c209c84 100644 --- a/ir/ir.cpp +++ b/ir/ir.cpp @@ -23,22 +23,22 @@ #include "ir/irfunction.h" -unsigned GetTypeAlignment(Ir* ir, Type* t) +unsigned GetTypeAlignment(Type* t) { return gDataLayout->getABITypeAlignment(DtoType(t)); } -unsigned GetPointerSize(Ir* ir) +unsigned GetPointerSize() { return gDataLayout->getPointerSize(ADDRESS_SPACE); } -unsigned GetTypeStoreSize(Ir* ir, Type* t) +unsigned GetTypeStoreSize(Type* t) { return gDataLayout->getTypeStoreSize(DtoType(t)); } -unsigned GetTypeAllocSize(Ir* ir, Type* t) +unsigned GetTypeAllocSize(Type* t) { return gDataLayout->getTypeAllocSize(DtoType(t)); } diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index b8e35258d6..35733b798a 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -12,6 +12,7 @@ #include "declaration.h" #include "init.h" #include "mtype.h" +#include "target.h" #include "gen/irstate.h" #include "gen/llvmhelpers.h" #include "gen/logger.h" @@ -25,8 +26,7 @@ ////////////////////////////////////////////////////////////////////////////// IrAggr::IrAggr(AggregateDeclaration* aggr) -: diCompositeType(NULL), - init_type(LLStructType::create(gIR->context(), std::string(aggr->toPrettyChars()) + "_init")) +: init_type(LLStructType::create(gIR->context(), std::string(aggr->toPrettyChars()) + "_init")) { aggrdecl = aggr; @@ -63,7 +63,7 @@ LLGlobalVariable * IrAggr::getInitSymbol() llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - init = new llvm::GlobalVariable( + init = getOrCreateGlobal(aggrdecl->loc, *gIR->module, init_type, true, _linkage, NULL, initname); // set alignment @@ -244,6 +244,7 @@ llvm::Constant* IrAggr::createInitializerConstant( llvm::StructType* initializerType) { IF_LOG Logger::println("Creating initializer constant for %s", aggrdecl->toChars()); + LOG_SCOPE; llvm::SmallVector constants; @@ -256,7 +257,7 @@ llvm::Constant* IrAggr::createInitializerConstant( constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo()))); // we start right after the vtbl and monitor - offset = PTRSIZE * 2; + offset = Target::ptrsize * 2; } addFieldInitializers(constants, explicitInitializers, aggrdecl, offset); @@ -409,14 +410,14 @@ void IrAggr::addFieldInitializers( size_t inter_idx = interfacesWithVtbls.size(); - offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); + offset = (offset + Target::ptrsize - 1) & ~(Target::ptrsize - 1); ArrayIter it2(*cd->vtblInterfaces); for (; !it2.done(); it2.next()) { BaseClass* b = it2.get(); constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx)); - offset += PTRSIZE; + offset += Target::ptrsize; // add to the interface list interfacesWithVtbls.push_back(b); diff --git a/ir/iraggr.h b/ir/iraggr.h index 033a716edf..04621c2843 100644 --- a/ir/iraggr.h +++ b/ir/iraggr.h @@ -45,9 +45,6 @@ struct IrAggr /// true only for: align(1) struct S { ... } bool packed; - /// Composite type debug description. - llvm::DIType diCompositeType; - ////////////////////////////////////////////////////////////////////////// /// Create the __initZ symbol lazily. diff --git a/ir/irclass.cpp b/ir/irclass.cpp index a17f6995b2..8f0094a1ae 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -19,6 +19,7 @@ #include "aggregate.h" #include "declaration.h" #include "mtype.h" +#include "target.h" #include "gen/irstate.h" #include "gen/logger.h" @@ -55,7 +56,7 @@ LLGlobalVariable * IrAggr::getVtblSymbol() LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl(); - vtbl = new llvm::GlobalVariable( + vtbl = getOrCreateGlobal(aggrdecl->loc, *gIR->module, vtblTy, true, _linkage, NULL, initname); return vtbl; @@ -85,7 +86,7 @@ LLGlobalVariable * IrAggr::getClassInfoSymbol() assert(tc && "invalid ClassInfo type"); // classinfos cannot be constants since they're used as locks for synchronized - classInfo = new llvm::GlobalVariable( + classInfo = getOrCreateGlobal(aggrdecl->loc, *gIR->module, tc->getMemoryLLType(), false, _linkage, NULL, initname); // Generate some metadata on this ClassInfo if it's for a class. @@ -137,7 +138,7 @@ LLGlobalVariable * IrAggr::getInterfaceArraySymbol() name.append("16__interfaceInfosZ"); llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl); - classInterfacesArray = new llvm::GlobalVariable(*gIR->module, + classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module, array_type, true, _linkage, NULL, name); return classInterfacesArray; @@ -334,7 +335,7 @@ llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance mangle.append(b->base->mangle()); mangle.append("6__vtblZ"); - llvm::GlobalVariable* GV = new llvm::GlobalVariable( + llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc, *gIR->module, vtbl_constant->getType(), true, @@ -393,7 +394,7 @@ LLConstant * IrAggr::getClassInfoInterfaces() IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars()); - IrAggr* irinter = it->base->ir.irStruct; + IrAggr* irinter = it->base->ir.irAggr; assert(irinter && "interface has null IrStruct"); IrTypeClass* itc = stripModifiers(irinter->type)->irtype->isClass(); assert(itc && "null interface IrTypeClass"); diff --git a/ir/irdsymbol.cpp b/ir/irdsymbol.cpp index 290cfcbceb..d16565e6f9 100644 --- a/ir/irdsymbol.cpp +++ b/ir/irdsymbol.cpp @@ -36,7 +36,7 @@ IrDsymbol::IrDsymbol(const IrDsymbol& s) assert(incr); DModule = s.DModule; irModule = s.irModule; - irStruct = s.irStruct; + irAggr = s.irAggr; irFunc = s.irFunc; resolved = s.resolved; declared = s.declared; @@ -56,7 +56,7 @@ void IrDsymbol::reset() { DModule = NULL; irModule = NULL; - irStruct = NULL; + irAggr = NULL; irFunc = NULL; resolved = declared = initialized = defined = false; irGlobal = NULL; @@ -66,7 +66,7 @@ void IrDsymbol::reset() bool IrDsymbol::isSet() { - return (irStruct || irFunc || irGlobal || irLocal || irField); + return (irAggr || irFunc || irGlobal || irLocal || irField); } IrVar* IrDsymbol::getIrVar() diff --git a/ir/irdsymbol.h b/ir/irdsymbol.h index 932ffdef7c..546b7891b7 100644 --- a/ir/irdsymbol.h +++ b/ir/irdsymbol.h @@ -52,7 +52,7 @@ struct IrDsymbol IrModule* irModule; - IrAggr* irStruct; + IrAggr* irAggr; IrFunction* irFunc; diff --git a/ir/irfunction.h b/ir/irfunction.h index 285730492c..7bfa142315 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -112,8 +112,8 @@ struct IrFunction llvm::Value* thisArg; // class/struct 'this' arg llvm::Value* nestArg; // nested function 'this' arg - llvm::Value* nestedVar; // nested var alloca - llvm::StructType* frameType; // type of nested context (not for -nested-ctx=array) + llvm::Value* nestedVar; // alloca for the nested context of this function + llvm::StructType* frameType; // type of nested context // number of enclosing functions with variables accessed by nested functions // (-1 if neither this function nor any enclosing ones access variables from enclosing functions) int depth; diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index 2d6adb0113..b3ae23b608 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -173,7 +173,7 @@ void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB) // create next block llvm::BasicBlock *next = llvm::BasicBlock::Create(gIR->context(), "eh.next", gIR->topfunc(), gIR->scopeend()); // get class info symbol - LLValue *classInfo = rit->catchType->ir.irStruct->getClassInfoSymbol(); + LLValue *classInfo = rit->catchType->ir.irAggr->getClassInfoSymbol(); // add that symbol as landing pad clause landingPad->addClause(classInfo); // call llvm.eh.typeid.for to get class info index in the exception table diff --git a/ir/irtypeaggr.cpp b/ir/irtypeaggr.cpp index 7ed76c1470..1c69c7af8c 100644 --- a/ir/irtypeaggr.cpp +++ b/ir/irtypeaggr.cpp @@ -24,6 +24,6 @@ IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad) : IrType(ad->type, LLStructType::create(gIR->context(), ad->toPrettyChars())), - aggr(ad) + diCompositeType(NULL), aggr(ad) { } diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 6dbe6b83fa..2fdc7b9f6f 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -12,6 +12,11 @@ #include "ir/irtype.h" #include "llvm/ADT/ArrayRef.h" +#if LDC_LLVM_VER >= 302 +#include "llvm/DebugInfo.h" +#else +#include "llvm/Analysis/DebugInfo.h" +#endif #include #include @@ -39,6 +44,11 @@ public: /// iterator def_end() { return default_fields.end(); } + + /// Composite type debug description. This is not only to cache, but also + /// used for resolving forward references. + llvm::DIType diCompositeType; + protected: /// IrTypeAggr(AggregateDeclaration* ad); diff --git a/ir/irtypeclass.cpp b/ir/irtypeclass.cpp index 7de395330b..eff6714142 100644 --- a/ir/irtypeclass.cpp +++ b/ir/irtypeclass.cpp @@ -17,6 +17,7 @@ #include "declaration.h" #include "dsymbol.h" #include "mtype.h" +#include "target.h" #include "template.h" #include "gen/irstate.h" @@ -190,7 +191,7 @@ void IrTypeClass::addBaseClassData( Type* first = interfaces_idx->type->nextOf()->pointerTo(); // align offset - offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1); + offset = (offset + Target::ptrsize - 1) & ~(Target::ptrsize - 1); for (; !it2.done(); it2.next()) { @@ -203,7 +204,7 @@ void IrTypeClass::addBaseClassData( llvm::Type* ivtbl_type = llvm::StructType::get(gIR->context(), buildVtblType(first, &arr)); defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0)); - offset += PTRSIZE; + offset += Target::ptrsize; // add to the interface map addInterfaceToMap(b->base, field_index); @@ -256,7 +257,7 @@ IrTypeClass* IrTypeClass::get(ClassDeclaration* cd) defaultTypes.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(gIR->context()), 0)); // we start right after the vtbl and monitor - size_t offset = PTRSIZE * 2; + size_t offset = Target::ptrsize * 2; size_t field_index = 2; // add data members recursively diff --git a/ir/irtypefunction.h b/ir/irtypefunction.h index e583a62195..a107d373f8 100644 --- a/ir/irtypefunction.h +++ b/ir/irtypefunction.h @@ -28,14 +28,9 @@ public: /// IrTypeFunction* isFunction() { return this; } - IrFuncTy* fty() { return irfty; } - protected: /// IrTypeFunction(Type* dt, llvm::Type* lt); - - /// - IrFuncTy* irfty; }; /// diff --git a/runtime/druntime b/runtime/druntime index 590316428b..adaeaf9e7b 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 590316428bce14986f69f476e15b12e4f185d65d +Subproject commit adaeaf9e7b3151d2efb710dca3d79cb724bd30bb diff --git a/runtime/phobos b/runtime/phobos index 8f636073a3..9fe205f1f7 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 8f636073a3c0bc6d693600ad6d187faca620f224 +Subproject commit 9fe205f1f7aee63cffe0a7105ff5acb7fcaa157f diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 2d8d874e2a..32aa48727a 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 2d8d874e2a33cea9d9fd751f9c2baab5e8ccc992 +Subproject commit 32aa48727a4db7a28878e6f13af603aaa3e0e48d