From 292caa14386e6d7bc1e7fdec425732c2dfc96660 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 7 Jun 2013 05:17:29 +0200 Subject: [PATCH 01/59] Merge the 2.063 frontend. --- dmd2/aggregate.h | 55 +- dmd2/aliasthis.c | 16 +- dmd2/apply.c | 17 +- dmd2/argtypes.c | 15 +- dmd2/arrayop.c | 559 ++--- dmd2/arraytypes.h | 1 + dmd2/attrib.c | 225 +- dmd2/builtin.c | 10 +- dmd2/cast.c | 213 +- dmd2/class.c | 194 +- dmd2/clone.c | 599 +++--- dmd2/cond.c | 222 +- dmd2/cond.h | 17 - dmd2/constfold.c | 3 + dmd2/ctfe.h | 15 +- dmd2/ctfeexpr.c | 107 +- dmd2/declaration.c | 382 ++-- dmd2/declaration.h | 94 +- dmd2/delegatize.c | 61 +- dmd2/doc.c | 247 ++- dmd2/dsymbol.c | 61 +- dmd2/dsymbol.h | 16 +- dmd2/entity.c | 4526 +++++++++++++++++++-------------------- dmd2/enum.c | 133 +- dmd2/enum.h | 14 +- dmd2/expression.c | 2296 +++++++++++++------- dmd2/expression.h | 205 +- dmd2/func.c | 795 ++++--- dmd2/identifier.c | 5 +- dmd2/identifier.h | 1 - dmd2/idgen.c | 6 +- dmd2/impcnvgen.c | 36 +- dmd2/import.c | 5 +- dmd2/init.c | 171 +- dmd2/init.h | 31 +- dmd2/inline.c | 40 +- dmd2/interpret.c | 452 ++-- dmd2/json.c | 19 +- dmd2/lexer.c | 24 +- dmd2/lexer.h | 7 +- dmd2/mangle.c | 47 +- dmd2/mars.c | 193 +- dmd2/mars.h | 77 +- dmd2/module.c | 21 +- dmd2/mtype.c | 1850 ++++++++-------- dmd2/mtype.h | 166 +- dmd2/opover.c | 255 ++- dmd2/optimize.c | 112 +- dmd2/parse.c | 449 ++-- dmd2/parse.h | 9 +- dmd2/root/longdouble.c | 21 +- dmd2/root/longdouble.h | 17 +- dmd2/root/root.c | 45 +- dmd2/root/root.h | 1 + dmd2/root/stringtable.c | 2 +- dmd2/root/stringtable.h | 8 +- dmd2/sapply.c | 210 ++ dmd2/scope.c | 10 +- dmd2/scope.h | 46 +- dmd2/statement.c | 851 +++----- dmd2/statement.h | 102 +- dmd2/staticassert.c | 6 +- dmd2/struct.c | 178 +- dmd2/target.c | 125 ++ dmd2/target.h | 31 + dmd2/template.c | 1279 +++++------ dmd2/template.h | 24 +- dmd2/traits.c | 83 +- dmd2/utf.c | 12 - dmd2/utf.h | 5 - driver/main.cpp | 7 +- gen/asm-x86.h | 8 +- gen/asmstmt.cpp | 7 +- gen/classes.cpp | 3 +- gen/llvmhelpers.cpp | 10 +- gen/llvmhelpers.h | 6 - gen/module.cpp | 3 +- gen/nested.cpp | 3 +- gen/statements.cpp | 43 - gen/tocall.cpp | 11 +- gen/todebug.cpp | 2 +- gen/toir.cpp | 4 +- gen/typinf.cpp | 18 +- ir/ir.cpp | 8 +- ir/iraggr.cpp | 7 +- ir/irclass.cpp | 1 + ir/irtypeclass.cpp | 7 +- runtime/druntime | 2 +- runtime/phobos | 2 +- tests/d2/dmd-testsuite | 2 +- 90 files changed, 10179 insertions(+), 8105 deletions(-) create mode 100644 dmd2/sapply.c create mode 100644 dmd2/target.c create mode 100644 dmd2/target.h diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index df9cae7f..82bb53e5 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); @@ -276,13 +281,12 @@ struct ClassDeclaration : AggregateDeclaration 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 +299,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 +313,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 b26731b9..68e1609f 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 e05a343e..320b24a8 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 a26a1166..0030cc2f 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 17b90dad..a2e38e4a 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -52,6 +52,280 @@ 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); +#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 +421,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 +565,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 +585,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 +604,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 +643,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 +661,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 e40009ac..9e54239a 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 d8defdf1..3b1135f1 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 ee51b891..ae3542c3 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 27ca1ef8..ede3f49f 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 1621b43c..ce85a096 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 c0a0b97a..03ea82c2 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 5846ee6c..87666ed2 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 71400314..9b297569 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 1afc55b9..06f9b302 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 d5d72908..0244a37b 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,15 @@ 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 +#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 +211,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 d14ddda7..f9ca92ea 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,6 +1952,8 @@ 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 || diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 5ee94b48..edd02409 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -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; @@ -535,6 +540,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 +587,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) @@ -605,7 +616,7 @@ void AliasDeclaration::semantic(Scope *sc) 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 +634,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 +712,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 +862,10 @@ void VarDeclaration::semantic(Scope *sc) // return; // sem = SemanticIn; + Scope *scx = NULL; if (scope) { sc = scope; + scx = sc; scope = NULL; } @@ -874,6 +887,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 +913,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 +934,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 +990,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 +1029,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 +1065,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 +1121,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 +1142,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 +1196,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()); } @@ -1191,19 +1226,19 @@ Lnomatch: { #if DMDV2 assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); - - if (storage_class & (STCconst | STCimmutable) && init) + if (storage_class & (STCconst | STCimmutable) && init && + global.params.vfield) { - if (!tb->isTypeBasic()) - storage_class |= STCstatic; + 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 #endif { 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 +1301,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 +1342,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 +1486,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 +1513,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 +1621,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 +1637,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 +1690,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 +1725,9 @@ Ldtor: } sem = SemanticDone; + + if (type->toBasetype()->ty == Terror) + errors = true; } void VarDeclaration::semantic2(Scope *sc) @@ -1781,6 +1771,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 +1842,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 +1863,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 +1873,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 +1964,6 @@ AggregateDeclaration *VarDeclaration::isThis() if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe))) { - if ((storage_class & (STCconst | STCimmutable | STCwild)) && init) - return NULL; - for (Dsymbol *s = this; s; s = s->parent) { ad = s->isMember(); @@ -1953,7 +1978,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 +1997,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 +2051,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 +2112,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 +2151,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 +2336,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 +2372,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 +2391,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 +2641,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 1c464050..a812372a 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); @@ -341,6 +336,7 @@ struct VarDeclaration : Declaration Initializer *hinit; AggregateDeclaration *isThis(); int needThis(); + int isExport(); int isImportedSymbol(); int isDataseg(); int isThreadlocal(); @@ -352,17 +348,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 +385,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 +780,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 +848,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 +856,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 +876,8 @@ struct FuncDeclaration : Declaration bool isSafeBypassingInference(); int isTrusted(); bool setUnsafe(); + bool isolateReturn(); + bool parametersIntersect(Type *t); virtual int isNested(); int needThis(); int isVirtualMethod(); @@ -953,11 +952,11 @@ 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 @@ -973,7 +972,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 +1013,6 @@ struct CtorDeclaration : FuncDeclaration int isVirtual(); int addPreInvariant(); int addPostInvariant(); - bool isImplicit; // implicitly generated ctor CtorDeclaration *isCtorDeclaration() { return this; } }; @@ -1040,7 +1038,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 +1112,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 +1126,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 3c9670f5..4fb060aa 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 4ac4bc85..edaac798 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 f7c85a34..20da3e69 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 c9f28003..54b56669 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 8cb063dc..53d25391 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 1addb844..9b665c71 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 165f5356..b9e2255c 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 c60814d1..2790afa1 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); @@ -4059,12 +4370,39 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * #if IN_LLVM constType = 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 +4417,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 +4464,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 +4482,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 +4514,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)); @@ -4315,7 +4645,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 +4741,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 +4830,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 +4849,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 +4893,7 @@ Expression *NewExp::semantic(Scope *sc) { Type *tb; ClassDeclaration *cdthis = NULL; + size_t nargs; #if LOGSEMANTIC printf("NewExp::semantic() %s\n", toChars()); @@ -4578,6 +4938,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 +4960,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 +5010,7 @@ Lagain: goto Lerr; } } - } + } else if (thisexp) { error("e.new is only for allocating nested classes"); goto Lerr; @@ -4678,7 +5040,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 +5054,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 +5074,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 +5085,6 @@ Lagain: functionParameters(loc, sc, tf, NULL, newargs, f); if (olderrors != global.errors) return new ErrorExp(); - } else { @@ -4738,8 +5100,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 +5113,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 +5134,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 +5145,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 +5182,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 +5214,7 @@ Lagain: } else if (tb->isscalar()) { - if (arguments && arguments->dim) + if (nargs) { error("no constructor for %s", type->toChars()); goto Lerr; } @@ -4918,7 +5290,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 +5497,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 +5530,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 +5543,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 +5565,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 +5625,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 +5641,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 +5652,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 +5676,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 +5723,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 +5757,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 +5814,9 @@ Expression *FuncExp::semantic(Scope *sc) } fd->tookAddressOf++; } - return this; +Ldone: + sc->needctfe = needctfe; + return e; } // used from CallExp::semantic() @@ -5713,7 +6113,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 +6276,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 +6363,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 +6445,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 +6495,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 +6514,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 +6555,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 +6765,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 +6775,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 +6836,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 +6904,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 +6924,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 +6957,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 +7066,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 +7082,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 +7119,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 +7128,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 +7146,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 +7156,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 +7173,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 +7252,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 +7260,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 +7296,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 +7319,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 +7373,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 +7398,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 +7468,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 +7494,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 +7512,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 +7552,22 @@ Expression *DotVarExp::semantic(Scope *sc) accessCheck(loc, sc, e1, var); VarDeclaration *v = var->isVarDeclaration(); - Expression *e = expandVar(WANTvalue, v); - if (e) + if (v && (v->isDataseg() || (v->storage_class & STCmanifest))) + { + 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 +7616,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 +7712,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 +7777,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 +7802,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 +7981,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 +8033,7 @@ Expression *CallExp::semantic(Scope *sc) return e1; } - Expression *e = resolveUFCS(sc); + Expression *e = resolveUFCS(sc, this); if (e) return e; @@ -7763,9 +8056,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 +8089,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 +8171,7 @@ Lagain: if (de->e2->op == TOKoverloadset) { ethis = de->e1; + tthis = de->e1->type; e1 = de->e2; } @@ -7898,6 +8193,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 +8205,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 +8259,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 +8289,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 +8304,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 +8322,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 +8332,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 +8387,7 @@ Lagain: } else { + checkRightThis(sc, ue1old); if (e1->op == TOKdotvar) { dve->var = f; @@ -8151,7 +8450,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 +8491,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 +8519,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 +8575,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 +8591,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 +8606,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 +8628,8 @@ Lagain: argExpTypesToCBuffer(&buf, arguments, &hgs); buf.writeByte(')'); - if (ethis) - ethis->type->modToBuffer(&buf); + if (tthis) + tthis->modToBuffer(&buf); } else buf.writeByte(')'); @@ -8367,9 +8659,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 +8685,8 @@ Lagain: return new ErrorExp(); } } + if (!f) + return new ErrorExp(); if (f->needThis()) { @@ -8403,9 +8698,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 +8714,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 +8729,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 +8853,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 +8918,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 +8958,6 @@ Expression *AddrExp::semantic(Scope *sc) } FuncDeclaration *f = ve->var->isFuncDeclaration(); - if (f) { #if IN_LLVM @@ -8694,6 +9021,7 @@ Expression *AddrExp::semantic(Scope *sc) ce->e2->type = NULL; ce->e2 = ce->e2->semantic(sc); } + return optimize(WANTvalue); } return this; @@ -8884,6 +9212,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 +9241,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 +9317,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 +9415,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 +9494,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 +9704,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 +9766,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 +9800,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 +9859,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 +9911,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 +9923,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 +10289,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 +10371,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 +10459,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 +10478,7 @@ Expression *PostExp::semantic(Scope *sc) return new ErrorExp(); } + e1 = e1->optimize(WANTvalue); if (e1->op != TOKarraylength) e1 = e1->modifiableLvalue(sc, e1); @@ -10246,6 +10615,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 +10634,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 +10642,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 +10665,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 +10694,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 +10702,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 +10729,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 +10754,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 +10790,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 +10804,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 +10823,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 +10861,8 @@ Expression *AssignExp::semantic(Scope *sc) return new ErrorExp(); } + e1 = checkRightThis(sc, e1); + assert(e1->type); Type *t1 = e1->type->toBasetype(); @@ -10515,15 +10888,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 +10915,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 +10941,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 +10977,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 +11073,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 +11112,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 +11128,7 @@ Ltupleassign: if (e1->op != TOKvar) e1 = e1->optimize(WANTvalue); - if (op != TOKconstruct) + if (op == TOKassign) e1 = e1->modifiableLvalue(sc, e1old); } @@ -10771,19 +11167,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 +11200,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 +11224,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 +11270,7 @@ Ltupleassign: type = e1->type; assert(type); - return this; + return reorderSettingAAElem(sc); } Expression *AssignExp::checkToBoolean(Scope *sc) @@ -10915,7 +11346,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 +11355,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 +11363,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 +11372,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 +11381,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 +11490,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 +11643,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 +11753,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 +11767,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 +12086,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 +12680,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 +12770,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 +13091,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 +13125,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 +13253,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 +13293,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 94fe0e46..67ad55f2 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; @@ -102,7 +102,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 +118,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 +134,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 +170,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 +194,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 +332,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 +347,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 +477,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 +523,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 +535,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 +567,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 +577,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 +604,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 +626,30 @@ struct StructLiteralExp : Expression void toMangleBuffer(OutBuffer *buf); Expression *optimize(int result, bool keepLvalue = false); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); - MATCH implicitConvTo(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 +#if 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. + /// 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. - StaticStructInitDeclaration *sinit; + 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); }; -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 +688,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 +775,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 +833,7 @@ struct OverExp : Expression { OverloadSet *vars; - OverExp(OverloadSet *s); + OverExp(Loc loc, OverloadSet *s); int isLvalue(); Expression *toLvalue(Scope *sc, Expression *e); }; @@ -822,7 +855,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 +959,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 +968,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 +982,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 +999,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 +1014,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 +1031,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 +1085,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 +1132,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 +1188,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 +1226,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 +1262,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 +1292,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 +1313,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 +1328,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 +1382,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 +1423,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 +1611,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 +1661,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 +1685,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 +1728,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 +1751,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 +1773,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 +1796,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 +1818,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 +1838,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 +1858,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 +1878,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 +1901,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 +1925,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 +1983,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 +2040,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 +2064,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 +2093,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 +2131,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 +2179,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 c24bfb49..8dc44e93 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) @@ -3831,7 +4132,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 +4163,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 +4300,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 +4333,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 +4428,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 +4562,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 +4649,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 +4661,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 +4681,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 +4730,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 +4752,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 825d78b6..e17ab7e7 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 b46c654f..e6cda8ec 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 25b97eae..e22b69f4 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 8f182364..298ed379 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 a9fecd1e..9e211718 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 b0d2dacb..0835e90d 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 88db7487..ba3b5683 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 3b3313d6..8f982203 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 ee1a8895..3ac4d020 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) { @@ -1361,12 +1399,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 +1444,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 +1474,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; @@ -1534,12 +1601,13 @@ Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) // ------------------------------------------------------------- // 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 +1647,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 +1660,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 +1757,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 +1826,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 +1904,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 +2286,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 +2373,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 +2426,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 +2497,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 +2572,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 +2613,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 +2628,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 +2683,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 +2752,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 +2804,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 +2872,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 +3122,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 +3148,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 +3303,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 +3355,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 +3572,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 +3955,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 +3996,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 +4017,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 +4046,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 +4102,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 +4138,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 +4166,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 +4188,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 +4289,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 +4447,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 +4753,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 +4909,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 +4949,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 24503b07..373215d3 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 4d92e357..b00de9d1 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 c3f3a826..88fdb4d6 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 e79318c9..03b1849f 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 2d9392dc..046a01f3 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 544e074a..1422d4db 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -102,9 +102,6 @@ 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 // 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 +156,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 @@ -211,16 +211,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 +309,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 +338,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 +350,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 +371,7 @@ struct Global */ bool endGagging(unsigned oldGagged); - Global(); + void init(); }; extern Global global; @@ -417,14 +427,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 +445,6 @@ struct Loc filename = NULL; } - Loc(int x) - { - linnum = x; - filename = NULL; - } - Loc(Module *mod, unsigned linnum); char *toChars(); @@ -534,13 +530,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 77b8aea0..b62807c3 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 8cad2251..fdfebafd 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) @@ -8974,21 +8805,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 +8832,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 +8846,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 +8880,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 +8898,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 +8967,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 +8976,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 +9048,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 +9069,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 +9086,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 +9295,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 +9309,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 +9404,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 +9419,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 +9540,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 6dbda261..6d2918d4 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 cf7d8cec..a4ddc520 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 2783ccfe..6b23a1e8 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 603e0c4f..28b7e664 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 7cce6c08..946b9570 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/root/longdouble.c b/dmd2/root/longdouble.c index 8852a835..6244c6cb 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 0e8e4498..8add2787 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 8a16e83f..900a3e65 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 6cb36d69..5935d4b5 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 f1ea45d3..dcde89f4 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 e4b13b3a..1645734c 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 00000000..4add7071 --- /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 09da8d9c..2bcc085a 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 a3b7725b..de5f63f0 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 96034062..9d9c5454 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 ede1ee65..6a2edf4c 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 3ce09b1d..9d3c7b02 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 29ba984f..8e64a647 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; @@ -594,7 +664,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 +674,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 +713,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 +743,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 +753,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 +771,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 +814,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 +828,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 +838,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 00000000..84205471 --- /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 00000000..ad3d956d --- /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 418f617d..86df030e 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,7 +4776,7 @@ 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; @@ -4673,7 +4810,7 @@ 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; @@ -4683,7 +4820,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->tmodule = NULL; #endif - assert((size_t)tempdecl->scope > 0x10000); + assert(tempdecl->scope); } @@ -4735,12 +4872,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(); } } @@ -4860,7 +4997,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) #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 +5009,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 +5045,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 +5136,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 +5179,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 +5203,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 +5327,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 +5436,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 +5504,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 +5625,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 +5657,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 +5679,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 +5698,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) } if (!s) { error("template '%s' is not defined", id->toChars()); - return NULL; + return false; } } @@ -5567,13 +5737,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 +5769,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 +5787,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 +5810,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 +5875,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 +5919,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 +5983,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 +6001,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 +6127,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 +6212,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 +6350,6 @@ void TemplateInstance::semantic3(Scope *sc) } } -#if IN_DMD - /************************************** * Given an error instantiating the TemplateInstance, * give the nested TemplateInstance instantiations that got @@ -6253,29 +6427,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 +6531,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 +6595,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 +6621,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 +6715,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 +6817,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 +6973,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 +7012,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 c01f6987..f686d1df 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -34,6 +34,7 @@ struct TemplateValueParameter; struct TemplateAliasParameter; struct TemplateTupleParameter; struct Type; +struct TypeQualified; struct TypeTypeof; struct Scope; struct Expression; @@ -90,15 +91,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 +307,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 +331,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 +340,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); @@ -361,10 +364,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 411bee0d..3594a7c9 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 c05fc101..804dfcac 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 22e405bc..cd279686 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/main.cpp b/driver/main.cpp index c91b32f0..83a6e3fd 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]; @@ -648,6 +651,7 @@ int main(int argc, char** argv) Type::init(&ir); Id::initialize(); Module::init(); + Target::init(); initPrecedence(); backend_init(); @@ -808,7 +812,7 @@ int main(int argc, char** argv) if (!Module::rootModule) Module::rootModule = m; m->importedFrom = m; - m->read(0); + m->read(Loc()); m->parse(global.params.doDocComments); m->buildTargetFiles(singleObj); m->deleteObjFile(); @@ -924,6 +928,7 @@ int main(int argc, char** argv) if (global.errors) fatal(); } + global.inExtraInliningSemantic = false; } if (global.errors || global.warnings) fatal(); diff --git a/gen/asm-x86.h b/gen/asm-x86.h index accec4d3..1f6e1e60 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" ); @@ -2474,7 +2474,7 @@ namespace AsmParserx8664 #endif { - e = new AddrExp ( 0, e ); + e = new AddrExp ( Loc(), e ); e->type = decl->type->pointerTo(); operand->constDisplacement = 0; @@ -2539,7 +2539,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; } @@ -2696,7 +2696,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 ) diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 7e3e3a06..2108fa91 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 efb8ac49..3f14da5a 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" @@ -198,7 +199,7 @@ 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"); diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 4097e199..c0e3a45f 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) diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 7c5c4e69..bf8e561e 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; diff --git a/gen/module.cpp b/gen/module.cpp index 5893de65..693ca36b 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" @@ -357,7 +358,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"); diff --git a/gen/nested.cpp b/gen/nested.cpp index 45e54802..3170eafc 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" @@ -444,7 +445,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/statements.cpp b/gen/statements.cpp index 5c5d7165..b2b0b806 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/tocall.cpp b/gen/tocall.cpp index fb06fc09..6d16cf8f 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); } diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 9e99bc53..0588c6f9 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -187,7 +187,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) diff --git a/gen/toir.cpp b/gen/toir.cpp index 8963d2f7..1ef38422 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -120,7 +120,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(); @@ -2086,7 +2086,7 @@ DValue* AssertExp::toElem(IRState* p) p->scope() = IRScope(endbb,oldend); - InvariantDeclaration* invdecl; + FuncDeclaration* invdecl; // class invariants if( global.params.useInvariants && diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 9e69d951..68b4261e 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -97,7 +97,7 @@ Expression *Type::getInternalTypeInfo(Scope *sc) { tid = new TypeInfoDeclaration(t, 1); 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 return e; @@ -118,7 +118,7 @@ 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(); } @@ -159,7 +159,7 @@ Expression *Type::getTypeInfo(Scope *sc) } } } - e = new VarExp(0, t->vtinfo); + e = new VarExp(Loc(), t->vtinfo); e = e->addressOf(sc); e->type = t->vtinfo->type; // do this so we don't get redundant dereference return e; @@ -409,7 +409,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 +446,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(); } @@ -618,7 +618,7 @@ 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(); @@ -633,11 +633,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 +652,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 diff --git a/ir/ir.cpp b/ir/ir.cpp index e50246da..156c209c 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 b8e35258..e644663e 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" @@ -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/irclass.cpp b/ir/irclass.cpp index a17f6995..b280a80d 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" diff --git a/ir/irtypeclass.cpp b/ir/irtypeclass.cpp index 7de39533..eff67141 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/runtime/druntime b/runtime/druntime index 59031642..8b9c6e5d 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 590316428bce14986f69f476e15b12e4f185d65d +Subproject commit 8b9c6e5d67f9533fdd5fe8bcf0f42f7430d4ad05 diff --git a/runtime/phobos b/runtime/phobos index 8f636073..1c80c826 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 8f636073a3c0bc6d693600ad6d187faca620f224 +Subproject commit 1c80c82684900a20e4cad056b65401310a5754ee diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 2d8d874e..99ef349c 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 2d8d874e2a33cea9d9fd751f9c2baab5e8ccc992 +Subproject commit 99ef349cd4889e0ad38af9a61db060a5d3744616 From 4d3f9333c6694d7987faa00b7221ee705db1b06b Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 7 Jun 2013 19:27:52 +0200 Subject: [PATCH 02/59] Never make functions without body available_externally. --- gen/llvmhelpers.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index c0e3a45f..3b150ac0 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1502,6 +1502,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; From ab7ffa99885b376e98f9bf75d9199d23119f186b Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 02:00:27 +0200 Subject: [PATCH 03/59] Removed obsolete importprot members. --- dmd2/declaration.c | 4 ---- dmd2/declaration.h | 2 -- dmd2/func.c | 3 --- gen/llvmhelpers.cpp | 2 +- 4 files changed, 1 insertion(+), 10 deletions(-) diff --git a/dmd2/declaration.c b/dmd2/declaration.c index edd02409..1f9db8a6 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -446,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); } @@ -612,9 +611,6 @@ 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(Loc(), overnext, f); overnext = NULL; diff --git a/dmd2/declaration.h b/dmd2/declaration.h index a812372a..cb326a57 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -268,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); @@ -963,7 +962,6 @@ struct FuncAliasDeclaration : FuncDeclaration { FuncDeclaration *funcalias; int hasOverloads; - PROT importprot; // if generated by import, store its protection FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1); diff --git a/dmd2/func.c b/dmd2/func.c index 8dc44e93..61595c02 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -4007,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) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 3b150ac0..6cbf1091 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1951,7 +1951,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(); From 6898d0fa4ae011c743afb5ee7cb55f7e382ab721 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 02:14:01 +0200 Subject: [PATCH 04/59] Removed last bit of interpret.c diff. --- dmd2/interpret.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/dmd2/interpret.c b/dmd2/interpret.c index 3ac4d020..3876b033 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -1135,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; @@ -1596,6 +1592,7 @@ Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal) return this; } + // ------------------------------------------------------------- // Remove out, ref, and this // ------------------------------------------------------------- From 24e3abff34c7f8f7b321b20228fd00c427b6bcac Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 02:14:39 +0200 Subject: [PATCH 05/59] Unions are always static since Issue 9244. --- dmd2/struct.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/dmd2/struct.c b/dmd2/struct.c index 8e64a647..39fe40bb 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -515,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()); From 33245282ef2e7f13be68e6afe5c9f88ea5f1067c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 02:39:57 +0200 Subject: [PATCH 06/59] More trivial DMD diff reduction. --- dmd2/template.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dmd2/template.h b/dmd2/template.h index f686d1df..33d627ca 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; From fd3c696d943199e46fe172b41b57db579fa94dff Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 21:31:47 +0200 Subject: [PATCH 07/59] Call Expression::init() during startup. Was added in 2.063. --- driver/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/driver/main.cpp b/driver/main.cpp index 83a6e3fd..ae930a55 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -652,6 +652,7 @@ int main(int argc, char** argv) Id::initialize(); Module::init(); Target::init(); + Expression::init(); initPrecedence(); backend_init(); From a9e620d428190f1411feb11689117d0287286722 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 21:46:59 +0200 Subject: [PATCH 08/59] Work around invalid special ref var initializations in 2.063. --- gen/toir.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 1ef38422..defd63f7 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -419,7 +419,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; } } From 2ebf6776612a8687ebe6e7e884fa0bd4d197d4bc Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 21:54:19 +0200 Subject: [PATCH 09/59] Handle explicit AddrExp for naked asm memory references. --- gen/asm-x86.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 1f6e1e60..847d04f9 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -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; From d7526157ab8f9d0fc40cb9f8744aa455b2a24df3 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Tue, 11 Jun 2013 23:20:10 +0200 Subject: [PATCH 10/59] Expression::optimize everything to resolve manifest constants in inline asm. --- gen/asm-x86.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 847d04f9..0d2384e9 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -2586,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 ) @@ -3220,6 +3212,7 @@ namespace AsmParserx8664 } e = e->semantic ( sc ); + e = e->optimize (WANTvalue); // Special case for floating point constant declarations. if ( e->op == TOKfloat64 ) From d3f89f81a8183c034da1f71cc0f9b68f90fc26dc Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 18:04:44 +0200 Subject: [PATCH 11/59] Never emit naked functions as available_externally. --- gen/tollvm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 11fa2f1a..54fe029b 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -343,7 +343,7 @@ LLGlobalValue::LinkageTypes DtoLinkage(Dsymbol* sym) if (fdecl->llvmInternal == LLVMintrinsic) return llvm::GlobalValue::ExternalLinkage; // generated by inlining semantics run - if (fdecl->availableExternally && mustDefine) + if (fdecl->availableExternally && mustDefine && !fdecl->naked) return llvm::GlobalValue::AvailableExternallyLinkage; // array operations are always template linkage if (fdecl->isArrayOp == 1) From b1465ae7e3453a98cb167f4388e704eb5f13b165 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 18:07:07 +0200 Subject: [PATCH 12/59] Extended DtoLinkage comments. --- gen/tollvm.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 54fe029b..cae8f2ea 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 + + // 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) From 4c788699aef85965273402d082ecfc9ef84ebb05 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 18:10:17 +0200 Subject: [PATCH 13/59] Initial, incomplete ClassReferenceExp::toConstElem implementation. Allows us to get through a Phobos build without errors. --- dmd2/ctfe.h | 1 + gen/toir.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/dmd2/ctfe.h b/dmd2/ctfe.h index 0244a37b..7dc157c3 100644 --- a/dmd2/ctfe.h +++ b/dmd2/ctfe.h @@ -55,6 +55,7 @@ struct ClassReferenceExp : Expression /// 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); diff --git a/gen/toir.cpp b/gen/toir.cpp index defd63f7..d66b5894 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -43,6 +43,9 @@ #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); @@ -2824,7 +2827,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) @@ -2933,7 +2936,9 @@ DValue* StructLiteralExp::toElem(IRState* p) 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) @@ -2965,6 +2970,16 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) return sd->ir.irStruct->createInitializerConstant(varInits); } +llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) +{ + IF_LOG Logger::print("ClassReferenceExp::toConstElem: %s @ %s\n", + toChars(), type->toChars()); + LOG_SCOPE; + + // FIXME: Handle type->sym->isInterfaceDeclaration(). + return value->toConstElem(p); +} + ////////////////////////////////////////////////////////////////////////////////////////// DValue* InExp::toElem(IRState* p) From bc910004a47a4c80127b03e1e857dfbf6376e1e3 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 20:34:50 +0200 Subject: [PATCH 14/59] Adapt codegen to removal of old _d_invariant from druntime. We should think about using symbolic constants for runtime function names though, this is not maintainable in the long run. --- gen/runtime.cpp | 2 +- gen/toir.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 3b2f3371..a0ccd41c 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -900,7 +900,7 @@ static void LLVM_D_BuildRuntimeModule() // void _d_invariant(Object o) { - llvm::StringRef fname("_d_invariant"); + llvm::StringRef fname("_D9invariant12_d_invariantFC6ObjectZv"); LLType *types[] = { objectTy }; LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); diff --git a/gen/toir.cpp b/gen/toir.cpp index d66b5894..afcd17a3 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2102,7 +2102,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); } From 95b34c36253f30253c86da38c0c6c964969f6210 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 20:39:34 +0200 Subject: [PATCH 15/59] zext bool to i8 in makeLValue. --- gen/llvmhelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 6cbf1091..d78c8e26 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1697,7 +1697,7 @@ LLValue* makeLValue(Loc& loc, DValue* value) if (needsMemory) { LLValue* tmp = DtoAlloca(valueType, ".makelvaluetmp"); - DtoStore(valuePointer, tmp); + DtoStoreZextI8(valuePointer, tmp); valuePointer = tmp; } From 48f784eda860385cc08b59e768ef08c4560ef98b Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 13 Jun 2013 00:17:39 +0200 Subject: [PATCH 16/59] Fold in out-of-source test build adaption changes. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 99ef349c..5f7363db 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 99ef349cd4889e0ad38af9a61db060a5d3744616 +Subproject commit 5f7363dbeb4b39bbeefb05a6ac6013fc9ada4eff From c64c4f479a494ee4a519f76a6b45187db55756eb Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 13 Jun 2013 18:45:07 +0200 Subject: [PATCH 17/59] Handle static array typed SliceExps. Fixes DMD testcase 'testbounds2'. --- gen/toir.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index afcd17a3..50f8ef9d 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1548,7 +1548,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); @@ -1603,13 +1603,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); } From cbe2c45b83d20dd4a7583645972b40d450f30c09 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 13 Jun 2013 18:46:37 +0200 Subject: [PATCH 18/59] Fold in rudimentary rt.sections implementation. --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 8b9c6e5d..03674ab8 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 8b9c6e5d67f9533fdd5fe8bcf0f42f7430d4ad05 +Subproject commit 03674ab8476771c58cb096813058b835b63fa4a6 From 83415eeeb87326b218beb45a05b851c0f5119056 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 13 Jun 2013 19:06:16 +0200 Subject: [PATCH 19/59] Minor debug log fixes. --- gen/toir.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 50f8ef9d..6789bd98 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -3156,7 +3156,9 @@ 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; + std::vector types; types.reserve(exps->dim); for (size_t i = 0; i < exps->dim; i++) @@ -3184,7 +3186,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()); From 4901877d241e49025431dbc08b909fd0d4828528 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 13 Jun 2013 19:08:59 +0200 Subject: [PATCH 20/59] Handle side-effects in TupleExp::e0. Fixes DMD testcase 'aliasthis'. --- gen/toir.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gen/toir.cpp b/gen/toir.cpp index 6789bd98..a4d81501 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -3159,6 +3159,9 @@ DValue* TupleExp::toElem(IRState *p) 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++) From 9c0514a9b1a0777bad4628f1ff1de670c1a85333 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 15:49:15 +0200 Subject: [PATCH 21/59] Correctly load context for nested class members with own nested context. Fixes DMD testcase 'xtest46'. --- gen/nested.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gen/nested.cpp b/gen/nested.cpp index 3170eafc..2b7e7785 100644 --- a/gen/nested.cpp +++ b/gen/nested.cpp @@ -96,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) From 86563a2ee181ef88afe4eb1b876e0cddc9b96ad3 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 16:01:09 +0200 Subject: [PATCH 22/59] Allow casting AAs to bool. Fixed DMD testcase 'nulltype'. --- gen/llvmhelpers.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index d78c8e26..1339dc1b 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -821,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; From 9dc387aa9145d4541f6f473724ca5dd0abaa9639 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 16:42:34 +0200 Subject: [PATCH 23/59] Do not invoke postblit twice on struct literal creation. The frontend seems to explicitly insert __cpctor now. Fixes DMD testcase 'sdtor'. --- gen/toir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index a4d81501..2ac4cbff 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2912,7 +2912,7 @@ DValue* StructLiteralExp::toElem(IRState* p) DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd)); // store the initializer there - DtoAssign(loc, &field, val, TOKconstruct); + DtoAssign(loc, &field, val, TOKconstruct, true); if (expr) callPostblit(loc, expr, field.getLVal()); From 349305cd1d471402fb8eef5c4d154ab30a201dcf Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 17:02:41 +0200 Subject: [PATCH 24/59] Fix array op argument evaluation order regression. Fixes DMD testcase 'arrayop'. --- dmd2/arrayop.c | 3 +++ gen/tocall.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index a2e38e4a..d0bad81a 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -255,7 +255,10 @@ ArrayOp *buildArrayOp(Identifier *ident, BinExp *exp, Scope *sc, Loc loc) 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); diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 6d16cf8f..257d32c1 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -513,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); From eb14970fd09c97850e223aa2c3c00f932401c291 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 17:10:50 +0200 Subject: [PATCH 25/59] Minor nested context doc comment improval. --- ir/irfunction.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ir/irfunction.h b/ir/irfunction.h index 28573049..7bfa1423 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; From 4f1374e211cec154f77ed041d21a722ae1038830 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 17:44:08 +0200 Subject: [PATCH 26/59] Fold in testsuite merge fixes. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 5f7363db..4bb37af4 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 5f7363dbeb4b39bbeefb05a6ac6013fc9ada4eff +Subproject commit 4bb37af42d11b835a3936296eabd65a07ee76bce From 3035735bc93568f86cecd11e7434654cf65caf9a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 19:11:43 +0200 Subject: [PATCH 27/59] FuncDeclaration::canInline diff reduction. The new arguments to the call in DtoLinkage do not exactly match what was there before, but have been harmonized with the other canInline call. --- dmd2/declaration.h | 2 +- gen/tollvm.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd2/declaration.h b/dmd2/declaration.h index cb326a57..27211c5a 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -886,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); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index cae8f2ea..d960442c 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -435,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 From 041e8e8b54ef5fa7e5b7f287fcd292e8c6d3935a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Fri, 14 Jun 2013 21:49:44 +0200 Subject: [PATCH 28/59] Remove LDC-specific .classinfo AST rewrite. Apart from reducing the diff to upstream DMD, this also fixes a "cannot interpret" CTFE issue. --- dmd2/mtype.c | 43 +------------------------------------------ gen/toir.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 42 deletions(-) diff --git a/dmd2/mtype.c b/dmd2/mtype.c index fdfebafd..eefbaa30 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -8703,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()) @@ -8767,9 +8729,6 @@ L1: } e = new PtrExp(e->loc, e, t); } - -#endif // !LDC - return e; } diff --git a/gen/toir.cpp b/gen/toir.cpp index 2ac4cbff..57e3615e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1333,6 +1333,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); } From bca5dac6690a1da2a5b8fd9c6bb7a6e651eff685 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 13:10:43 +0200 Subject: [PATCH 29/59] Fixed ClassReferenceExp codegen, handle self-referential literals. --- dmd2/expression.c | 2 + dmd2/expression.h | 9 +++ gen/toir.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 151 insertions(+), 11 deletions(-) diff --git a/dmd2/expression.c b/dmd2/expression.c index 2790afa1..00cef6e4 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -4369,6 +4369,8 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * this->ctorinit = 0; #if IN_LLVM constType = NULL; + this->inProgressMemory = NULL; + this->globalVar = NULL; #endif this->origin = this; this->stageflags = 0; diff --git a/dmd2/expression.h b/dmd2/expression.h index 67ad55f2..9272ddee 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -76,6 +76,7 @@ class DValue; namespace llvm { class Constant; class ConstantInt; + class GlobalVariable; class StructType; } #endif @@ -628,8 +629,16 @@ struct StructLiteralExp : Expression 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); llvm::StructType *constType; + // 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. diff --git a/gen/toir.cpp b/gen/toir.cpp index 57e3615e..fe8ae5d2 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -36,11 +36,13 @@ #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. @@ -1102,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; } @@ -1287,9 +1308,36 @@ 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); + + 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); + 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(); @@ -2873,11 +2921,13 @@ DValue* StructLiteralExp::toElem(IRState* p) 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"); @@ -2885,7 +2935,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 @@ -2933,7 +2983,7 @@ 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, true); @@ -2957,7 +3007,9 @@ 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; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2985,8 +3037,7 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) 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]) @@ -3004,8 +3055,86 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) toChars(), type->toChars()); LOG_SCOPE; - // FIXME: Handle type->sym->isInterfaceDeclaration(). - return value->toConstElem(p); + 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); + + 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.irStruct->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); + 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)); } ////////////////////////////////////////////////////////////////////////////////////////// From 7874c95cdc338074d796d4bbdb0b3e57e9e4d778 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 13:11:36 +0200 Subject: [PATCH 30/59] Remove unused StructLiteralExp::constType variable. --- dmd2/expression.c | 1 - dmd2/expression.h | 1 - 2 files changed, 2 deletions(-) diff --git a/dmd2/expression.c b/dmd2/expression.c index 00cef6e4..fa4ea1a0 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -4368,7 +4368,6 @@ 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 diff --git a/dmd2/expression.h b/dmd2/expression.h index 9272ddee..47794e61 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -635,7 +635,6 @@ struct StructLiteralExp : Expression llvm::Value* inProgressMemory; llvm::Constant *toConstElem(IRState *irs); - llvm::StructType *constType; // A global variable for taking the address of this struct literal constant, // if it already exists. Used to resolve self-references. llvm::GlobalVariable *globalVar; From 66e9427f883da417ac570194f55a5f9fb3c3a80a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 13:13:37 +0200 Subject: [PATCH 31/59] Backport StructLiteralExp::toChars infinite recursion fix. We absolutely need this for log output/debugging. --- dmd2/expression.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dmd2/expression.c b/dmd2/expression.c index fa4ea1a0..822ed996 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -4620,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(')'); } From c813ccdcf71e44a115043dee92a9bde56a156293 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 13:14:14 +0200 Subject: [PATCH 32/59] Small debug diagnostics improvements. --- gen/toir.cpp | 6 ++++-- ir/iraggr.cpp | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index fe8ae5d2..686bace7 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1130,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; @@ -1229,7 +1229,7 @@ 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; DValue* v = e1->toElem(p); if (v->isField()) { @@ -1270,6 +1270,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 diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index e644663e..5e5acf23 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -245,6 +245,7 @@ llvm::Constant* IrAggr::createInitializerConstant( llvm::StructType* initializerType) { IF_LOG Logger::println("Creating initializer constant for %s", aggrdecl->toChars()); + LOG_SCOPE; llvm::SmallVector constants; From 0e49a57a5f5f23ef327a6a2c92853516e9383787 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 15:06:49 +0200 Subject: [PATCH 33/59] More upstream DMD alignment. --- dmd2/aggregate.h | 1 + dmd2/ctfeexpr.c | 1 - dmd2/declaration.c | 4 ++-- dmd2/readme.txt | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index 82bb53e5..518cae13 100644 --- a/dmd2/aggregate.h +++ b/dmd2/aggregate.h @@ -278,6 +278,7 @@ 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) diff --git a/dmd2/ctfeexpr.c b/dmd2/ctfeexpr.c index f9ca92ea..3ca582d6 100644 --- a/dmd2/ctfeexpr.c +++ b/dmd2/ctfeexpr.c @@ -1955,7 +1955,6 @@ bool isCtfeValueValid(Expression *newval) 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 1f9db8a6..a8b602d3 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 @@ -84,7 +84,7 @@ Declaration::Declaration(Identifier *id) linkage = LINKdefault; inuse = 0; sem = SemanticStart; - mangleOverride = NULL; + mangleOverride = NULL; } void Declaration::semantic(Scope *sc) diff --git a/dmd2/readme.txt b/dmd2/readme.txt index 0d72c9be..2b79949d 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 From a7882a8ae67d121d084689c5108cf6c847890655 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 15:07:06 +0200 Subject: [PATCH 34/59] Fix another few issues caused by the upstream v2.063.1 retagging. --- dmd2/declaration.c | 16 +++++++++++++++- dmd2/expression.c | 2 ++ dmd2/mars.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dmd2/declaration.c b/dmd2/declaration.c index a8b602d3..a266be82 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -1220,7 +1220,7 @@ 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) @@ -1229,6 +1229,16 @@ Lnomatch: 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; + } + else #endif { storage_class |= STCfield; @@ -1960,6 +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(); diff --git a/dmd2/expression.c b/dmd2/expression.c index 822ed996..18406d87 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -7565,7 +7565,9 @@ Expression *DotVarExp::semantic(Scope *sc) accessCheck(loc, sc, e1, var); VarDeclaration *v = var->isVarDeclaration(); +#if PULL93 if (v && (v->isDataseg() || (v->storage_class & STCmanifest))) +#endif { Expression *e = expandVar(WANTvalue, v); if (e) diff --git a/dmd2/mars.h b/dmd2/mars.h index 1422d4db..1c641383 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -102,6 +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 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)) From e9d7c10109abd19b3d441a9b5889495f12b0ad9a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 15:11:17 +0200 Subject: [PATCH 35/59] Align our copy of TypeInfo code to upstream DMD version. --- gen/typinf.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 68b4261e..0d07ab7f 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(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: @@ -122,12 +122,10 @@ Expression *Type::getTypeInfo(Scope *sc) 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(Loc(), 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; } From 2e0941c1943c0c2a846418ec8849b993b45f6726 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 16:16:47 +0200 Subject: [PATCH 36/59] Add names for globals to make LDC compile against LLVM 3.1. --- gen/toir.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gen/toir.cpp b/gen/toir.cpp index 686bace7..7bd2b511 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1321,14 +1321,15 @@ LLConstant* AddrExp::toConstElem(IRState* p) } se->globalVar = new llvm::GlobalVariable(*p->module, - DtoType(e1->type), false, llvm::GlobalValue::InternalLinkage, 0); + 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); + llvm::GlobalValue::InternalLinkage, 0, ".structliteral"); se->globalVar->replaceAllUsesWith( DtoBitCast(finalGlobalVar, se->globalVar->getType())); se->globalVar->eraseFromParent(); @@ -3069,7 +3070,7 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) { value->globalVar = new llvm::GlobalVariable(*p->module, origClass->type->irtype->isClass()->getMemoryLLType(), - false, llvm::GlobalValue::InternalLinkage, 0); + false, llvm::GlobalValue::InternalLinkage, 0, ".classref"); std::map varInits; @@ -3109,8 +3110,9 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) if (constValue->getType() != value->globalVar->getType()->getContainedType(0)) { - llvm::GlobalVariable* finalGlobalVar = new llvm::GlobalVariable(*p->module, - constValue->getType(), false, llvm::GlobalValue::InternalLinkage, 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(); From 08f27c0b6d48a685e8d078948ce643687b25a06c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 22:55:28 +0200 Subject: [PATCH 37/59] Test suite updates. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 4bb37af4..b3604507 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 4bb37af42d11b835a3936296eabd65a07ee76bce +Subproject commit b36045076137f87d4caa341a31dca0a2cf90cfb0 From bed6243481835ea9bec947a68da938d500df7a13 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 22:57:57 +0200 Subject: [PATCH 38/59] LDC does not support -transition yet. --- driver/ldmd.cpp | 10 ++++++++-- tests/d2/dmd-testsuite | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index d02680c9..903cda51 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -199,8 +199,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\ @@ -495,6 +499,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/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index b3604507..2b025b7f 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit b36045076137f87d4caa341a31dca0a2cf90cfb0 +Subproject commit 2b025b7f2a18147fefc7eea9664451160a07ffb1 From 46b6fdd53125dc19991c7c19fd27a07f0ed2b392 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 23:09:59 +0200 Subject: [PATCH 39/59] Implement '-main'. --- driver/cl_options.cpp | 4 ++++ driver/main.cpp | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index c88a2633..61c389bd 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -204,6 +204,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: diff --git a/driver/main.cpp b/driver/main.cpp index ae930a55..b52c1f3d 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -693,6 +693,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); @@ -813,7 +819,18 @@ int main(int argc, char** argv) if (!Module::rootModule) Module::rootModule = m; m->importedFrom = m; - m->read(Loc()); + + 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(); From 0305d3bce25c17a6361f98f953d15058cc67df07 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sat, 15 Jun 2013 23:22:34 +0200 Subject: [PATCH 40/59] Never make external variables something else than external. Fixes crash in DMD testcase 'mangle'. --- gen/llvmhelpers.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 1339dc1b..4d71b928 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1546,6 +1546,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) From acd508945a4d5c020d401f23dda91e6f1c108ddb Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 00:12:02 +0200 Subject: [PATCH 41/59] Allow multiple declarations to share the same mangled name/LLVM global. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is necessary to enable aliasing compiler-generated symbols with pragma(mangle, …). Note that globals for internal use are still directly created. --- gen/classes.cpp | 3 ++- gen/declarations.cpp | 26 +++++--------------------- gen/llvmhelpers.cpp | 29 +++++++++++++++++++++++++++++ gen/llvmhelpers.h | 12 ++++++++++++ gen/module.cpp | 8 +++++--- gen/rttibuilder.cpp | 4 ++-- gen/runtime.cpp | 5 +++-- ir/iraggr.cpp | 2 +- ir/irclass.cpp | 8 ++++---- 9 files changed, 63 insertions(+), 34 deletions(-) diff --git a/gen/classes.cpp b/gen/classes.cpp index 3f14da5a..d5046211 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -605,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); diff --git a/gen/declarations.cpp b/gen/declarations.cpp index 237bbc95..dcb710bb 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/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 4d71b928..53198c29 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -2024,3 +2024,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 bf8e561e..a23b2a55 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -226,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 693ca36b..f8151904 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -178,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); @@ -341,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; } diff --git a/gen/rttibuilder.cpp b/gen/rttibuilder.cpp index bc182b5f..79f1c9bf 100644 --- a/gen/rttibuilder.cpp +++ b/gen/rttibuilder.cpp @@ -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 a0ccd41c..6d49356f 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -17,6 +17,7 @@ #include "root.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" @@ -121,8 +122,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()); } ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index 5e5acf23..ce4bdc9d 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -64,7 +64,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 diff --git a/ir/irclass.cpp b/ir/irclass.cpp index b280a80d..755d5048 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -56,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; @@ -86,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. @@ -138,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; @@ -335,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, From 1d9804d03cf4644988696f74ab675e33ebc3dcef Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 00:17:46 +0200 Subject: [PATCH 42/59] Use '__ModuleInfoZ' for ModuleInfos, like DMD does. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way, we stay at least compatible w.r.t. demanglers, pragma(mangle, …) tricks. Fixes DMD testcase 'mangle'. --- gen/module.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/module.cpp b/gen/module.cpp index f8151904..2b4de34f 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -327,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); @@ -388,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); From 68798f06c84763b4689660abfb7ac553109f2689 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 00:39:47 +0200 Subject: [PATCH 43/59] Accept '.dd' pure DDoc files. --- driver/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/driver/main.cpp b/driver/main.cpp index b52c1f3d..b9f6a207 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -772,7 +772,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 == '.'); From 897c4382affbe67052db5d15798588a85e370b7b Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 01:02:46 +0200 Subject: [PATCH 44/59] Do not re-codegen struct literals on taking address of globals. The AST the frontend generates is arguably invalid, but we have to deal with that. Fixes DMD testcase 'interpret'. --- gen/toir.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gen/toir.cpp b/gen/toir.cpp index 7bd2b511..32395461 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1231,6 +1231,24 @@ DValue* AddrExp::toElem(IRState* p) { 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"); From 6a1fef81f4707fdbdd11d5fe8327b5e6625f737a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 01:06:20 +0200 Subject: [PATCH 45/59] Test suite updates. --- tests/d2/dmd-testsuite | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/d2/dmd-testsuite b/tests/d2/dmd-testsuite index 2b025b7f..32aa4872 160000 --- a/tests/d2/dmd-testsuite +++ b/tests/d2/dmd-testsuite @@ -1 +1 @@ -Subproject commit 2b025b7f2a18147fefc7eea9664451160a07ffb1 +Subproject commit 32aa48727a4db7a28878e6f13af603aaa3e0e48d From 480d05c76e6d371e47807108b3c38e22d4658b2c Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 18:21:36 +0200 Subject: [PATCH 46/59] Removed unused and broken template instantiation origin detection. Having something like this would be useful in determining whether to define a given template symbol during codegen, but the frontend sometimes produces TemplateInstances in a scope where sc->tinst has not been semantic'd, thus breaking the chaining mechanism. --- dmd2/template.c | 23 +++++------------------ dmd2/template.h | 1 - 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/dmd2/template.c b/dmd2/template.c index 86df030e..2daed08d 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -4778,11 +4778,10 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->havetempdecl = 0; this->enclosing = NULL; this->speculative = 0; - this->ignore = true; #if IN_LLVM + this->ignore = true; this->emittedInModule = NULL; - this->tmodule = NULL; #endif } @@ -4812,12 +4811,10 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->havetempdecl = 1; 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(tempdecl->scope); @@ -4962,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; @@ -4980,17 +4978,6 @@ 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"); diff --git a/dmd2/template.h b/dmd2/template.h index 33d627ca..ddb2a5b5 100644 --- a/dmd2/template.h +++ b/dmd2/template.h @@ -354,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*); From a0ffaf56bf4db6c162d6e38c60e0c9d4148e47ba Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 19:16:50 +0200 Subject: [PATCH 47/59] Do not codegen aggregate types from within debug info generation. This avoids problems where we would codegen children of an "inner" template instantiation (i.e. a member of a non-template aggregate in another module) because we have no way to know the outer (declare-only) entity exists in the respective mustDefineSymbol invocation. An example for this are the std.typecons.RefCounted internals of std.file.DirIterator, as used from std.datetime and other modules. This is not only inefficient, but also causes linking issues due to attribute inference for these functions not having run yet (and consequently the mangled name being different from the actual definition). --- gen/todebug.cpp | 34 ++++++++++++++++------------------ ir/iraggr.cpp | 3 +-- ir/iraggr.h | 3 --- ir/irtypeaggr.cpp | 2 +- ir/irtypeaggr.h | 6 ++++++ 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 0588c6f9..3db36789 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" @@ -254,9 +255,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; @@ -272,19 +271,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; @@ -295,17 +295,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) { @@ -321,7 +319,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/ir/iraggr.cpp b/ir/iraggr.cpp index ce4bdc9d..35733b79 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -26,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; diff --git a/ir/iraggr.h b/ir/iraggr.h index 033a716e..04621c28 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/irtypeaggr.cpp b/ir/irtypeaggr.cpp index 7ed76c14..a55aca7e 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) + aggr(ad), diCompositeType(NULL) { } diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 6dbe6b83..2c8579f4 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -12,6 +12,7 @@ #include "ir/irtype.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo.h" #include #include @@ -39,6 +40,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); From 4774745f44cac66af99fd841f10c16b69cb79244 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 20:23:07 +0200 Subject: [PATCH 48/59] Do not try to generate metadata for unresolved types. This does not fix the root cause, which is likely a frontend bug/oddity, but avoids the crash. --- gen/typinf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/typinf.cpp b/gen/typinf.cpp index 0d07ab7f..cbbb0ed8 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -320,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); From cfd5c052fe0bebf09406f12621f17539d99947ee Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 20:49:23 +0200 Subject: [PATCH 49/59] Fix LLVM 3.1 build. --- ir/irtypeaggr.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 2c8579f4..2fdc7b9f 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -12,7 +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 From 0206269230121e10f3f64429a5c896c41b94b495 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 16 Jun 2013 21:16:51 +0200 Subject: [PATCH 50/59] Ignore StaticAssert in DtoDeclarationExp. Fixes DMD testcase 'testrightthis'. --- gen/llvmhelpers.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 53198c29..32676228 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1137,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()) { @@ -1195,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; From e86a87ab6d88babcb69a1093637d4e9b19a6fe3a Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 00:03:52 +0200 Subject: [PATCH 51/59] Complete switch to extern(D) _d_invariant. --- gen/runtime.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 6d49356f..65affd3f 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -15,6 +15,7 @@ #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" @@ -899,12 +900,13 @@ static void LLVM_D_BuildRuntimeModule() ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// - // void _d_invariant(Object o) + // void invariant._d_invariant(Object o) { llvm::StringRef fname("_D9invariant12_d_invariantFC6ObjectZv"); LLType *types[] = { objectTy }; LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false); - llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + llvm::Function* fn = llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + fn->setCallingConv(gABI->callingConv(LINKd)); } // void _d_hidden_func() From 9b68c486111af2e3706e417d7af0838254e6eb28 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 00:46:49 +0200 Subject: [PATCH 52/59] Fold in disabling of std.traits test. --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 1c80c826..3842d014 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 1c80c82684900a20e4cad056b65401310a5754ee +Subproject commit 3842d0149e173becdc39e0d6dc64dab35e744322 From dd8652768c83bb54d7e1b24a6a1753a6cab57882 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 02:37:55 +0200 Subject: [PATCH 53/59] Remove unused IrTypeFunction::fty(). The design split between IrFuncTy/IrTypeFunction might need a review at some point. --- ir/irtypefunction.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ir/irtypefunction.h b/ir/irtypefunction.h index e583a621..a107d373 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; }; /// From 9700d841326981b1114ede41585a610b39395edf Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 02:38:38 +0200 Subject: [PATCH 54/59] Initialize IrTypeAggr members in order to silence warning. --- ir/irtypeaggr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ir/irtypeaggr.cpp b/ir/irtypeaggr.cpp index a55aca7e..1c69c7af 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) + diCompositeType(NULL), aggr(ad) { } From b15588ed15fdd83db98b6e923ae48118524077a9 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 02:40:13 +0200 Subject: [PATCH 55/59] Finally fix the _d_invariant declaration on x86. --- gen/runtime.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 65affd3f..c6e4af34 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -22,6 +22,7 @@ #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" @@ -94,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; } @@ -902,10 +904,23 @@ static void LLVM_D_BuildRuntimeModule() // void invariant._d_invariant(Object o) { + // 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"); - LLType *types[] = { objectTy }; - LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false); - llvm::Function* fn = llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + 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)); } From 1215ffacd327cd88b9af868289bcc4ba3b173e05 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 02:41:37 +0200 Subject: [PATCH 56/59] Complete IrStruct->IrAggr rename. --- gen/classes.cpp | 22 +++++++++++----------- gen/llvmhelpers.cpp | 6 +++--- gen/module.cpp | 2 +- gen/rttibuilder.cpp | 4 ++-- gen/structs.cpp | 8 ++++---- gen/toir.cpp | 12 ++++++------ gen/typinf.cpp | 6 +++--- ir/irclass.cpp | 2 +- ir/irdsymbol.cpp | 6 +++--- ir/irdsymbol.h | 2 +- ir/irlandingpad.cpp | 2 +- 11 files changed, 36 insertions(+), 36 deletions(-) diff --git a/gen/classes.cpp b/gen/classes.cpp index d5046211..f5d164ac 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -57,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); @@ -152,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"); } @@ -203,7 +203,7 @@ void DtoInitClass(TypeClass* tc, LLValue* dst) // 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 @@ -219,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"); @@ -380,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)); @@ -441,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)); @@ -580,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); @@ -691,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/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 32676228..8c01cd7b 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1279,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()) { @@ -1851,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()) @@ -1960,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); } diff --git a/gen/module.cpp b/gen/module.cpp index 2b4de34f..7ff40101 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -431,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/rttibuilder.cpp b/gen/rttibuilder.cpp index 79f1c9bf..c1711d70 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) diff --git a/gen/structs.cpp b/gen/structs.cpp index 118e70d7..19055036 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/toir.cpp b/gen/toir.cpp index 32395461..b6238238 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -134,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()) @@ -2038,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); @@ -2937,7 +2937,7 @@ 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); } @@ -3051,7 +3051,7 @@ 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 @@ -3067,7 +3067,7 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p) } } - return sd->ir.irStruct->createInitializerConstant(varInits); + return sd->ir.irAggr->createInitializerConstant(varInits); } llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) @@ -3124,7 +3124,7 @@ llvm::Constant* ClassReferenceExp::toConstElem(IRState *p) assert(i == nexprs); } - llvm::Constant* constValue = origClass->ir.irStruct->createInitializerConstant(varInits); + llvm::Constant* constValue = origClass->ir.irAggr->createInitializerConstant(varInits); if (constValue->getType() != value->globalVar->getType()->getContainedType(0)) { diff --git a/gen/typinf.cpp b/gen/typinf.cpp index cbbb0ed8..bcdab264 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -604,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,7 +618,7 @@ void TypeInfoStructDeclaration::llvmDefine() 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 @@ -737,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/irclass.cpp b/ir/irclass.cpp index 755d5048..8f0094a1 100644 --- a/ir/irclass.cpp +++ b/ir/irclass.cpp @@ -394,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 290cfcbc..d16565e6 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 932ffdef..546b7891 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/irlandingpad.cpp b/ir/irlandingpad.cpp index 2d6adb01..b3ae23b6 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 From 235bb94878186ca54a63d02ec38887d521647ae3 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 13:07:33 +0200 Subject: [PATCH 57/59] Make -release only disable bounds checking in non-@safe code. --- dmd2/mars.h | 4 ---- driver/cl_options.cpp | 13 ++++++------- driver/cl_options.h | 5 ++++- driver/main.cpp | 9 +++++++++ gen/aa.cpp | 2 +- gen/arrays.cpp | 2 +- gen/irstate.cpp | 15 +++++++++++++++ gen/irstate.h | 3 +++ gen/toir.cpp | 6 +++--- 9 files changed, 42 insertions(+), 17 deletions(-) diff --git a/dmd2/mars.h b/dmd2/mars.h index 1c641383..dc391ade 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -193,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 diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 61c389bd..8b688953 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" @@ -221,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; @@ -320,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"), @@ -348,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 d1320894..25afb5a6 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/main.cpp b/driver/main.cpp index b9f6a207..ddc06278 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -175,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(); @@ -369,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 diff --git a/gen/aa.cpp b/gen/aa.cpp index 9ab363a2..bbebda5d 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 278aa762..36c0c519 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/irstate.cpp b/gen/irstate.cpp index e260b763..be6f1840 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 3d57918e..45659988 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/toir.cpp b/gen/toir.cpp index b6238238..d1ee19fe 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1609,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()); @@ -1672,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 From c9c8f511188adfd7f760e7988e16ead86a85b4c9 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 13:37:53 +0200 Subject: [PATCH 58/59] Fold in broken std.exception test case fix. --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 3842d014..9fe205f1 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 3842d0149e173becdc39e0d6dc64dab35e744322 +Subproject commit 9fe205f1f7aee63cffe0a7105ff5acb7fcaa157f From 46e699b635f5fe48854175f9990bbbfd9987e55b Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Mon, 17 Jun 2013 15:21:24 +0200 Subject: [PATCH 59/59] Fold in druntime OS X build fix. --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 03674ab8..adaeaf9e 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 03674ab8476771c58cb096813058b835b63fa4a6 +Subproject commit adaeaf9e7b3151d2efb710dca3d79cb724bd30bb