From 837ef30fec72471fee199b6453d127f2c7ce5ad7 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Sun, 26 Aug 2012 21:10:13 +0200 Subject: [PATCH] Merged DMD 2.060 frontend. Upstream Git tag v2.060 (e8fe11c20249cb9e42538be88c99b74ede4d12e3). --- dmd2/aggregate.h | 15 +- dmd2/aliasthis.c | 24 ++ dmd2/argtypes.c | 272 ++++++++++++- dmd2/arrayop.c | 24 +- dmd2/attrib.c | 79 ++-- dmd2/attrib.h | 7 +- dmd2/builtin.c | 10 +- dmd2/canthrow.c | 7 +- dmd2/cast.c | 140 +++++-- dmd2/class.c | 111 ++--- dmd2/clone.c | 32 +- dmd2/cond.c | 10 +- dmd2/constfold.c | 67 ++- dmd2/cppmangle.c | 11 +- dmd2/declaration.c | 178 +++++--- dmd2/declaration.h | 20 +- dmd2/dmd_msc.vcproj | 112 +++-- dmd2/doc.c | 17 +- dmd2/dsymbol.c | 41 +- dmd2/dsymbol.h | 3 +- dmd2/dump.c | 4 +- dmd2/enum.c | 20 +- dmd2/enum.h | 2 +- dmd2/expression.c | 880 ++++++++++++++++++++++++---------------- dmd2/expression.h | 20 +- dmd2/func.c | 589 ++++++++++++++------------- dmd2/hdrgen.c | 2 +- dmd2/hdrgen.h | 1 + dmd2/idgen.c | 4 +- dmd2/import.c | 42 +- dmd2/inifile.c | 6 +- dmd2/init.c | 77 +++- dmd2/init.h | 14 +- dmd2/inline.c | 96 ++++- dmd2/interpret.c | 803 ++++++++++++++++++++++++++---------- dmd2/intrange.h | 12 +- dmd2/json.c | 18 +- dmd2/lexer.c | 199 ++------- dmd2/lexer.h | 4 +- dmd2/lib.h | 54 +-- dmd2/mars.c | 80 ++-- dmd2/mars.h | 18 +- dmd2/module.c | 97 ++--- dmd2/module.h | 3 - dmd2/mtype.c | 476 +++++++++++++--------- dmd2/mtype.h | 17 +- dmd2/opover.c | 151 ++++--- dmd2/optimize.c | 33 +- dmd2/parse.c | 43 +- dmd2/readme.txt | 4 +- dmd2/root/aav.c | 9 + dmd2/root/aav.h | 8 + dmd2/root/array.c | 1 - dmd2/root/async.c | 8 + dmd2/root/dchar.c | 482 ---------------------- dmd2/root/dchar.h | 194 --------- dmd2/root/gnuc.c | 8 + dmd2/root/gnuc.h | 8 + dmd2/root/lstring.c | 63 --- dmd2/root/lstring.h | 74 ---- dmd2/root/response.c | 19 +- dmd2/root/rmem.c | 9 +- dmd2/root/rmem.h | 8 +- dmd2/root/root.c | 118 +----- dmd2/root/root.h | 10 - dmd2/root/speller.c | 8 + dmd2/root/speller.h | 8 + dmd2/root/stringtable.c | 92 ++++- dmd2/root/stringtable.h | 41 +- dmd2/scope.c | 1 + dmd2/scope.h | 4 +- dmd2/statement.c | 248 +++++++---- dmd2/statement.h | 8 +- dmd2/staticassert.c | 12 +- dmd2/struct.c | 160 ++++++-- dmd2/template.c | 688 +++++++++++++++++++------------ dmd2/traits.c | 32 +- dmd2/unialpha.c | 323 --------------- dmd2/unittests.c | 8 + dmd2/utf.c | 465 +++++++++++---------- dmd2/utf.h | 109 ++++- driver/main.cpp | 10 +- runtime/CMakeLists.txt | 2 +- runtime/druntime | 2 +- runtime/phobos | 2 +- 85 files changed, 4411 insertions(+), 3780 deletions(-) delete mode 100644 dmd2/root/dchar.c delete mode 100644 dmd2/root/dchar.h delete mode 100644 dmd2/root/lstring.c delete mode 100644 dmd2/root/lstring.h delete mode 100644 dmd2/unialpha.c diff --git a/dmd2/aggregate.h b/dmd2/aggregate.h index 46af2b3d..6deae43e 100644 --- a/dmd2/aggregate.h +++ b/dmd2/aggregate.h @@ -67,7 +67,6 @@ struct AggregateDeclaration : ScopeDsymbol Type *handle; // 'this' type unsigned structsize; // size of struct unsigned alignsize; // size of struct for alignment purposes - unsigned structalign; // struct member alignment in effect int hasUnions; // set if aggregate has overlapping fields VarDeclarations fields; // VarDeclaration fields enum Sizeok sizeok; // set when structsize contains valid data @@ -96,17 +95,18 @@ struct AggregateDeclaration : ScopeDsymbol #ifdef IN_GCC Expressions *attributes; // GCC decl/type attributes - FuncDeclarations methods; // flat list of all methods for debug information #endif + Expression *getRTInfo; // pointer to GC info generated by object.RTInfo(this) + AggregateDeclaration(Loc loc, Identifier *id); void semantic2(Scope *sc); void semantic3(Scope *sc); void inlineScan(); unsigned size(Loc loc); - static void alignmember(unsigned salign, unsigned size, unsigned *poffset); + static void alignmember(structalign_t salign, unsigned size, unsigned *poffset); static unsigned placeField(unsigned *nextoffset, - unsigned memsize, unsigned memalignsize, unsigned memalign, + unsigned memsize, unsigned memalignsize, structalign_t memalign, unsigned *paggsize, unsigned *paggalignsize, bool isunion); Type *getType(); int firstFieldInUnion(int indx); // first field in union that includes indx @@ -165,8 +165,14 @@ struct StructDeclaration : AggregateDeclaration FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals static FuncDeclaration *xerreq; // object.xopEquals + + structalign_t alignment; // alignment applied outside of the struct #endif + // For 64 bit Efl function call/return ABI + Type *arg1type; + Type *arg2type; + StructDeclaration(Loc loc, Identifier *id); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); @@ -175,6 +181,7 @@ struct StructDeclaration : AggregateDeclaration char *mangle(); const char *kind(); void finalizeSize(Scope *sc); + bool isPOD(); #if DMDV1 Expression *cloneMembers(); #endif diff --git a/dmd2/aliasthis.c b/dmd2/aliasthis.c index 0f6ff452..b26731b9 100644 --- a/dmd2/aliasthis.c +++ b/dmd2/aliasthis.c @@ -18,6 +18,7 @@ #include "aggregate.h" #include "dsymbol.h" #include "mtype.h" +#include "declaration.h" #if DMDV2 @@ -78,9 +79,32 @@ void AliasThis::semantic(Scope *sc) ::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars()); else ::error(loc, "undefined identifier %s", ident->toChars()); + return; } else if (ad->aliasthis && s != ad->aliasthis) error("there can be only one alias this"); + + /* disable the alias this conversion so the implicit conversion check + * doesn't use it. + */ + /* This should use ad->aliasthis directly, but with static foreach and templates + * ad->type->sym might be different to ad. + */ + AggregateDeclaration *ad2 = ad->type->toDsymbol(NULL)->isAggregateDeclaration(); + Dsymbol *save = ad2->aliasthis; + ad2->aliasthis = NULL; + + if (Declaration *d = s->isDeclaration()) + { + Type *t = d->type; + assert(t); + if (ad->type->implicitConvTo(t)) + { + ::error(loc, "alias this is not reachable as %s already converts to %s", ad->toChars(), t->toChars()); + } + } + + ad2->aliasthis = save; ad->aliasthis = s; } else diff --git a/dmd2/argtypes.c b/dmd2/argtypes.c index 3f1d3620..ffa38a86 100644 --- a/dmd2/argtypes.c +++ b/dmd2/argtypes.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 2010-2011 by Digital Mars +// Copyright (c) 2010-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -27,6 +27,9 @@ #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. @@ -40,6 +43,10 @@ TypeTuple *Type::toArgTypes() return NULL; // not valid for a parameter } +TypeTuple *TypeError::toArgTypes() +{ + return new TypeTuple(Type::terror); +} TypeTuple *TypeBasic::toArgTypes() { Type *t1 = NULL; @@ -78,7 +85,7 @@ TypeTuple *TypeBasic::toArgTypes() case Tcomplex32: if (global.params.is64bit) - t1 = Type::tfloat64; // weird, eh? + t1 = Type::tfloat2; else { t1 = Type::tfloat64; @@ -124,23 +131,39 @@ TypeTuple *TypeBasic::toArgTypes() return t; } +#if DMDV2 TypeTuple *TypeVector::toArgTypes() { - return new TypeTuple(Type::tfloat64); + return new TypeTuple(this); } +#endif TypeTuple *TypeSArray::toArgTypes() { #if DMDV2 + if (dim) + { + /* Should really be done as if it were a struct with dim members + * of the array's elements. + * I.e. int[2] should be done like struct S { int a; int b; } + */ + dinteger_t sz = dim->toInteger(); + if (sz == 1) + // T[1] should be passed like T + return next->toArgTypes(); + } return new TypeTuple(); // pass on the stack for efficiency #else - return new TypeTuple(Type::tvoidptr); + return new TypeTuple(); // pass on the stack for efficiency #endif } TypeTuple *TypeDArray::toArgTypes() { - return new TypeTuple(); // pass on the stack for efficiency + /* Should be done as if it were: + * struct S { size_t length; void* ptr; } + */ + return new TypeTuple(Type::tsize_t, Type::tvoidptr); } TypeTuple *TypeAArray::toArgTypes() @@ -150,30 +173,255 @@ TypeTuple *TypeAArray::toArgTypes() TypeTuple *TypePointer::toArgTypes() { - return new TypeTuple(this); + return new TypeTuple(Type::tvoidptr); } TypeTuple *TypeDelegate::toArgTypes() { - return new TypeTuple(); // pass on the stack for efficiency + /* Should be done as if it were: + * struct S { void* ptr; void* funcptr; } + */ + return new TypeTuple(Type::tvoidptr, Type::tvoidptr); +} + +/************************************* + * Convert a floating point type into the equivalent integral type. + */ + +Type *mergeFloatToInt(Type *t) +{ + switch (t->ty) + { + case Tfloat32: + case Timaginary32: + t = Type::tint32; + break; + case Tfloat64: + case Timaginary64: + case Tcomplex32: + t = Type::tint64; + break; + default: +#ifdef DEBUG + printf("mergeFloatToInt() %s\n", t->toChars()); +#endif + assert(0); + } + return t; +} + +/************************************* + * This merges two types into an 8byte type. + */ + +Type *argtypemerge(Type *t1, Type *t2, unsigned offset2) +{ + //printf("argtypemerge(%s, %s, %d)\n", t1 ? t1->toChars() : "", t2 ? t2->toChars() : "", offset2); + if (!t1) + { assert(!t2 || offset2 == 0); + return t2; + } + if (!t2) + return t1; + + unsigned sz1 = t1->size(0); + unsigned sz2 = t2->size(0); + + if (t1->ty != t2->ty && + (t1->ty == Tfloat80 || t2->ty == Tfloat80)) + return NULL; + + // [float,float] => [cfloat] + if (t1->ty == Tfloat32 && t2->ty == Tfloat32 && offset2 == 4) + return Type::tfloat2; + + // Merging floating and non-floating types produces the non-floating type + if (t1->isfloating()) + { + if (!t2->isfloating()) + t1 = mergeFloatToInt(t1); + } + else if (t2->isfloating()) + t2 = mergeFloatToInt(t2); + + Type *t; + + // Pick type with larger size + if (sz1 < sz2) + t = t2; + else + t = t1; + + // If t2 does not lie within t1, need to increase the size of t to enclose both + if (offset2 && sz1 < offset2 + sz2) + { + switch (offset2 + sz2) + { + case 2: + t = Type::tint16; + break; + case 3: + case 4: + t = Type::tint32; + break; + case 5: + case 6: + case 7: + case 8: + t = Type::tint64; + break; + default: + assert(0); + } + } + return t; } TypeTuple *TypeStruct::toArgTypes() { + //printf("TypeStruct::toArgTypes() %s\n", toChars()); + if (!sym->isPOD()) + { + Lmemory: + //printf("\ttoArgTypes() %s => [ ]\n", toChars()); + return new TypeTuple(); // pass on the stack + } + Type *t1 = NULL; + Type *t2 = NULL; d_uns64 sz = size(0); assert(sz < 0xFFFFFFFF); switch ((unsigned)sz) { case 1: - return new TypeTuple(Type::tint8); + t1 = Type::tint8; + break; case 2: - return new TypeTuple(Type::tint16); + t1 = Type::tint16; + break; case 4: - return new TypeTuple(Type::tint32); + t1 = Type::tint32; + break; case 8: - return new TypeTuple(Type::tint64); + t1 = Type::tint64; + break; + case 16: + t1 = NULL; // could be a TypeVector + break; + default: + goto Lmemory; } - return new TypeTuple(); // pass on the stack + if (global.params.is64bit && sym->fields.dim) + { +#if 1 + unsigned sz1 = 0; + unsigned sz2 = 0; + t1 = NULL; + for (size_t i = 0; i < sym->fields.dim; i++) + { VarDeclaration *f = sym->fields[i]; + //printf("f->type = %s\n", f->type->toChars()); + + TypeTuple *tup = f->type->toArgTypes(); + if (!tup) + goto Lmemory; + size_t dim = tup->arguments->dim; + Type *ft1 = NULL; + Type *ft2 = NULL; + switch (dim) + { + case 2: + ft1 = (*tup->arguments)[0]->type; + ft2 = (*tup->arguments)[1]->type; + break; + case 1: + if (f->offset < 8) + ft1 = (*tup->arguments)[0]->type; + else + ft2 = (*tup->arguments)[0]->type; + break; + default: + goto Lmemory; + } + + if (f->offset & 7) + { + // Misaligned fields goto Lmemory + unsigned alignsz = f->type->alignsize(); + if (f->offset & (alignsz - 1)) + goto Lmemory; + + // Fields that overlap the 8byte boundary goto Lmemory + unsigned fieldsz = f->type->size(0); + if (f->offset < 8 && (f->offset + fieldsz) > 8) + goto Lmemory; + } + + // First field in 8byte must be at start of 8byte + assert(t1 || f->offset == 0); + + if (ft1) + { + t1 = argtypemerge(t1, ft1, f->offset); + if (!t1) + goto Lmemory; + } + + if (ft2) + { + unsigned off2 = f->offset; + if (ft1) + off2 = 8; + assert(t2 || off2 == 8); + t2 = argtypemerge(t2, ft2, off2 - 8); + if (!t2) + goto Lmemory; + } + } + + if (t2) + { + if (t1->isfloating() && t2->isfloating()) + { + if (t1->ty == Tfloat64 && t2->ty == Tfloat64) + ; + else + goto Lmemory; + } + else if (t1->isfloating()) + goto Lmemory; + else if (t2->isfloating()) + goto Lmemory; + else + ; + } +#else + if (sym->fields.dim == 1) + { VarDeclaration *f = sym->fields[0]; + //printf("f->type = %s\n", f->type->toChars()); + TypeTuple *tup = f->type->toArgTypes(); + if (tup) + { + size_t dim = tup->arguments->dim; + if (dim == 1) + t1 = (*tup->arguments)[0]->type; + } + } +#endif + } + + //printf("\ttoArgTypes() %s => [%s,%s]\n", toChars(), t1 ? t1->toChars() : "", t2 ? t2->toChars() : ""); + + TypeTuple *t; + if (t1) + { + //if (t1) printf("test1: %s => %s\n", toChars(), t1->toChars()); + if (t2) + t = new TypeTuple(t1, t2); + else + t = new TypeTuple(t1); + } + else + goto Lmemory; + return t; } TypeTuple *TypeEnum::toArgTypes() diff --git a/dmd2/arrayop.c b/dmd2/arrayop.c index ed685c18..bac8391a 100644 --- a/dmd2/arrayop.c +++ b/dmd2/arrayop.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -142,7 +142,6 @@ Expression *BinExp::arrayOp(Scope *sc) buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco); #endif - size_t namelen = buf.offset; buf.writeByte(0); char *name = buf.toChars(); Identifier *ident = Lexer::idPool(name); @@ -349,7 +348,7 @@ Expression *BinExp::arrayOp(Scope *sc) 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 DeclarationStatement(0, d), + new ExpStatement(0, d), new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), new ExpStatement(0, loopbody)); @@ -357,7 +356,7 @@ Expression *BinExp::arrayOp(Scope *sc) // foreach (i; 0 .. p.length) Statement *s1 = new ForeachRangeStatement(0, TOKforeach, new Parameter(0, NULL, Id::p, NULL), - new IntegerExp(0, 0, Type::tint32), + new IntegerExp(0, 0, Type::tsize_t), new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), new ExpStatement(0, loopbody)); #endif @@ -413,6 +412,23 @@ Expression *BinExp::arrayOp(Scope *sc) return e; } +Expression *BinAssignExp::arrayOp(Scope *sc) +{ + //printf("BinAssignExp::arrayOp() %s\n", toChars()); + + /* Check that the elements of e1 can be assigned to + */ + Type *tn = e1->type->toBasetype()->nextOf(); + + if (tn && (!tn->isMutable() || !tn->isAssignable())) + { + error("slice %s is not mutable", e1->toChars()); + return new ErrorExp(); + } + + return BinExp::arrayOp(sc); +} + /****************************************** * Construct the identifier for the array operation function, * and build the argument list to pass to it. diff --git a/dmd2/attrib.c b/dmd2/attrib.c index 776565d0..a21213f9 100644 --- a/dmd2/attrib.c +++ b/dmd2/attrib.c @@ -11,6 +11,7 @@ #include #include #include +#include // memcpy() #include "rmem.h" @@ -37,7 +38,7 @@ extern void obj_includelib(const char *name); #if IN_DMD -void obj_startaddress(Symbol *s); +bool obj_startaddress(Symbol *s); #endif @@ -90,7 +91,7 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) void AttribDeclaration::setScopeNewSc(Scope *sc, StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection, - unsigned structalign) + structalign_t structalign) { if (decl) { @@ -125,7 +126,7 @@ void AttribDeclaration::setScopeNewSc(Scope *sc, void AttribDeclaration::semanticNewSc(Scope *sc, StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection, - unsigned structalign) + structalign_t structalign) { if (decl) { @@ -760,7 +761,10 @@ void AlignDeclaration::semantic(Scope *sc) void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - buf->printf("align (%d)", salign); + if (salign == STRUCTALIGN_DEFAULT) + buf->printf("align"); + else + buf->printf("align (%d)", salign); AttribDeclaration::toCBuffer(buf, hgs); } @@ -938,7 +942,7 @@ void PragmaDeclaration::setScope(Scope *sc) { Expression *e = (*args)[0]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); (*args)[0] = e; StringExp* se = e->toString(); if (!se) @@ -977,8 +981,8 @@ void PragmaDeclaration::semantic(Scope *sc) Expression *e = (*args)[i]; e = e->semantic(sc); - if (e->op != TOKerror) - e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKerror && e->op != TOKtype) + e = e->ctfeInterpret(); if (e->op == TOKerror) { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); return; @@ -1004,7 +1008,7 @@ void PragmaDeclaration::semantic(Scope *sc) Expression *e = (*args)[0]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); (*args)[0] = e; if (e->op == TOKerror) goto Lnodecl; @@ -1022,7 +1026,7 @@ void PragmaDeclaration::semantic(Scope *sc) } goto Lnodecl; } -#if IN_GCC +#ifdef IN_GCC else if (ident == Id::GNU_asm) { if (! args || args->dim != 2) @@ -1046,7 +1050,7 @@ void PragmaDeclaration::semantic(Scope *sc) e = (*args)[1]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); e = e->toString(); if (e && ((StringExp *)e)->sz == 1) s = ((StringExp *)e); @@ -1068,7 +1072,7 @@ void PragmaDeclaration::semantic(Scope *sc) { Expression *e = (*args)[0]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) @@ -1105,7 +1109,7 @@ void PragmaDeclaration::semantic(Scope *sc) unsigned errors_save = global.errors; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (i == 0) printf(" ("); else @@ -1175,21 +1179,19 @@ void PragmaDeclaration::toObjFile(int multiobj) char *name = (char *)mem.malloc(se->len + 1); memcpy(name, se->string, se->len); name[se->len] = 0; -#if OMFOBJ - /* The OMF format allows library names to be inserted - * into the object file. The linker will then automatically + + /* Embed the library names into the object file. + * The linker will then automatically * search that library, too. */ - obj_includelib(name); -#elif ELFOBJ || MACHOBJ - /* 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); -#else - error("pragma lib not supported"); -#endif + 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) @@ -1406,6 +1408,31 @@ Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s) return dd; } +Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *sd) +{ + //printf("StaticIfDeclaration::include(sc = %p) scope = %p\n", sc, scope); + + if (condition->inc == 0) + { + Dsymbols *d = ConditionalDeclaration::include(sc, sd); + + // Set the scopes lazily. + if (scope && d) + { + for (size_t i = 0; i < d->dim; i++) + { + Dsymbol *s = (*d)[i]; + + s->setScope(sc); + } + } + return d; + } + else + { + return ConditionalDeclaration::include(sc, sd); + } +} int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { @@ -1512,7 +1539,7 @@ void CompileDeclaration::compileIt(Scope *sc) //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - exp = exp->optimize(WANTvalue | WANTinterpret); + exp = exp->ctfeInterpret(); StringExp *se = exp->toString(); if (!se) { exp->error("argument to mixin must be a string, not (%s)", exp->toChars()); diff --git a/dmd2/attrib.h b/dmd2/attrib.h index 6762d338..aa8d0447 100644 --- a/dmd2/attrib.h +++ b/dmd2/attrib.h @@ -37,10 +37,10 @@ struct AttribDeclaration : Dsymbol int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void setScopeNewSc(Scope *sc, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, - unsigned structalign); + structalign_t structalign); void semanticNewSc(Scope *sc, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, - unsigned structalign); + structalign_t structalign); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); @@ -122,7 +122,7 @@ struct AlignDeclaration : AttribDeclaration struct AnonDeclaration : AttribDeclaration { bool isunion; - unsigned alignment; + structalign_t alignment; int sem; // 1 if successful semantic() AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); @@ -178,6 +178,7 @@ struct StaticIfDeclaration : ConditionalDeclaration StaticIfDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl); Dsymbol *syntaxCopy(Dsymbol *s); + Dsymbols *include(Scope *sc, ScopeDsymbol *s); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void semantic(Scope *sc); void importAll(Scope *sc); diff --git a/dmd2/builtin.c b/dmd2/builtin.c index 0c8a780a..c1494b5f 100644 --- a/dmd2/builtin.c +++ b/dmd2/builtin.c @@ -10,9 +10,9 @@ #include #include +#include // strcmp() #include - #include "mars.h" #include "declaration.h" #include "attrib.h" @@ -44,10 +44,10 @@ enum BUILTIN FuncDeclaration::isBuiltin() { static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real) static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real) - static const char FuintZint[] = "FNaNbkZi"; // pure nothrow int function(uint) - static const char FuintZuint[] = "FNaNbkZk"; // pure nothrow uint function(uint) + static const char FuintZint[] = "FNaNbNfkZi"; // @safe pure nothrow int function(uint) + static const char FuintZuint[] = "FNaNbNfkZk"; // @safe pure nothrow uint function(uint) static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong) - static const char FulongZint[] = "FNaNbmZi"; // pure nothrow int function(uint) + static const char FulongZint[] = "FNaNbNfmZi"; // @safe pure nothrow int function(uint) static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real) static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real) @@ -167,7 +167,7 @@ uinteger_t eval_bswap(Expression *arg0) Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments) { assert(arguments && arguments->dim); - Expression *arg0 = arguments->tdata()[0]; + Expression *arg0 = (*arguments)[0]; Expression *e = NULL; switch (builtin) { diff --git a/dmd2/canthrow.c b/dmd2/canthrow.c index 885b241a..27992b08 100644 --- a/dmd2/canthrow.c +++ b/dmd2/canthrow.c @@ -42,6 +42,7 @@ struct CanThrow int Expression::canThrow(bool mustNotThrow) { + //printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars()); CanThrow ct; ct.can = FALSE; ct.mustnot = mustNotThrow; @@ -132,7 +133,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) { for (size_t i = 0; i < decl->dim; i++) { - s = decl->tdata()[i]; + s = (*decl)[i]; if (Dsymbol_canThrow(s, mustNotThrow)) return 1; } @@ -165,7 +166,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) { for (size_t i = 0; i < tm->members->dim; i++) { - Dsymbol *sm = tm->members->tdata()[i]; + Dsymbol *sm = (*tm->members)[i]; if (Dsymbol_canThrow(sm, mustNotThrow)) return 1; } @@ -174,7 +175,7 @@ int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow) else if ((td = s->isTupleDeclaration()) != NULL) { for (size_t i = 0; i < td->objects->dim; i++) - { Object *o = td->objects->tdata()[i]; + { Object *o = (*td->objects)[i]; if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *eo = (Expression *)o; if (eo->op == TOKdsymbol) diff --git a/dmd2/cast.c b/dmd2/cast.c index 7aaf2517..1d30d275 100644 --- a/dmd2/cast.c +++ b/dmd2/cast.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -9,6 +9,7 @@ #include #include +#include // mem{set|cpy}() #include "rmem.h" @@ -36,9 +37,10 @@ Expression *Expression::implicitCastTo(Scope *sc, Type *t) MATCH match = implicitConvTo(t); if (match) - { TY tyfrom = type->toBasetype()->ty; - TY tyto = t->toBasetype()->ty; + { #if DMDV1 + TY tyfrom = type->toBasetype()->ty; + TY tyto = t->toBasetype()->ty; if (global.params.warnings && Type::impcnvWarn[tyfrom][tyto] && op != TOKint64) @@ -138,7 +140,7 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t) Expression *FuncExp::implicitCastTo(Scope *sc, Type *t) { //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); - return inferType(t); + return inferType(t)->Expression::implicitCastTo(sc, t); } /******************************************* @@ -215,6 +217,7 @@ MATCH IntegerExp::implicitConvTo(Type *t) TY ty = type->toBasetype()->ty; TY toty = t->toBasetype()->ty; + TY oldty = ty; if (m == MATCHnomatch && t->ty == Tenum) goto Lno; @@ -282,6 +285,8 @@ MATCH IntegerExp::implicitConvTo(Type *t) goto Lyes; case Tchar: + if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F) + goto Lno; case Tuns8: //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); if ((unsigned char)value != value) @@ -293,6 +298,9 @@ MATCH IntegerExp::implicitConvTo(Type *t) goto Lno; goto Lyes; + case Twchar: + if (oldty == Tdchar && value > 0xD7FF && value < 0xE000) + goto Lno; case Tuns16: if ((unsigned short)value != value) goto Lno; @@ -319,11 +327,6 @@ MATCH IntegerExp::implicitConvTo(Type *t) goto Lno; goto Lyes; - case Twchar: - if ((unsigned short)value != value) - goto Lno; - goto Lyes; - case Tfloat32: { volatile float f; @@ -540,19 +543,28 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t) if ((tb->ty == Tarray || tb->ty == Tsarray) && (typeb->ty == Tarray || typeb->ty == Tsarray)) { + Type *typen = typeb->nextOf()->toBasetype(); + if (tb->ty == Tsarray) { TypeSArray *tsa = (TypeSArray *)tb; if (elements->dim != tsa->dim->toInteger()) result = MATCHnomatch; } - for (size_t i = 0; i < elements->dim; i++) - { Expression *e = (*elements)[i]; - MATCH m = (MATCH)e->implicitConvTo(tb->nextOf()); - if (m < result) - result = m; // remember worst match - if (result == MATCHnomatch) - break; // no need to check for worse + Type *telement = tb->nextOf(); + if (!elements->dim) + { if (typen->ty != Tvoid) + result = typen->implicitConvTo(telement); + } + else + { for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; + if (result == MATCHnomatch) + break; // no need to check for worse + MATCH m = (MATCH)e->implicitConvTo(telement); + if (m < result) + result = m; // remember worst match + } } if (!result) @@ -560,25 +572,46 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t) return result; } + else if (tb->ty == Tvector && + (typeb->ty == Tarray || typeb->ty == Tsarray)) + { + // Convert array literal to vector type + TypeVector *tv = (TypeVector *)tb; + TypeSArray *tbase = (TypeSArray *)tv->basetype; + assert(tbase->ty == Tsarray); + if (elements->dim != tbase->dim->toInteger()) + return MATCHnomatch; + + Type *telement = tv->elementType(); + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; + MATCH m = (MATCH)e->implicitConvTo(telement); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + } + return result; + } else return Expression::implicitConvTo(t); } MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) -{ MATCH result = MATCHexact; - +{ Type *typeb = type->toBasetype(); Type *tb = t->toBasetype(); if (tb->ty == Taarray && typeb->ty == Taarray) { + MATCH result = MATCHexact; for (size_t i = 0; i < keys->dim; i++) - { Expression *e = keys->tdata()[i]; + { Expression *e = (*keys)[i]; MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index); if (m < result) result = m; // remember worst match if (result == MATCHnomatch) break; // no need to check for worse - e = values->tdata()[i]; + e = (*values)[i]; m = (MATCH)e->implicitConvTo(tb->nextOf()); if (m < result) result = m; // remember worst match @@ -905,6 +938,9 @@ Expression *Expression::castTo(Scope *sc, Type *t) } else if (tb->ty == Tvector && typeb->ty != Tvector) { + //printf("test1 e = %s, e->type = %s, tb = %s\n", e->toChars(), e->type->toChars(), tb->toChars()); + TypeVector *tv = (TypeVector *)tb; + e = new CastExp(loc, e, tv->elementType()); e = new VectorExp(loc, e, tb); e = e->semantic(sc); return e; @@ -1372,9 +1408,9 @@ Expression *TupleExp::castTo(Scope *sc, Type *t) { TupleExp *e = (TupleExp *)copy(); e->exps = (Expressions *)exps->copy(); for (size_t i = 0; i < e->exps->dim; i++) - { Expression *ex = e->exps->tdata()[i]; + { Expression *ex = (*e->exps)[i]; ex = ex->castTo(sc, t); - e->exps->tdata()[i] = ex; + (*e->exps)[i] = ex; } return e; } @@ -1420,6 +1456,28 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) e->type = tp; } } + else if (tb->ty == Tvector && + (typeb->ty == Tarray || typeb->ty == Tsarray)) + { + // Convert array literal to vector type + TypeVector *tv = (TypeVector *)tb; + TypeSArray *tbase = (TypeSArray *)tv->basetype; + assert(tbase->ty == Tsarray); + if (elements->dim != tbase->dim->toInteger()) + goto L1; + + e = (ArrayLiteralExp *)copy(); + e->elements = (Expressions *)elements->copy(); + Type *telement = tv->elementType(); + for (size_t i = 0; i < elements->dim; i++) + { Expression *ex = (*elements)[i]; + ex = ex->castTo(sc, telement); + (*e->elements)[i] = ex; + } + Expression *ev = new VectorExp(loc, e, tb); + ev = ev->semantic(sc); + return ev; + } L1: return e->Expression::castTo(sc, t); } @@ -1439,13 +1497,13 @@ Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t) e->values = (Expressions *)values->copy(); assert(keys->dim == values->dim); for (size_t i = 0; i < keys->dim; i++) - { Expression *ex = values->tdata()[i]; + { Expression *ex = (*values)[i]; ex = ex->castTo(sc, tb->nextOf()); - e->values->tdata()[i] = ex; + (*e->values)[i] = ex; - ex = keys->tdata()[i]; + ex = (*keys)[i]; ex = ex->castTo(sc, ((TypeAArray *)tb)->index); - e->keys->tdata()[i] = ex; + (*e->keys)[i] = ex; } e->type = t; return e; @@ -1688,7 +1746,7 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) { if (to->ty == Tdelegate || to->ty == Tpointer && to->nextOf()->ty == Tfunction) - { treq = to; + { fd->treq = to; } return this; } @@ -1714,6 +1772,8 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) { TypeFunction *tfv = (TypeFunction *)t; TypeFunction *tfl = (TypeFunction *)fd->type; + //printf("\ttfv = %s\n", tfv->toChars()); + //printf("\ttfl = %s\n", tfl->toChars()); size_t dim = Parameter::dim(tfl->parameters); if (Parameter::dim(tfv->parameters) == dim && @@ -1740,6 +1800,13 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) } } + // Set target of return type inference + assert(td->onemember); + FuncLiteralDeclaration *fld = td->onemember->isFuncLiteralDeclaration(); + assert(fld); + if (!fld->type->nextOf() && tfv->next) + fld->treq = tfv; + TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); e = (new ScopeExp(loc, ti))->semantic(td->scope); if (e->op == TOKfunction) @@ -1759,14 +1826,12 @@ Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) to->ty == Tdelegate) { Type *typen = type->nextOf(); - assert(typen->deco); - //if (typen->covariant(to->nextOf()) == 1) + if (typen->deco) { FuncExp *fe = (FuncExp *)copy(); fe->tok = TOKdelegate; fe->type = (new TypeDelegate(typen))->merge(); e = fe; - //e = fe->Expression::implicitCastTo(sc, to); } } else @@ -1879,7 +1944,7 @@ bool isVoidArrayLiteral(Expression *e, Type *other) while (e->op == TOKarrayliteral && e->type->ty == Tarray && (((ArrayLiteralExp *)e)->elements->dim == 1)) { - e = ((ArrayLiteralExp *)e)->elements->tdata()[0]; + e = (*((ArrayLiteralExp *)e)->elements)[0]; if (other->ty == Tsarray || other->ty == Tarray) other = other->nextOf(); else @@ -1910,6 +1975,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars()); //e->dump(0); + MATCH m; Expression *e1 = *pe1; Expression *e2 = *pe2; @@ -2110,10 +2176,20 @@ Lagain: */ goto Lx2; } - else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) + else if ((t1->ty == Tsarray || t1->ty == Tarray) && + (m = t1->implicitConvTo(t2)) != MATCHnomatch) { if (t1->ty == Tsarray && e2->op == TOKarrayliteral) goto Lt1; + if (m == MATCHconst && + (e->op == TOKaddass || e->op == TOKminass || e->op == TOKmulass || + e->op == TOKdivass || e->op == TOKmodass || e->op == TOKpowass || + e->op == TOKandass || e->op == TOKorass || e->op == TOKxorass) + ) + { // Don't make the lvalue const + t = t2; + goto Lret; + } goto Lt2; } else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1)) diff --git a/dmd2/class.c b/dmd2/class.c index 25644248..6721e925 100644 --- a/dmd2/class.c +++ b/dmd2/class.c @@ -11,6 +11,7 @@ #include #include #include +#include // mem{cpy|set}() #include "root.h" #include "rmem.h" @@ -177,6 +178,12 @@ ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *basecla Type::typeinfowild->error("%s", msg); Type::typeinfowild = this; } + + if (id == Id::TypeInfo_Vector) + { if (Type::typeinfovector) + Type::typeinfovector->error("%s", msg); + Type::typeinfovector = this; + } #endif } @@ -241,9 +248,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) cd->baseclasses->setDim(this->baseclasses->dim); for (size_t i = 0; i < cd->baseclasses->dim; i++) { - BaseClass *b = this->baseclasses->tdata()[i]; + BaseClass *b = (*this->baseclasses)[i]; BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); - cd->baseclasses->tdata()[i] = b2; + (*cd->baseclasses)[i] = b2; } ScopeDsymbol::syntaxCopy(cd); @@ -292,10 +299,6 @@ void ClassDeclaration::semantic(Scope *sc) scope = NULL; } unsigned dprogress_save = Module::dprogress; -#ifdef IN_GCC - methods.setDim(0); -#endif - int errors = global.gaggedErrors; if (sc->stc & STCdeprecated) @@ -308,7 +311,7 @@ void ClassDeclaration::semantic(Scope *sc) // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = baseclasses->tdata()[i]; + { BaseClass *b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -333,7 +336,7 @@ void ClassDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = baseclasses->tdata()[0]; + b = (*baseclasses)[0]; //b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty != Tclass) @@ -403,7 +406,7 @@ void ClassDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = baseclasses->tdata()[i]; + b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -432,7 +435,7 @@ void ClassDeclaration::semantic(Scope *sc) // Check for duplicate interfaces for (size_t j = (baseClass ? 1 : 0); j < i; j++) { - BaseClass *b2 = baseclasses->tdata()[j]; + BaseClass *b2 = (*baseclasses)[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -464,22 +467,20 @@ void ClassDeclaration::semantic(Scope *sc) // If no base class, and this is not an Object, use Object as base class if (!baseClass && ident != Id::Object) { - // BUG: what if Object is redefined in an inner scope? - Type *tbase = new TypeIdentifier(0, Id::Object); - BaseClass *b; - TypeClass *tc; - Type *bt; - if (!object) { error("missing or corrupt object.d"); fatal(); } - bt = tbase->semantic(loc, sc)->toBasetype(); - b = new BaseClass(bt, PROTpublic); + + Type *t = object->type; + t = t->semantic(loc, sc)->toBasetype(); + assert(t->ty == Tclass); + TypeClass *tc = (TypeClass *)t; + + BaseClass *b = new BaseClass(tc, PROTpublic); baseclasses->shift(b); - assert(b->type->ty == Tclass); - tc = (TypeClass *)(b->type); + baseClass = tc->sym; assert(!baseClass->isInterfaceDeclaration()); b->base = baseClass; @@ -535,7 +536,9 @@ void ClassDeclaration::semantic(Scope *sc) isnested = 1; if (storage_class & STCstatic) error("static class cannot inherit from nested class %s", baseClass->toChars()); - if (toParent2() != baseClass->toParent2()) + if (toParent2() != baseClass->toParent2() && + (!toParent2() || + !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL))) { if (toParent2()) { @@ -614,8 +617,7 @@ void ClassDeclaration::semantic(Scope *sc) } sc->protection = PROTpublic; sc->explicitProtection = 0; - sc->structalign = 8; - structalign = sc->structalign; + sc->structalign = STRUCTALIGN_DEFAULT; if (baseClass) { sc->offset = baseClass->structsize; alignsize = baseClass->alignsize; @@ -642,9 +644,10 @@ void ClassDeclaration::semantic(Scope *sc) if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident) || s->isTemplateMixin() || + s->isAttribDeclaration() || s->isAliasDeclaration()) { - //printf("setScope %s %s\n", s->kind(), s->toChars()); + //printf("[%d] setScope %s %s, sc = %p\n", i, s->kind(), s->toChars(), sc); s->setScope(sc); } } @@ -682,7 +685,7 @@ void ClassDeclaration::semantic(Scope *sc) fields.setDim(0); structsize = 0; alignsize = 0; - structalign = 0; +// structalign = 0; sc = sc->pop(); @@ -757,7 +760,7 @@ void ClassDeclaration::semantic(Scope *sc) BaseClass *b = (*vtblInterfaces)[i]; unsigned thissize = PTRSIZE; - alignmember(structalign, thissize, &sc->offset); + alignmember(STRUCTALIGN_DEFAULT, thissize, &sc->offset); assert(b->offset == 0); b->offset = sc->offset; @@ -774,9 +777,12 @@ void ClassDeclaration::semantic(Scope *sc) } structsize = sc->offset; #if IN_LLVM - if (global.params.is64bit) - structsize = (structsize + structalign - 1) & ~(structalign - 1); + if (sc->structalign == STRUCTALIGN_DEFAULT) + structsize = (structsize + alignsize - 1) & ~(alignsize - 1); + else + structsize = (structsize + sc->structalign - 1) & ~(sc->structalign - 1); #endif + sizeok = SIZEOKdone; Module::dprogress++; @@ -788,7 +794,7 @@ void ClassDeclaration::semantic(Scope *sc) // Fill in base class vtbl[]s for (i = 0; i < vtblInterfaces->dim; i++) { - BaseClass *b = vtblInterfaces->tdata()[i]; + BaseClass *b = (*vtblInterfaces)[i]; //b->fillVtbl(this, &b->vtbl, 1); } @@ -813,7 +819,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } for (size_t i = 0; i < baseclasses->dim; i++) { - BaseClass *b = baseclasses->tdata()[i]; + BaseClass *b = (*baseclasses)[i]; if (i) buf->writeByte(','); @@ -827,7 +833,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -862,7 +868,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); for (size_t i = 0; i < cd->baseclasses->dim; i++) - { BaseClass *b = cd->baseclasses->tdata()[i]; + { BaseClass *b = (*cd->baseclasses)[i]; if (b->base == this || isBaseOf2(b->base)) return 1; @@ -908,7 +914,7 @@ int ClassDeclaration::isBaseInfoComplete() if (!baseClass) return ident == Id::Object; for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *b = baseclasses->tdata()[i]; + { BaseClass *b = (*baseclasses)[i]; if (!b->base || !b->base->isBaseInfoComplete()) return 0; } @@ -946,7 +952,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) for (size_t i = 0; i < baseclasses->dim; i++) { - BaseClass *b = baseclasses->tdata()[i]; + BaseClass *b = (*baseclasses)[i]; if (b->base) { @@ -1011,7 +1017,7 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) if (os) { for (size_t i = 0; i < os->a.dim; i++) - { Dsymbol *s2 = os->a.tdata()[i]; + { Dsymbol *s2 = os->a[i]; FuncDeclaration *f2 = s2->isFuncDeclaration(); if (f2 && overloadApply(f2, &isf, fd)) return 0; @@ -1054,9 +1060,11 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) //printf("\t[%d] = %s\n", i, fd->toChars()); if (ident == fd->ident && fd->type->covariant(tf) == 1) - { //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration()); + { //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration()); if (!fdmatch) goto Lfd; + if (fd == fdmatch) + goto Lfdmatch; { // Function type matcing: exact > covariant @@ -1068,6 +1076,15 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) goto Lfdmatch; } + { + int m1 = (tf->mod == fd ->type->mod) ? MATCHexact : MATCHnomatch; + int m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch; + if (m1 > m2) + goto Lfd; + else if (m1 < m2) + goto Lfdmatch; + } + { // The way of definition: non-mixin > mixin int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; @@ -1158,7 +1175,7 @@ int ClassDeclaration::isAbstract() return TRUE; for (size_t i = 1; i < vtbl.dim; i++) { - FuncDeclaration *fd = vtbl.tdata()[i]->isFuncDeclaration(); + FuncDeclaration *fd = vtbl[i]->isFuncDeclaration(); //printf("\tvtbl[%d] = %p\n", i, fd); if (!fd || fd->isAbstract()) @@ -1266,7 +1283,7 @@ void InterfaceDeclaration::semantic(Scope *sc) // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = (*baseclasses)[0]; + { BaseClass *b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -1294,7 +1311,7 @@ void InterfaceDeclaration::semantic(Scope *sc) BaseClass *b; Type *tb; - b = baseclasses->tdata()[i]; + b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) @@ -1312,7 +1329,7 @@ void InterfaceDeclaration::semantic(Scope *sc) // Check for duplicate interfaces for (size_t j = 0; j < i; j++) { - BaseClass *b2 = baseclasses->tdata()[j]; + BaseClass *b2 = (*baseclasses)[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } @@ -1373,7 +1390,7 @@ void InterfaceDeclaration::semantic(Scope *sc) { vtbl.reserve(d - 1); for (size_t j = 1; j < d; j++) - vtbl.push(b->base->vtbl.tdata()[j]); + vtbl.push(b->base->vtbl[j]); } } else @@ -1401,10 +1418,10 @@ void InterfaceDeclaration::semantic(Scope *sc) sc->linkage = LINKwindows; else if (isCPPinterface()) sc->linkage = LINKcpp; - sc->structalign = 8; + sc->structalign = STRUCTALIGN_DEFAULT; sc->protection = PROTpublic; sc->explicitProtection = 0; - structalign = sc->structalign; +// structalign = sc->structalign; sc->offset = PTRSIZE * 2; structsize = sc->offset; inuse++; @@ -1426,7 +1443,7 @@ void InterfaceDeclaration::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic(sc); } @@ -1526,7 +1543,7 @@ int InterfaceDeclaration::isBaseInfoComplete() { assert(!baseClass); for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *b = baseclasses->tdata()[i]; + { BaseClass *b = (*baseclasses)[i]; if (!b->base || !b->base->isBaseInfoComplete ()) return 0; } @@ -1610,7 +1627,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins // first entry is ClassInfo reference for (size_t j = base->vtblOffset(); j < base->vtbl.dim; j++) { - FuncDeclaration *ifd = base->vtbl.tdata()[j]->isFuncDeclaration(); + FuncDeclaration *ifd = base->vtbl[j]->isFuncDeclaration(); FuncDeclaration *fd; TypeFunction *tf; @@ -1647,7 +1664,7 @@ int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newins fd = NULL; } if (vtbl) - vtbl->tdata()[j] = fd; + (*vtbl)[j] = fd; } return result; diff --git a/dmd2/clone.c b/dmd2/clone.c index d0b22c40..bfd167ae 100644 --- a/dmd2/clone.c +++ b/dmd2/clone.c @@ -45,7 +45,7 @@ int StructDeclaration::needOpAssign() */ for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) @@ -153,7 +153,7 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) //printf("\tmemberwise copy\n"); for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); // this.v = s.v; @@ -214,7 +214,7 @@ int StructDeclaration::needOpEquals() */ for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) @@ -304,7 +304,7 @@ FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc) //printf("\tmemberwise compare\n"); for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) @@ -513,13 +513,13 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); - dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); + dinteger_t dim = 1; while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; dim *= ((TypeSArray *)tv)->dim->toInteger(); @@ -528,7 +528,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) if (tv->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tv; StructDeclaration *sd = ts->sym; - if (sd->postblit) + if (sd->postblit && dim) { stc |= sd->postblit->storage_class & STCdisable; @@ -542,7 +542,7 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) Expression *ex = new ThisExp(0); ex = new DotVarExp(0, ex, v, 0); - if (dim == 0) + if (v->type->toBasetype()->ty == Tstruct) { // this.v.postblit() ex = new DotVarExp(0, ex, sd->postblit, 0); ex = new CallExp(0, ex); @@ -581,12 +581,12 @@ FuncDeclaration *StructDeclaration::buildPostBlit(Scope *sc) return NULL; case 1: - return postblits.tdata()[0]; + return postblits[0]; default: e = NULL; for (size_t i = 0; i < postblits.dim; i++) - { FuncDeclaration *fd = postblits.tdata()[i]; + { FuncDeclaration *fd = postblits[i]; stc |= fd->storage_class & STCdisable; if (stc & STCdisable) { @@ -625,13 +625,13 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) #if DMDV2 for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); - dinteger_t dim = (tv->ty == Tsarray ? 1 : 0); + dinteger_t dim = 1; while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; dim *= ((TypeSArray *)tv)->dim->toInteger(); @@ -640,14 +640,14 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) if (tv->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tv; StructDeclaration *sd = ts->sym; - if (sd->dtor) + if (sd->dtor && dim) { Expression *ex; // this.v ex = new ThisExp(0); ex = new DotVarExp(0, ex, v, 0); - if (dim == 0) + if (v->type->toBasetype()->ty == Tstruct) { // this.v.dtor() ex = new DotVarExp(0, ex, sd->dtor, 0); ex = new CallExp(0, ex); @@ -686,12 +686,12 @@ FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc) return NULL; case 1: - return dtors.tdata()[0]; + return dtors[0]; default: e = NULL; for (size_t i = 0; i < dtors.dim; i++) - { FuncDeclaration *fd = dtors.tdata()[i]; + { FuncDeclaration *fd = dtors[i]; Expression *ex = new ThisExp(0); ex = new DotVarExp(0, ex, fd, 0); ex = new CallExp(0, ex); diff --git a/dmd2/cond.c b/dmd2/cond.c index afce513e..f54fd467 100644 --- a/dmd2/cond.c +++ b/dmd2/cond.c @@ -10,6 +10,7 @@ #include #include +#include // strcmp() #include "id.h" #include "init.h" @@ -266,7 +267,14 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) sc->flags |= SCOPEstaticif; Expression *e = exp->semantic(sc); sc->pop(); - e = e->optimize(WANTvalue | WANTinterpret); + if (!e->type->checkBoolean()) + { + if (e->type->toBasetype() != Type::terror) + exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars()); + inc = 0; + return 0; + } + e = e->ctfeInterpret(); --nest; if (e->op == TOKerror) { exp = e; diff --git a/dmd2/constfold.c b/dmd2/constfold.c index 0be4cb82..8ecd2b40 100644 --- a/dmd2/constfold.c +++ b/dmd2/constfold.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -11,6 +11,7 @@ #include #include #include +#include // mem{cpy|set|cmp}() #include #if __DMC__ @@ -621,7 +622,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) // Special case: call sqrt directly. Expressions args; args.setDim(1); - args.tdata()[0] = e1; + args[0] = e1; e = eval_builtin(loc, BUILTINsqrt, &args); if (!e) e = EXP_CANT_INTERPRET; @@ -1290,7 +1291,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1) assert(sd); Expressions *elements = new Expressions; for (size_t i = 0; i < sd->fields.dim; i++) - { Dsymbol *s = sd->fields.tdata()[i]; + { Dsymbol *s = sd->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); @@ -1374,7 +1375,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) } else if (e1->op == TOKarrayliteral) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; - e = ale->elements->tdata()[i]; + e = (*ale->elements)[i]; e->type = type; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; @@ -1392,7 +1393,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) e = new ErrorExp(); } else - { e = ale->elements->tdata()[i]; + { e = (*ale->elements)[i]; e->type = type; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; @@ -1407,12 +1408,12 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) for (size_t i = ae->keys->dim; i;) { i--; - Expression *ekey = ae->keys->tdata()[i]; + Expression *ekey = (*ae->keys)[i]; Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); if (ex == EXP_CANT_INTERPRET) return ex; if (ex->isBool(TRUE)) - { e = ae->values->tdata()[i]; + { e = (*ae->values)[i]; e->type = type; if (e->hasSideEffect()) e = EXP_CANT_INTERPRET; @@ -1483,7 +1484,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) elements->setDim(iupr - ilwr); memcpy(elements->tdata(), es1->elements->tdata() + ilwr, - (iupr - ilwr) * sizeof(es1->elements->tdata()[0])); + (iupr - ilwr) * sizeof((*es1->elements)[0])); e = new ArrayLiteralExp(e1->loc, elements); e->type = type; } @@ -1512,7 +1513,7 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n assert(0); break; } - existingAE->elements->tdata()[j+firstIndex] + (*existingAE->elements)[j+firstIndex] = new IntegerExp(newval->loc, val, elemType); } } @@ -1525,7 +1526,7 @@ void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *n unsigned char *s = (unsigned char *)existingSE->string; for (size_t j = 0; j < newae->elements->dim; j++) { - unsigned value = (unsigned)(newae->elements->tdata()[j]->toInteger()); + unsigned value = (unsigned)((*newae->elements)[j]->toInteger()); switch (existingSE->sz) { case 1: s[j+firstIndex] = value; break; @@ -1549,6 +1550,48 @@ void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int f memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len); } +/* Compare a string slice with another string slice. + * Conceptually equivalent to memcmp( se1[lo1..lo1+len], se2[lo2..lo2+len]) + */ +int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len) +{ + unsigned char *s1 = (unsigned char *)se1->string; + unsigned char *s2 = (unsigned char *)se2->string; + size_t sz = se1->sz; + assert(sz == se2->sz); + + return memcmp(s1 + sz * lo1, s2 + sz * lo2, sz * len); +} + +/* Compare a string slice with an array literal slice + * Conceptually equivalent to memcmp( se1[lo1..lo1+len], ae2[lo2..lo2+len]) + */ +int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len) +{ + unsigned char *s = (unsigned char *)se1->string; + size_t sz = se1->sz; + + int c = 0; + + for (size_t j = 0; j < len; j++) + { + unsigned value = (unsigned)((*ae2->elements)[j + lo2]->toInteger()); + unsigned svalue; + switch (sz) + { + case 1: svalue = s[j + lo1]; break; + case 2: svalue = ((unsigned short *)s)[j+lo1]; break; + case 4: svalue = ((unsigned *)s)[j + lo1]; break; + default: + assert(0); + } + int c = svalue - value; + if (c) + return c; + } + return 0; +} + /* Also return EXP_CANT_INTERPRET if this fails */ Expression *Cat(Type *type, Expression *e1, Expression *e2) @@ -1666,7 +1709,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) elems->setDim(len); for (size_t i= 0; i < ea->elements->dim; ++i) { - elems->tdata()[i] = ea->elements->tdata()[i]; + (*elems)[i] = (*ea->elements)[i]; } ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); dest->type = type; @@ -1684,7 +1727,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) elems->setDim(len); for (size_t i= 0; i < ea->elements->dim; ++i) { - elems->tdata()[es->len + i] = ea->elements->tdata()[i]; + (*elems)[es->len + i] = (*ea->elements)[i]; } ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems); dest->type = type; diff --git a/dmd2/cppmangle.c b/dmd2/cppmangle.c index 915bb23c..f29eaa83 100644 --- a/dmd2/cppmangle.c +++ b/dmd2/cppmangle.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2010 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -9,6 +9,7 @@ // See the included readme.txt for details. #include +#include #include #include "mars.h" @@ -69,7 +70,7 @@ int CppMangleState::substitute(OutBuffer *buf, void *p) { for (size_t i = 0; i < components.dim; i++) { - if (p == components.tdata()[i]) + if (p == components[i]) { /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ... */ @@ -88,7 +89,7 @@ int CppMangleState::exist(void *p) { for (size_t i = 0; i < components.dim; i++) { - if (p == components.tdata()[i]) + if (p == components[i]) { return 1; } @@ -160,7 +161,7 @@ char *cpp_mangle(Dsymbol *s) cms.components.setDim(0); OutBuffer buf; -#if MACHOBJ +#if TARGET_OSX buf.writestring("__Z"); #else buf.writestring("_Z"); @@ -417,7 +418,7 @@ void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *a if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Parameter *arg = arguments->tdata()[i]; + { Parameter *arg = (*arguments)[i]; Type *t = arg->type; if (arg->storageClass & (STCout | STCref)) t = t->referenceTo(); diff --git a/dmd2/declaration.c b/dmd2/declaration.c index 4da51432..23001ce8 100644 --- a/dmd2/declaration.c +++ b/dmd2/declaration.c @@ -122,6 +122,18 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t) } #endif +Dsymbol *Declaration::search(Loc loc, Identifier *ident, int flags) +{ + Dsymbol *s = Dsymbol::search(loc, ident, flags); + if (!s && type) + { + s = type->toDsymbol(NULL); + if (s) + s = s->search(loc, ident, flags); + } + return s; +} + /********************************* TupleDeclaration ****************************/ @@ -159,7 +171,7 @@ Type *TupleDeclaration::getType() /* It's only a type tuple if all the Object's are types */ for (size_t i = 0; i < objects->dim; i++) - { Object *o = objects->tdata()[i]; + { Object *o = (*objects)[i]; if (o->dyncast() != DYNCAST_TYPE) { @@ -176,7 +188,7 @@ Type *TupleDeclaration::getType() OutBuffer buf; int hasdeco = 1; for (size_t i = 0; i < types->dim; i++) - { Type *t = types->tdata()[i]; + { Type *t = (*types)[i]; //printf("type = %s\n", t->toChars()); #if 0 @@ -187,7 +199,7 @@ Type *TupleDeclaration::getType() #else Parameter *arg = new Parameter(0, t, NULL, NULL); #endif - args->tdata()[i] = arg; + (*args)[i] = arg; if (!t->deco) hasdeco = 0; } @@ -204,7 +216,7 @@ int TupleDeclaration::needThis() { //printf("TupleDeclaration::needThis(%s)\n", toChars()); for (size_t i = 0; i < objects->dim; i++) - { Object *o = objects->tdata()[i]; + { Object *o = (*objects)[i]; if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; if (e->op == TOKdsymbol) @@ -336,7 +348,7 @@ void TypedefDeclaration::semantic2(Scope *sc) { Initializer *savedinit = init; int errors = global.errors; - init = init->semantic(sc, basetype, WANTinterpret); + init = init->semantic(sc, basetype, INITinterpret); if (errors != global.errors) { init = savedinit; @@ -557,6 +569,17 @@ void AliasDeclaration::semantic(Scope *sc) s->parent = sc->parent; } } + OverloadSet *o = s->toAlias()->isOverloadSet(); + if (o) + { + if (overnext) + { + o->push(overnext); + overnext = NULL; + s = o; + s->parent = sc->parent; + } + } if (overnext) ScopeDsymbol::multiplyDefined(0, this, overnext); if (s == this) @@ -619,7 +642,9 @@ const char *AliasDeclaration::kind() Type *AliasDeclaration::getType() { - return type; + if (type) + return type; + return toAlias()->getType(); } Dsymbol *AliasDeclaration::toAlias() @@ -632,7 +657,9 @@ Dsymbol *AliasDeclaration::toAlias() aliassym = new AliasDeclaration(loc, ident, Type::terror); type = Type::terror; } - else if (!aliassym && scope) + else if (aliassym || type->deco) + ; // semantic is already done. + else if (scope) semantic(scope); Dsymbol *s = aliassym ? aliassym->toAlias() : this; return s; @@ -845,6 +872,14 @@ void VarDeclaration::semantic(Scope *sc) this->parent = sc->parent; //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); protection = sc->protection; + + /* If scope's alignment is the default, use the type's alignment, + * otherwise the scope overrrides. + */ + alignment = sc->structalign; + if (alignment == STRUCTALIGN_DEFAULT) + alignment = type->alignment(); // use type's alignment + //printf("sc->stc = %x\n", sc->stc); //printf("storage_class = x%x\n", storage_class); @@ -931,7 +966,7 @@ void VarDeclaration::semantic(Scope *sc) for (size_t pos = 0; pos < iexps->dim; pos++) { Lexpand1: - Expression *e = iexps->tdata()[pos]; + Expression *e = (*iexps)[pos]; Parameter *arg = Parameter::getNth(tt->arguments, pos); arg->type = arg->type->semantic(loc, sc); //printf("[%d] iexps->dim = %d, ", pos, iexps->dim); @@ -1028,7 +1063,7 @@ Lnomatch: Expression *einit = ie; if (ie && ie->op == TOKtuple) - { einit = ((TupleExp *)ie)->exps->tdata()[i]; + { einit = (*((TupleExp *)ie)->exps)[i]; } Initializer *ti = init; if (einit) @@ -1051,7 +1086,7 @@ Lnomatch: } #endif Expression *e = new DsymbolExp(loc, v); - exps->tdata()[i] = e; + (*exps)[i] = e; } TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); v2->isexp = 1; @@ -1091,7 +1126,7 @@ Lnomatch: } else if (storage_class & STCfinal) { - error("final cannot be applied to variable"); + error("final cannot be applied to variable, perhaps you meant const?"); } if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls | STCgshared | STCctfe)) @@ -1114,7 +1149,6 @@ Lnomatch: #endif { storage_class |= STCfield; - alignment = sc->structalign; #if DMDV2 if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor || tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor) @@ -1244,6 +1278,19 @@ Lnomatch: init = new ExpInitializer(loc, e); goto Ldtor; } + else if (type->ty == Tstruct && + (((TypeStruct *)type)->sym->isnested)) + { + /* Nested struct requires valid enclosing frame pointer. + * In StructLiteralExp::toElem(), it's calculated. + */ + Expression *e = type->defaultInitLiteral(loc); + Expression *e1 = new VarExp(loc, this); + e = new ConstructExp(loc, e1, e); + e = e->semantic(sc); + init = new ExpInitializer(loc, e); + goto Ldtor; + } else if (type->ty == Ttypedef) { TypeTypedef *td = (TypeTypedef *)type; if (td->sym->init) @@ -1313,7 +1360,8 @@ Lnomatch: Expression *e = init->toExpression(); if (!e) { - init = init->semantic(sc, type, 0); // Don't need to interpret + // Run semantic, but don't need to interpret + init = init->semantic(sc, type, INITnointerpret); e = init->toExpression(); if (!e) { error("is not a static and cannot have static initializer"); @@ -1395,16 +1443,26 @@ Lnomatch: { e = new ConstructExp(loc, new VarExp(loc, this), new IntegerExp(loc, 0, Type::tint32)); } + else if (sd->isNested()) + { e = new AssignExp(loc, new VarExp(loc, this), t->defaultInitLiteral(loc)); + e->op = TOKblit; + } else { e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc)); e->op = TOKblit; } e->type = t; - (*pinit) = new CommaExp(loc, e, (*pinit)); - /* Replace __ctmp being constructed with e1 + /* Replace __ctmp being constructed with e1. + * We need to copy constructor call expression, + * because it may be used in other place. */ - dve->e1 = e1; + DotVarExp *dvx = (DotVarExp *)dve->copy(); + dvx->e1 = e1; + CallExp *cx = (CallExp *)ce->copy(); + cx->e1 = dvx; + + (*pinit) = new CommaExp(loc, e, cx); (*pinit) = (*pinit)->semantic(sc); goto Ldtor; } @@ -1466,7 +1524,7 @@ Lnomatch: } else { - init = init->semantic(sc, type, WANTinterpret); + init = init->semantic(sc, type, INITinterpret); } } else if (storage_class & (STCconst | STCimmutable | STCmanifest) || @@ -1537,7 +1595,7 @@ Lnomatch: } else if (si || ai) { i2 = init->syntaxCopy(); - i2 = i2->semantic(sc, type, WANTinterpret); + i2 = i2->semantic(sc, type, INITinterpret); } inuse--; if (global.endGagging(errors)) // if errors happened @@ -1552,7 +1610,7 @@ Lnomatch: else if (ei) { if (isDataseg() || (storage_class & STCmanifest)) - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); else e = e->optimize(WANTvalue); switch (e->op) @@ -1639,7 +1697,7 @@ void VarDeclaration::semantic2(Scope *sc) printf("type = %p\n", ei->exp->type); } #endif - init = init->semantic(sc, type, WANTinterpret); + init = init->semantic(sc, type, INITinterpret); inuse--; } sem = Semantic2Done; @@ -1710,9 +1768,8 @@ void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, unsigned memsize = t->size(loc); // size of member unsigned memalignsize = t->alignsize(); // size of member for alignment purposes - unsigned memalign = t->memalign(alignment); // alignment boundaries - offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign, + offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, alignment, &ad->structsize, &ad->alignsize, isunion); //printf("\t%s: alignsize = %d\n", toChars(), alignsize); @@ -1831,28 +1888,8 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) // The current function FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); - if (fdv && fdthis && fdv != fdthis && fdthis->ident != Id::ensure && fdthis->ident != Id::require) + if (fdv && fdthis && fdv != fdthis) { - /* __ensure is always called directly, - * so it never becomes closure. - */ - - //printf("\tfdv = %s\n", fdv->toChars()); - //printf("\tfdthis = %s\n", fdthis->toChars()); - - if (loc.filename) - fdthis->getLevel(loc, sc, fdv); - - // Function literals from fdthis to fdv must be delegates - for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2()) - { - // function literal has reference to enclosing scope is delegate - if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration()) - { - fld->tok = TOKdelegate; - } - } - // Add fdthis to nestedrefs[] if not already there for (size_t i = 0; 1; i++) { @@ -1865,23 +1902,46 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) break; } - // Add this to fdv->closureVars[] if not already there - for (size_t i = 0; 1; i++) + if (fdthis->ident != Id::ensure) { - if (i == fdv->closureVars.dim) - { - fdv->closureVars.push(this); - break; - } - if (fdv->closureVars[i] == this) - break; - } + /* __ensure is always called directly, + * so it never becomes closure. + */ - //printf("fdthis is %s\n", fdthis->toChars()); - //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); - // __dollar creates problems because it isn't a real variable Bugzilla 3326 - if (ident == Id::dollar) - ::error(loc, "cannnot use $ inside a function literal"); + //printf("\tfdv = %s\n", fdv->toChars()); + //printf("\tfdthis = %s\n", fdthis->toChars()); + + if (loc.filename) + fdthis->getLevel(loc, sc, fdv); + + // Function literals from fdthis to fdv must be delegates + for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2()) + { + // function literal has reference to enclosing scope is delegate + if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration()) + { + fld->tok = TOKdelegate; + } + } + + // Add this to fdv->closureVars[] if not already there + for (size_t i = 0; 1; i++) + { + if (i == fdv->closureVars.dim) + { + fdv->closureVars.push(this); + break; + } + if (fdv->closureVars[i] == this) + break; + } + + //printf("fdthis is %s\n", fdthis->toChars()); + //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); + // __dollar creates problems because it isn't a real variable Bugzilla 3326 + if (ident == Id::dollar) + ::error(loc, "cannnot use $ inside a function literal"); + } } } } @@ -2353,7 +2413,7 @@ TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *t TypeInfoVectorDeclaration::TypeInfoVectorDeclaration(Type *tinfo) : TypeInfoDeclaration(tinfo, 0) { - if (!Type::typeinfoarray) + if (!Type::typeinfovector) { ObjectNotFound(Id::TypeInfo_Vector); } diff --git a/dmd2/declaration.h b/dmd2/declaration.h index 5a546f63..0da189f1 100644 --- a/dmd2/declaration.h +++ b/dmd2/declaration.h @@ -101,6 +101,12 @@ enum PURE; #define STCdisable 0x2000000000LL // for functions that are not callable #define STCresult 0x4000000000LL // for result variables passed to out contracts #define STCnodefaultctor 0x8000000000LL // must be set inside constructor +#define STCtemp 0x10000000000LL // temporary variable introduced by inlining + // and used only in backend process, so it's rvalue + +#ifdef BUG6652 +#define STCbug6652 0x800000000000LL // +#endif struct Match { @@ -136,7 +142,7 @@ struct Declaration : Dsymbol enum LINK linkage; int inuse; // used to detect cycles -#if IN_GCC +#ifdef IN_GCC Expressions *attributes; // GCC decl/type attributes #endif @@ -148,6 +154,8 @@ struct Declaration : Dsymbol unsigned size(Loc loc); void checkModify(Loc loc, Scope *sc, Type *t); + Dsymbol *search(Loc loc, Identifier *ident, int flags); + void emitComment(Scope *sc); void toJsonBuffer(OutBuffer *buf); void toDocBuffer(OutBuffer *buf); @@ -288,7 +296,7 @@ struct VarDeclaration : Declaration #else int nestedref; // referenced by a lexically nested function #endif - unsigned short alignment; + structalign_t alignment; int ctorinit; // it has been initialized in a ctor int onstack; // 1: it has been allocated on the stack // 2: on stack, run destructor anyway @@ -710,7 +718,7 @@ enum BUILTIN BUILTINbsr, // core.bitop.bsr BUILTINbsf, // core.bitop.bsf BUILTINbswap, // core.bitop.bswap -#if IN_GCC +#ifdef IN_GCC BUILTINgcc, // GCC builtin #endif }; @@ -738,12 +746,14 @@ struct FuncDeclaration : Declaration Identifier *outId; // identifier for out statement VarDeclaration *vresult; // variable corresponding to outId LabelDsymbol *returnLabel; // where the return goes + Scope *scout; // out contract scope for vresult->semantic DsymbolTable *localsymtab; // used to prevent symbols in different // scopes from having the same name VarDeclaration *vthis; // 'this' parameter (member and nested) VarDeclaration *v_arguments; // '_arguments' parameter -#if IN_GCC +#ifdef IN_GCC + VarDeclaration *v_arguments_var; // '_arguments' variable VarDeclaration *v_argptr; // '_argptr' variable #endif VarDeclaration *v_argsave; // save area for args passed in registers for variadic functions @@ -861,6 +871,7 @@ struct FuncDeclaration : Declaration void checkNestedReference(Scope *sc, Loc loc); int needsClosure(); int hasNestedFrameRefs(); + void buildResultVar(); Statement *mergeFrequire(Statement *, Expressions *params = 0); Statement *mergeFensure(Statement *, Expressions *params = 0); Parameters *getParameters(int *pvarargs); @@ -941,6 +952,7 @@ struct FuncAliasDeclaration : FuncDeclaration struct FuncLiteralDeclaration : FuncDeclaration { enum TOK tok; // TOKfunction or TOKdelegate + Type *treq; // target of return type inference FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, enum TOK tok, ForeachStatement *fes); diff --git a/dmd2/dmd_msc.vcproj b/dmd2/dmd_msc.vcproj index 94a9e4f9..1d27f7e3 100644 --- a/dmd2/dmd_msc.vcproj +++ b/dmd2/dmd_msc.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + - - - - + RelativePath=".\root\dmgcmem.c" > - - - - + RelativePath=".\root\man.c" > + + + + + + + + + + + + + + + + + + @@ -1656,7 +1718,7 @@ @@ -1667,7 +1729,7 @@ @@ -1678,7 +1740,7 @@ diff --git a/dmd2/doc.c b/dmd2/doc.c index 4d8f104d..e9631c42 100644 --- a/dmd2/doc.c +++ b/dmd2/doc.c @@ -19,6 +19,10 @@ #include "rmem.h" #include "root.h" +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ +#include "gnuc.h" +#endif + #include "mars.h" #include "dsymbol.h" #include "macro.h" @@ -77,7 +81,9 @@ struct DocComment Macro **pmacrotable; Escape **pescapetable; - DocComment(); + DocComment() : + summary(NULL), copyright(NULL), macros(NULL), pmacrotable(NULL), pescapetable(NULL) + { } static DocComment *parse(Scope *sc, Dsymbol *s, unsigned char *comment); static void parseMacros(Escape **pescapetable, Macro **pmacrotable, unsigned char *m, unsigned mlen); @@ -227,7 +233,7 @@ void Module::gendocfile() // Override with the ddoc macro files from the command line for (size_t i = 0; i < global.params.ddocfiles->dim; i++) { - FileName f(global.params.ddocfiles->tdata()[i], 0); + FileName f((*global.params.ddocfiles)[i], 0); File file(&f); file.readv(); // BUG: convert file contents to UTF-8 before use @@ -1014,11 +1020,6 @@ void EnumMember::toDocBuffer(OutBuffer *buf) /********************************* DocComment *********************************/ -DocComment::DocComment() -{ - memset(this, 0, sizeof(DocComment)); -} - DocComment *DocComment::parse(Scope *sc, Dsymbol *s, unsigned char *comment) { //printf("parse(%s): '%s'\n", s->toChars(), comment); @@ -1780,7 +1781,7 @@ void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset) int leadingBlank = 1; int inCode = 0; - int inComment = 0; // in comment + //int inComment = 0; // in comment unsigned iCodeStart; // start of code section unsigned iLineStart = offset; diff --git a/dmd2/dsymbol.c b/dmd2/dsymbol.c index 71efca43..fdc799ed 100644 --- a/dmd2/dsymbol.c +++ b/dmd2/dsymbol.c @@ -624,7 +624,7 @@ void Dsymbol::error(const char *format, ...) } va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(loc, format, ap, kind(), toPrettyChars()); va_end(ap); } @@ -632,41 +632,10 @@ void Dsymbol::error(Loc loc, const char *format, ...) { va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(loc, format, ap, kind(), toPrettyChars()); va_end(ap); } -void Dsymbol::verror(Loc loc, const char *format, va_list ap) -{ - if (!global.gag) - { - char *p = loc.toChars(); - if (!*p) - p = locToChars(); - - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); - - fprintf(stdmsg, "Error: "); - fprintf(stdmsg, "%s %s ", kind(), toPrettyChars()); - - vfprintf(stdmsg, format, ap); - - fprintf(stdmsg, "\n"); - fflush(stdmsg); -halt(); - } - else - { - global.gaggedErrors++; - } - - global.errors++; - - //fatal(); -} - void Dsymbol::checkDeprecated(Loc loc, Scope *sc) { if (!global.params.useDeprecated && isDeprecated()) @@ -903,7 +872,8 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags) s = s2; else if (s2 && s != s2) { - if (s->toAlias() == s2->toAlias()) + if (s->toAlias() == s2->toAlias() || + s->getType() == s2->getType() && s->getType()) { /* After following aliases, we found the same * symbol, so it's not an ambiguity. But if one @@ -1175,6 +1145,8 @@ int ScopeDsymbol::foreach(Scope *sc, Dsymbols *members, ScopeDsymbol::ForeachDg result = foreach(sc, tm->members, dg, ctx, &n); else if (s->isTemplateInstance()) ; + else if (s->isUnitTestDeclaration()) + ; else result = dg(ctx, n++, s); @@ -1423,6 +1395,7 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) VoidInitializer *e = new VoidInitializer(0); e->type = Type::tsize_t; v->init = e; + v->storage_class |= STCctfe; // it's never a true static variable } *pvar = v; } diff --git a/dmd2/dsymbol.h b/dmd2/dsymbol.h index 850b880a..47f97f2a 100644 --- a/dmd2/dsymbol.h +++ b/dmd2/dsymbol.h @@ -90,7 +90,7 @@ struct TypeInfoDeclaration; struct ClassInfoDeclaration; #endif -#if IN_GCC +#ifdef IN_GCC union tree_node; typedef union tree_node TYPE; #else @@ -158,7 +158,6 @@ struct Dsymbol : Object int isAnonymous(); void error(Loc loc, const char *format, ...) IS_PRINTF(3); void error(const char *format, ...) IS_PRINTF(2); - void verror(Loc loc, const char *format, va_list ap); void checkDeprecated(Loc loc, Scope *sc); Module *getModule(); // module where declared Module *getAccessModule(); diff --git a/dmd2/dump.c b/dmd2/dump.c index c9e4f5ff..e0d43186 100644 --- a/dmd2/dump.c +++ b/dmd2/dump.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -36,7 +36,7 @@ void dumpExpressions(int i, Expressions *exps) if (exps) { for (size_t j = 0; j < exps->dim; j++) - { Expression *e = exps->tdata()[j]; + { Expression *e = (*exps)[j]; indent(i); printf("(\n"); e->dump(i + 2); diff --git a/dmd2/enum.c b/dmd2/enum.c index a09a7e93..93fc79c4 100644 --- a/dmd2/enum.c +++ b/dmd2/enum.c @@ -185,11 +185,11 @@ void EnumDeclaration::semantic(Scope *sc) { assert(e->dyncast() == DYNCAST_EXPRESSION); e = e->semantic(sce); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (memtype) { e = e->implicitCastTo(sce, memtype); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (!isAnonymous()) e = e->castTo(sce, type); t = memtype; @@ -197,7 +197,7 @@ void EnumDeclaration::semantic(Scope *sc) else if (em->type) { e = e->implicitCastTo(sce, em->type); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); assert(isAnonymous()); t = e->type; } @@ -214,7 +214,7 @@ void EnumDeclaration::semantic(Scope *sc) t = Type::tint32; e = new IntegerExp(em->loc, 0, Type::tint32); e = e->implicitCastTo(sce, t); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (!isAnonymous()) e = e->castTo(sce, type); } @@ -225,7 +225,7 @@ void EnumDeclaration::semantic(Scope *sc) { emax = t->getProperty(0, Id::max); emax = emax->semantic(sce); - emax = emax->optimize(WANTvalue | WANTinterpret); + emax = emax->ctfeInterpret(); } // Set value to (elast + 1). @@ -233,7 +233,7 @@ void EnumDeclaration::semantic(Scope *sc) assert(elast); e = new EqualExp(TOKequal, em->loc, elast, emax); e = e->semantic(sce); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (e->toInteger()) error("overflow of enum value %s", elast->toChars()); @@ -241,14 +241,14 @@ void EnumDeclaration::semantic(Scope *sc) e = new AddExp(em->loc, elast, new IntegerExp(em->loc, 1, Type::tint32)); e = e->semantic(sce); e = e->castTo(sce, elast->type); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (t->isfloating()) { // Check that e != elast (not always true for floats) Expression *etest = new EqualExp(TOKequal, em->loc, e, elast); etest = etest->semantic(sce); - etest = etest->optimize(WANTvalue | WANTinterpret); + etest = etest->ctfeInterpret(); if (etest->toInteger()) error("enum member %s has inexact value, due to loss of precision", em->toChars()); } @@ -298,13 +298,13 @@ void EnumDeclaration::semantic(Scope *sc) // Compute if(e < minval) ec = new CmpExp(TOKlt, em->loc, e, minval); ec = ec->semantic(sce); - ec = ec->optimize(WANTvalue | WANTinterpret); + ec = ec->ctfeInterpret(); if (ec->toInteger()) minval = e; ec = new CmpExp(TOKgt, em->loc, e, maxval); ec = ec->semantic(sce); - ec = ec->optimize(WANTvalue | WANTinterpret); + ec = ec->ctfeInterpret(); if (ec->toInteger()) maxval = e; } diff --git a/dmd2/enum.h b/dmd2/enum.h index c13d90ca..1c7d5e9d 100644 --- a/dmd2/enum.h +++ b/dmd2/enum.h @@ -42,7 +42,7 @@ struct EnumDeclaration : ScopeDsymbol int isdeprecated; int isdone; // 0: not done // 1: semantic() successfully completed -#if IN_GCC +#ifdef IN_GCC Expressions *attributes; // GCC decl/type attributes #endif diff --git a/dmd2/expression.c b/dmd2/expression.c index 6fd1d480..c898cdb9 100644 --- a/dmd2/expression.c +++ b/dmd2/expression.c @@ -1,4 +1,3 @@ - // Compiler implementation of the D programming language // Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved @@ -116,6 +115,7 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, e1 = new DotVarExp(loc, e1, tcd->vthis); e1->type = tcd->vthis->type; + e1->type = e1->type->addMod(t->mod); // Do not call checkNestedRef() //e1 = e1->semantic(sc); @@ -151,6 +151,7 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, } if (s && s->isClassDeclaration()) { e1->type = s->isClassDeclaration()->type; + e1->type = e1->type->addMod(t->mod); if (n > 1) e1 = e1->semantic(sc); } @@ -570,14 +571,14 @@ int expandAliasThisTuples(Expressions *exps, int starti) for (size_t u = starti; u < exps->dim; u++) { - Expression *exp = exps->tdata()[u]; + Expression *exp = (*exps)[u]; TupleDeclaration *td = isAliasThisTuple(exp); if (td) { exps->remove(u); for (size_t i = 0; iobjects->dim; ++i) { - Expression *e = isExpression(td->objects->tdata()[i]); + Expression *e = isExpression((*td->objects)[i]); assert(e); assert(e->op == TOKdsymbol); DsymbolExp *se = (DsymbolExp *)e; @@ -592,7 +593,7 @@ int expandAliasThisTuples(Expressions *exps, int starti) printf("expansion ->\n"); for (size_t i = 0; idim; ++i) { - Expression *e = exps->tdata()[i]; + Expression *e = (*exps)[i]; printf("\texps[%d] e = %s %s\n", i, Token::tochars[e->op], e->toChars()); } #endif @@ -738,6 +739,12 @@ void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps) { Expression *arg = (*exps)[i]; arg = resolveProperties(sc, arg); +#if 0 + if (arg->op == TOKtype) + { arg->error("%s is not an expression", arg->toChars()); + arg = new ErrorExp(); + } +#endif (*exps)[i] = arg; //arg->rvalue(); @@ -794,24 +801,41 @@ void valueNoDtor(Expression *e) #if DMDV2 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) { - Type *tb = e->type->toBasetype(); - assert(tb->ty == Tstruct); - StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->cpctor) + if (e->op == TOKarrayliteral) { - /* Create a variable tmp, and replace the argument e with: - * (tmp = e),tmp - * and let AssignExp() handle the construction. - * This is not the most efficent, ideally tmp would be constructed - * directly onto the stack. - */ - Identifier *idtmp = Lexer::uniqueId("__cpcttmp"); - VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); - tmp->storage_class |= STCctfe; - tmp->noscope = noscope; - Expression *ae = new DeclarationExp(loc, tmp); - e = new CommaExp(loc, ae, new VarExp(loc, tmp)); - e = e->semantic(sc); + ArrayLiteralExp *ae = (ArrayLiteralExp *)e; + for (size_t i = 0; i < ae->elements->dim; i++) + { + ae->elements->tdata()[i] = + callCpCtor(loc, sc, ae->elements->tdata()[i], noscope); + } + e = ae->semantic(sc); + return e; + } + + Type *tb = e->type->toBasetype(); + Type *tv = tb; + while (tv->ty == Tsarray) + tv = tv->nextOf()->toBasetype(); + if (tv->ty == Tstruct) + { + StructDeclaration *sd = ((TypeStruct *)tv)->sym; + if (sd->cpctor) + { + /* Create a variable tmp, and replace the argument e with: + * (tmp = e),tmp + * and let AssignExp() handle the construction. + * This is not the most efficent, ideally tmp would be constructed + * directly onto the stack. + */ + Identifier *idtmp = Lexer::uniqueId("__cpcttmp"); + VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); + tmp->storage_class |= STCctfe; + tmp->noscope = noscope; + Expression *ae = new DeclarationExp(loc, tmp); + e = new CommaExp(loc, ae, new VarExp(loc, tmp)); + e = e->semantic(sc); + } } return e; } @@ -825,6 +849,8 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) * 3. do default promotions on arguments corresponding to ... * 4. add hidden _arguments[] argument * 5. call copy constructor for struct value arguments + * Input: + * fd the function being called, NULL if called indirectly * Returns: * return type from function */ @@ -877,7 +903,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expression *arg; if (i < nargs) - arg = arguments->tdata()[i]; + arg = (*arguments)[i]; else arg = NULL; @@ -887,7 +913,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, if (!arg) { - if (!p->defaultArg) + if (!p->defaultArg || !fd) { if (tf->varargs == 2 && i + 1 == nparams) goto L2; @@ -908,7 +934,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, if (tf->varargs == 2 && i + 1 == nparams && pt->nextOf()) pt = pt->nextOf(); arg = arg->inferType(pt, 2); - arguments->tdata()[i] = arg; + (*arguments)[i] = arg; } if (tf->varargs == 2 && i + 1 == nparams) @@ -958,7 +984,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, c->type = v->type; for (size_t u = i; u < nargs; u++) - { Expression *a = arguments->tdata()[u]; + { Expression *a = (*arguments)[u]; if (tret && !((TypeArray *)tb)->next->equals(a->type)) a = a->toDelegate(sc, tret); @@ -982,7 +1008,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *args = new Expressions(); args->setDim(nargs - i); for (size_t u = i; u < nargs; u++) - args->tdata()[u - i] = arguments->tdata()[u]; + (*args)[u - i] = (*arguments)[u]; arg = new NewExp(loc, NULL, NULL, p->type, args); break; } @@ -996,7 +1022,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arg = arg->semantic(sc); //printf("\targ = '%s'\n", arg->toChars()); arguments->setDim(i + 1); - arguments->tdata()[i] = arg; + (*arguments)[i] = arg; nargs = i + 1; done = 1; } @@ -1032,7 +1058,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, assert(nargs >= nparams); for (size_t i = 0; i < nargs; i++) { - Expression *arg = arguments->tdata()[i]; + Expression *arg = (*arguments)[i]; assert(arg); if (i < nparams) @@ -1097,45 +1123,50 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, { arg = arg->modifiableLvalue(sc, arg); } - - Type *tb = arg->type->toBasetype(); -// LDC we don't want this! -#if !IN_LLVM -#if !SARRAYVALUE - // Convert static arrays to pointers - if (tb->ty == Tsarray) - { - arg = arg->checkToPointer(); + else if (p->storageClass & STClazy) + { // Convert lazy argument to a delegate + arg = arg->toDelegate(sc, p->type); } -#endif -#endif -#if DMDV2 - if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) + else { - if (arg->op == TOKcall) + Type *tb = arg->type->toBasetype(); + if (arg->op == TOKarrayliteral) { - /* The struct value returned from the function is transferred - * to the function, so the callee should not call the destructor - * on it. - */ - valueNoDtor(arg); - } - else - { /* Not transferring it, so call the copy constructor - */ arg = callCpCtor(loc, sc, arg, 1); } - } + else if (tb->ty == Tsarray) + { +#if !SARRAYVALUE && !IN_LLVM + // Convert static arrays to pointers + arg = arg->checkToPointer(); +#else + // call copy constructor of each element + arg = callCpCtor(loc, sc, arg, 1); #endif + } +#if DMDV2 + else if (tb->ty == Tstruct) + { + if (arg->op == TOKcall && !arg->isLvalue()) + { + /* The struct value returned from the function is transferred + * to the function, so the callee should not call the destructor + * on it. + */ + valueNoDtor(arg); + } + else + { /* Not transferring it, so call the copy constructor + */ + arg = callCpCtor(loc, sc, arg, 1); + } + } +#endif + } //printf("arg: %s\n", arg->toChars()); //printf("type: %s\n", arg->type->toChars()); - // Convert lazy argument to a delegate - if (p->storageClass & STClazy) - { - arg = arg->toDelegate(sc, p->type); - } #if DMDV2 /* Look for arguments that cannot 'escape' from the called * function. @@ -1253,7 +1284,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, } arg = arg->optimize(WANTvalue); L3: - arguments->tdata()[i] = arg; + (*arguments)[i] = arg; } #if !IN_LLVM @@ -1434,13 +1465,16 @@ void Expression::print() } char *Expression::toChars() -{ OutBuffer *buf; +{ HdrGenState hgs; - memset(&hgs, 0, sizeof(hgs)); - buf = new OutBuffer(); - toCBuffer(buf, &hgs); - return buf->toChars(); + + OutBuffer buf; + toCBuffer(&buf, &hgs); + buf.writeByte(0); + char *p = (char *)buf.data; + buf.data = NULL; + return p; } void Expression::error(const char *format, ...) @@ -1548,12 +1582,12 @@ void Expression::toMangleBuffer(OutBuffer *buf) /*************************************** * Return !=0 if expression is an lvalue. */ -#if DMDV2 + int Expression::isLvalue() { return 0; } -#endif + /******************************* * Give error if we're not an lvalue. @@ -1934,7 +1968,7 @@ Expressions *Expression::arraySyntaxCopy(Expressions *exps) if (e) e = e->syntaxCopy(); - a->tdata()[i] = e; + (*a)[i] = e; } } return a; @@ -2814,12 +2848,12 @@ void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(ident->toChars()); } -#if DMDV2 + int IdentifierExp::isLvalue() { return 1; } -#endif + Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) { @@ -2854,7 +2888,7 @@ AggregateDeclaration *isAggregate(Type *t); Expression *DsymbolExp::semantic(Scope *sc) { #if LOGSEMANTIC - printf("DsymbolExp::semantic('%s')\n", s->toChars()); + printf("DsymbolExp::semantic(%s %s)\n", s->kind(), s->toChars()); #endif Lagain: @@ -2872,7 +2906,7 @@ Lagain: //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); - if (type) + if (type && !s->needThis()) return this; if (!s->isFuncDeclaration()) // functions are checked after overloading checkDeprecated(sc, s); @@ -3038,6 +3072,24 @@ 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; @@ -3050,6 +3102,8 @@ Lagain: s = ti->toAlias(); if (!s->isTemplateInstance()) goto Lagain; + if (ti->errors) + return new ErrorExp(); e = new ScopeExp(loc, ti); e = e->semantic(sc); return e; @@ -3085,12 +3139,12 @@ void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring(s->toChars()); } -#if DMDV2 + int DsymbolExp::isLvalue() { return 1; } -#endif + Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) { @@ -3187,12 +3241,12 @@ void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("this"); } -#if DMDV2 + int ThisExp::isLvalue() { return 1; } -#endif + Expression *ThisExp::toLvalue(Scope *sc, Expression *e) { @@ -3404,20 +3458,6 @@ int StringExp::equals(Object *o) return FALSE; } -char *StringExp::toChars() -{ - OutBuffer buf; - HdrGenState hgs; - char *p; - - memset(&hgs, 0, sizeof(hgs)); - toCBuffer(&buf, &hgs); - buf.writeByte(0); - p = (char *)buf.data; - buf.data = NULL; - return p; -} - Expression *StringExp::semantic(Scope *sc) { #if LOGSEMANTIC @@ -3625,7 +3665,7 @@ int StringExp::isBool(int result) return result ? TRUE : FALSE; } -#if DMDV2 + int StringExp::isLvalue() { /* string literal is rvalue in default, but @@ -3633,7 +3673,7 @@ int StringExp::isLvalue() */ return 0; } -#endif + Expression *StringExp::toLvalue(Scope *sc, Expression *e) { @@ -3783,6 +3823,7 @@ ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) { elements = new Expressions; elements->push(e); + this->ownedByCtfe = false; } Expression *ArrayLiteralExp::syntaxCopy() @@ -3838,10 +3879,10 @@ StringExp *ArrayLiteralExp::toString() if (elements) for (int i = 0; i < elements->dim; ++i) { - Expression *ch = elements->tdata()[i]; + Expression *ch = (*elements)[i]; if (ch->op != TOKint64) return NULL; - buf.writedchar(ch->toInteger()); + buf.writeUTF8(ch->toInteger()); } buf.writebyte(0); @@ -3849,7 +3890,8 @@ StringExp *ArrayLiteralExp::toString() if (telem == Twchar) prefix = 'w'; else if (telem == Tdchar) prefix = 'd'; - StringExp *se = new StringExp(loc, buf.extractData(), buf.size - 1, prefix); + const size_t len = buf.offset - 1; + StringExp *se = new StringExp(loc, buf.extractData(), len, prefix); se->type = type; return se; } @@ -3868,7 +3910,7 @@ void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) size_t dim = elements ? elements->dim : 0; buf->printf("A%zu", dim); for (size_t i = 0; i < dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; e->toMangleBuffer(buf); } } @@ -3937,8 +3979,8 @@ void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writeByte('['); for (size_t i = 0; i < keys->dim; i++) - { Expression *key = keys->tdata()[i]; - Expression *value = values->tdata()[i]; + { Expression *key = (*keys)[i]; + Expression *value = (*values)[i]; if (i) buf->writeByte(','); @@ -3954,8 +3996,8 @@ void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) size_t dim = keys->dim; buf->printf("A%zu", dim); for (size_t i = 0; i < dim; i++) - { Expression *key = keys->tdata()[i]; - Expression *value = values->tdata()[i]; + { Expression *key = (*keys)[i]; + Expression *value = (*values)[i]; key->toMangleBuffer(buf); value->toMangleBuffer(buf); @@ -4008,7 +4050,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) expandTuples(elements); size_t offset = 0; for (size_t i = 0; i < elements->dim; i++) - { e = elements->tdata()[i]; + { e = (*elements)[i]; if (!e) continue; @@ -4022,7 +4064,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) error("more initializers than fields (%d) of %s", nfields, sd->toChars()); return new ErrorExp(); } - Dsymbol *s = sd->fields.tdata()[i]; + Dsymbol *s = sd->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); if (v->offset < offset) @@ -4043,13 +4085,13 @@ Expression *StructLiteralExp::semantic(Scope *sc) e = e->implicitCastTo(sc, telem); - elements->tdata()[i] = e; + (*elements)[i] = e; } /* Fill out remainder of elements[] with default initializers for fields[] */ for (size_t i = elements->dim; i < nfields; i++) - { Dsymbol *s = sd->fields.tdata()[i]; + { Dsymbol *s = sd->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); assert(!v->isThisDeclaration()); @@ -4072,7 +4114,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) else if (v->scope) { // Do deferred semantic analysis Initializer *i2 = v->init->syntaxCopy(); - i2 = i2->semantic(v->scope, v->type, WANTinterpret); + 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. @@ -4124,7 +4166,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset) { //printf("\ti = %d\n", i); assert(i < elements->dim); - e = elements->tdata()[i]; + e = (*elements)[i]; if (e) { //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars()); @@ -4138,7 +4180,7 @@ Expression *StructLiteralExp::getField(Type *type, unsigned offset) Expressions *z = new Expressions; z->setDim(length); for (int q = 0; q < length; ++q) - z->tdata()[q] = e->copy(); + (*z)[q] = e->copy(); e = new ArrayLiteralExp(loc, z); e->type = type; } @@ -4165,13 +4207,13 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) { for (size_t i = 0; i < sd->fields.dim; i++) { - Dsymbol *s = sd->fields.tdata()[i]; + Dsymbol *s = sd->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); if (offset == v->offset && type->size() == v->type->size()) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; if (e) { return i; @@ -4196,7 +4238,7 @@ void StructLiteralExp::toMangleBuffer(OutBuffer *buf) size_t dim = elements ? elements->dim : 0; buf->printf("S%zu", dim); for (size_t i = 0; i < dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; if (e) e->toMangleBuffer(buf); else @@ -4239,8 +4281,32 @@ Expression *TypeExp::syntaxCopy() Expression *TypeExp::semantic(Scope *sc) { //printf("TypeExp::semantic(%s)\n", type->toChars()); - type = type->semantic(loc, sc); - return this; + Expression *e; + Type *t; + Dsymbol *s; + + type->resolve(loc, sc, &e, &t, &s); + if (e) + { + //printf("e = %s %s\n", Token::toChars(e->op), e->toChars()); + e = e->semantic(sc); + } + else if (t) + { + //printf("t = %d %s\n", t->ty, t->toChars()); + type = t->semantic(loc, sc); + e = this; + } + else if (s) + { + //printf("s = %s %s\n", s->kind(), s->toChars()); + e = new DsymbolExp(loc, s, s->hasOverloads()); + e = e->semantic(sc); + } + else + assert(0); + + return e; } int TypeExp::rvalue() @@ -4289,6 +4355,8 @@ Lagain: ti->semantic(sc); if (ti->inst) { + if (ti->inst->errors) + return new ErrorExp(); Dsymbol *s = ti->inst->toAlias(); sds2 = s->isScopeDsymbol(); if (!sds2) @@ -4302,7 +4370,7 @@ Lagain: e = new DotVarExp(loc, e, s->isDeclaration()); } else - e = new DsymbolExp(loc, s); + e = new DsymbolExp(loc, s, s->hasOverloads()); e = e->semantic(sc); //printf("-1ScopeExp::semantic()\n"); return e; @@ -4425,6 +4493,13 @@ Lagain: sc = sc->push(cdthis); type = newtype->semantic(loc, sc); sc = sc->pop(); + + if (!MODimplicitConv(thisexp->type->mod, newtype->mod)) + { + error("nested type %s should have the same or weaker constancy as enclosing type %s", + newtype->toChars(), thisexp->type->toChars()); + goto Lerr; + } } else { @@ -4459,7 +4534,7 @@ Lagain: else if (cd->isAbstract()) { error("cannot create instance of abstract class %s", cd->toChars()); for (size_t i = 0; i < cd->vtbl.dim; i++) - { FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration(); + { FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration(); if (fd && fd->isAbstract()) error("function %s is abstract", fd->toChars()); } @@ -4712,7 +4787,7 @@ Lagain: goto Lerr; } - Expression *arg = arguments->tdata()[i]; + Expression *arg = (*arguments)[i]; arg = resolveProperties(sc, arg); arg = arg->implicitCastTo(sc, Type::tsize_t); arg = arg->optimize(WANTvalue); @@ -4720,7 +4795,7 @@ Lagain: { error("negative array index %s", arg->toChars()); goto Lerr; } - arguments->tdata()[i] = arg; + (*arguments)[i] = arg; tb = ((TypeDArray *)tb)->next->toBasetype(); } } @@ -5018,14 +5093,14 @@ void VarExp::checkEscapeRef() } } -#if DMDV2 + int VarExp::isLvalue() { - if (var->storage_class & STClazy) + if (var->storage_class & (STClazy | STCtemp)) return 0; return 1; } -#endif + Expression *VarExp::toLvalue(Scope *sc, Expression *e) { @@ -5049,6 +5124,16 @@ Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) //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) && global.params.warnings) + warning("Variable modified in foreach body requires ref storage class"); +#elif (BUG6652 == 2) + VarDeclaration *v = var->isVarDeclaration(); + if (v && (v->storage_class & STCbug6652) && !global.params.useDeprecated) + error("Variable modified in foreach body requires ref storage class"); +#endif + var->checkModify(loc, sc, type); // See if this expression is a modifiable lvalue (i.e. not const) @@ -5098,7 +5183,7 @@ TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) exps->reserve(tup->objects->dim); for (size_t i = 0; i < tup->objects->dim; i++) - { Object *o = tup->objects->tdata()[i]; + { Object *o = (*tup->objects)[i]; if (o->dyncast() == DYNCAST_EXPRESSION) { Expression *e = (Expression *)o; @@ -5202,7 +5287,6 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td) this->fd = fd; this->td = td; tok = fd->tok; // save original kind of function/delegate/(infer) - treq = NULL; } Expression *FuncExp::syntaxCopy() @@ -5215,36 +5299,41 @@ Expression *FuncExp::semantic(Scope *sc) { #if LOGSEMANTIC printf("FuncExp::semantic(%s)\n", toChars()); - if (treq) printf(" treq = %s\n", treq->toChars()); + if (fd->treq) printf(" treq = %s\n", fd->treq->toChars()); #endif if (!type || type == Type::tvoid) { - if (treq) - treq = treq->semantic(loc, sc); + /* fd->treq might be incomplete type, + * so should not semantic it. + * void foo(T)(T delegate(int) dg){} + * foo(a=>a); // in IFTI, treq == T delegate(int) + */ + //if (fd->treq) + // fd->treq = fd->treq->semantic(loc, sc); // Set target of return type inference - if (treq && !fd->type->nextOf()) + if (fd->treq && !fd->type->nextOf()) { TypeFunction *tfv = NULL; - if (treq->ty == Tdelegate || - (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)) - tfv = (TypeFunction *)treq->nextOf(); + if (fd->treq->ty == Tdelegate || + (fd->treq->ty == Tpointer && fd->treq->nextOf()->ty == Tfunction)) + tfv = (TypeFunction *)fd->treq->nextOf(); if (tfv) { TypeFunction *tfl = (TypeFunction *)fd->type; tfl->next = tfv->nextOf(); } } - //printf("td = %p, treq = %p\n", td, treq); + //printf("td = %p, treq = %p\n", td, fd->treq); if (td) { assert(td->parameters && td->parameters->dim); td->semantic(sc); type = Type::tvoid; // temporary type - if (!treq) // defer type determination + if (!fd->treq) // defer type determination return this; - return inferType(treq); + return inferType(fd->treq); } unsigned olderrors = global.errors; @@ -5273,14 +5362,32 @@ Expression *FuncExp::semantic(Scope *sc) // Type is a "delegate to" or "pointer to" the function literal if ((fd->isNested() && fd->tok == TOKdelegate) || - (tok == TOKreserved && treq && treq->ty == Tdelegate)) + (tok == TOKreserved && fd->treq && fd->treq->ty == Tdelegate)) { type = new TypeDelegate(fd->type); type = type->semantic(loc, sc); + + fd->tok = TOKdelegate; } else { - type = fd->type->pointerTo(); + type = new TypePointer(fd->type); + type = type->semantic(loc, sc); + //type = fd->type->pointerTo(); + + /* A lambda expression deduced to function pointer might become + * to a delegate literal implicitly. + * + * auto foo(void function() fp) { return 1; } + * assert(foo({}) == 1); + * + * So, should keep fd->tok == TOKreserve if fd->treq == NULL. + */ + if (fd->treq && fd->treq->ty == Tpointer) + { // change to non-nested + fd->tok = TOKfunction; + fd->vthis = NULL; + } } fd->tookAddressOf++; } @@ -5293,7 +5400,7 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) if ((!type || type == Type::tvoid) && td && arguments && arguments->dim) { for (size_t k = 0; k < arguments->dim; k++) - { Expression *checkarg = arguments->tdata()[k]; + { Expression *checkarg = (*arguments)[k]; if (checkarg->op == TOKerror) return checkarg; } @@ -5303,6 +5410,12 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) TypeFunction *tfl = (TypeFunction *)fd->type; size_t dim = Parameter::dim(tfl->parameters); + if (arguments->dim < dim) + { // Default arguments are always typed, so they don't need inference. + Parameter *p = Parameter::getNth(tfl->parameters, arguments->dim); + if (p->defaultArg) + dim = arguments->dim; + } if ((!tfl->varargs && arguments->dim == dim) || ( tfl->varargs && arguments->dim >= dim)) @@ -5379,7 +5492,7 @@ Expression *DeclarationExp::semantic(Scope *sc) if (ad) { if (ad->decl && ad->decl->dim == 1) - s = ad->decl->tdata()[0]; + s = (*ad->decl)[0]; } if (s->isVarDeclaration()) @@ -5570,7 +5683,7 @@ void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 0; i < args->dim; i++) { buf->writeByte(','); - Object *oarg = args->tdata()[i]; + Object *oarg = (*args)[i]; ObjectToCBuffer(buf, hgs, oarg); } } @@ -5623,8 +5736,8 @@ Expression *IsExp::syntaxCopy() p = new TemplateParameters(); p->setDim(parameters->dim); for (size_t i = 0; i < p->dim; i++) - { TemplateParameter *tp = parameters->tdata()[i]; - p->tdata()[i] = tp->syntaxCopy(); + { TemplateParameter *tp = (*parameters)[i]; + (*p)[i] = tp->syntaxCopy(); } } @@ -5734,7 +5847,7 @@ Expression *IsExp::semantic(Scope *sc) Parameters *args = new Parameters; args->reserve(cd->baseclasses->dim); for (size_t i = 0; i < cd->baseclasses->dim; i++) - { BaseClass *b = cd->baseclasses->tdata()[i]; + { BaseClass *b = (*cd->baseclasses)[i]; args->push(new Parameter(STCin, b->type, NULL, NULL)); } tded = new TypeTuple(args); @@ -5754,6 +5867,7 @@ Expression *IsExp::semantic(Scope *sc) break; case TOKfunction: + case TOKparameters: { if (targ->ty != Tfunction) goto Lno; @@ -5769,7 +5883,9 @@ Expression *IsExp::semantic(Scope *sc) for (size_t i = 0; i < dim; i++) { Parameter *arg = Parameter::getNth(params, i); assert(arg && arg->type); - args->push(new Parameter(arg->storageClass, arg->type, NULL, NULL)); + args->push(new Parameter(arg->storageClass, arg->type, + (tok2 == TOKparameters) ? arg->ident : NULL, + (tok2 == TOKparameters) ? arg->defaultArg : NULL)); } tded = new TypeTuple(args); break; @@ -5831,13 +5947,13 @@ Expression *IsExp::semantic(Scope *sc) } else { - tded = (Type *)dedtypes.tdata()[0]; + tded = (Type *)dedtypes[0]; if (!tded) tded = targ; #if DMDV2 Objects tiargs; tiargs.setDim(1); - tiargs.tdata()[0] = targ; + tiargs[0] = targ; /* Declare trailing parameters */ @@ -5936,7 +6052,7 @@ void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 1; i < parameters->dim; i++) { buf->writeByte(','); - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; tp->toCBuffer(buf, hgs); } } @@ -6342,7 +6458,7 @@ Expression *CompileExp::semantic(Scope *sc) error("argument to mixin must be a string type, not %s\n", e1->type->toChars()); return new ErrorExp(); } - e1 = e1->optimize(WANTvalue | WANTinterpret); + e1 = e1->ctfeInterpret(); StringExp *se = e1->toString(); if (!se) { error("argument to mixin must be a string, not (%s)", e1->toChars()); @@ -6384,7 +6500,7 @@ Expression *FileExp::semantic(Scope *sc) #endif UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); - e1 = e1->optimize(WANTvalue | WANTinterpret); + e1 = e1->ctfeInterpret(); if (e1->op != TOKstring) { error("file name argument must be a string, not (%s)", e1->toChars()); goto Lerror; @@ -6576,8 +6692,30 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) } } +// Type *t1save = e1->type; + UnaExp::semantic(sc); +#if 0 + /* + * Identify typeof(var).stringof and use the original type of var, if possible + */ + if (ident == Id::stringof && e1->op == TOKtype && t1save && t1save->ty == Ttypeof) + { TypeTypeof *t = (TypeTypeof *)t1save; + if (t->exp->op == TOKvar) + { + Type *ot = ((VarExp *)t->exp)->var->originalType; + if (ot) + { + char *s = ((VarExp *)t->exp)->var->originalType->toChars(); + e = new StringExp(loc, s, strlen(s), 'c'); + e = e->semantic(sc); + return e; + } + } + } +#endif + if (ident == Id::mangleof) { // symbol.mangleof Dsymbol *ds; @@ -6918,7 +7056,7 @@ Expression *DotVarExp::semantic(Scope *sc) exps->reserve(tup->objects->dim); for (size_t i = 0; i < tup->objects->dim; i++) - { Object *o = tup->objects->tdata()[i]; + { Object *o = (*tup->objects)[i]; if (o->dyncast() != DYNCAST_EXPRESSION) { error("%s is not an expression", o->toChars()); @@ -7003,12 +7141,12 @@ Lerr: return new ErrorExp(); } -#if DMDV2 + int DotVarExp::isLvalue() { return 1; } -#endif + Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) { @@ -7153,15 +7291,31 @@ Expression *DotTemplateInstanceExp::semantic(Scope *sc, int flag) #endif UnaExp::semantic(sc); - Expression *e = new DotIdExp(loc, e1, ti->name); + if (e1->op == TOKerror) + return e1; - if (e1->op == TOKimport && ((ScopeExp *)e1)->sds->isModule()) - e = ((DotIdExp *)e)->semantic(sc, 1); + 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 { + 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. + */ + return resolveUFCSProperties(sc, this); + } + unsigned errors = global.startGagging(); - e = ((DotIdExp *)e)->semantic(sc, 1); - if (global.endGagging(errors) && !flag) + e = die->semantic(sc, 1); + if (global.endGagging(errors)) { return resolveUFCSProperties(sc, this); } @@ -7367,7 +7521,7 @@ CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) Expressions *arguments = new Expressions(); if (earg1) { arguments->setDim(1); - arguments->tdata()[0] = earg1; + (*arguments)[0] = earg1; } this->arguments = arguments; } @@ -7377,8 +7531,8 @@ CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) { Expressions *arguments = new Expressions(); arguments->setDim(2); - arguments->tdata()[0] = earg1; - arguments->tdata()[1] = earg2; + (*arguments)[0] = earg1; + (*arguments)[1] = earg2; this->arguments = arguments; } @@ -7391,162 +7545,128 @@ Expression *CallExp::syntaxCopy() Expression *CallExp::resolveUFCS(Scope *sc) { - Expression *e = NULL; - DotIdExp *dotid; - DotTemplateInstanceExp *dotti; + Expression *e; Identifier *ident; + Objects *tiargs; if (e1->op == TOKdot) { - dotid = (DotIdExp *)e1; - ident = dotid->ident; - e = dotid->e1 = dotid->e1->semantic(sc); - if (e->op == TOKdotexp) - return NULL; - e = resolveProperties(sc, e); + DotIdExp *die = (DotIdExp *)e1; + e = (die->e1 = die->e1->semantic(sc)); + ident = die->ident; + tiargs = NULL; } else if (e1->op == TOKdotti) { - dotti = (DotTemplateInstanceExp *)e1; - ident = dotti->ti->name; - e = dotti->e1 = dotti->e1->semantic(sc); - if (e->op == TOKdotexp) - return NULL; - e = resolveProperties(sc, e); + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)e1; + e = (dti->e1 = dti->e1->semantic(sc)); + ident = dti->ti->name; + tiargs = dti->ti->tiargs; } + else + return NULL; - if (e && e->type) + 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 (e->op == TOKtype || e->op == TOKimport) + 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()) + { const char *p = NULL; + if (e->type->isConst()) + p = "const"; + else if (e->type->isImmutable()) + p = "immutable"; + else + p = "inout"; + error("cannot remove key from %s associative array %s", p, 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; - //printf("resolveUCSS %s, e->op = %s\n", toChars(), Token::toChars(e->op)); - AggregateDeclaration *ad; - Expression *esave = e; -Lagain: - Type *t = e->type->toBasetype(); - if (t->ty == Tpointer) - { Type *tn = t->nextOf(); - if (tn->ty == Tclass || tn->ty == Tstruct) - { - e = new PtrExp(e->loc, e); - e = e->semantic(sc); - t = e->type->toBasetype(); - } } - if (t->ty == Tclass) - { - ad = ((TypeClass *)t)->sym; - goto L1; - } - else if (t->ty == Tstruct) - { - ad = ((TypeStruct *)t)->sym; - L1: - if (ad->search(loc, ident, 0)) + else + { TypeAArray *taa = (TypeAArray *)t; + assert(taa->ty == Taarray); + StructDeclaration *sd = taa->getImpl(); + Dsymbol *s = sd->search(0, ident, 2); + if (s) return NULL; - if (ad->aliasthis) - { - e = resolveAliasThis(sc, e); - goto Lagain; - } - if (ad->search(loc, Id::opDot, 0)) - { - e = new DotIdExp(e->loc, e, Id::opDot); - e = e->semantic(sc); - e = resolveProperties(sc, e); - goto Lagain; - } - if (ad->search(loc, Id::opDispatch, 0)) - return NULL; - e = esave; goto Lshift; } - else if ((t->isTypeBasic() && t->ty != Tvoid) || - t->ty == Tenum || t->ty == Tnull) - { - goto Lshift; - } - else if (t->ty == Taarray && e1->op == TOKdot) - { - 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()) - { const char *p = NULL; - if (e->type->isConst()) - p = "const"; - else if (e->type->isImmutable()) - p = "immutable"; - else - p = "inout"; - error("cannot remove key from %s associative array %s", p, e->toChars()); - return new ErrorExp(); - } - Expression *key = arguments->tdata()[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) - { + } + 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 (e1->op == TOKdot) - { - /* Transform: - * array.id(args) into .id(array,args) - */ -#if DMDV2 - e1 = new DotIdExp(dotid->loc, - new IdentifierExp(dotid->loc, Id::empty), - ident); -#else - e1 = new IdentifierExp(dotid->loc, ident); -#endif - } - else if (e1->op == TOKdotti) - { - /* Transform: - * array.foo!(tiargs)(args) into .foo!(tiargs)(array,args) - */ -#if DMDV2 - e1 = new DotTemplateInstanceExp(dotti->loc, - new IdentifierExp(dotti->loc, Id::empty), - dotti->ti->name, dotti->ti->tiargs); -#else - e1 = new ScopeExp(dotti->loc, dotti->ti); -#endif - } - //printf("-> this = %s\n", toChars()); + 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; @@ -7568,7 +7688,7 @@ Expression *CallExp::semantic(Scope *sc) #if 0 if (arguments && arguments->dim) { - Expression *earg = arguments->tdata()[0]; + Expression *earg = (*arguments)[0]; earg->print(); if (earg->type) earg->type->print(); } @@ -7836,7 +7956,13 @@ Lagain: goto L1; // overload of opCall, therefore it's a call if (e1->op != TOKtype) - { error("%s %s does not overload ()", ad->kind(), ad->toChars()); + { + if (ad->aliasthis) + { + e1 = resolveAliasThis(sc, e1); + goto Lagain; + } + error("%s %s does not overload ()", ad->kind(), ad->toChars()); return new ErrorExp(); } @@ -7867,7 +7993,7 @@ Lagain: if (arguments && arguments->dim) { for (size_t k = 0; k < arguments->dim; k++) - { Expression *checkarg = arguments->tdata()[k]; + { Expression *checkarg = (*arguments)[k]; if (checkarg->op == TOKerror) return checkarg; } @@ -7880,7 +8006,7 @@ Lagain: if (targsi && targsi->dim) { for (size_t k = 0; k < targsi->dim; k++) - { Object *o = targsi->tdata()[k]; + { Object *o = (*targsi)[k]; if (isError(o)) return new ErrorExp(); } @@ -7894,13 +8020,23 @@ Lagain: AggregateDeclaration *ad; UnaExp *ue = (UnaExp *)(e1); + Expression *ue1 = ue->e1; + VarDeclaration *v; + if (ue1->op == TOKvar && + (v = ((VarExp *)ue1)->var->isVarDeclaration()) != NULL && + v->needThis()) + { + ue->e1 = new TypeExp(ue1->loc, ue1->type); + ue1 = NULL; + } + if (e1->op == TOKdotvar) { // Do overload resolution dve = (DotVarExp *)(e1); f = dve->var->isFuncDeclaration(); assert(f); - f = f->overloadResolve(loc, ue->e1, arguments); + f = f->overloadResolve(loc, ue1, arguments); ad = f->toParent()->isAggregateDeclaration(); } @@ -7911,7 +8047,7 @@ Lagain: if (!arguments) // Should fix deduceFunctionTemplate() so it works on NULL argument arguments = new Expressions(); - f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments); + f = td->deduceFunctionTemplate(sc, loc, targsi, ue1, arguments); if (!f) return new ErrorExp(); ad = td->toParent()->isAggregateDeclaration(); @@ -7960,6 +8096,7 @@ Lagain: { e1 = new DotVarExp(loc, dte->e1, f); e1 = e1->semantic(sc); + ue = (UnaExp *)e1; } #if 0 printf("ue->e1 = %s\n", ue->e1->toChars()); @@ -8115,7 +8252,7 @@ Lagain: FuncDeclaration *f = NULL; Dsymbol *s = NULL; for (size_t i = 0; i < eo->vars->a.dim; i++) - { s = eo->vars->a.tdata()[i]; + { s = eo->vars->a[i]; FuncDeclaration *f2 = s->isFuncDeclaration(); if (f2) { @@ -8157,7 +8294,17 @@ Lagain: { TypeFunction *tf; const char *p; - if (t1->ty == Tdelegate) + if (e1->op == TOKfunction) + { + // function literal that direct called is always inferred. + assert(((FuncExp *)e1)->fd); + f = ((FuncExp *)e1)->fd; + tf = (TypeFunction *)f->type; + p = "function literal"; + + f->checkNestedReference(sc, loc); + } + else if (t1->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)t1; assert(td->next->ty == Tfunction); tf = (TypeFunction *)(td->next); @@ -8222,7 +8369,7 @@ Lagain: else buf.writeByte(')'); - //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco); + //printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco); ::error(loc, "%s %s %s is not callable using argument types %s", p, e1->toChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), buf.toChars()); @@ -8306,10 +8453,12 @@ Lagain: } -#if DMDV2 + int CallExp::isLvalue() { Type *tb = e1->type->toBasetype(); + if (tb->ty == Tdelegate || tb->ty == Tpointer) + tb = tb->nextOf(); if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) { if (e1->op == TOKdotvar) @@ -8319,7 +8468,7 @@ int CallExp::isLvalue() } return 0; } -#endif + Expression *CallExp::toLvalue(Scope *sc, Expression *e) { @@ -8404,8 +8553,10 @@ Expression *AddrExp::semantic(Scope *sc) m = sc->module; #endif UnaExp::semantic(sc); + Expression *olde1 = e1; if (e1->type == Type::terror) return new ErrorExp(); + int wasCond = e1->op == TOKquestion; e1 = e1->toLvalue(sc, NULL); if (e1->op == TOKerror) return e1; @@ -8515,6 +8666,24 @@ Expression *AddrExp::semantic(Scope *sc) } } } + else if (wasCond) + { + /* a ? b : c was transformed to *(a ? &b : &c), but we still + * need to do safety checks + */ + assert(e1->op == TOKstar); + PtrExp *pe = (PtrExp *)e1; + assert(pe->e1->op == TOKquestion); + CondExp *ce = (CondExp *)pe->e1; + assert(ce->e1->op == TOKaddress); + assert(ce->e2->op == TOKaddress); + + // Re-run semantic on the address expressions only + ce->e1->type = NULL; + ce->e1 = ce->e1->semantic(sc); + ce->e2->type = NULL; + ce->e2 = ce->e2->semantic(sc); + } return optimize(WANTvalue); } return this; @@ -8576,12 +8745,12 @@ Expression *PtrExp::semantic(Scope *sc) return this; } -#if DMDV2 + int PtrExp::isLvalue() { return 1; } -#endif + void PtrExp::checkEscapeRef() { @@ -8992,6 +9161,12 @@ Expression *CastExp::semantic(Scope *sc) { return new VectorExp(loc, e1, to); } + + if (tob->isintegral() && t1b->ty == Tarray && + !global.params.useDeprecated) + { + error("casting %s to %s is deprecated", e1->type->toChars(), to->toChars()); + } } else if (!to) { error("cannot cast tuple"); @@ -9122,7 +9297,7 @@ VectorExp::VectorExp(Loc loc, Expression *e, Type *t) : UnaExp(loc, TOKvector, sizeof(VectorExp), e) { assert(t->ty == Tvector); - to = t; + to = (TypeVector *)t; dim = ~0; } @@ -9295,8 +9470,8 @@ Lagain: if (t->ty == Ttuple) { - lwr = lwr->optimize(WANTvalue | WANTinterpret); - upr = upr->optimize(WANTvalue | WANTinterpret); + lwr = lwr->ctfeInterpret(); + upr = upr->ctfeInterpret(); uinteger_t i1 = lwr->toUInteger(); uinteger_t i2 = upr->toUInteger(); @@ -9384,12 +9559,12 @@ void SliceExp::checkEscapeRef() e1->checkEscapeRef(); } -#if DMDV2 + int SliceExp::isLvalue() { return 1; } -#endif + Expression *SliceExp::toLvalue(Scope *sc, Expression *e) { @@ -9540,6 +9715,8 @@ Expression *ArrayExp::semantic(Scope *sc) #endif UnaExp::semantic(sc); e1 = resolveProperties(sc, e1); + if (e1->op == TOKerror) + return e1; t1 = e1->type->toBasetype(); if (t1->ty != Tclass && t1->ty != Tstruct) @@ -9548,7 +9725,7 @@ Expression *ArrayExp::semantic(Scope *sc) { error("only one index allowed to index %s", t1->toChars()); goto Lerr; } - e = new IndexExp(loc, e1, arguments->tdata()[0]); + e = new IndexExp(loc, e1, (*arguments)[0]); return e->semantic(sc); } @@ -9563,14 +9740,14 @@ Lerr: return new ErrorExp(); } -#if DMDV2 + int ArrayExp::isLvalue() { if (type && type->toBasetype()->ty == Tvoid) return 0; return 1; } -#endif + Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) { @@ -9652,12 +9829,12 @@ void CommaExp::checkEscapeRef() e2->checkEscapeRef(); } -#if DMDV2 + int CommaExp::isLvalue() { return e2->isLvalue(); } -#endif + Expression *CommaExp::toLvalue(Scope *sc, Expression *e) { @@ -9736,7 +9913,7 @@ Expression *IndexExp::semantic(Scope *sc) if (e2->type == Type::terror) goto Lerr; if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix - e2 = ((TupleExp *)e2)->exps->tdata()[0]; + e2 = (*((TupleExp *)e2)->exps)[0]; if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) sc = sc->pop(); @@ -9787,7 +9964,7 @@ Expression *IndexExp::semantic(Scope *sc) case Ttuple: { e2 = e2->implicitCastTo(sc, Type::tsize_t); - e2 = e2->optimize(WANTvalue | WANTinterpret); + e2 = e2->ctfeInterpret(); uinteger_t index = e2->toUInteger(); size_t length; TupleExp *te; @@ -9844,12 +10021,12 @@ Lerr: return new ErrorExp(); } -#if DMDV2 + int IndexExp::isLvalue() { return 1; } -#endif + Expression *IndexExp::toLvalue(Scope *sc, Expression *e) { @@ -10064,7 +10241,7 @@ Expression *AssignExp::semantic(Scope *sc) { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); // Deal with $ for (size_t i = 0; i < ae->arguments->dim; i++) - { Expression *x = ae->arguments->tdata()[i]; + { Expression *x = (*ae->arguments)[i]; // Create scope for '$' variable for this dimension ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae); sym->loc = loc; @@ -10082,7 +10259,7 @@ Expression *AssignExp::semantic(Scope *sc) x = new CommaExp(0, av, x); x->semantic(sc); } - ae->arguments->tdata()[i] = x; + (*ae->arguments)[i] = x; sc = sc->pop(); } Expressions *a = (Expressions *)ae->arguments->copy(); @@ -10104,7 +10281,7 @@ Expression *AssignExp::semantic(Scope *sc) return new ErrorExp(); } - e = new CallExp(loc, e, ae->arguments->tdata()[0], e2); + e = new CallExp(loc, e, (*ae->arguments)[0], e2); e = e->semantic(sc); return e; } @@ -10385,7 +10562,7 @@ Ltupleassign: for (size_t u = 0; u < iexps->dim ; u++) { Lexpand: - Expression *e = iexps->tdata()[u]; + Expression *e = (*iexps)[u]; Parameter *arg = Parameter::getNth(tt->arguments, u); //printf("[%d] iexps->dim = %d, ", u, iexps->dim); @@ -10401,7 +10578,7 @@ Ltupleassign: goto Lnomatch; } } - iexps->tdata()[0] = new CommaExp(loc, new DeclarationExp(e2->loc, v), iexps->tdata()[0]); + (*iexps)[0] = new CommaExp(loc, new DeclarationExp(e2->loc, v), (*iexps)[0]); e2 = new TupleExp(e2->loc, iexps); e2 = e2->semantic(sc); goto Ltupleassign; @@ -10474,16 +10651,6 @@ Ltupleassign: sd->cpctor) { /* We have a copy constructor for this */ - // Scan past commma's - Expression *ec = NULL; - while (e2->op == TOKcomma) - { CommaExp *ecomma = (CommaExp *)e2; - e2 = ecomma->e2; - if (ec) - ec = new CommaExp(ecomma->loc, ec, ecomma->e1); - else - ec = ecomma->e1; - } if (e2->op == TOKquestion) { /* Write as: * a ? e1 = b : e1 = c; @@ -10494,15 +10661,9 @@ Ltupleassign: AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2); ea2->op = op; Expression *e = new CondExp(loc, econd->econd, ea1, ea2); - if (ec) - e = new CommaExp(loc, ec, e); return e->semantic(sc); } - else if (e2->op == TOKvar || - e2->op == TOKdotvar || - e2->op == TOKstar || - e2->op == TOKthis || - e2->op == TOKindex) + else if (e2->isLvalue()) { /* Write as: * e1.cpctor(e2); */ @@ -10511,8 +10672,6 @@ Ltupleassign: Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0); e = new CallExp(loc, e, e2); - if (ec) - e = new CommaExp(loc, ec, e); return e->semantic(sc); } else if (e2->op == TOKcall) @@ -10537,6 +10696,21 @@ Ltupleassign: if (t1->ty == Tsarray && !refinit) { + Type *t2 = e2->type->toBasetype(); + + if (t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) + { // static array assignment should check their lengths + TypeSArray *tsa1 = (TypeSArray *)t1; + TypeSArray *tsa2 = (TypeSArray *)t2; + uinteger_t dim1 = tsa1->dim->toInteger(); + uinteger_t dim2 = tsa2->dim->toInteger(); + if (dim1 != dim2) + { + error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2); + return new ErrorExp(); + } + } + if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray) { @@ -10548,7 +10722,6 @@ Ltupleassign: } else { - Type *t2 = e2->type->toBasetype(); // Convert e2 to e2[], unless e2-> e1[0] if (t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf())) { @@ -10567,6 +10740,11 @@ Ltupleassign: if (!e2->rvalue()) return new ErrorExp(); + if (e2->op == TOKarrayliteral) + { + e2 = callCpCtor(loc, sc, e2, 1); + } + if (e1->op == TOKarraylength) { // e1 is not an lvalue, but we let code generator handle it @@ -10741,7 +10919,9 @@ Expression *CatAssignExp::semantic(Scope *sc) (tb2->ty == Tarray || tb2->ty == Tsarray) && (e2->implicitConvTo(e1->type) #if DMDV2 - || tb2->nextOf()->implicitConvTo(tb1next) + || (tb2->nextOf()->implicitConvTo(tb1next) && + (tb2->nextOf()->size(0) == tb1next->size(0) || + tb1next->ty == Tchar || tb1next->ty == Twchar || tb1next->ty == Tdchar)) #endif ) ) @@ -11476,7 +11656,7 @@ Expression *PowExp::semantic(Scope *sc) { importMathChecked = 1; for (size_t i = 0; i < Module::amodules.dim; i++) - { Module *mi = Module::amodules.tdata()[i]; + { Module *mi = Module::amodules[i]; //printf("\t[%d] %s\n", i, mi->toChars()); if (mi->ident == Id::math && mi->parent->ident == Id::std && @@ -12315,12 +12495,12 @@ Expression *CondExp::semantic(Scope *sc) return this; } -#if DMDV2 + int CondExp::isLvalue() { return e1->isLvalue() && e2->isLvalue(); } -#endif + Expression *CondExp::toLvalue(Scope *sc, Expression *ex) { diff --git a/dmd2/expression.h b/dmd2/expression.h index 762ff71c..2e372650 100644 --- a/dmd2/expression.h +++ b/dmd2/expression.h @@ -18,6 +18,7 @@ #include "intrange.h" struct Type; +struct TypeVector; struct Scope; struct TupleDeclaration; struct VarDeclaration; @@ -183,6 +184,11 @@ struct Expression : Object // 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 + Expression *ctfeInterpret(); + + // Implementation of CTFE for this expression virtual Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); virtual int isConst(); @@ -432,7 +438,6 @@ struct StringExp : Expression StringExp(Loc loc, void *s, size_t len, unsigned char postfix); //Expression *syntaxCopy(); int equals(Object *o); - char *toChars(); Expression *semantic(Scope *sc); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); size_t length(); @@ -793,7 +798,6 @@ struct FuncExp : Expression FuncLiteralDeclaration *fd; TemplateDeclaration *td; enum TOK tok; - Type *treq; FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL); Expression *syntaxCopy(); @@ -947,10 +951,11 @@ struct BinExp : Expression Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, CtfeGoal goal, - Expression *(*fp)(TOK, Type *, Expression *, Expression *)); + Expression *(*fp)(Loc, TOK, Type *, Expression *, Expression *)); Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); - Expression *arrayOp(Scope *sc); + Expression *interpretFourPointerRelation(InterState *istate, CtfeGoal goal); + virtual Expression *arrayOp(Scope *sc); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -971,6 +976,7 @@ struct BinAssignExp : BinExp } Expression *semantic(Scope *sc); + Expression *arrayOp(Scope *sc); Expression *op_overload(Scope *sc); @@ -1330,7 +1336,7 @@ struct CastExp : UnaExp struct VectorExp : UnaExp { - Type *to; + TypeVector *to; // the target vector type before semantic() unsigned dim; // number of elements in the vector VectorExp(Loc loc, Expression *e, Type *t); @@ -1339,6 +1345,7 @@ struct VectorExp : UnaExp void toCBuffer(OutBuffer *buf, HdrGenState *hgs); #if IN_DMD elem *toElem(IRState *irs); + dt_t **toDt(dt_t **pdt); #endif #if IN_LLVM DValue* toElem(IRState* irs); @@ -2154,5 +2161,8 @@ void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *n void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex); void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex); +int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len); +int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len); + #endif /* DMD_EXPRESSION_H */ diff --git a/dmd2/func.c b/dmd2/func.c index eb512522..62b493d0 100644 --- a/dmd2/func.c +++ b/dmd2/func.c @@ -51,13 +51,15 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla outId = NULL; vresult = NULL; returnLabel = NULL; + scout = NULL; fensure = NULL; fbody = NULL; localsymtab = NULL; vthis = NULL; v_arguments = NULL; -#if IN_GCC +#ifdef IN_GCC v_argptr = NULL; + v_arguments_var = NULL; #endif v_argsave = NULL; parameters = NULL; @@ -223,11 +225,9 @@ void FuncDeclaration::semantic(Scope *sc) if (isCtorDeclaration()) sc->flags |= SCOPEctor; - type = type->semantic(loc, sc); - sc = sc->pop(); - /* Apply const, immutable and shared storage class - * to the function type + /* Apply const, immutable, wild and shared storage class + * to the function type. Do this before type semantic. */ StorageClass stc = storage_class; if (type->isImmutable()) @@ -250,35 +250,28 @@ void FuncDeclaration::semantic(Scope *sc) case STCimmutable | STCshared | STCwild: // Don't use toInvariant(), as that will do a merge() type = type->makeInvariant(); - goto Lmerge; + break; case STCconst: case STCconst | STCwild: type = type->makeConst(); - goto Lmerge; + break; case STCshared | STCconst: case STCshared | STCconst | STCwild: type = type->makeSharedConst(); - goto Lmerge; + break; case STCshared: type = type->makeShared(); - goto Lmerge; + break; case STCwild: type = type->makeWild(); - goto Lmerge; + break; case STCshared | STCwild: type = type->makeSharedWild(); - goto Lmerge; - - Lmerge: - if (!(type->ty == Tfunction && !type->nextOf())) - /* Can't do merge if return type is not known yet - */ - type->deco = type->merge()->deco; break; case 0: @@ -287,7 +280,11 @@ void FuncDeclaration::semantic(Scope *sc) default: assert(0); } + + type = type->semantic(loc, sc); + sc = sc->pop(); } + storage_class &= ~STCref; if (type->ty != Tfunction) { @@ -401,18 +398,6 @@ void FuncDeclaration::semantic(Scope *sc) if (!fbody && (fensure || frequire) && !(id && isVirtual())) error("in and out contracts require function body"); - /* Template member functions aren't virtual: - * interface TestInterface { void tpl(T)(); } - * and so won't work in interfaces - */ - if ((pd = toParent()) != NULL && - pd->isTemplateInstance() && - (pd = toParent2()) != NULL && - (id = pd->isInterfaceDeclaration()) != NULL) - { - error("template member functions are not allowed in interface %s", id->toChars()); - } - cd = parent->isClassDeclaration(); if (cd) { int vi; @@ -550,9 +535,6 @@ void FuncDeclaration::semantic(Scope *sc) break; else if (!this->parent->isClassDeclaration() // if both are mixins then error -#if !BREAKABI - && !isDtorDeclaration() -#endif #if DMDV2 && !isPostBlitDeclaration() #endif @@ -610,7 +592,7 @@ void FuncDeclaration::semantic(Scope *sc) return; default: - { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi]; + { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl[vi]; Type *ti = NULL; /* Remember which functions this overrides @@ -920,7 +902,7 @@ void FuncDeclaration::semantic3(Scope *sc) { for (int i = 0; i < fthrows->dim; i++) { - Type *t = fthrows->tdata()[i]; + Type *t = (*fthrows)[i]; t = t->semantic(loc, sc); if (!t->isClassHandle()) @@ -929,11 +911,17 @@ void FuncDeclaration::semantic3(Scope *sc) } #endif + if (!fbody && inferRetType && !type->nextOf()) + { + error("has no function body with return type inference"); + return; + } + if (frequire) { for (int i = 0; i < foverrides.dim; i++) { - FuncDeclaration *fdv = foverrides.tdata()[i]; + FuncDeclaration *fdv = foverrides[i]; if (fdv->fbody && !fdv->frequire) { @@ -971,7 +959,7 @@ void FuncDeclaration::semantic3(Scope *sc) STCproperty | STCsafe | STCtrusted | STCsystem); sc2->protection = PROTpublic; sc2->explicitProtection = 0; - sc2->structalign = 8; + sc2->structalign = STRUCTALIGN_DEFAULT; sc2->incontract = 0; #if !IN_LLVM sc2->tf = NULL; @@ -992,9 +980,6 @@ void FuncDeclaration::semantic3(Scope *sc) } else assert(!isNested() || sc->intypeof); // can't be both member and nested -#if IN_GCC - ad->methods.push(this); -#endif } vthis = declareThis(sc2, ad); @@ -1028,7 +1013,6 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->linkage == LINKd) { // Declare _arguments[] -#if BREAKABI v_arguments = new VarDeclaration(0, Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL); v_arguments->storage_class = STCparameter; v_arguments->semantic(sc2); @@ -1041,18 +1025,10 @@ void FuncDeclaration::semantic3(Scope *sc) _arguments->semantic(sc2); sc2->insert(_arguments); _arguments->parent = this; -#else - t = Type::typeinfo->type->arrayOf(); - v_arguments = new VarDeclaration(0, t, Id::_arguments, NULL); - v_arguments->storage_class = STCparameter | STCin; - v_arguments->semantic(sc2); - sc2->insert(v_arguments); - v_arguments->parent = this; -#endif } if (f->linkage == LINKd || (f->parameters && Parameter::dim(f->parameters))) { // Declare _argptr -#if IN_GCC +#ifdef IN_GCC t = d_gcc_builtin_va_list_d_type; #else t = Type::tvoid->pointerTo(); @@ -1094,7 +1070,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->parameters) { for (size_t i = 0; i < f->parameters->dim; i++) - { Parameter *arg = f->parameters->tdata()[i]; + { Parameter *arg = (*f->parameters)[i]; //printf("[%d] arg->type->ty = %d %s\n", i, arg->type->ty, arg->type->toChars()); if (arg->type->ty == Ttuple) @@ -1158,7 +1134,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (f->parameters) { for (size_t i = 0; i < f->parameters->dim; i++) - { Parameter *arg = f->parameters->tdata()[i]; + { Parameter *arg = (*f->parameters)[i]; if (!arg->ident) continue; // never used, so ignore @@ -1173,7 +1149,7 @@ void FuncDeclaration::semantic3(Scope *sc) VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration(); assert(v); Expression *e = new VarExp(v->loc, v); - exps->tdata()[j] = e; + (*exps)[j] = e; } assert(arg->ident); TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps); @@ -1187,151 +1163,120 @@ void FuncDeclaration::semantic3(Scope *sc) } } - /* Do the semantic analysis on the [in] preconditions and - * [out] postconditions. - */ - sc2->incontract++; + // Precondition invariant + Statement *fpreinv = NULL; + if (addPreInvariant()) + { + Expression *e = NULL; + if (isDtorDeclaration()) + { + // Call invariant directly only if it exists + InvariantDeclaration *inv = ad->inv; + ClassDeclaration *cd = ad->isClassDeclaration(); - if (frequire) - { /* frequire is composed of the [in] contracts - */ - // BUG: need to error if accessing out parameters - // BUG: need to treat parameters as const - // BUG: need to disallow returns and throws - // BUG: verify that all in and ref parameters are read - frequire = frequire->semantic(sc2); - labtab = NULL; // so body can't refer to labels + while (!inv && cd) + { + cd = cd->baseClass; + if (!cd) + break; + inv = cd->inv; + } + if (inv) + { + e = new DsymbolExp(0, inv); + e = new CallExp(0, e); + e = e->semantic(sc2); + } + } + else + { // Call invariant virtually +#if IN_LLVM + // We actually need a valid 'var' for codegen. + ThisExp* tv = new ThisExp(0); + tv->var = vthis; + Expression *v = tv; +#else + Expression *v = new ThisExp(0); +#endif + v->type = vthis->type; +#if STRUCTTHISREF + if (ad->isStructDeclaration()) + v = v->addressOf(sc); +#endif + Expression *se = new StringExp(0, (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); + } + + // Postcondition invariant + Statement *fpostinv = NULL; + if (addPostInvariant()) + { + Expression *e = NULL; + if (isCtorDeclaration()) + { + // Call invariant directly only if it exists + InvariantDeclaration *inv = ad->inv; + ClassDeclaration *cd = ad->isClassDeclaration(); + + while (!inv && cd) + { + cd = cd->baseClass; + if (!cd) + break; + inv = cd->inv; + } + if (inv) + { + e = new DsymbolExp(0, inv); + e = new CallExp(0, e); + e = e->semantic(sc2); + } + } + else + { // Call invariant virtually +#if IN_LLVM + // We actually need a valid 'var' for codegen. + ThisExp* tv = new ThisExp(0); + tv->var = vthis; + Expression *v = tv; +#else + Expression *v = new ThisExp(0); +#endif + v->type = vthis->type; +#if STRUCTTHISREF + if (ad->isStructDeclaration()) + v = v->addressOf(sc); +#endif + e = new AssertExp(0, v); + } + if (e) + fpostinv = new ExpStatement(0, e); } if (fensure || addPostInvariant()) - { /* fensure is composed of the [out] contracts - */ - if (!type->nextOf()) // if return type is inferred - { /* This case: - * auto fp = function() out { } body { }; - * Can fix by doing semantic() onf fbody first. - */ - error("post conditions are not supported if the return type is inferred"); - return; + { + if ((fensure && global.params.useOut) || fpostinv) + { returnLabel = new LabelDsymbol(Id::returnLabel); } + // scope of out contract (need for vresult->semantic) + ScopeDsymbol *sym = new ScopeDsymbol(); + sym->parent = sc2->scopesym; + scout = sc2->push(sym); + } + + if (fbody) + { ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc2->scopesym; sc2 = sc2->push(sym); - assert(type->nextOf()); - if (type->nextOf()->ty == Tvoid) - { - if (outId) - error("void functions have no result"); - } - else - { - if (!outId) - outId = Id::result; // provide a default - } - - if (outId) - { // Declare result variable - Loc loc = this->loc; - - if (fensure) - loc = fensure->loc; - - VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL); - v->noscope = 1; - v->storage_class |= STCresult; -#if DMDV2 - if (!isVirtual()) - v->storage_class |= STCconst; - if (f->isref) - { - v->storage_class |= STCref | STCforeach; - } -#endif - sc2->incontract--; - v->semantic(sc2); - sc2->incontract++; - if (!sc2->insert(v)) - error("out result %s is already defined", v->toChars()); - v->parent = this; - vresult = v; - - // vresult gets initialized with the function return value - // in ReturnStatement::semantic() - } - - // BUG: need to treat parameters as const - // BUG: need to disallow returns and throws - if (fensure) - { fensure = fensure->semantic(sc2); - labtab = NULL; // so body can't refer to labels - } - - if (!global.params.useOut) - { fensure = NULL; // discard - vresult = NULL; - } - - // Postcondition invariant - if (addPostInvariant()) - { - Expression *e = NULL; - if (isCtorDeclaration()) - { - // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; - ClassDeclaration *cd = ad->isClassDeclaration(); - - while (!inv && cd) - { - cd = cd->baseClass; - if (!cd) - break; - inv = cd->inv; - } - if (inv) - { - e = new DsymbolExp(0, inv); - e = new CallExp(0, e); - e = e->semantic(sc2); - } - } - else - { // Call invariant virtually - ThisExp *tv = new ThisExp(0); - tv->type = vthis->type; - tv->var = vthis; - Expression* v = tv; - -#if STRUCTTHISREF - if (ad->isStructDeclaration()) - v = v->addressOf(sc); -#endif - e = new AssertExp(0, v); - } - if (e) - { - ExpStatement *s = new ExpStatement(0, e); - if (fensure) - fensure = new CompoundStatement(0, s, fensure); - else - fensure = s; - } - } - - if (fensure) - { returnLabel = new LabelDsymbol(Id::returnLabel); - LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fensure); - returnLabel->statement = ls; - } - sc2 = sc2->pop(); - } - - sc2->incontract--; - - if (fbody) - { AggregateDeclaration *ad = isAggregateMember(); + AggregateDeclaration *ad = isAggregateMember(); /* If this is a class constructor */ @@ -1375,7 +1320,7 @@ void FuncDeclaration::semantic3(Scope *sc) else { for (size_t i = 0; i < pd->members->dim; i++) - { Dsymbol *s = pd->members->tdata()[i]; + { Dsymbol *s = (*pd->members)[i]; s->checkCtorConstInit(); } @@ -1460,15 +1405,7 @@ void FuncDeclaration::semantic3(Scope *sc) int offend = blockexit & BEfallthru; #endif - if (type->nextOf()->ty == Tvoid) - { - if (offend && isMain()) - { // Add a return 0; statement - Statement *s = new ReturnStatement(0, new IntegerExp(0)); - fbody = new CompoundStatement(0, fbody, s); - } - } - else + if (type->nextOf()->ty != Tvoid) { if (offend) { Expression *e; @@ -1497,6 +1434,66 @@ void FuncDeclaration::semantic3(Scope *sc) } } } + + sc2 = sc2->pop(); + } + + Statement *freq = frequire; + Statement *fens = fensure; + + /* Do the semantic analysis on the [in] preconditions and + * [out] postconditions. + */ + if (freq) + { /* frequire is composed of the [in] contracts + */ + ScopeDsymbol *sym = new ScopeDsymbol(); + sym->parent = sc2->scopesym; + sc2 = sc2->push(sym); + sc2->incontract++; + + // BUG: need to error if accessing out parameters + // BUG: need to treat parameters as const + // BUG: need to disallow returns and throws + // BUG: verify that all in and ref parameters are read + DsymbolTable *labtab_save = labtab; + labtab = NULL; // so in contract can't refer to out/body labels + freq = freq->semantic(sc2); + labtab = labtab_save; + + sc2->incontract--; + sc2 = sc2->pop(); + + if (!global.params.useIn) + freq = NULL; + } + + if (fens) + { /* fensure is composed of the [out] contracts + */ + if (type->nextOf()->ty == Tvoid && outId) + { + error("void functions have no result"); + } + + if (type->nextOf()->ty != Tvoid) + buildResultVar(); + + sc2 = scout; //push + sc2->incontract++; + + // BUG: need to treat parameters as const + // BUG: need to disallow returns and throws + DsymbolTable *labtab_save = labtab; + labtab = NULL; // so out contract can't refer to in/body labels + fens = fens->semantic(sc2); + labtab = labtab_save; + + sc2->incontract--; + sc2 = sc2->pop(); + + if (!global.params.useOut) + fens = NULL; } { @@ -1506,7 +1503,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (parameters) { for (size_t i = 0; i < parameters->dim; i++) { - VarDeclaration *v = parameters->tdata()[i]; + VarDeclaration *v = (*parameters)[i]; if (v->storage_class & STCout) { assert(v->init); @@ -1548,7 +1545,7 @@ void FuncDeclaration::semantic3(Scope *sc) if (parameters && parameters->dim) { int lastNonref = parameters->dim -1; - p = parameters->tdata()[lastNonref]; + p = (*parameters)[lastNonref]; /* The trouble with out and ref parameters is that taking * the address of it doesn't work, because later processing * adds in an extra level of indirection. So we skip over them. @@ -1562,7 +1559,7 @@ void FuncDeclaration::semantic3(Scope *sc) p = v_arguments; break; } - p = parameters->tdata()[lastNonref]; + p = (*parameters)[lastNonref]; } } else @@ -1586,6 +1583,10 @@ void FuncDeclaration::semantic3(Scope *sc) if (_arguments) { +#ifdef IN_GCC + v_arguments_var = _arguments; + v_arguments_var->init = new VoidInitializer(loc); +#endif /* Advance to elements[] member of TypeInfo_Tuple with: * _arguments = v_arguments.elements; */ @@ -1601,74 +1602,32 @@ void FuncDeclaration::semantic3(Scope *sc) // Merge contracts together with body into one compound statement - if (frequire && global.params.useIn) - { frequire->incontract = 1; - a->push(frequire); - } - - // Precondition invariant - if (addPreInvariant()) + if (freq || fpreinv) { - Expression *e = NULL; - Expression *ee = NULL; - if (isDtorDeclaration()) - { - // Call invariant directly only if it exists - InvariantDeclaration *inv = ad->inv; - ClassDeclaration *cd = ad->isClassDeclaration(); + if (!freq) + freq = fpreinv; + else if (fpreinv) + freq = new CompoundStatement(0, freq, fpreinv); - while (!inv && cd) - { - cd = cd->baseClass; - if (!cd) - break; - inv = cd->inv; - } - if (inv) - { - e = new DsymbolExp(0, inv); - e = new CallExp(0, e); - e = e->semantic(sc2); - } - } - else - { // Call invariant virtually - ThisExp* tv = new ThisExp(0); - tv->type = vthis->type; - tv->var = vthis; - Expression *v = tv; - -#if STRUCTTHISREF - if (ad->isStructDeclaration()) - v = v->addressOf(sc); -#endif - Expression *se = new StringExp(0, (char *)"null this"); - se = se->semantic(sc); -#if !IN_LLVM - se->type = Type::tchar->arrayOf(); -#endif - e = new AssertExp(loc, v, se); - } - if (ee) - { - ExpStatement *s = new ExpStatement(0, ee); - a->push(s); - } - if (e) - { - ExpStatement *s = new ExpStatement(0, e); - a->push(s); - } + freq->incontract = 1; + a->push(freq); } if (fbody) a->push(fbody); - if (fensure) + if (fens || fpostinv) { + if (!fens) + fens = fpostinv; + else if (fpostinv) + fens = new CompoundStatement(0, fpostinv, fens); + + LabelStatement *ls = new LabelStatement(0, Id::returnLabel, fens); + returnLabel->statement = ls; a->push(returnLabel->statement); - if (type->nextOf()->ty != Tvoid) + if (type->nextOf()->ty != Tvoid && vresult) { #if IN_LLVM Expression *e = 0; @@ -1682,7 +1641,6 @@ void FuncDeclaration::semantic3(Scope *sc) } #else // Create: return vresult; - assert(vresult); Expression *e = new VarExp(0, vresult); #endif if (tintro) @@ -1693,6 +1651,11 @@ void FuncDeclaration::semantic3(Scope *sc) a->push(s); } } + if (isMain() && type->nextOf()->ty == Tvoid) + { // Add a return 0; statement + Statement *s = new ReturnStatement(0, new IntegerExp(0)); + a->push(s); + } fbody = new CompoundStatement(0, a); @@ -1740,17 +1703,19 @@ void FuncDeclaration::semantic3(Scope *sc) if (parameters) { for (size_t i = 0; i < parameters->dim; i++) { - VarDeclaration *v = parameters->tdata()[i]; + VarDeclaration *v = (*parameters)[i]; - if (v->storage_class & (STCref | STCout)) + if (v->storage_class & (STCref | STCout | STClazy)) continue; +#if !SARRAYVALUE /* Don't do this for static arrays, since static * arrays are called by reference. Remove this * when we change them to call by value. */ if (v->type->toBasetype()->ty == Tsarray) continue; +#endif if (v->noscope) continue; @@ -1987,6 +1952,48 @@ void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs) } } +/**************************************************** + * Declare result variable lazily. + */ + +void FuncDeclaration::buildResultVar() +{ + if (vresult) + return; + + assert(type->nextOf()); + assert(type->nextOf()->toBasetype()->ty != Tvoid); + TypeFunction *tf = (TypeFunction *)(type); + + Loc loc = this->loc; + + if (fensure) + loc = fensure->loc; + + if (!outId) + outId = Id::result; // provide a default + + VarDeclaration *v = new VarDeclaration(loc, type->nextOf(), outId, NULL); + v->noscope = 1; + v->storage_class |= STCresult; +#if DMDV2 + if (!isVirtual()) + v->storage_class |= STCconst; + if (tf->isref) + { + v->storage_class |= STCref | STCforeach; + } +#endif + v->semantic(scout); + if (!scout->insert(v)) + error("out result %s is already defined", v->toChars()); + v->parent = this; + vresult = v; + + // vresult gets initialized with the function return value + // in ReturnStatement::semantic() +} + /**************************************************** * Merge into this function the 'in' contracts of all it overrides. * 'in's are OR'd together, i.e. only one of them needs to pass. @@ -2031,7 +2038,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf, Expressions *params) */ for (int i = 0; i < foverrides.dim; i++) { - FuncDeclaration *fdv = foverrides.tdata()[i]; + FuncDeclaration *fdv = foverrides[i]; /* The semantic pass on the contracts of the overridden functions must * be completed before code generation occurs (bug 3602). @@ -2089,7 +2096,7 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf, Expressions *params) */ for (int i = 0; i < foverrides.dim; i++) { - FuncDeclaration *fdv = foverrides.tdata()[i]; + FuncDeclaration *fdv = foverrides[i]; /* The semantic pass on the contracts of the overridden functions must * be completed before code generation occurs (bug 3602 and 5230). @@ -2158,14 +2165,28 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) FuncDeclaration *mismatch = NULL; StorageClass mismatchstc = 0; int mismatchvi = -1; + int exactvi = -1; int bestvi = -1; for (int vi = 0; vi < dim; vi++) { - FuncDeclaration *fdv = vtbl->tdata()[vi]->isFuncDeclaration(); + FuncDeclaration *fdv = (*vtbl)[vi]->isFuncDeclaration(); if (fdv && fdv->ident == ident) { if (type->equals(fdv->type)) // if exact match - return vi; // no need to look further + { + if (fdv->parent->isClassDeclaration()) + return vi; // no need to look further + + if (exactvi >= 0) + { + error("cannot determine overridden function"); + return exactvi; + } + exactvi = vi; + + bestvi = vi; + continue; + } StorageClass stc = 0; int cov = type->covariant(fdv->type, &stc); @@ -2527,7 +2548,7 @@ if (arguments) for (i = 0; i < arguments->dim; i++) { Expression *arg; - arg = arguments->tdata()[i]; + arg = (*arguments)[i]; assert(arg->type); printf("\t%s: ", arg->toChars()); arg->type->print(); @@ -2570,7 +2591,7 @@ if (arguments) OutBuffer buf2; tf->modToBuffer(&buf2); - //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco); + //printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco); error(loc, "%s%s is not callable using argument types %s", Parameter::argsTypesToChars(tf->parameters, tf->varargs), buf2.toChars(), @@ -2656,7 +2677,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) } else e = p->type->defaultInitLiteral(0); - args.tdata()[u] = e; + args[u] = e; } MATCH m = (MATCH) tg->callMatch(NULL, &args, 1); @@ -2797,14 +2818,25 @@ int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd) //printf("\ts = %s, '%s'\n", s->kind(), s->toChars()); FuncDeclaration *thisfd = s->isFuncDeclaration(); if (thisfd) - { if (!thisfd->isNested() && !thisfd->vthis) + { if (!thisfd->isNested() && !thisfd->vthis && !sc->intypeof) goto Lerr; } else { AggregateDeclaration *thiscd = s->isAggregateDeclaration(); if (thiscd) - { if (!thiscd->isNested()) + { + /* AggregateDeclaration::isNested returns true only when + * it has a hidden pointer. + * But, calling the function belongs unrelated lexical scope + * is still allowed inside typeof. + * + * struct Map(alias fun) { + * typeof({ return fun(); }) RetType; + * // No member function makes Map struct 'not nested'. + * } + */ + if (!thiscd->isNested() && !sc->intypeof) goto Lerr; } else @@ -3081,6 +3113,7 @@ int FuncDeclaration::isNested() FuncDeclaration *f = toAliasFunc(); //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars()); return ((f->storage_class & STCstatic) == 0) && + (f->linkage == LINKd) && (f->toParent2()->isFuncDeclaration() != NULL); } @@ -3222,12 +3255,12 @@ int FuncDeclaration::needsClosure() //printf("FuncDeclaration::needsClosure() %s\n", toChars()); for (int i = 0; i < closureVars.dim; i++) - { VarDeclaration *v = closureVars.tdata()[i]; + { VarDeclaration *v = closureVars[i]; assert(v->isVarDeclaration()); //printf("\tv = %s\n", v->toChars()); for (int j = 0; j < v->nestedrefs.dim; j++) - { FuncDeclaration *f = v->nestedrefs.tdata()[j]; + { FuncDeclaration *f = v->nestedrefs[j]; assert(f != this); //printf("\t\tf = %s, %d, %p, %d\n", f->toChars(), f->isVirtual(), f->isThis(), f->tookAddressOf); @@ -3298,7 +3331,7 @@ int FuncDeclaration::hasNestedFrameRefs() { for (size_t i = 0; i < foverrides.dim; i++) { - FuncDeclaration *fdv = foverrides.tdata()[i]; + FuncDeclaration *fdv = foverrides[i]; if (fdv->hasNestedFrameRefs()) return 1; } @@ -3386,6 +3419,7 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type, this->ident = Lexer::uniqueId(id); this->tok = tok; this->fes = fes; + this->treq = NULL; //printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars()); } @@ -3399,6 +3433,7 @@ Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s) else { f = new FuncLiteralDeclaration(loc, endloc, type->syntaxCopy(), tok, fes); f->ident = ident; // keep old identifier + f->treq = treq; // don't need to copy } FuncDeclaration::syntaxCopy(f); return f; @@ -3713,14 +3748,8 @@ char *DtorDeclaration::toChars() int DtorDeclaration::isVirtual() { - /* This should be FALSE so that dtor's don't get put into the vtbl[], - * but doing so will require recompiling everything. - */ -#if BREAKABI + // FALSE so that dtor's don't get put into the vtbl[] return FALSE; -#else - return FuncDeclaration::isVirtual(); -#endif } void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/dmd2/hdrgen.c b/dmd2/hdrgen.c index 78dd4001..87b8368f 100644 --- a/dmd2/hdrgen.c +++ b/dmd2/hdrgen.c @@ -84,7 +84,7 @@ void Module::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; s->toHBuffer(buf, hgs); } diff --git a/dmd2/hdrgen.h b/dmd2/hdrgen.h index 79cfb732..c60787ae 100644 --- a/dmd2/hdrgen.h +++ b/dmd2/hdrgen.h @@ -8,6 +8,7 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +#include // memset() struct HdrGenState { diff --git a/dmd2/idgen.c b/dmd2/idgen.c index 41f52ab7..457220bd 100644 --- a/dmd2/idgen.c +++ b/dmd2/idgen.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -66,6 +66,7 @@ Msgtable msgtable[] = { "outer" }, { "Exception" }, { "AssociativeArray" }, + { "RTInfo" }, { "Throwable" }, { "Error" }, { "withSym", "__withSym" }, @@ -356,6 +357,7 @@ Msgtable msgtable[] = { "derivedMembers" }, { "isSame" }, { "compiles" }, + { "parameters" }, }; diff --git a/dmd2/import.c b/dmd2/import.c index f4582c23..07670f4f 100644 --- a/dmd2/import.c +++ b/dmd2/import.c @@ -45,7 +45,7 @@ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *alias this->ident = aliasId; // import [std].stdio; else if (packages && packages->dim) - this->ident = packages->tdata()[0]; + this->ident = (*packages)[0]; // import [foo]; else this->ident = id; @@ -112,8 +112,18 @@ void Import::load(Scope *sc) if (s->isModule()) mod = (Module *)s; else - ::error(loc, "can only import from a module, not from package %s.%s", - pkg->toPrettyChars(), id->toChars()); + { + if (pkg) + { + ::error(loc, "can only import from a module, not from package %s.%s", + pkg->toPrettyChars(), id->toChars()); + } + else + { + ::error(loc, "can only import from a module, not from package %s", + id->toChars()); + } + } #endif } @@ -356,8 +366,8 @@ int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) */ for (size_t i = 0; i < names.dim; i++) { - Identifier *name = names.tdata()[i]; - Identifier *alias = aliases.tdata()[i]; + Identifier *name = names[i]; + Identifier *alias = aliases[i]; if (!alias) alias = name; @@ -413,12 +423,30 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (packages && packages->dim) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = packages->tdata()[i]; + { Identifier *pid = (*packages)[i]; buf->printf("%s.", pid->toChars()); } } - buf->printf("%s;", id->toChars()); + buf->printf("%s", id->toChars()); + if (names.dim) + { + buf->writestring(" : "); + for (size_t i = 0; i < names.dim; i++) + { + Identifier *name = names[i]; + Identifier *alias = aliases[i]; + + if (alias) + buf->printf("%s = %s", alias->toChars(), name->toChars()); + else + buf->printf("%s", name->toChars()); + + if (i < names.dim - 1) + buf->writestring(", "); + } + } + buf->printf(";"); buf->writenl(); } diff --git a/dmd2/inifile.c b/dmd2/inifile.c index 1bed9fe7..36b2dd41 100644 --- a/dmd2/inifile.c +++ b/dmd2/inifile.c @@ -1,6 +1,6 @@ /* * Some portions copyright (c) 1994-1995 by Symantec - * Copyright (c) 1999-2011 by Digital Mars + * Copyright (c) 1999-2012 by Digital Mars * All Rights Reserved * http://www.digitalmars.com * Written by Walter Bright @@ -31,6 +31,10 @@ #include #endif +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ +#include "gnuc.h" +#endif + #include "root.h" #include "rmem.h" diff --git a/dmd2/init.c b/dmd2/init.c index 5de6b114..23758bda 100644 --- a/dmd2/init.c +++ b/dmd2/init.c @@ -35,7 +35,7 @@ Initializer *Initializer::syntaxCopy() return this; } -Initializer *Initializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *Initializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { return this; } @@ -88,7 +88,7 @@ Initializer *VoidInitializer::syntaxCopy() } -Initializer *VoidInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *VoidInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("VoidInitializer::semantic(t = %p)\n", t); type = t; @@ -145,7 +145,7 @@ void StructInitializer::addInit(Identifier *field, Initializer *value) this->value.push(value); } -Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { int errors = 0; @@ -227,7 +227,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) } if (s && (v = s->isVarDeclaration()) != NULL) { - val = val->semantic(sc, v->type, needInterpret); + val = val->semantic(sc, v->type->addMod(t->mod), needInterpret); value[i] = val; vars[i] = v; } @@ -353,8 +353,12 @@ Expression *StructInitializer::toExpression() else { if (!(*elements)[i]) - // Default initialize - (*elements)[i] = vd->type->defaultInit(); + { // Default initialize + if (vd->init) + (*elements)[i] = vd->init->toExpression(); + else + (*elements)[i] = vd->type->defaultInit(); + } } offset = vd->offset + vd->type->size(); i++; @@ -464,7 +468,7 @@ void ArrayInitializer::addInit(Expression *index, Initializer *value) type = NULL; } -Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { unsigned i; unsigned length; const unsigned amax = 0x80000000; @@ -482,6 +486,10 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) case Tarray: break; + case Tvector: + t = ((TypeVector *)t)->basetype; + break; + default: error(loc, "cannot use array to initialize %s", type->toChars()); goto Lerr; @@ -493,14 +501,39 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); - idx = idx->optimize(WANTvalue | WANTinterpret); + idx = idx->ctfeInterpret(); index[i] = idx; length = idx->toInteger(); } Initializer *val = value[i]; + ExpInitializer *ei = val->isExpInitializer(); + if (ei && !idx) + ei->expandTuples = 1; val = val->semantic(sc, t->nextOf(), needInterpret); - value[i] = val; + + ei = val->isExpInitializer(); + // found a tuple, expand it + if (ei && ei->exp->op == TOKtuple) + { + TupleExp *te = (TupleExp *)ei->exp; + index.remove(i); + value.remove(i); + + for (size_t j = 0; j < te->exps->dim; ++j) + { + Expression *e = (*te->exps)[j]; + index.insert(i + j, (Expression *)NULL); + value.insert(i + j, new ExpInitializer(e->loc, e)); + } + i--; + continue; + } + else + { + value[i] = val; + } + length++; if (length == 0) { error(loc, "array dimension overflow"); @@ -746,6 +779,7 @@ ExpInitializer::ExpInitializer(Loc loc, Expression *exp) : Initializer(loc) { this->exp = exp; + this->expandTuples = 0; } Initializer *ExpInitializer::syntaxCopy() @@ -757,6 +791,9 @@ bool arrayHasNonConstPointers(Expressions *elems); bool hasNonConstPointers(Expression *e) { + if (e->type->ty == Terror) + return false; + if (e->op == TOKnull) return false; if (e->op == TOKstructliteral) @@ -817,15 +854,19 @@ bool arrayHasNonConstPointers(Expressions *elems) -Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) +Initializer *ExpInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - int wantOptimize = needInterpret ? WANTinterpret|WANTvalue : WANTvalue; + if (exp->op == TOKerror) + return this; int olderrors = global.errors; - exp = exp->optimize(wantOptimize); + if (needInterpret) + exp = exp->ctfeInterpret(); + else + exp = exp->optimize(WANTvalue); if (!global.gag && olderrors != global.errors) return this; // Failed, suppress duplicate error messages @@ -841,6 +882,11 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) Type *tb = t->toBasetype(); + if (exp->op == TOKtuple && + expandTuples && + !exp->implicitConvTo(t)) + return new ExpInitializer(loc, exp); + /* Look for case of initializing a static array with a too-short * string literal, such as: * char[5] foo = "abc"; @@ -870,8 +916,13 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) } exp = exp->implicitCastTo(sc, t); + if (exp->op == TOKerror) + return this; L1: - exp = exp->optimize(wantOptimize); + if (needInterpret) + exp = exp->ctfeInterpret(); + else + exp = exp->optimize(WANTvalue); //printf("-ExpInitializer::semantic(): "); exp->print(); return this; } diff --git a/dmd2/init.h b/dmd2/init.h index d038dd9e..260f35c8 100644 --- a/dmd2/init.h +++ b/dmd2/init.h @@ -34,6 +34,7 @@ namespace llvm { } #endif +enum NeedInterpret { INITnointerpret, INITinterpret }; struct Initializer : Object { @@ -41,8 +42,8 @@ struct Initializer : Object Initializer(Loc loc); virtual Initializer *syntaxCopy(); - // needInterpret is WANTinterpret if must be a manifest constant, 0 if not. - virtual Initializer *semantic(Scope *sc, Type *t, int needInterpret); + // 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 void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; @@ -66,7 +67,7 @@ struct VoidInitializer : Initializer VoidInitializer(Loc loc); Initializer *syntaxCopy(); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); Expression *toExpression(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -88,7 +89,7 @@ struct StructInitializer : Initializer StructInitializer(Loc loc); Initializer *syntaxCopy(); void addInit(Identifier *field, Initializer *value); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); Expression *toExpression(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -113,7 +114,7 @@ struct ArrayInitializer : Initializer ArrayInitializer(Loc loc); Initializer *syntaxCopy(); void addInit(Expression *index, Initializer *value); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); int isAssociativeArray(); Type *inferType(Scope *sc); Expression *toExpression(); @@ -131,10 +132,11 @@ struct ArrayInitializer : Initializer struct ExpInitializer : Initializer { Expression *exp; + int expandTuples; ExpInitializer(Loc loc, Expression *exp); Initializer *syntaxCopy(); - Initializer *semantic(Scope *sc, Type *t, int needInterpret); + Initializer *semantic(Scope *sc, Type *t, NeedInterpret needInterpret); Type *inferType(Scope *sc); Expression *toExpression(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/dmd2/inline.c b/dmd2/inline.c index 47eebe6d..a8e682b4 100644 --- a/dmd2/inline.c +++ b/dmd2/inline.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -14,6 +14,7 @@ #include #include #include +#include // memset() #include "id.h" #include "init.h" @@ -618,11 +619,11 @@ Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) newa->setDim(a->dim); for (size_t i = 0; i < a->dim; i++) - { Expression *e = a->tdata()[i]; + { Expression *e = (*a)[i]; if (e) e = e->doInline(ids); - newa->tdata()[i] = e; + (*newa)[i] = e; } } return newa; @@ -639,11 +640,11 @@ Expression *SymOffExp::doInline(InlineDoState *ids) //printf("SymOffExp::doInline(%s)\n", toChars()); for (size_t i = 0; i < ids->from.dim; i++) { - if (var == ids->from.tdata()[i]) + if (var == ids->from[i]) { SymOffExp *se = (SymOffExp *)copy(); - se->var = (Declaration *)ids->to.tdata()[i]; + se->var = (Declaration *)ids->to[i]; return se; } } @@ -655,11 +656,11 @@ Expression *VarExp::doInline(InlineDoState *ids) //printf("VarExp::doInline(%s)\n", toChars()); for (size_t i = 0; i < ids->from.dim; i++) { - if (var == ids->from.tdata()[i]) + if (var == ids->from[i]) { VarExp *ve = (VarExp *)copy(); - ve->var = (Declaration *)ids->to.tdata()[i]; + ve->var = (Declaration *)ids->to[i]; return ve; } } @@ -709,7 +710,7 @@ Expression *DeclarationExp::doInline(InlineDoState *ids) if (td) { for (size_t i = 0; i < td->objects->dim; i++) - { DsymbolExp *se = td->objects->tdata()[i]; + { DsymbolExp *se = (*td->objects)[i]; assert(se->op == TOKdsymbol); se->s; } @@ -1098,8 +1099,8 @@ Statement *SwitchStatement::inlineScan(InlineScanState *iss) for (size_t i = 0; i < cases->dim; i++) { CaseStatement *s; - s = cases->tdata()[i]; - cases->tdata()[i] = (CaseStatement *)s->inlineScan(iss); + s = (*cases)[i]; + (*cases)[i] = (CaseStatement *)s->inlineScan(iss); } } return this; @@ -1130,6 +1131,65 @@ Statement *ReturnStatement::inlineScan(InlineScanState *iss) if (exp) { exp = exp->inlineScan(iss); + + FuncDeclaration *func = iss->fd; + TypeFunction *tf = (TypeFunction *)(func->type); + + /* Postblit call on return statement is processed in glue layer + * (Because NRVO may eliminate the copy), but inlining may remove + * ReturnStatement itself. To keep semantics we should insert + * temporary variable for postblit call. + * This is mostly the same as ReturnStatement::toIR. + */ + enum RET retmethod = tf->retStyle(); + if (retmethod == RETstack) + { + if (func->nrvo_can && func->nrvo_var) + ; + else + { + Type *tb = exp->type->toBasetype(); + if (exp->isLvalue() && tb->ty == Tstruct) + { StructDeclaration *sd = ((TypeStruct *)tb)->sym; + if (sd->postblit) + { FuncDeclaration *fd = sd->postblit; + if (fd->storage_class & STCdisable) + { + fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); + } + + /* Rewirte exp as: + * (__inlinectmp = exp), __inlinectmp.__postblit(), __inlinectmp + * And, __inlinectmp is marked as rvalue (See STCtemp comment) + */ + ExpInitializer *ei = new ExpInitializer(loc, exp); + + Identifier* tmp = Identifier::generateId("__inlinectmp"); + VarDeclaration *v = new VarDeclaration(loc, exp->type, tmp, ei); + v->storage_class = STCtemp; + v->linkage = LINKd; + v->parent = func; + + VarExp *ve = new VarExp(loc, v); + ve->type = exp->type; + + ei->exp = new ConstructExp(loc, ve, exp); + ei->exp->type = exp->type; + + DeclarationExp *de = new DeclarationExp(0, v); + de->type = Type::tvoid; + + Expression *e = new DotVarExp(ve->loc, ve, sd->postblit, 0); + e->type = sd->postblit->type; + e = new CallExp(ve->loc, e); + e->type = Type::tvoid; + + exp = Expression::combine(de, e); + exp = Expression::combine(exp, ve); + } + } + } + } } return this; } @@ -1162,7 +1222,7 @@ Statement *TryCatchStatement::inlineScan(InlineScanState *iss) if (catches) { for (size_t i = 0; i < catches->dim; i++) - { Catch *c = catches->tdata()[i]; + { Catch *c = (*catches)[i]; if (c->handler) c->handler = c->handler->inlineScan(iss); @@ -1212,12 +1272,12 @@ void arrayInlineScan(InlineScanState *iss, Expressions *arguments) if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = (*arguments)[i]; if (e) { e = e->inlineScan(iss); - arguments->tdata()[i] = e; + (*arguments)[i] = e; } } } @@ -1237,7 +1297,7 @@ void scanVar(Dsymbol *s, InlineScanState *iss) if (td) { for (size_t i = 0; i < td->objects->dim; i++) - { DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i]; + { DsymbolExp *se = (DsymbolExp *)(*td->objects)[i]; assert(se->op == TOKdsymbol); scanVar(se->s, iss); } @@ -1546,7 +1606,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) { for (size_t i = 0; i < parameters->dim; i++) { - VarDeclaration *v = parameters->tdata()[i]; + VarDeclaration *v = (*parameters)[i]; if (v->type->toBasetype()->ty == Tsarray) goto Lno; } @@ -1701,9 +1761,9 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi for (size_t i = 0; i < arguments->dim; i++) { - VarDeclaration *vfrom = parameters->tdata()[i]; + VarDeclaration *vfrom = (*parameters)[i]; VarDeclaration *vto; - Expression *arg = arguments->tdata()[i]; + Expression *arg = (*arguments)[i]; ExpInitializer *ei; VarExp *ve; @@ -1778,7 +1838,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi Identifier* tmp = Identifier::generateId("__inlineretval"); VarDeclaration* vd = new VarDeclaration(loc, tf->next, tmp, ei); - vd->storage_class = tf->isref ? STCref : 0; + vd->storage_class = (tf->isref ? STCref : 0) | STCtemp; vd->linkage = tf->linkage; vd->parent = iss->fd; diff --git a/dmd2/interpret.c b/dmd2/interpret.c index 425a836d..b213d624 100644 --- a/dmd2/interpret.c +++ b/dmd2/interpret.c @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -10,6 +10,7 @@ #include #include #include +#include // mem{cpy|set}() #include "rmem.h" @@ -27,6 +28,8 @@ #include "attrib.h" // for AttribDeclaration #include "template.h" +#include "port.h" +int RealEquals(real_t x1, real_t x2); #define LOG 0 @@ -62,7 +65,7 @@ private: size_t framepointer; // current frame pointer size_t maxStackPointer; // most stack we've ever used public: - CtfeStack() : framepointer(0) + CtfeStack() : framepointer(0), maxStackPointer(0) { } size_t stackPointer() @@ -92,16 +95,16 @@ public: { assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < globalValues.dim); - return globalValues.tdata()[v->ctfeAdrOnStack]; + return globalValues[v->ctfeAdrOnStack]; } assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); - return values.tdata()[v->ctfeAdrOnStack]; + return values[v->ctfeAdrOnStack]; } void setValue(VarDeclaration *v, Expression *e) { assert(!v->isDataseg() || v->isCTFE()); assert(v->ctfeAdrOnStack >= 0 && v->ctfeAdrOnStack < stackPointer()); - values.tdata()[v->ctfeAdrOnStack] = e; + values[v->ctfeAdrOnStack] = e; } void push(VarDeclaration *v) { @@ -109,7 +112,7 @@ public: if (v->ctfeAdrOnStack!= (size_t)-1 && v->ctfeAdrOnStack >= framepointer) { // Already exists in this frame, reuse it. - values.tdata()[v->ctfeAdrOnStack] = NULL; + values[v->ctfeAdrOnStack] = NULL; return; } savedId.push((void *)(v->ctfeAdrOnStack)); @@ -122,7 +125,7 @@ public: assert(!v->isDataseg() || v->isCTFE()); assert(!(v->storage_class & (STCref | STCout))); int oldid = v->ctfeAdrOnStack; - v->ctfeAdrOnStack = (size_t)(savedId.tdata()[oldid]); + v->ctfeAdrOnStack = (size_t)(savedId[oldid]); if (v->ctfeAdrOnStack == values.dim - 1) { values.pop(); @@ -137,8 +140,8 @@ public: assert(values.dim >= stackpointer && stackpointer >= 0); for (size_t i = stackpointer; i < values.dim; ++i) { - VarDeclaration *v = vars.tdata()[i]; - v->ctfeAdrOnStack = (size_t)(savedId.tdata()[i]); + VarDeclaration *v = vars[i]; + v->ctfeAdrOnStack = (size_t)(savedId[i]); } values.setDim(stackpointer); vars.setDim(stackpointer); @@ -221,6 +224,7 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, Expression *scrubReturnValue(Loc loc, Expression *e); bool isAssocArray(Type *t); bool isPointer(Type *t); +Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2); // CTFE only expressions #define TOKclassreference ((TOK)(TOKMAX+1)) @@ -258,7 +262,7 @@ struct ClassReferenceExp : Expression { fieldsSoFar += cd->fields.dim; cd = cd->baseClass; } - return cd->fields.tdata()[index - fieldsSoFar]; + return cd->fields[index - fieldsSoFar]; } // Return index of the field, or -1 if not found int getFieldIndex(Type *fieldtype, size_t fieldoffset) @@ -270,7 +274,7 @@ struct ClassReferenceExp : Expression { fieldsSoFar += cd->fields.dim; cd = cd->baseClass; } - Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; + Dsymbol *s = cd->fields[j - fieldsSoFar]; VarDeclaration *v2 = s->isVarDeclaration(); if (fieldoffset == v2->offset && fieldtype->size() == v2->type->size()) @@ -290,7 +294,7 @@ struct ClassReferenceExp : Expression { fieldsSoFar += cd->fields.dim; cd = cd->baseClass; } - Dsymbol *s = cd->fields.tdata()[j - fieldsSoFar]; + Dsymbol *s = cd->fields[j - fieldsSoFar]; VarDeclaration *v2 = s->isVarDeclaration(); if (v == v2) { return value->elements->dim - fieldsSoFar - cd->fields.dim + (j-fieldsSoFar); @@ -328,7 +332,7 @@ int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) { for (int i = 0; i < sd->fields.dim; ++i) { - if (sd->fields.tdata()[i] == v) + if (sd->fields[i] == v) return i; } return -1; @@ -449,8 +453,8 @@ void showCtfeExpr(Expression *e, int level = 0) return; } if (sd) - { s = sd->fields.tdata()[i]; - z = elements->tdata()[i]; + { s = sd->fields[i]; + z = (*elements)[i]; } else if (cd) { while (i - fieldsSoFar >= cd->fields.dim) @@ -459,11 +463,11 @@ void showCtfeExpr(Expression *e, int level = 0) for (int j = level; j>0; --j) printf(" "); printf(" BASE CLASS: %s\n", cd->toChars()); } - s = cd->fields.tdata()[i - fieldsSoFar]; + s = cd->fields[i - fieldsSoFar]; size_t indx = (elements->dim - fieldsSoFar)- cd->fields.dim + i; assert(indx >= 0); assert(indx < elements->dim); - z = elements->tdata()[indx]; + z = (*elements)[indx]; } if (!z) { for (int j = level; j>0; --j) printf(" "); @@ -488,6 +492,16 @@ void showCtfeExpr(Expression *e, int level = 0) } } +/************************************* + * + * Entry point for CTFE. + * A compile-time result is required. Give an error if not possible + */ +Expression *Expression::ctfeInterpret() +{ + return optimize(WANTvalue | WANTinterpret); +} + /************************************* * Attempt to interpret a function given the arguments. * Input: @@ -582,7 +596,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument Expressions eargs; eargs.setDim(dim); for (size_t i = 0; i < dim; i++) - { Expression *earg = arguments->tdata()[i]; + { Expression *earg = (*arguments)[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); if (arg->storageClass & (STCout | STCref)) @@ -635,13 +649,13 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument ((ThrownExceptionExp *)earg)->generateUncaughtError(); return EXP_CANT_INTERPRET; } - eargs.tdata()[i] = earg; + eargs[i] = earg; } for (size_t i = 0; i < dim; i++) - { Expression *earg = eargs.tdata()[i]; + { Expression *earg = eargs[i]; Parameter *arg = Parameter::getNth(tf->parameters, i); - VarDeclaration *v = parameters->tdata()[i]; + VarDeclaration *v = (*parameters)[i]; #if LOG printf("arg[%d] = %s\n", i, earg->toChars()); #endif @@ -807,7 +821,7 @@ Expression *CompoundStatement::interpret(InterState *istate) if (statements) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = statements->tdata()[i]; + { Statement *s = (*statements)[i]; if (s) { @@ -834,7 +848,7 @@ Expression *UnrolledLoopStatement::interpret(InterState *istate) if (statements) { for (size_t i = 0; i < statements->dim; i++) - { Statement *s = statements->tdata()[i]; + { Statement *s = (*statements)[i]; e = s->interpret(istate); if (e == EXP_CANT_INTERPRET) @@ -954,19 +968,6 @@ uinteger_t resolveArrayLength(Expression *e) return 0; } -// As Equal, but resolves slices before comparing -Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) -{ - if (e1->op == TOKslice) - e1 = resolveSlice(e1); - if (e2->op == TOKslice) - e2 = resolveSlice(e2); - Expression *e = Equal(op, type, e1, e2); - if (e == EXP_CANT_INTERPRET) - error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars()); - return e; -} - Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) { Loc loc = e1->loc; @@ -1219,38 +1220,14 @@ Expression *DoStatement::interpret(InterState *istate) istate->start = NULL; Expression *e; - if (istate->start) - { - e = body ? body->interpret(istate) : NULL; - if (istate->start) - return NULL; - if (e == EXP_CANT_INTERPRET) - return e; - if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level - return e; - } - if (e == EXP_CONTINUE_INTERPRET) - if (!istate->gotoTarget || istate->gotoTarget == this) - { - goto Lcontinue; - } - else // else continue at a higher level - return e; - if (e) - return e; - } - while (1) { + bool wasGoto = !!istate->start; e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) break; + if (wasGoto && istate->start) + return NULL; if (e == EXP_BREAK_INTERPRET) { if (!istate->gotoTarget || istate->gotoTarget == this) @@ -1303,79 +1280,53 @@ Expression *ForStatement::interpret(InterState *istate) return e; assert(!e); } - - if (istate->start) + while (1) { + if (condition && !istate->start) + { + e = condition->interpret(istate); + if (exceptionOrCantInterpret(e)) + break; + if (!e->isConst()) + { e = EXP_CANT_INTERPRET; + break; + } + if (e->isBool(FALSE)) + { e = NULL; + break; + } + assert( isTrueBool(e) ); + } + + bool wasGoto = !!istate->start; e = body ? body->interpret(istate) : NULL; - if (istate->start) - return NULL; if (e == EXP_CANT_INTERPRET) - return e; + break; + if (wasGoto && istate->start) + return NULL; + if (e == EXP_BREAK_INTERPRET) { if (!istate->gotoTarget || istate->gotoTarget == this) { istate->gotoTarget = NULL; - return NULL; + e = NULL; } // else break at a higher level + break; } - if (e == EXP_CONTINUE_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - goto Lcontinue; - } // else continue at a higher level - } - if (e) - return e; - } + if (e && e != EXP_CONTINUE_INTERPRET) + break; - while (1) - { - if (!condition) - goto Lhead; - e = condition->interpret(istate); - if (exceptionOrCantInterpret(e)) - break; - if (!e->isConst()) - { e = EXP_CANT_INTERPRET; - break; - } - if (isTrueBool(e)) + if (istate->gotoTarget && istate->gotoTarget != this) + break; // continue at a higher level + istate->gotoTarget = NULL; + + if (increment) { - Lhead: - e = body ? body->interpret(istate) : NULL; + e = increment->interpret(istate); if (e == EXP_CANT_INTERPRET) break; - if (e == EXP_BREAK_INTERPRET) - { - if (!istate->gotoTarget || istate->gotoTarget == this) - { - istate->gotoTarget = NULL; - e = NULL; - } // else break at a higher level - break; - } - if (e && e != EXP_CONTINUE_INTERPRET) - break; - if (istate->gotoTarget && istate->gotoTarget != this) - break; // continue at a higher level - Lcontinue: - istate->gotoTarget = NULL; - if (increment) - { - e = increment->interpret(istate); - if (e == EXP_CANT_INTERPRET) - break; - } } - else if (e->isBool(FALSE)) - { e = NULL; - break; - } - else - assert(0); } return e; } @@ -1433,7 +1384,7 @@ Expression *SwitchStatement::interpret(InterState *istate) { for (size_t i = 0; i < cases->dim; i++) { - CaseStatement *cs = cases->tdata()[i]; + CaseStatement *cs = (*cases)[i]; Expression * caseExp = cs->exp->interpret(istate); if (exceptionOrCantInterpret(caseExp)) return caseExp; @@ -1973,11 +1924,12 @@ Expression * resolveReferences(Expression *e, Expression *thisval) { VarExp *ve = (VarExp *)e; VarDeclaration *v = ve->var->isVarDeclaration(); + assert(v); if (v->type->ty == Tpointer) break; if (v->ctfeAdrOnStack == (size_t)-1) // If not on the stack, can't possibly be a ref. break; - if (v && v->getValue() && (v->getValue()->op == TOKslice)) + if (v->getValue() && (v->getValue()->op == TOKslice)) { SliceExp *se = (SliceExp *)v->getValue(); if (se->e1->op == TOKarrayliteral || se->e1->op == TOKassocarrayliteral || se->e1->op == TOKstring) @@ -1985,7 +1937,7 @@ Expression * resolveReferences(Expression *e, Expression *thisval) e = v->getValue(); continue; } - else if (v && v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar + else if (v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar || v->getValue()->op == TOKthis )) { e = v->getValue(); @@ -2076,10 +2028,10 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal e = EXP_CANT_INTERPRET; } else if (!e) - { - assert(0); - assert(v->init && v->init->isVoidInitializer()); - e = v->type->voidInitLiteral(v); + { assert(!(v->init && v->init->isVoidInitializer())); + // CTFE initiated from inside a function + error(loc, "variable %s cannot be read at compile time", v->toChars()); + return EXP_CANT_INTERPRET; } else if (exceptionOrCantInterpret(e)) return e; @@ -2261,7 +2213,7 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) Expressions *expsx = NULL; for (size_t i = 0; i < exps->dim; i++) - { Expression *e = exps->tdata()[i]; + { Expression *e = (*exps)[i]; Expression *ex; ex = e->interpret(istate); @@ -2289,10 +2241,10 @@ Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal) expsx->setDim(exps->dim); for (size_t j = 0; j < i; j++) { - expsx->tdata()[j] = exps->tdata()[j]; + (*expsx)[j] = (*exps)[j]; } } - expsx->tdata()[i] = ex; + (*expsx)[i] = ex; } } if (expsx) @@ -2315,7 +2267,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; Expression *ex; if (e->op == TOKindex) // segfault bug 6250 @@ -2336,10 +2288,10 @@ Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) expsx->setDim(elements->dim); for (size_t j = 0; j < elements->dim; j++) { - expsx->tdata()[j] = elements->tdata()[j]; + (*expsx)[j] = (*elements)[j]; } } - expsx->tdata()[i] = ex; + (*expsx)[i] = ex; } } } @@ -2481,7 +2433,7 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; if (!e) continue; @@ -2501,10 +2453,10 @@ Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal) expsx->setDim(elements->dim); for (size_t j = 0; j < elements->dim; j++) { - expsx->tdata()[j] = elements->tdata()[j]; + (*expsx)[j] = (*elements)[j]; } } - expsx->tdata()[i] = ex; + (*expsx)[i] = ex; } } } @@ -2536,7 +2488,7 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Loc loc, Type *type, for (size_t i = 0; i < dim; i++) { if (mustCopy) elem = copyLiteral(elem); - elements->tdata()[i] = elem; + (*elements)[i] = elem; } ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); ae->type = type; @@ -2576,7 +2528,7 @@ StringExp *createBlockDuplicatedStringLiteral(Loc loc, Type *type, Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *istate, Expressions *arguments, int argnum) { - Expression *lenExpr = ((arguments->tdata()[argnum]))->interpret(istate); + Expression *lenExpr = (((*arguments)[argnum]))->interpret(istate); if (exceptionOrCantInterpret(lenExpr)) return lenExpr; size_t len = (size_t)(lenExpr->toInteger()); @@ -2591,7 +2543,7 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is Expressions *elements = new Expressions(); elements->setDim(len); for (size_t i = 0; i < len; i++) - elements->tdata()[i] = copyLiteral(elem); + (*elements)[i] = copyLiteral(elem); ArrayLiteralExp *ae = new ArrayLiteralExp(loc, elements); ae->type = newtype; ae->ownedByCtfe = true; @@ -2652,7 +2604,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) fieldsSoFar -= c->fields.dim; for (size_t i = 0; i < c->fields.dim; i++) { - Dsymbol *s = c->fields.tdata()[i]; + Dsymbol *s = c->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc); @@ -2930,20 +2882,24 @@ BIN_INTERPRET(Pow) #endif -typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *); +typedef Expression *(*fp2_t)(Loc loc, enum TOK, Type *, Expression *, Expression *); -// Return EXP_CANT_INTERPRET if they point to independent memory blocks -Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) +/** Return true if agg1 and agg2 are pointers to the same memory block +*/ +bool pointToSameMemoryBlock(Expression *agg1, Expression *agg2) { - dinteger_t ofs1, ofs2; - Expression *agg1 = getAggregateFromPointer(e1, &ofs1); - Expression *agg2 = getAggregateFromPointer(e2, &ofs2); // Note that type painting can occur with VarExp, so we // must compare the variables being pointed to. - if (agg1 == agg2 || - (agg1->op == TOKvar && agg2->op == TOKvar && - ((VarExp *)agg1)->var == ((VarExp *)agg2)->var) - ) + return agg1 == agg2 || + (agg1->op == TOKvar && agg2->op == TOKvar && + ((VarExp *)agg1)->var == ((VarExp *)agg2)->var); +} + +// Return 1 if true, 0 if false +// -1 if comparison is illegal because they point to non-comparable memory blocks +int comparePointers(Loc loc, enum TOK op, Type *type, Expression *agg1, dinteger_t ofs1, Expression *agg2, dinteger_t ofs2) +{ + if ( pointToSameMemoryBlock(agg1, agg2) ) { dinteger_t cm = ofs1 - ofs2; dinteger_t n; @@ -2961,16 +2917,27 @@ Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Ex default: assert(0); } - return new IntegerExp(loc, n, type); + return n; } + bool null1 = ( agg1->op == TOKnull ); + bool null2 = ( agg2->op == TOKnull ); + int cmp; - if (agg1->op == TOKnull) + if (null1 || null2) { - cmp = (agg2->op == TOKnull); - } - else if (agg2->op == TOKnull) - { - cmp = 0; + switch (op) + { + case TOKlt: cmp = null1 && !null2; break; + case TOKgt: cmp = !null1 && null2; break; + case TOKle: cmp = null1; break; + case TOKge: cmp = null2; break; + case TOKidentity: + case TOKequal: + case TOKnotidentity: // 'cmp' gets inverted below + case TOKnotequal: + cmp = (null1 == null2); + break; + } } else { @@ -2983,30 +2950,237 @@ Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Ex cmp = 0; break; default: - return EXP_CANT_INTERPRET; + return -1; // memory blocks are different } } + if (op == TOKnotidentity || op == TOKnotequal) + cmp ^= 1; + return cmp; +} + + +int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2); + +/* Conceptually the same as memcmp(e1, e2). + * e1 and e2 may be strings, arrayliterals, or slices. + * For string types, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2. + * For all other types, return 0 if e1 == e2, !=0 if e1 != e2. + */ +int ctfeCmpArrays(Loc loc, Expression *e1, Expression *e2, uinteger_t len) +{ + // Resolve slices, if necessary + uinteger_t lo1 = 0; + uinteger_t lo2 = 0; + + Expression *x = e1; + if (x->op == TOKslice) + { lo1 = ((SliceExp *)x)->lwr->toInteger(); + x = ((SliceExp*)x)->e1; + } + StringExp *se1 = (x->op == TOKstring) ? (StringExp *)x : 0; + ArrayLiteralExp *ae1 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : 0; + + x = e2; + if (x->op == TOKslice) + { lo2 = ((SliceExp *)x)->lwr->toInteger(); + x = ((SliceExp*)x)->e1; + } + StringExp *se2 = (x->op == TOKstring) ? (StringExp *)x : 0; + ArrayLiteralExp *ae2 = (x->op == TOKarrayliteral) ? (ArrayLiteralExp *)x : 0; + + // Now both must be either TOKarrayliteral or TOKstring + if (se1 && se2) + return sliceCmpStringWithString(se1, se2, lo1, lo2, len); + if (se1 && ae2) + return sliceCmpStringWithArray(se1, ae2, lo1, lo2, len); + if (se2 && ae1) + return -sliceCmpStringWithArray(se2, ae1, lo2, lo1, len); + + assert (ae1 && ae2); + // Comparing two array literals. This case is potentially recursive. + // If they aren't strings, we just need an equality check rather than + // a full cmp. + bool needCmp = ae1->type->nextOf()->isintegral(); + for (size_t i = 0; i < len; i++) + { Expression *ee1 = (*ae1->elements)[lo1 + i]; + Expression *ee2 = (*ae2->elements)[lo2 + i]; + if (needCmp) + { int c = ee1->toInteger() - ee2->toInteger(); + if (c) + return c; + } + else + { if (ctfeRawCmp(loc, ee1, ee2)) + return 1; + } + } + return 0; +} + +bool isArray(Expression *e) +{ + return e->op == TOKarrayliteral || e->op == TOKstring || + e->op == TOKslice || e->op == TOKnull; +} + +/* For strings, return <0 if e1 < e2, 0 if e1==e2, >0 if e1 > e2. + * For all other types, return 0 if e1 == e2, !=0 if e1 != e2. + */ +int ctfeRawCmp(Loc loc, Expression *e1, Expression *e2) +{ + if (e1->op == TOKclassreference || e2->op == TOKclassreference) + { if (e1->op == TOKclassreference && e2->op == TOKclassreference && + ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value) + return 0; + return 1; + } + if (e1->op == TOKnull && e2->op == TOKnull) + return 0; + + if (e1->type->ty == Tpointer && e2->type->ty == Tpointer) + { // Can only be an equality test. + if (e1->op == TOKnull && e2->op == TOKnull) + return 0; + dinteger_t ofs1, ofs2; + Expression *agg1 = getAggregateFromPointer(e1, &ofs1); + Expression *agg2 = getAggregateFromPointer(e2, &ofs2); + if ((agg1 == agg2) || (agg1->op == TOKvar && agg2->op == TOKvar && + ((VarExp *)agg1)->var == ((VarExp *)agg2)->var)) + { if (ofs1 == ofs2) + return 0; + } + return 1; + } + if (isArray(e1) && isArray(e2)) + { + uinteger_t len1 = resolveArrayLength(e1); + uinteger_t len2 = resolveArrayLength(e2); + if (len1 != len2) // only for equality + return len1 - len2; + if (len1 == 0 || len2 == 0) + return len1 - len2; // Equal - both are empty + return ctfeCmpArrays(loc, e1, e2, len1); + } + if (e1->type->isintegral()) + { + return e1->toInteger() - e2->toInteger(); + } + real_t r1; + real_t r2; + if (e1->type->isreal()) + { + r1 = e1->toReal(); + r2 = e2->toReal(); + goto L1; + } + else if (e1->type->isimaginary()) + { + r1 = e1->toImaginary(); + r2 = e2->toImaginary(); + L1: +#if __DMC__ + return (r1 != r2); +#else + if (Port::isNan(r1) || Port::isNan(r2)) // if unordered + { + return 1; + } + else + { + return (r1 != r2); + } +#endif + } + else if (e1->type->iscomplex()) + { + return e1->toComplex() != e2->toComplex(); + } + + if (e1->op == TOKstructliteral && e2->op == TOKstructliteral) + { StructLiteralExp *es1 = (StructLiteralExp *)e1; + StructLiteralExp *es2 = (StructLiteralExp *)e2; + // For structs, we only need to return 0 or 1 (< and > aren't legal). + + if (es1->sd != es2->sd) + return 1; + else if ((!es1->elements || !es1->elements->dim) && + (!es2->elements || !es2->elements->dim)) + return 0; // both arrays are empty + else if (!es1->elements || !es2->elements) + return 1; + else if (es1->elements->dim != es2->elements->dim) + return 1; + else + { + for (size_t i = 0; i < es1->elements->dim; i++) + { Expression *ee1 = (*es1->elements)[i]; + Expression *ee2 = (*es2->elements)[i]; + + if (ee1 == ee2) + continue; + if (!ee1 || !ee2) + return 1; + int cmp = ctfeRawCmp(loc, ee1, ee2); + if (cmp) + return 1; + } + return 0; // All elements are equal + } + } + error(loc, "CTFE internal error: bad compare"); + assert(0); + return 0; +} + +// As Equal, but resolves slices before comparing +Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) +{ + int cmp = !ctfeRawCmp(loc, e1, e2); + if (op == TOKnotequal) + cmp ^= 1; + return new IntegerExp(loc, cmp, type); +} + +Expression *ctfeIdentity(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) +{ + int cmp; + if (e1->op == TOKnull) + { + cmp = (e2->op == TOKnull); + } + else if (e2->op == TOKnull) + { + cmp = 0; + } + else if (e1->op == TOKsymoff && e2->op == TOKsymoff) + { + SymOffExp *es1 = (SymOffExp *)e1; + SymOffExp *es2 = (SymOffExp *)e2; + cmp = (es1->var == es2->var && es1->offset == es2->offset); + } + else if (e1->type->isreal()) + cmp = RealEquals(e1->toReal(), e2->toReal()); + else if (e1->type->isimaginary()) + cmp = RealEquals(e1->toImaginary(), e2->toImaginary()); + else if (e1->type->iscomplex()) + { complex_t v1 = e1->toComplex(); + complex_t v2 = e2->toComplex(); + cmp = RealEquals(creall(v1), creall(v2)) && + RealEquals(cimagl(v1), cimagl(v1)); + } + else + cmp = !ctfeRawCmp(loc, e1, e2); + if (op == TOKnotidentity || op == TOKnotequal) cmp ^= 1; return new IntegerExp(loc, cmp, type); } -Expression *ctfeIdentity(enum TOK op, Type *type, Expression *e1, Expression *e2) +Expression *ctfeCmp(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) { - if (e1->op == TOKclassreference || e2->op == TOKclassreference) - { - int cmp = 0; - if (e1->op == TOKclassreference && e2->op == TOKclassreference && - ((ClassReferenceExp *)e1)->value == ((ClassReferenceExp *)e2)->value) - cmp = 1; - if (op == TOKnotidentity || op == TOKnotequal) - cmp ^= 1; - return new IntegerExp(e1->loc, cmp, type); - } - return Identity(op, type, e1, e2); + return Cmp(op, type, e1, e2); } - Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp) { Expression *e; Expression *e1; @@ -3023,14 +3197,20 @@ Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp e2 = this->e2->interpret(istate, ctfeNeedLvalue); if (exceptionOrCantInterpret(e2)) return e2; - e = comparePointers(loc, op, type, e1, e2); - if (e == EXP_CANT_INTERPRET) + dinteger_t ofs1, ofs2; + Expression *agg1 = getAggregateFromPointer(e1, &ofs1); + Expression *agg2 = getAggregateFromPointer(e2, &ofs2); + int cmp = comparePointers(loc, op, type, agg1, ofs1, agg2, ofs2); + if (cmp == -1) { - error("%s and %s point to independent memory blocks and " - "cannot be compared at compile time", this->e1->toChars(), - this->e2->toChars()); + char dir = (op == TOKgt || op == TOKge) ? '<' : '>'; + error("The ordering of pointers to unrelated memory blocks is indeterminate in CTFE." + " To check if they point to the same memory block, use both > and < inside && or ||, " + "eg (%s && %s %c= %s + 1)", + toChars(), this->e1->toChars(), dir, this->e2->toChars()); + return EXP_CANT_INTERPRET; } - return e; + return new IntegerExp(loc, cmp, type); } e1 = this->e1->interpret(istate); if (exceptionOrCantInterpret(e1)) @@ -3064,7 +3244,7 @@ Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp error("cannot compare %s at compile time", e2->toChars()); goto Lcant; } - e = (*fp)(op, type, e1, e2); + e = (*fp)(loc, op, type, e1, e2); if (e == EXP_CANT_INTERPRET) error("%s cannot be interpreted at compile time", toChars()); return e; @@ -3079,9 +3259,9 @@ Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \ return interpretCommon2(istate, goal, &opfunc); \ } -BIN_INTERPRET2(Equal, Equal) +BIN_INTERPRET2(Equal, ctfeEqual) BIN_INTERPRET2(Identity, ctfeIdentity) -BIN_INTERPRET2(Cmp, Cmp) +BIN_INTERPRET2(Cmp, ctfeCmp) /* Helper functions for BinExp::interpretAssignCommon */ @@ -3097,9 +3277,9 @@ Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expre for (size_t j = 0; j < expsx->dim; j++) { if (j == indexToChange) - expsx->tdata()[j] = newelem; + (*expsx)[j] = newelem; else - expsx->tdata()[j] = oldelems->tdata()[j]; + (*expsx)[j] = oldelems->tdata()[j]; } return expsx; } @@ -3299,7 +3479,7 @@ Expression *copyLiteral(Expression *e) Expression *m = oldelems->tdata()[i]; // We need the struct definition to detect block assignment AggregateDeclaration *sd = se->sd; - Dsymbol *s = sd->fields.tdata()[i]; + Dsymbol *s = sd->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); // If it is a void assignment, use the default initializer @@ -3591,7 +3771,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } bool wantRef = false; if (!fp && this->e1->type->toBasetype() == this->e2->type->toBasetype() && - (e1->type->toBasetype()->ty == Tarray || isAssocArray(e1->type)) + (e1->type->toBasetype()->ty == Tarray || isAssocArray(e1->type) + || e1->type->toBasetype()->ty == Tclass) // e = *x is never a reference, because *x is always a value && this->e2->op != TOKstar ) @@ -3831,18 +4012,18 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ assert(oldval->op == TOKarrayliteral); ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval; for (size_t i = 0; i < copylen; i++) - elements->tdata()[i] = ae->elements->tdata()[i]; + (*elements)[i] = ae->elements->tdata()[i]; if (elemType->ty == Tstruct || elemType->ty == Tsarray) { /* If it is an aggregate literal representing a value type, * we need to create a unique copy for each element */ for (size_t i = copylen; i < newlen; i++) - elements->tdata()[i] = copyLiteral(defaultElem); + (*elements)[i] = copyLiteral(defaultElem); } else { for (size_t i = copylen; i < newlen; i++) - elements->tdata()[i] = defaultElem; + (*elements)[i] = defaultElem; } ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements); aae->type = t; @@ -4046,7 +4227,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // (in which case, we already have the lvalue). if (this->e1->op != TOKcall && !(this->e1->op==TOKvar && ((VarExp*)this->e1)->var->storage_class & (STCref | STCout))) - e1 = e1->interpret(istate, ctfeNeedLvalue); + e1 = e1->interpret(istate, isPointer(type)? ctfeNeedLvalueRef : ctfeNeedLvalue); if (exceptionOrCantInterpret(e1)) return e1; if (e1->op == TOKstructliteral && newval->op == TOKstructliteral) @@ -4684,12 +4865,184 @@ Expression *PostExp::interpret(InterState *istate, CtfeGoal goal) return e; } +/* Return 1 if e is a p1 > p2 or p1 >= p2 pointer comparison; + * -1 if e is a p1 < p2 or p1 <= p2 pointer comparison; + * 0 otherwise + */ +int isPointerCmpExp(Expression *e, Expression **p1, Expression **p2) +{ + int ret = 1; + while (e->op == TOKnot) + { ret *= -1; + e = ((NotExp *)e)->e1; + } + switch(e->op) + { + case TOKlt: + case TOKle: + ret *= -1; + /* fall through */ + case TOKgt: + case TOKge: + *p1 = ((BinExp *)e)->e1; + *p2 = ((BinExp *)e)->e2; + if ( !(isPointer((*p1)->type) && isPointer((*p2)->type)) ) + ret = 0; + break; + default: + ret = 0; + break; + } + return ret; +} + +/** Negate a relational operator, eg >= becomes < + */ +TOK reverseRelation(TOK op) +{ + switch(op) + { + case TOKge: return TOKlt; + case TOKgt: return TOKle; + case TOKle: return TOKgt; + case TOKlt: return TOKge; + default: + return assert(0), TOKreserved; + } +} + +/** If this is a four pointer relation, evaluate it, else return NULL. + * + * This is an expression of the form (p1 > q1 && p2 < q2) or (p1 < q1 || p2 > q2) + * where p1, p2 are expressions yielding pointers to memory block p, + * and q1, q2 are expressions yielding pointers to memory block q. + * This expression is valid even if p and q are independent memory + * blocks and are therefore not normally comparable; the && form returns true + * if [p1..p2] lies inside [q1..q2], and false otherwise; the || form returns + * true if [p1..p2] lies outside [q1..q2], and false otherwise. + * + * Within the expression, any ordering of p1, p2, q1, q2 is permissible; + * the comparison operators can be any of >, <, <=, >=, provided that + * both directions (p > q and p < q) are checked. Additionally the + * relational sub-expressions can be negated, eg + * ( !(q1 < p1) && p2 <= q2 ) is valid. + */ +Expression *BinExp::interpretFourPointerRelation(InterState *istate, CtfeGoal goal) +{ + assert(op == TOKandand || op == TOKoror); + + /* It can only be an isInside expression, if both e1 and e2 are + * directional pointer comparisons. + * Note that this check can be made statically; it does not depends on + * any runtime values. This allows a JIT implementation to compile a + * special AndAndPossiblyInside, keeping the normal AndAnd case efficient. + */ + + // Save the pointer expressions and the comparison directions, + // so we can use them later. + Expression *p1, *p2, *p3, *p4; + int dir1 = isPointerCmpExp(e1, &p1, &p2); + int dir2 = isPointerCmpExp(e2, &p3, &p4); + if ( dir1 == 0 || dir2 == 0 ) + return NULL; + + //printf("FourPointerRelation %s\n", toChars()); + + // Evaluate the first two pointers + p1 = p1->interpret(istate); + if (exceptionOrCantInterpret(p1)) + return p1; + p2 = p2->interpret(istate); + if (exceptionOrCantInterpret(p1)) + return p1; + dinteger_t ofs1, ofs2; + Expression *agg1 = getAggregateFromPointer(p1, &ofs1); + Expression *agg2 = getAggregateFromPointer(p2, &ofs2); + + if ( !pointToSameMemoryBlock(agg1, agg2) + && agg1->op != TOKnull && agg2->op != TOKnull) + { // Here it is either CANT_INTERPRET, + // or an IsInside comparison returning FALSE. + p3 = p3->interpret(istate); + if (p3 == EXP_CANT_INTERPRET) + return p3; + // Note that it is NOT legal for it to throw an exception! + Expression *except = NULL; + if (exceptionOrCantInterpret(p3)) + except = p3; + else + { + p4 = p4->interpret(istate); + if (p4 == EXP_CANT_INTERPRET) + return p4; + if (exceptionOrCantInterpret(p3)) + except = p4; + } + if (except) + { error("Comparison %s of pointers to unrelated memory blocks remains " + "indeterminate at compile time " + "because exception %s was thrown while evaluating %s", + this->e1->toChars(), except->toChars(), this->e2->toChars()); + return EXP_CANT_INTERPRET; + } + dinteger_t ofs3,ofs4; + Expression *agg3 = getAggregateFromPointer(p3, &ofs3); + Expression *agg4 = getAggregateFromPointer(p4, &ofs4); + // The valid cases are: + // p1 > p2 && p3 > p4 (same direction, also for < && <) + // p1 > p2 && p3 < p4 (different direction, also < && >) + // Changing any > into >= doesnt affect the result + if ( (dir1 == dir2 && pointToSameMemoryBlock(agg1, agg4) + && pointToSameMemoryBlock(agg2, agg3)) + || (dir1 != dir2 && pointToSameMemoryBlock(agg1, agg3) + && pointToSameMemoryBlock(agg2, agg4)) ) + { // it's a legal two-sided comparison + return new IntegerExp(loc, (op == TOKandand) ? 0 : 1, type); + } + // It's an invalid four-pointer comparison. Either the second + // comparison is in the same direction as the first, or else + // more than two memory blocks are involved (either two independent + // invalid comparisons are present, or else agg3 == agg4). + error("Comparison %s of pointers to unrelated memory blocks is " + "indeterminate at compile time, even when combined with %s.", + e1->toChars(), e2->toChars()); + return EXP_CANT_INTERPRET; + } + // The first pointer expression didn't need special treatment, so we + // we need to interpret the entire expression exactly as a normal && or ||. + // This is easy because we haven't evaluated e2 at all yet, and we already + // know it will return a bool. + // But we mustn't evaluate the pointer expressions in e1 again, in case + // they have side-effects. + bool nott = false; + Expression *e = e1; + while (e->op == TOKnot) + { nott= !nott; + e = ((NotExp *)e)->e1; + } + TOK cmpop = e->op; + if (nott) + cmpop = reverseRelation(cmpop); + int cmp = comparePointers(loc, cmpop, e1->type, agg1, ofs1, agg2, ofs2); + // We already know this is a valid comparison. + assert(cmp >= 0); + if ( (op == TOKandand && cmp == 1) || (op == TOKoror && cmp == 0) ) + return e2->interpret(istate); + return new IntegerExp(loc, (op == TOKandand) ? 0 : 1, type); +} + Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) { #if LOG printf("AndAndExp::interpret() %s\n", toChars()); #endif - Expression *e = e1->interpret(istate); + + // Check for an insidePointer expression, evaluate it if so + Expression *e = interpretFourPointerRelation(istate, goal); + if (e) + return e; + + e = e1->interpret(istate); if (exceptionOrCantInterpret(e)) return e; @@ -4708,17 +5061,14 @@ Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal) assert(type->ty == Tvoid); return NULL; } - if (e != EXP_CANT_INTERPRET) + if (e->isBool(FALSE)) + result = 0; + else if (isTrueBool(e)) + result = 1; + else { - if (e->isBool(FALSE)) - result = 0; - else if (isTrueBool(e)) - result = 1; - else - { - error("%s does not evaluate to a boolean", e->toChars()); - e = EXP_CANT_INTERPRET; - } + error("%s does not evaluate to a boolean", e->toChars()); + e = EXP_CANT_INTERPRET; } } else @@ -4737,7 +5087,13 @@ Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal) #if LOG printf("OrOrExp::interpret() %s\n", toChars()); #endif - Expression *e = e1->interpret(istate); + + // Check for an insidePointer expression, evaluate it if so + Expression *e = interpretFourPointerRelation(istate, goal); + if (e) + return e; + + e = e1->interpret(istate); if (exceptionOrCantInterpret(e)) return e; @@ -4997,7 +5353,7 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) // Inline .dup. Special case because it needs the return type. if (!pthis && fd->ident == Id::adDup && arguments && arguments->dim == 2) { - e = arguments->tdata()[1]; + e = (*arguments)[1]; e = e->interpret(istate); if (exceptionOrCantInterpret(e)) return e; @@ -5233,7 +5589,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if ( agg->op == TOKarrayliteral || agg->op == TOKstring) { dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; + //Type *pointee = ((TypePointer *)agg->type)->next; if ((indx + ofs) < 0 || (indx+ofs) > len) { error("pointer index [%lld] exceeds allocated memory block [0..%lld]", @@ -5402,7 +5758,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) } assert(agg->op == TOKarrayliteral || agg->op == TOKstring); dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; + //Type *pointee = ((TypePointer *)agg->type)->next; if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) { error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]", @@ -5561,7 +5917,9 @@ Expression *CatExp::interpret(InterState *istate, CtfeGoal goal) e2 = resolveSlice(e2); e = ctfeCat(type, e1, e2); if (e == EXP_CANT_INTERPRET) - error("%s cannot be interpreted at compile time", toChars()); + { error("%s cannot be interpreted at compile time", toChars()); + return e; + } // We know we still own it, because we interpreted both e1 and e2 if (e->op == TOKarrayliteral) ((ArrayLiteralExp *)e)->ownedByCtfe = true; @@ -5759,9 +6117,16 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) } } if (to->ty == Tarray && e1->op == TOKslice) - { - e1 = new SliceExp(e1->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr, - ((SliceExp *)e1)->upr); + { // Note that the slice may be void[], so when checking for dangerous + // casts, we need to use the original type, which is se->e1. + SliceExp *se = (SliceExp *)e1; + if ( !isSafePointerCast( se->e1->type->nextOf(), to->nextOf() ) ) + { + error("array cast from %s to %s is not supported at compile time", + se->e1->type->toChars(), to->toChars()); + return EXP_CANT_INTERPRET; + } + e1 = new SliceExp(e1->loc, se->e1, se->lwr, se->upr); e1->type = to; return e1; } @@ -5920,7 +6285,9 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) } if (ie->e1->op == TOKassocarrayliteral) { - e = Index(type, ie->e1, ie->e2); + e = findKeyInAA(loc, (AssocArrayLiteralExp *)ie->e1, ie->e2); + assert(e != EXP_CANT_INTERPRET); + e = paintTypeOntoLiteral(type, e); if (isGenuineIndex) { if (e->op == TOKindex) @@ -6206,8 +6573,8 @@ Expression *interpret_aaApply(InterState *istate, Expression *aa, Expression *de { Expression *ekey = ae->keys->tdata()[i]; Expression *evalue = ae->values->tdata()[i]; - args.tdata()[numParams - 1] = evalue; - if (numParams == 2) args.tdata()[0] = ekey; + args[numParams - 1] = evalue; + if (numParams == 2) args[0] = ekey; eresult = fd->interpret(istate, &args, pthis); if (exceptionOrCantInterpret(eresult)) @@ -6438,7 +6805,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del // The index only needs to be set once if (numParams == 2) - args.tdata()[0] = new IntegerExp(deleg->loc, currentIndex, indexType); + args[0] = new IntegerExp(deleg->loc, currentIndex, indexType); Expression *val = NULL; @@ -6461,7 +6828,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del } val = new IntegerExp(str->loc, codepoint, charType); - args.tdata()[numParams - 1] = val; + args[numParams - 1] = val; eresult = fd->interpret(istate, &args, pthis); if (exceptionOrCantInterpret(eresult)) @@ -6502,11 +6869,11 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, args.setDim(nargs); for (size_t i = 0; i < args.dim; i++) { - Expression *earg = arguments->tdata()[i]; + Expression *earg = (*arguments)[i]; earg = earg->interpret(istate); if (exceptionOrCantInterpret(earg)) return earg; - args.tdata()[i] = earg; + args[i] = earg; } e = eval_builtin(loc, b, &args); if (!e) @@ -6579,7 +6946,7 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, assert(arguments->dim <= se->elements->dim); for (int i = 0; i < arguments->dim; ++i) { - Expression *e = arguments->tdata()[i]->interpret(istate); + Expression *e = (*arguments)[i]->interpret(istate); if (exceptionOrCantInterpret(e)) return e; se->elements->tdata()[i] = e; @@ -6607,11 +6974,11 @@ Expression *evaluateIfBuiltin(InterState *istate, Loc loc, if ( (n == '1' || n == '2') && (c == 'c' || c == 'w' || c == 'd') && (s == 'c' || s == 'w' || s == 'd') && c != s) - { Expression *str = arguments->tdata()[0]; + { Expression *str = (*arguments)[0]; str = str->interpret(istate); if (exceptionOrCantInterpret(str)) return str; - return foreachApplyUtf(istate, str, arguments->tdata()[1], rvs); + return foreachApplyUtf(istate, str, (*arguments)[1], rvs); } } } diff --git a/dmd2/intrange.h b/dmd2/intrange.h index 77685b02..2904dab9 100644 --- a/dmd2/intrange.h +++ b/dmd2/intrange.h @@ -95,14 +95,14 @@ struct IntRange IntRange(const SignExtendedNumber& a) : imin(a), imax(a) {} /// Create a range with the lower and upper bounds. - IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper) + IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper) : imin(lower), imax(upper) {} - + /// Create the tightest range containing all valid integers in the specified - /// type. + /// type. static IntRange fromType(Type *type); /// Create the tightest range containing all valid integers in the type with - /// a forced signedness. + /// a forced signedness. static IntRange fromType(Type *type, bool isUnsigned); @@ -131,7 +131,7 @@ struct IntRange /// Check if this range contains 0. bool containsZero() const; - /// Compute the range of the negated absolute values of the original range. + /// Compute the range of the negated absolute values of the original range. IntRange absNeg() const; /// Compute the union of two ranges. @@ -139,7 +139,7 @@ struct IntRange void unionOrAssign(const IntRange& other, bool& union_); /// Dump the content of the integer range to the console. - const IntRange& dump(const char* funcName, Expression *e) const; + const IntRange& dump(const char* funcName, Expression *e) const; /// Split the range into two nonnegative- and negative-only subintervals. void splitBySign(IntRange& negRange, bool& hasNegRange, diff --git a/dmd2/json.c b/dmd2/json.c index d3efacf5..26daa65e 100644 --- a/dmd2/json.c +++ b/dmd2/json.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -53,7 +53,7 @@ void json_generate(Modules *modules) buf.writestring("[\n"); for (size_t i = 0; i < modules->dim; i++) - { Module *m = modules->tdata()[i]; + { Module *m = (*modules)[i]; if (global.params.verbose) printf("json gen %s\n", m->toChars()); m->toJsonBuffer(&buf); @@ -66,7 +66,7 @@ void json_generate(Modules *modules) char *arg = global.params.xfilename; if (!arg || !*arg) { // Generate lib file name from first obj name - char *n = global.params.objfiles->tdata()[0]; + char *n = (*global.params.objfiles)[0]; n = FileName::name(n); FileName *fn = FileName::forceExt(n, global.json_ext); @@ -195,7 +195,7 @@ void Module::toJsonBuffer(OutBuffer *buf) size_t offset = buf->offset; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; if (offset != buf->offset) { buf->writestring(",\n"); offset = buf->offset; @@ -219,7 +219,7 @@ void AttribDeclaration::toJsonBuffer(OutBuffer *buf) { size_t offset = buf->offset; for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::toJsonBuffer %s\n", s->toChars()); if (offset != buf->offset) { buf->writestring(",\n"); @@ -332,7 +332,7 @@ void AggregateDeclaration::toJsonBuffer(OutBuffer *buf) buf->writestring(" : [\n"); size_t offset = buf->offset; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; if (offset != buf->offset) { buf->writestring(",\n"); offset = buf->offset; @@ -369,7 +369,7 @@ void TemplateDeclaration::toJsonBuffer(OutBuffer *buf) buf->writestring(" : [\n"); size_t offset = buf->offset; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; if (offset != buf->offset) { buf->writestring(",\n"); offset = buf->offset; @@ -391,7 +391,7 @@ void EnumDeclaration::toJsonBuffer(OutBuffer *buf) { for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->toJsonBuffer(buf); buf->writestring(",\n"); } @@ -423,7 +423,7 @@ void EnumDeclaration::toJsonBuffer(OutBuffer *buf) buf->writestring(" : [\n"); size_t offset = buf->offset; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; if (offset != buf->offset) { buf->writestring(",\n"); offset = buf->offset; diff --git a/dmd2/lexer.c b/dmd2/lexer.c index ed3dfae0..741cc859 100644 --- a/dmd2/lexer.c +++ b/dmd2/lexer.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -108,14 +108,22 @@ const char *Token::toChars() switch (value) { case TOKint32v: +#if defined(IN_GCC) || defined(IN_LLVM) sprintf(buffer,"%d",(d_int32)int64value); +#else + sprintf(buffer,"%d",int32value); +#endif break; case TOKuns32v: case TOKcharv: case TOKwcharv: case TOKdcharv: +#ifdef defined(IN_GCC) || defined(IN_LLVM) sprintf(buffer,"%uU",(d_uns32)uns64value); +#else + sprintf(buffer,"%uU",uns32value); +#endif break; case TOKint64v: @@ -126,7 +134,7 @@ const char *Token::toChars() sprintf(buffer,"%lluUL",(uintmax_t)uns64value); break; -#if IN_GCC +#ifdef IN_GCC case TOKfloat32v: case TOKfloat64v: case TOKfloat80v: @@ -171,9 +179,6 @@ const char *Token::toChars() #endif case TOKstring: -#if CSTRINGS - p = string; -#else { OutBuffer buf; buf.writeByte('"'); @@ -208,7 +213,6 @@ const char *Token::toChars() buf.writeByte(0); p = (char *)buf.extractData(); } -#endif break; case TOKidentifier: @@ -305,7 +309,7 @@ void Lexer::error(const char *format, ...) { va_list ap; va_start(ap, format); - verror(tokenLoc(), format, ap); + ::verror(tokenLoc(), format, ap); va_end(ap); } @@ -313,34 +317,10 @@ void Lexer::error(Loc loc, const char *format, ...) { va_list ap; va_start(ap, format); - verror(loc, format, ap); + ::verror(loc, format, ap); va_end(ap); } -void Lexer::verror(Loc loc, const char *format, va_list ap) -{ - if (mod && !global.gag) - { - char *p = loc.toChars(); - if (*p) - fprintf(stdmsg, "%s: ", p); - mem.free(p); - - vfprintf(stdmsg, format, ap); - - fprintf(stdmsg, "\n"); - fflush(stdmsg); - - if (global.errors >= 20) // moderate blizzard of cascading messages - fatal(); - } - else - { - global.gaggedErrors++; - } - global.errors++; -} - TOK Lexer::nextToken() { Token *t; @@ -524,30 +504,6 @@ void Lexer::scan(Token *t) t->value = number(t); return; -#if CSTRINGS - case '\'': - t->value = charConstant(t, 0); - return; - - case '"': - t->value = stringConstant(t,0); - return; - - case 'l': - case 'L': - if (p[1] == '\'') - { - p++; - t->value = charConstant(t, 1); - return; - } - else if (p[1] == '"') - { - p++; - t->value = stringConstant(t, 1); - return; - } -#else case '\'': t->value = charConstant(t,0); return; @@ -627,12 +583,9 @@ void Lexer::scan(Token *t) } #endif - case 'l': - case 'L': -#endif case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'm': case 'n': case 'o': + case 'k': case 'l': case 'm': case 'n': case 'o': #if DMDV2 case 'p': /*case 'q': case 'r':*/ case 's': case 't': #else @@ -642,7 +595,7 @@ void Lexer::scan(Token *t) case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'M': case 'N': case 'O': + case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': @@ -669,7 +622,7 @@ void Lexer::scan(Token *t) StringValue *sv = stringtable.update((char *)t->ptr, p - t->ptr); Identifier *id = (Identifier *) sv->ptrvalue; if (!id) - { id = new Identifier(sv->lstring.string,TOKidentifier); + { id = new Identifier(sv->toDchars(),TOKidentifier); sv->ptrvalue = id; } t->ident = id; @@ -1228,10 +1181,10 @@ void Lexer::scan(Token *t) case '#': { p++; - Token *n = peek(t); - if (n->value == TOKidentifier && n->ident == Id::line) + Token n; + scan(&n); + if (n.value == TOKidentifier && n.ident == Id::line) { - nextToken(); poundLine(); continue; } @@ -1931,45 +1884,6 @@ void Lexer::stringPostfix(Token *t) } } -/*************************************** - * Read \u or \U unicode sequence - * Input: - * u 'u' or 'U' - */ - -#if 0 -unsigned Lexer::wchar(unsigned u) -{ - unsigned value; - unsigned n; - unsigned char c; - unsigned nchars; - - nchars = (u == 'U') ? 8 : 4; - value = 0; - for (n = 0; 1; n++) - { - ++p; - if (n == nchars) - break; - c = *p; - if (!ishex(c)) - { error("\\%c sequence must be followed by %d hex characters", u, nchars); - break; - } - if (isdigit(c)) - c -= '0'; - else if (islower(c)) - c -= 'a' - 10; - else - c -= 'A' - 10; - value <<= 4; - value |= c; - } - return value; -} -#endif - /************************************** * Read in a number. * If it's an integer, store it in tok.TKutok.Vlong. @@ -1996,14 +1910,12 @@ TOK Lexer::number(Token *t) }; enum FLAGS flags = FLAGS_decimal; - int base; unsigned c; unsigned char *start; TOK result; //printf("Lexer::number()\n"); state = STATE_initial; - base = 0; stringbuffer.reset(); start = p; while (1) @@ -2022,11 +1934,6 @@ TOK Lexer::number(Token *t) flags = (FLAGS) (flags & ~FLAGS_decimal); switch (c) { -#if ZEROH - case 'H': // 0h - case 'h': - goto hexh; -#endif case 'X': case 'x': state = STATE_hex0; @@ -2035,15 +1942,14 @@ TOK Lexer::number(Token *t) case '.': if (p[1] == '.') // .. is a separate token goto done; +#if DMDV2 + if (isalpha(p[1]) || p[1] == '_') + goto done; +#endif case 'i': case 'f': case 'F': goto real; -#if ZEROH - case 'E': - case 'e': - goto case_hex; -#endif case 'B': case 'b': state = STATE_binary0; @@ -2054,14 +1960,6 @@ TOK Lexer::number(Token *t) state = STATE_octal; break; -#if ZEROH - case '8': case '9': case 'A': - case 'C': case 'D': case 'F': - case 'a': case 'c': case 'd': case 'f': - case_hex: - state = STATE_hexh; - break; -#endif case '_': state = STATE_octal; p++; @@ -2080,12 +1978,6 @@ TOK Lexer::number(Token *t) case STATE_decimal: // reading decimal number if (!isdigit(c)) { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif if (c == '_') // ignore embedded _ { p++; continue; @@ -2130,41 +2022,10 @@ TOK Lexer::number(Token *t) state = STATE_hex; break; -#if ZEROH - hexh: - state = STATE_hexh; - case STATE_hexh: // parse numbers like 0FFh - if (!ishex(c)) - { - if (c == 'H' || c == 'h') - { - p++; - base = 16; - goto done; - } - else - { - // Check for something like 1E3 or 0E24 - if (memchr((char *)stringbuffer.data, 'E', stringbuffer.offset) || - memchr((char *)stringbuffer.data, 'e', stringbuffer.offset)) - goto real; - error("Hex digit expected, not '%c'", c); - goto done; - } - } - break; -#endif - case STATE_octal: // reading octal number case STATE_octale: // reading octal number with non-octal digits if (!isoctal(c)) { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif if (c == '_') // ignore embedded _ { p++; continue; @@ -2186,12 +2047,6 @@ TOK Lexer::number(Token *t) case STATE_binary: // reading binary number if (c != '0' && c != '1') { -#if ZEROH - if (ishex(c) - || c == 'H' || c == 'h' - ) - goto hexh; -#endif if (c == '_') // ignore embedded _ { p++; continue; @@ -2232,7 +2087,7 @@ done: // Convert string to integer #if __DMC__ errno = 0; - n = strtoull((char *)stringbuffer.data,NULL,base); + n = strtoull((char *)stringbuffer.data,NULL,0); if (errno == ERANGE) error("integer overflow"); #else @@ -2636,8 +2491,9 @@ void Lexer::poundLine() { p += 8; filespec = mem.strdup(loc.filename ? loc.filename : mod->ident->toChars()); + continue; } - continue; + goto Lerr; case '"': if (filespec) @@ -2920,7 +2776,7 @@ Identifier *Lexer::idPool(const char *s) Identifier *id = (Identifier *) sv->ptrvalue; if (!id) { - id = new Identifier(sv->lstring.string, TOKidentifier); + id = new Identifier(sv->toDchars(), TOKidentifier); sv->ptrvalue = id; } return id; @@ -3067,6 +2923,7 @@ static Keyword keywords[] = // Added after 1.0 { "__argTypes", TOKargTypes }, + { "__parameters", TOKparameters }, { "ref", TOKref }, { "macro", TOKmacro }, #if DMDV2 @@ -3111,7 +2968,7 @@ void Lexer::initKeywords() const char *s = keywords[u].name; enum TOK v = keywords[u].value; StringValue *sv = stringtable.insert(s, strlen(s)); - sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v); + sv->ptrvalue = (void *) new Identifier(sv->toDchars(),v); //printf("tochars[%d] = '%s'\n",v, s); Token::tochars[v] = s; diff --git a/dmd2/lexer.h b/dmd2/lexer.h index 848d7123..293c9538 100644 --- a/dmd2/lexer.h +++ b/dmd2/lexer.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2010 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -156,6 +156,7 @@ enum TOK TOKref, TOKmacro, #if DMDV2 + TOKparameters, TOKtraits, TOKoverloadset, TOKpure, @@ -311,7 +312,6 @@ struct Lexer TOK inreal(Token *t); void error(const char *format, ...) IS_PRINTF(2); void error(Loc loc, const char *format, ...) IS_PRINTF(3); - void verror(Loc loc, const char *format, va_list ap); void poundLine(); unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); diff --git a/dmd2/lib.h b/dmd2/lib.h index 3a67ed30..d63e1ace 100644 --- a/dmd2/lib.h +++ b/dmd2/lib.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -15,53 +15,15 @@ #pragma once #endif /* __DMC__ */ -struct ObjModule; - -struct ObjSymbol +class Library { - char *name; - ObjModule *om; -}; + public: + static Library *factory(); -#include "arraytypes.h" - -typedef ArrayBase ObjModules; -typedef ArrayBase ObjSymbols; - -struct Library -{ - File *libfile; - ObjModules objmodules; // ObjModule[] - ObjSymbols objsymbols; // ObjSymbol[] - - StringTable tab; - - Library(); - void setFilename(char *dir, char *filename); - void addObject(const char *module_name, void *buf, size_t buflen); - void addLibrary(void *buf, size_t buflen); - void write(); - - private: - void addSymbol(ObjModule *om, char *name, int pickAny = 0); - void scanObjModule(ObjModule *om); - unsigned short numDictPages(unsigned padding); - int FillDict(unsigned char *bucketsP, unsigned short uNumPages); - void WriteLibToBuffer(OutBuffer *libbuf); - - void error(const char *format, ...) - { - Loc loc; - if (libfile) - { - loc.filename = libfile->name->toChars(); - loc.linnum = 0; - } - va_list ap; - va_start(ap, format); - ::verror(loc, format, ap); - va_end(ap); - } + virtual void setFilename(char *dir, char *filename) = 0; + virtual void addObject(const char *module_name, void *buf, size_t buflen) = 0; + virtual void addLibrary(void *buf, size_t buflen) = 0; + virtual void write() = 0; }; #endif /* DMD_LIB_H */ diff --git a/dmd2/mars.c b/dmd2/mars.c index ea79ce2f..0533e3fc 100644 --- a/dmd2/mars.c +++ b/dmd2/mars.c @@ -101,12 +101,12 @@ Global::Global() "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.059"; + version = "v2.060"; #if IN_LLVM ldc_version = "LDC trunk"; llvm_version = "LLVM "LDC_LLVM_VERSION_STRING; #endif - global.structalign = 8; + global.structalign = STRUCTALIGN_DEFAULT; // This should only be used as a global, so the other fields are // automatically initialized to zero when the program is loaded. @@ -197,7 +197,7 @@ void errorSupplemental(Loc loc, const char *format, ...) va_end( ap ); } -void verror(Loc loc, const char *format, va_list ap) +void verror(Loc loc, const char *format, va_list ap, const char *p1, const char *p2) { if (!global.gag) { @@ -208,16 +208,22 @@ void verror(Loc loc, const char *format, va_list ap) mem.free(p); fprintf(stdmsg, "Error: "); + if (p1) + fprintf(stdmsg, "%s ", p1); + if (p2) + fprintf(stdmsg, "%s ", p2); +#if _MSC_VER // MS doesn't recognize %zu format OutBuffer tmp; tmp.vprintf(format, ap); -#if _MSC_VER fprintf(stdmsg, "%s", tmp.toChars()); #else vfprintf(stdmsg, format, ap); #endif fprintf(stdmsg, "\n"); fflush(stdmsg); + if (global.errors >= 20) // moderate blizzard of cascading messages + fatal(); //halt(); } else @@ -372,8 +378,8 @@ Usage:\n\ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ -vtls list all variables going into thread local storage\n\ - -w enable warnings\n\ - -wi enable informational warnings\n\ + -w warnings as errors (compilation will halt)\n\ + -wi warnings as messages (compilation will continue)\n\ -X generate JSON file\n\ -Xffilename write JSON file to filename\n\ ", fpic); @@ -1040,7 +1046,7 @@ int tryMain(int argc, char *argv[]) { for (size_t i = 0; i < global.params.fileImppath->dim; i++) { - char *path = global.params.fileImppath->tdata()[i]; + char *path = (*global.params.fileImppath)[i]; Strings *a = FileName::splitPath(path); if (a) @@ -1061,7 +1067,7 @@ int tryMain(int argc, char *argv[]) char *ext; char *name; - p = files.tdata()[i]; + p = files[i]; #if _WIN32 // Convert / to \ so linker will work @@ -1079,47 +1085,47 @@ int tryMain(int argc, char *argv[]) */ if (FileName::equals(ext, global.obj_ext)) { - global.params.objfiles->push(files.tdata()[i]); - libmodules.push(files.tdata()[i]); + global.params.objfiles->push(files[i]); + libmodules.push(files[i]); continue; } if (FileName::equals(ext, global.lib_ext)) { - global.params.libfiles->push(files.tdata()[i]); - libmodules.push(files.tdata()[i]); + global.params.libfiles->push(files[i]); + libmodules.push(files[i]); continue; } if (strcmp(ext, global.ddoc_ext) == 0) { - global.params.ddocfiles->push(files.tdata()[i]); + global.params.ddocfiles->push(files[i]); continue; } if (FileName::equals(ext, global.json_ext)) { global.params.doXGeneration = 1; - global.params.xfilename = files.tdata()[i]; + global.params.xfilename = files[i]; continue; } if (FileName::equals(ext, global.map_ext)) { - global.params.mapfile = files.tdata()[i]; + global.params.mapfile = files[i]; continue; } #if TARGET_WINDOS if (FileName::equals(ext, "res")) { - global.params.resfile = files.tdata()[i]; + global.params.resfile = files[i]; continue; } if (FileName::equals(ext, "def")) { - global.params.deffile = files.tdata()[i]; + global.params.deffile = files[i]; continue; } @@ -1134,10 +1140,7 @@ int tryMain(int argc, char *argv[]) */ if (FileName::equals(ext, global.mars_ext) || FileName::equals(ext, global.hdr_ext) || - FileName::equals(ext, "dd") || - FileName::equals(ext, "htm") || - FileName::equals(ext, "html") || - FileName::equals(ext, "xhtml")) + FileName::equals(ext, "dd")) { ext--; // skip onto '.' assert(*ext == '.'); @@ -1150,7 +1153,7 @@ int tryMain(int argc, char *argv[]) strcmp(name, ".") == 0) { Linvalid: - error(0, "invalid file name '%s'", files.tdata()[i]); + error(0, "invalid file name '%s'", files[i]); fatal(); } } @@ -1232,7 +1235,7 @@ int tryMain(int argc, char *argv[]) // Remove m's object file from list of object files for (size_t j = 0; j < global.params.objfiles->dim; j++) { - if (m->objfile->name->str == global.params.objfiles->tdata()[j]) + if (m->objfile->name->str == (*global.params.objfiles)[j]) { global.params.objfiles->remove(j); break; @@ -1322,24 +1325,13 @@ int tryMain(int argc, char *argv[]) if (global.errors) fatal(); - if (global.params.moduleDeps != NULL) - { - assert(global.params.moduleDepsFile != NULL); - - File deps(global.params.moduleDepsFile); - OutBuffer* ob = global.params.moduleDeps; - deps.setbuffer((void*)ob->data, ob->offset); - deps.writev(); - } - - - // Scan for functions to inline if (global.params.useInline) { /* The problem with useArrayBounds and useAssert is that the * module being linked to may not have generated them, so if * we inline functions from those modules, the symbols for them will * not be found at link time. + * We must do this BEFORE generating the .deps file! */ if (!global.params.useArrayBounds && !global.params.useAssert) { @@ -1355,7 +1347,21 @@ int tryMain(int argc, char *argv[]) if (global.errors) fatal(); } + } + if (global.params.moduleDeps != NULL) + { + assert(global.params.moduleDepsFile != NULL); + + File deps(global.params.moduleDepsFile); + OutBuffer* ob = global.params.moduleDeps; + deps.setbuffer((void*)ob->data, ob->offset); + deps.writev(); + } + + // Scan for functions to inline + if (global.params.useInline) + { for (size_t i = 0; i < modules.dim; i++) { m = modules[i]; @@ -1374,7 +1380,7 @@ int tryMain(int argc, char *argv[]) Library *library = NULL; if (global.params.lib) { - library = new Library(); + library = Library::factory(); library->setFilename(global.params.objdir, global.params.libname); // Add input object and input library files to output library @@ -1405,7 +1411,7 @@ int tryMain(int argc, char *argv[]) } if (!global.errors && modules.dim) { - obj_end(library, modules.tdata()[0]->objfile); + obj_end(library, modules[0]->objfile); } } else diff --git a/dmd2/mars.h b/dmd2/mars.h index 36dc7b51..e3db7751 100644 --- a/dmd2/mars.h +++ b/dmd2/mars.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -97,11 +97,13 @@ void unittests(); #define DMDV1 0 #define DMDV2 1 // Version 2.0 features -#define BREAKABI 1 // 0 if not ready to break the ABI just yet #define STRUCTTHISREF DMDV2 // if 'this' for struct is a reference, not a pointer #define SNAN_DEFAULT_INIT DMDV2 // if floats are default initialized to signalling NaN #define SARRAYVALUE DMDV2 // static arrays are value types #define MODULEINFO_IS_STRUCT DMDV2 // if ModuleInfo is a struct rather than a class +#define BUG6652 1 // 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)) @@ -279,6 +281,10 @@ struct Param #endif }; +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 + struct Global { const char *mars_ext; @@ -303,7 +309,9 @@ struct Global const char *written; 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 - int structalign; + + structalign_t structalign; // default alignment for struct fields + const char *version; #if IN_LLVM char *ldc_version; @@ -475,7 +483,7 @@ typedef uint64_t StorageClass; void warning(Loc loc, const char *format, ...) IS_PRINTF(2); void error(Loc loc, const char *format, ...) IS_PRINTF(2); void errorSupplemental(Loc loc, const char *format, ...); -void verror(Loc loc, const char *format, va_list); +void verror(Loc loc, const char *format, va_list, const char *p1 = NULL, const char *p2 = NULL); void vwarning(Loc loc, const char *format, va_list); void verrorSupplemental(Loc loc, const char *format, va_list); void fatal(); @@ -495,7 +503,7 @@ void util_progress(); #endif /*** Where to send error messages ***/ -#if IN_GCC || IN_LLVM +#if defined(IN_GCC) || IN_LLVM #define stdmsg stderr #else #define stdmsg stderr diff --git a/dmd2/module.c b/dmd2/module.c index bd381808..15f1272e 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -20,7 +20,7 @@ #include #endif -#if IN_GCC +#ifdef IN_GCC #include "gdc_alloca.h" #endif @@ -37,7 +37,10 @@ #include "hdrgen.h" #include "lexer.h" -#include "html.h" +// stricmp +#if __GNUC__ && !_WIN32 +#include "gnuc.h" +#endif #ifdef IN_GCC #include "d-dmd-gcc.h" @@ -88,7 +91,6 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen errors = 0; numlines = 0; members = NULL; - isHtml = 0; isDocFile = 0; needmoduleinfo = 0; #ifdef IN_GCC @@ -146,17 +148,8 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen !srcfilename->equalsExt(global.hdr_ext) && !srcfilename->equalsExt("dd")) { - if (srcfilename->equalsExt("html") || - srcfilename->equalsExt("htm") || - srcfilename->equalsExt("xhtml")) - { if (!global.params.useDeprecated) - error("html source files is deprecated %s", srcfilename->toChars()); - isHtml = 1; - } - else - { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); - fatal(); - } + error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); + fatal(); } #if !IN_LLVM char *argobj; @@ -438,7 +431,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) OutBuffer buf; for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = packages->tdata()[i]; + { Identifier *pid = (*packages)[i]; buf.writestring(pid->toChars()); #if _WIN32 @@ -499,7 +492,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) if (packages) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = packages->tdata()[i]; + { Identifier *pid = (*packages)[i]; printf("%s.", pid->toChars()); } } @@ -530,7 +523,7 @@ bool Module::read(Loc loc) { for (size_t i = 0; i < global.path->dim; i++) { - char *p = global.path->tdata()[i]; + char *p = (*global.path)[i]; fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p); } } @@ -579,24 +572,17 @@ inline unsigned readlongBE(unsigned *p) #if IN_LLVM void Module::parse(bool gen_docs) -#elif IN_GCC -void Module::parse(bool dump_source) #else void Module::parse() #endif -{ char *srcname; - unsigned char *buf; - unsigned buflen; - unsigned le; - unsigned bom; - +{ //printf("Module::parse()\n"); - srcname = srcfile->name->toChars(); + char *srcname = srcfile->name->toChars(); //printf("Module::parse(srcname = '%s')\n", srcname); - buf = srcfile->buffer; - buflen = srcfile->len; + unsigned char *buf = srcfile->buffer; + unsigned buflen = srcfile->len; if (buflen >= 2) { @@ -609,7 +595,8 @@ void Module::parse() * EF BB BF UTF-8 */ - bom = 1; // assume there's a BOM + unsigned le; + unsigned bom = 1; // assume there's a BOM if (buf[0] == 0xFF && buf[1] == 0xFE) { if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) @@ -760,7 +747,7 @@ void Module::parse() #ifdef IN_GCC // dump utf-8 encoded source - if (dump_source) + if (global.params.dump_source) { // %% srcname could contain a path ... d_gcc_dump_source(srcname, "utf-8", buf, buflen); } @@ -779,19 +766,6 @@ void Module::parse() #endif return; } - if (isHtml) - { - OutBuffer *dbuf = new OutBuffer(); - Html h(srcname, buf, buflen); - h.extractCode(dbuf); - buf = dbuf->data; - buflen = dbuf->offset; -#ifdef IN_GCC - // dump extracted source - if (dump_source) - d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); -#endif - } #if IN_LLVM Parser p(this, buf, buflen, gen_docs); #else @@ -890,7 +864,7 @@ void Module::importAll(Scope *prevsc) symtab = new DsymbolTable(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->addMember(NULL, sc->scopesym, 1); } } @@ -903,13 +877,13 @@ void Module::importAll(Scope *prevsc) */ setScope(sc); // remember module scope for semantic for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; s->setScope(sc); } for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->importAll(sc); } @@ -964,7 +938,7 @@ void Module::semantic(Scope* unused_sc) // Do semantic() on members that don't depend on others for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; //printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars()); s->semantic0(sc); @@ -972,7 +946,7 @@ void Module::semantic(Scope* unused_sc) // Pass 1 semantic routines: do public side of the definition for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); s->semantic(sc); @@ -993,7 +967,7 @@ void Module::semantic2(Scope* unused_sc) { for (size_t i = 0; i < deferred.dim; i++) { - Dsymbol *sd = deferred.tdata()[i]; + Dsymbol *sd = deferred[i]; sd->error("unable to resolve forward reference in definition"); } @@ -1017,7 +991,7 @@ void Module::semantic2(Scope* unused_sc) for (size_t i = 0; i < members->dim; i++) { Dsymbol *s; - s = members->tdata()[i]; + s = (*members)[i]; s->semantic2(sc); } @@ -1045,7 +1019,7 @@ void Module::semantic3(Scope* unused_sc) for (size_t i = 0; i < members->dim; i++) { Dsymbol *s; - s = members->tdata()[i]; + s = (*members)[i]; //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars()); s->semantic3(sc); } @@ -1068,7 +1042,7 @@ void Module::inlineScan() //printf("Module = %p\n", sc.scopesym); for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; //if (global.params.verbose) //printf("inline scan symbol %s\n", s->toChars()); @@ -1093,7 +1067,7 @@ void Module::gensymfile() buf.writenl(); for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; s->toCBuffer(&buf, &hgs); } @@ -1154,7 +1128,7 @@ Dsymbol *Module::symtabInsert(Dsymbol *s) void Module::clearCache() { for (size_t i = 0; i < amodules.dim; i++) - { Module *m = amodules.tdata()[i]; + { Module *m = amodules[i]; m->searchCacheIdent = NULL; } } @@ -1168,7 +1142,7 @@ void Module::addDeferredSemantic(Dsymbol *s) // Don't add it if it is already there for (size_t i = 0; i < deferred.dim; i++) { - Dsymbol *sd = deferred.tdata()[i]; + Dsymbol *sd = deferred[i]; if (sd == s) return; @@ -1238,7 +1212,6 @@ void Module::runDeferredSemantic() int Module::imports(Module *m) { //printf("%s Module::imports(%s)\n", toChars(), m->toChars()); - int aimports_dim = aimports.dim; #if 0 for (size_t i = 0; i < aimports.dim; i++) { Module *mi = (Module *)aimports.data[i]; @@ -1246,7 +1219,7 @@ int Module::imports(Module *m) } #endif for (size_t i = 0; i < aimports.dim; i++) - { Module *mi = aimports.tdata()[i]; + { Module *mi = aimports[i]; if (mi == m) return TRUE; if (!mi->insearch) @@ -1270,7 +1243,7 @@ int Module::selfImports() if (!selfimports) { for (size_t i = 0; i < amodules.dim; i++) - { Module *mi = amodules.tdata()[i]; + { Module *mi = amodules[i]; //printf("\t[%d] %s\n", i, mi->toChars()); mi->insearch = 0; } @@ -1278,7 +1251,7 @@ int Module::selfImports() selfimports = imports(this) + 1; for (size_t i = 0; i < amodules.dim; i++) - { Module *mi = amodules.tdata()[i]; + { Module *mi = amodules[i]; //printf("\t[%d] %s\n", i, mi->toChars()); mi->insearch = 0; } @@ -1303,7 +1276,7 @@ char *ModuleDeclaration::toChars() if (packages && packages->dim) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = packages->tdata()[i]; + { Identifier *pid = (*packages)[i]; buf.writestring(pid->toChars()); buf.writeByte('.'); @@ -1340,7 +1313,7 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package if (packages) { for (size_t i = 0; i < packages->dim; i++) - { Identifier *pid = packages->tdata()[i]; + { Identifier *pid = (*packages)[i]; Dsymbol *p; p = dst->lookup(pid); diff --git a/dmd2/module.h b/dmd2/module.h index 609017ea..82156d7d 100644 --- a/dmd2/module.h +++ b/dmd2/module.h @@ -79,7 +79,6 @@ struct Module : Package unsigned errors; // if any errors in file unsigned numlines; // number of lines in source file - int isHtml; // if it is an HTML file int isDocFile; // if it is a documentation input file, not D source int needmoduleinfo; #ifdef IN_GCC @@ -141,8 +140,6 @@ struct Module : Package bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise. #if IN_LLVM void parse(bool gen_docs = false); // syntactic parse -#elif IN_GCC - void parse(bool dump_source = false); // syntactic parse #else void parse(); // syntactic parse #endif diff --git a/dmd2/mtype.c b/dmd2/mtype.c index 2958f4e9..48faf831 100644 --- a/dmd2/mtype.c +++ b/dmd2/mtype.c @@ -87,10 +87,10 @@ int REALSIZE = 16; int REALPAD = 6; int REALALIGNSIZE = 16; #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS -int REALSIZE = 12; +int REALSIZE = 12; // FIXME: We differ from DMD here, yet target defines are never set?! int REALPAD = 2; int REALALIGNSIZE = 4; -#elif IN_GCC +#elif defined(IN_GCC) int REALSIZE = 0; int REALPAD = 0; int REALALIGNSIZE = 0; @@ -131,6 +131,7 @@ ClassDeclaration *Type::typeinfoshared; ClassDeclaration *Type::typeinfowild; TemplateDeclaration *Type::associativearray; +TemplateDeclaration *Type::rtinfo; Type *Type::tvoidptr; Type *Type::tstring; @@ -1399,7 +1400,7 @@ Type *Type::aliasthisOf() if (spec && global.errors != olderrs) spec->errors = global.errors - olderrs; } - if (!global.errors) + if (!fd->errors) { Type *t = fd->type->nextOf(); t = t->substWildTo(mod == 0 ? MODmutable : mod); @@ -1728,9 +1729,11 @@ Type *Type::merge() { sv->ptrvalue = this; +#if IN_LLVM // we still need deco strings to be unique // or Type::equals fails, which breaks a bunch of stuff, // like covariant member function overloads. + // TODO: Check if and why this is still needed. OutBuffer mangle; toDecoBuffer(&mangle, 0, true); StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset); @@ -1742,8 +1745,11 @@ Type *Type::merge() else { sv2->ptrvalue = this; - deco = (char *)sv2->lstring.string; + deco = (char *)sv2->toDchars(); } +#else + deco = (char *)sv->toDchars(); +#endif //printf("new value, deco = '%s' %p\n", t->deco, t->deco); } } @@ -2044,7 +2050,13 @@ Expression *Type::getProperty(Loc loc, Identifier *ident) error(loc, "void does not have an initializer"); if (ty == Tfunction) error(loc, "function does not have an initializer"); - e = defaultInitLiteral(loc); + if (toBasetype()->ty == Tstruct && + ((TypeStruct *)toBasetype())->sym->isNested()) + { + e = defaultInit(loc); + } + else + e = defaultInitLiteral(loc); } else if (ident == Id::mangleof) { const char *s; @@ -2118,7 +2130,13 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) } else if (ident == Id::init) { - e = defaultInitLiteral(e->loc); + if (toBasetype()->ty == Tstruct && + ((TypeStruct *)toBasetype())->sym->isNested()) + { + e = defaultInit(e->loc); + } + else + e = defaultInitLiteral(e->loc); goto Lreturn; } } @@ -2143,6 +2161,15 @@ Lreturn: return e; } +/************************************ + * Return alignment to use for this type. + */ + +structalign_t Type::alignment() +{ + return STRUCTALIGN_DEFAULT; +} + /*************************************** * Figures out what to do with an undefined member reference * for classes and structs. @@ -2191,10 +2218,9 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) StringExp *se = new StringExp(e->loc, ident->toChars()); Objects *tiargs = new Objects(); tiargs->push(se); - e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); - ((DotTemplateInstanceExp *)e)->ti->tempdecl = td; - e = e->semantic(sc); - return e; + DotTemplateInstanceExp *dti = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); + dti->ti->tempdecl = td; + return dti->semantic(sc, 1); } /* See if we should forward to the alias this. @@ -2204,19 +2230,14 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) * e.aliasthis.ident */ e = resolveAliasThis(sc, e); - e = new DotIdExp(e->loc, e, ident); - return e->semantic(sc); + DotIdExp *die = new DotIdExp(e->loc, e, ident); + return die->semantic(sc, 1); } } return Type::dotExp(sc, e, ident); } -unsigned Type::memalign(unsigned salign) -{ - return salign; -} - void Type::error(Loc loc, const char *format, ...) { va_list ap; @@ -2859,11 +2880,11 @@ unsigned TypeBasic::alignsize() } #if IN_LLVM -unsigned TypeBasic::memalign(unsigned salign) +unsigned TypeBasic::alignment() { if (global.params.cpu == ARCHx86_64 && (ty == Tfloat80 || ty == Timaginary80)) return 16; - return Type::memalign(salign); + return Type::alignment(); } #endif @@ -3354,7 +3375,7 @@ MATCH TypeBasic::implicitConvTo(Type *to) return MATCHnomatch; TypeBasic *tob; - if (to->ty == Tvector) + if (to->ty == Tvector && to->deco) { TypeVector *tv = (TypeVector *)to; tob = tv->elementType(); @@ -3422,6 +3443,8 @@ TypeBasic *TypeBasic::isTypeBasic() /* The basetype must be one of: * byte[16],ubyte[16],short[8],ushort[8],int[4],uint[4],long[2],ulong[2],float[4],double[2] + * For AVX: + * byte[32],ubyte[32],short[16],ushort[16],int[8],uint[8],long[4],ulong[4],float[8],double[4] */ TypeVector::TypeVector(Loc loc, Type *basetype) : Type(Tvector) @@ -3456,8 +3479,9 @@ Type *TypeVector::semantic(Loc loc, Scope *sc) return this; } - if (t->size(loc) != 16) - { error(loc, "base type of __vector must be a 16 byte static array, not %s", t->toChars()); + d_uns64 sz = t->size(loc); + if (sz != 16 && sz != 32) + { error(loc, "base type of __vector must be a 16 or 32 byte static array, not %s", t->toChars()); return terror; } TypeBasic *tb = t->nextOf()->isTypeBasic(); @@ -3511,12 +3535,12 @@ void TypeVector::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) d_uns64 TypeVector::size(Loc loc) { - return 16; + return basetype->size(); } unsigned TypeVector::alignsize() { - return 16; + return (unsigned)basetype->size(); } Expression *TypeVector::getProperty(Loc loc, Identifier *ident) @@ -3865,7 +3889,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->push(sym); dim = dim->semantic(sc); - dim = dim->optimize(WANTvalue | WANTinterpret); + dim = dim->ctfeInterpret(); uinteger_t d = dim->toUInteger(); sc = sc->pop(); @@ -3874,7 +3898,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol { error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim); goto Ldefault; } - Object *o = td->objects->tdata()[(size_t)d]; + Object *o = (*td->objects)[(size_t)d]; if (o->dyncast() == DYNCAST_DSYMBOL) { *ps = (Dsymbol *)o; @@ -3900,7 +3924,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol */ Objects *objects = new Objects; objects->setDim(1); - objects->tdata()[0] = o; + (*objects)[0] = o; TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); *ps = tds; @@ -3927,14 +3951,14 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) { TupleDeclaration *sd = s->isTupleDeclaration(); dim = semanticLength(sc, sd, dim); - dim = dim->optimize(WANTvalue | WANTinterpret); + dim = dim->ctfeInterpret(); uinteger_t d = dim->toUInteger(); if (d >= sd->objects->dim) { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim); return Type::terror; } - Object *o = sd->objects->tdata()[(size_t)d]; + Object *o = (*sd->objects)[(size_t)d]; if (o->dyncast() != DYNCAST_TYPE) { error(loc, "%s is not a type", toChars()); return Type::terror; @@ -3966,11 +3990,17 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) */ return this; } - dim = dim->optimize(WANTvalue | WANTinterpret); + dim = dim->ctfeInterpret(); + errors = global.errors; dinteger_t d1 = dim->toInteger(); + if (errors != global.errors) + goto Lerror; dim = dim->implicitCastTo(sc, tsize_t); dim = dim->optimize(WANTvalue); + errors = global.errors; dinteger_t d2 = dim->toInteger(); + if (errors != global.errors) + goto Lerror; if (dim->op == TOKerror) goto Lerror; @@ -4015,7 +4045,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim); goto Lerror; } - Parameter *arg = tt->arguments->tdata()[(size_t)d]; + Parameter *arg = (*tt->arguments)[(size_t)d]; return arg->type; } case Tstruct: @@ -4094,17 +4124,17 @@ Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident) return e; } +structalign_t TypeSArray::alignment() +{ + return next->alignment(); +} + int TypeSArray::isString() { TY nty = next->toBasetype()->ty; return nty == Tchar || nty == Twchar || nty == Tdchar; } -unsigned TypeSArray::memalign(unsigned salign) -{ - return next->memalign(salign); -} - MATCH TypeSArray::constConv(Type *to) { if (to->ty == Tsarray) @@ -4210,7 +4240,7 @@ Expression *TypeSArray::defaultInitLiteral(Loc loc) Expressions *elements = new Expressions(); elements->setDim(d); for (size_t i = 0; i < d; i++) - elements->tdata()[i] = elementinit; + (*elements)[i] = elementinit; ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); ae->type = this; return ae; @@ -4895,6 +4925,15 @@ MATCH TypeAArray::constConv(Type *to) return Type::constConv(to); } +Type *TypeAArray::reliesOnTident(TemplateParameters *tparams) +{ + Type *t = TypeNext::reliesOnTident(tparams); + if (!t) + t = index->reliesOnTident(tparams); + return t; +} + + /***************************** TypePointer *****************************/ TypePointer::TypePointer(Type *t) @@ -4916,7 +4955,7 @@ Type *TypePointer::syntaxCopy() Type *TypePointer::semantic(Loc loc, Scope *sc) { - //printf("TypePointer::semantic()\n"); + //printf("TypePointer::semantic() %s\n", toChars()); if (deco) return this; Type *n = next->semantic(loc, sc); @@ -4933,8 +4972,19 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) } next = n; if (next->ty != Tfunction) - transitive(); + { transitive(); + return merge(); + } +#if 1 return merge(); +#else + deco = merge()->deco; + /* Don't return merge(), because arg identifiers and default args + * can be different + * even though the types match + */ + return this; +#endif } @@ -5302,6 +5352,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)) + goto Lcovariant; } goto Lnotcovariant; @@ -5536,7 +5588,7 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd { buf->writeByte('('); for (size_t i = 0; i < td->origParameters->dim; i++) { - TemplateParameter *tp = td->origParameters->tdata()[i]; + TemplateParameter *tp = (*td->origParameters)[i]; if (i) buf->writestring(", "); tp->toCBuffer(buf, hgs); @@ -5547,18 +5599,13 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd inuse--; } -void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) +// kind is inserted before the argument list and will usually be "function" or "delegate". +void functionToCBuffer2(TypeFunction *t, OutBuffer *buf, HdrGenState *hgs, int mod, const char *kind) { - //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); - if (inuse) - { inuse = 2; // flag error to caller - return; - } - inuse++; if (hgs->ddoc != 1) { const char *p = NULL; - switch (linkage) + switch (t->linkage) { case LINKd: p = NULL; break; case LINKc: p = "C"; break; @@ -5579,14 +5626,27 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) buf->writestring(") "); } } - if (next) + if (t->next) { - next->toCBuffer2(buf, hgs, 0); + t->next->toCBuffer2(buf, hgs, 0); buf->writeByte(' '); } - buf->writestring("function"); - Parameter::argsToCBuffer(buf, hgs, parameters, varargs); - attributesToCBuffer(buf, mod); + buf->writestring(kind); + Parameter::argsToCBuffer(buf, hgs, t->parameters, t->varargs); + t->attributesToCBuffer(buf, mod); +} + +void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) +{ + //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); + if (inuse) + { inuse = 2; // flag error to caller + return; + } + inuse++; + + functionToCBuffer2(this, buf, hgs, mod, "function"); + inuse--; } @@ -5642,10 +5702,10 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (parameters) { tf->parameters = (Parameters *)parameters->copy(); for (size_t i = 0; i < parameters->dim; i++) - { Parameter *arg = parameters->tdata()[i]; + { Parameter *arg = (*parameters)[i]; Parameter *cpy = (Parameter *)mem.malloc(sizeof(Parameter)); memcpy(cpy, arg, sizeof(Parameter)); - tf->parameters->tdata()[i] = cpy; + (*tf->parameters)[i] = cpy; } } @@ -5767,24 +5827,12 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) e = resolveProperties(argsc, e); if (e->op == TOKfunction) // see Bugzilla 4820 { FuncExp *fe = (FuncExp *)e; - if (fe->fd) - { if (fe->fd->tok == TOKreserved) - { - if (fe->type->ty == Tpointer) - { - fe->fd->vthis = NULL; - fe->fd->tok = TOKfunction; - } - else - fe->fd->tok = TOKdelegate; - } - // Replace function literal with a function symbol, - // since default arg expression must be copied when used - // and copying the literal itself is wrong. - e = new VarExp(e->loc, fe->fd, 0); - e = new AddrExp(e->loc, e); - e = e->semantic(argsc); - } + // Replace function literal with a function symbol, + // since default arg expression must be copied when used + // and copying the literal itself is wrong. + e = new VarExp(e->loc, fe->fd, 0); + e = new AddrExp(e->loc, e); + e = e->semantic(argsc); } e = e->implicitCastTo(argsc, fparam->type); fparam->defaultArg = e; @@ -5795,8 +5843,13 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) */ if (t->ty == Ttuple) { + /* TypeFunction::parameter also is used as the storage of + * Parameter objects for FuncDeclaration. So we should copy + * the elements of TypeTuple::arguments to avoid unintended + * sharing of Parameter object among other functions. + */ TypeTuple *tt = (TypeTuple *)t; - if (fparam->storageClass && tt->arguments && tt->arguments->dim) + if (tt->arguments && tt->arguments->dim) { /* Propagate additional storage class from tuple parameters to their * element-parameters. @@ -5807,7 +5860,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) newparams->setDim(tdim); for (size_t j = 0; j < tdim; j++) { Parameter *narg = (*tt->arguments)[j]; - newparams->tdata()[j] = new Parameter(narg->storageClass | fparam->storageClass, + (*newparams)[j] = new Parameter(narg->storageClass | fparam->storageClass, narg->type, narg->ident, narg->defaultArg); } fparam->type = new TypeTuple(newparams); @@ -5828,7 +5881,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (fparam->storageClass & STCauto) { if (fargs && i < fargs->dim) - { Expression *farg = fargs->tdata()[i]; + { Expression *farg = (*fargs)[i]; if (farg->isLvalue()) ; // ref parameter else @@ -6008,7 +6061,7 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) if (u >= nparams) break; Parameter *p = Parameter::getNth(parameters, u); - Expression *arg = args->tdata()[u]; + Expression *arg = (*args)[u]; assert(arg); if (!(p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid)) @@ -6049,7 +6102,7 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) goto L1; // try typesafe variadics } { - Expression *arg = args->tdata()[u]; + Expression *arg = (*args)[u]; assert(arg); if (arg->op == TOKfunction) @@ -6064,17 +6117,38 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) Type *targ = arg->type; Type *tprm = wildmatch ? p->type->substWildTo(wildmatch) : p->type; + if (p->storageClass & STClazy && tprm->ty == Tvoid && targ->ty != Tvoid) + m = MATCHconvert; + else + { + //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars()); + if (flag) + // for partial ordering, value is an irrelevant mockup, just look at the type + m = targ->implicitConvTo(tprm); + else + m = arg->implicitConvTo(tprm); + //printf("match %d\n", m); + } + // Non-lvalues do not match ref or out parameters if (p->storageClass & STCref) - { if (!arg->isLvalue()) - { if (arg->op == TOKstring && tprm->ty == Tsarray) + { 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 if (ta && ta->implicitConvTo(tprm)) + { + goto Nomatch; + } else if (arg->op == TOKstructliteral) + { match = MATCHconvert; + } else if (arg->op == TOKcall) { CallExp *ce = (CallExp *)arg; @@ -6090,13 +6164,24 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) goto Nomatch; } - /* Don't allow static arrays to be passed to mutable references - * to static arrays if the argument cannot be modified. - */ Type *targb = targ->toBasetype(); Type *tprmb = tprm->toBasetype(); //printf("%s\n", targb->toChars()); //printf("%s\n", tprmb->toChars()); + + /* find most derived alias this type being matched. + */ + while (1) + { + Type *tat = targb->aliasthisOf(); + if (!tat || !tat->implicitConvTo(tprm)) + break; + targb = tat; + } + + /* Don't allow static arrays to be passed to mutable references + * to static arrays if the argument cannot be modified. + */ if (targb->nextOf() && tprmb->ty == Tsarray && !MODimplicitConv(targb->nextOf()->mod, tprmb->nextOf()->mod)) goto Nomatch; @@ -6106,22 +6191,9 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) goto Nomatch; } else if (p->storageClass & STCout) - { if (!arg->isLvalue()) + { if (m && !arg->isLvalue()) goto Nomatch; } - - if (p->storageClass & STClazy && tprm->ty == Tvoid && targ->ty != Tvoid) - m = MATCHconvert; - else - { - //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars()); - if (flag) - // for partial ordering, value is an irrelevant mockup, just look at the type - m = targ->implicitConvTo(tprm); - else - m = arg->implicitConvTo(tprm); - //printf("match %d\n", m); - } } /* prefer matching the element type rather than the array @@ -6150,7 +6222,7 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) { TypeArray *ta = (TypeArray *)tb; for (; u < nargs; u++) { - Expression *arg = args->tdata()[u]; + Expression *arg = (*args)[u]; assert(arg); #if 1 if (arg->op == TOKfunction) @@ -6338,6 +6410,7 @@ Type *TypeDelegate::syntaxCopy() Type *TypeDelegate::semantic(Loc loc, Scope *sc) { + //printf("TypeDelegate::semantic() %s\n", toChars()); if (deco) // if semantic() already run { //printf("already done\n"); @@ -6348,13 +6421,16 @@ Type *TypeDelegate::semantic(Loc loc, Scope *sc) * be removed from next before the merge. */ +#if 1 + return merge(); +#else /* Don't return merge(), because arg identifiers and default args * can be different * even though the types match */ - //deco = merge()->deco; - //return this; - return merge(); + deco = merge()->deco; + return this; +#endif } d_uns64 TypeDelegate::size(Loc loc) @@ -6390,12 +6466,8 @@ void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) { toCBuffer3(buf, hgs, mod); return; } - TypeFunction *tf = (TypeFunction *)next; - tf->next->toCBuffer2(buf, hgs, 0); - buf->writestring(" delegate"); - Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs); - tf->attributesToCBuffer(buf, mod); + functionToCBuffer2((TypeFunction *)next, buf, hgs, mod, "delegate"); } Expression *TypeDelegate::defaultInit(Loc loc) @@ -6461,7 +6533,7 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t) idents.setDim(t->idents.dim); for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = t->idents.tdata()[i]; + Identifier *id = t->idents[i]; if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; @@ -6469,7 +6541,7 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t) ti = (TemplateInstance *)ti->syntaxCopy(NULL); id = (Identifier *)ti; } - idents.tdata()[i] = id; + idents[i] = id; } } @@ -6482,7 +6554,7 @@ void TypeQualified::addIdent(Identifier *ident) void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs) { for (size_t i = 0; i < idents.dim; i++) - { Identifier *id = idents.tdata()[i]; + { Identifier *id = idents[i]; buf->writeByte('.'); @@ -6534,7 +6606,7 @@ 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.tdata()[i]; + Identifier *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()); @@ -6544,9 +6616,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, v = s->isVarDeclaration(); if (v && id == Id::length) { - e = v->getConstInitializer(); - if (!e) - e = new VarExp(loc, v); + e = new VarExp(loc, v); t = e->type; if (!t) goto Lerror; @@ -6557,7 +6627,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, e = new DsymbolExp(loc, s, 0); do { - id = idents.tdata()[i]; + id = idents[i]; e = new DotIdExp(loc, e, id); } while (++i < idents.dim); e = e->semantic(sc); @@ -6590,7 +6660,7 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, L3: for (; i < idents.dim; i++) { - id = idents.tdata()[i]; + 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); @@ -6819,7 +6889,7 @@ Dsymbol *TypeIdentifier::toDsymbol(Scope *sc) { for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = idents.tdata()[i]; + Identifier *id = idents[i]; s = s->searchX(loc, sc, id); if (!s) // failed to find a symbol { //printf("\tdidn't find a symbol\n"); @@ -6872,7 +6942,7 @@ Type *TypeIdentifier::reliesOnTident(TemplateParameters *tparams) if (idents.dim == 0) { for (size_t i = 0; i < tparams->dim; i++) - { TemplateParameter *tp = tparams->tdata()[i]; + { TemplateParameter *tp = (*tparams)[i]; if (tp->ident->equals(ident)) return this; @@ -6889,7 +6959,7 @@ Expression *TypeIdentifier::toExpression() Expression *e = new IdentifierExp(loc, ident); for (size_t i = 0; i < idents.dim; i++) { - Identifier *id = idents.tdata()[i]; + Identifier *id = idents[i]; e = new DotIdExp(loc, e, id); } @@ -7008,6 +7078,33 @@ Dsymbol *TypeInstance::toDsymbol(Scope *sc) return s; } +Type *TypeInstance::reliesOnTident(TemplateParameters *tparams) +{ + if (tparams) + { + for (size_t i = 0; i < tparams->dim; i++) + { + TemplateParameter *tp = (*tparams)[i]; + if (tempinst->name == tp->ident) + return this; + } + if (!tempinst->tiargs) + return NULL; + for (size_t i = 0; i < tempinst->tiargs->dim; i++) + { + Type *t = isType((*tempinst->tiargs)[i]); + t = t ? t->reliesOnTident(tparams) : NULL; + if (t) + return t; + } + return NULL; + } + else + { + return Type::reliesOnTident(tparams); + } +} + /***************************** TypeTypeof *****************************/ @@ -7160,7 +7257,7 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { if (!s) break; - Identifier *id = idents.tdata()[i]; + Identifier *id = idents[i]; s = s->searchX(loc, sc, id); } @@ -7240,7 +7337,7 @@ Type *TypeReturn::semantic(Loc loc, Scope *sc) { if (!s) break; - Identifier *id = idents.tdata()[i]; + Identifier *id = idents[i]; s = s->searchX(loc, sc, id); } if (s) @@ -7607,6 +7704,20 @@ Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident) return sym->basetype->dotExp(sc, e, ident); } +structalign_t TypeTypedef::alignment() +{ + if (sym->inuse) + { + sym->error("circular definition"); + sym->basetype = Type::terror; + return STRUCTALIGN_DEFAULT; + } + sym->inuse = 1; + structalign_t a = sym->basetype->alignment(); + sym->inuse = 0; + return a; +} + Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident) { #if LOGDOTEXP @@ -7843,13 +7954,9 @@ d_uns64 TypeStruct::size(Loc loc) } unsigned TypeStruct::alignsize() -{ unsigned sz; - +{ sym->size(0); // give error for forward references - sz = sym->alignsize; - if (sz > sym->structalign) - sz = sym->structalign; - return sz; + return sym->alignsize; } Dsymbol *TypeStruct::toDsymbol(Scope *sc) @@ -7908,7 +8015,7 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *ev = e; for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields.tdata()[i]; + { VarDeclaration *v = sym->fields[i]; Expression *fe; if (i == 0 && sc->func && sym->fields.dim > 1 && e->hasSideEffect()) @@ -8061,7 +8168,10 @@ L1: e = e->semantic(sc); return e; } - return new VarExp(e->loc, d, 1); + VarExp *ve = new VarExp(e->loc, d, 1); + if (d->isVarDeclaration() && d->needThis()) + ve->type = d->type->addMod(e->type->mod); + return ve; } if (d->isDataseg()) @@ -8098,10 +8208,11 @@ L1: return de->semantic(sc); } -unsigned TypeStruct::memalign(unsigned salign) +structalign_t TypeStruct::alignment() { - sym->size(0); // give error for forward references - return sym->structalign; + if (sym->alignment == 0) + sym->size(0); + return sym->alignment; } Expression *TypeStruct::defaultInit(Loc loc) @@ -8124,13 +8235,13 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) #if LOGDEFAULTINIT printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); #endif - if (sym->isNested()) - return defaultInit(loc); + //if (sym->isNested()) + // return defaultInit(loc); Expressions *structelems = new Expressions(); - structelems->setDim(sym->fields.dim); + structelems->setDim(sym->fields.dim - sym->isnested); for (size_t j = 0; j < structelems->dim; j++) { - VarDeclaration *vd = sym->fields.tdata()[j]; + VarDeclaration *vd = sym->fields[j]; Expression *e; if (vd->init) { if (vd->init->isVoidInitializer()) @@ -8148,7 +8259,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) + if (size(loc) > PTRSIZE * 4 && !sym->isnested) structinit->sinit = sym->toInitializer(); #endif @@ -8183,7 +8294,7 @@ int TypeStruct::isAssignable() * then one cannot assign this struct. */ for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields.tdata()[i]; + { VarDeclaration *v = sym->fields[i]; //printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind()); if (i == 0) ; @@ -8217,7 +8328,7 @@ int TypeStruct::hasPointers() sym->size(0); // give error for forward references for (size_t i = 0; i < s->fields.dim; i++) { - Dsymbol *sm = s->fields.tdata()[i]; + Dsymbol *sm = s->fields[i]; Declaration *d = sm->isDeclaration(); if (d->storage_class & STCref || d->hasPointers()) return TRUE; @@ -8246,14 +8357,15 @@ MATCH TypeStruct::implicitConvTo(Type *to) { m = MATCHexact; // exact match if (mod != to->mod) { + m = MATCHconst; if (MODimplicitConv(mod, to->mod)) - m = MATCHconst; + ; else { /* Check all the fields. If they can all be converted, * allow the conversion. */ for (size_t i = 0; i < sym->fields.dim; i++) - { Dsymbol *s = sym->fields.tdata()[i]; + { Dsymbol *s = sym->fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->storage_class & STCfield); @@ -8263,11 +8375,15 @@ MATCH TypeStruct::implicitConvTo(Type *to) // 'to' type Type *tv = v->type->castMod(to->mod); - //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), tvf->implicitConvTo(tv)); - if (tvf->implicitConvTo(tv) < MATCHconst) - return MATCHnomatch; + // field match + MATCH mf = tvf->implicitConvTo(tv); + //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), mf); + + if (mf == MATCHnomatch) + return mf; + if (mf < m) // if field match is worse + m = mf; } - m = MATCHconst; } } } @@ -8408,7 +8524,7 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident) Expression *ev = e; for (size_t i = 0; i < sym->fields.dim; i++) - { VarDeclaration *v = sym->fields.tdata()[i]; + { VarDeclaration *v = sym->fields[i]; // Don't include hidden 'this' pointer if (v->isThisDeclaration()) continue; @@ -8638,14 +8754,12 @@ L1: return de; } -#if 0 // shouldn't this be here? if (s->isImport() || s->isModule() || s->isPackage()) { e = new DsymbolExp(e->loc, s, 0); e = e->semantic(sc); return e; } -#endif OverloadSet *o = s->isOverloadSet(); if (o) @@ -8706,11 +8820,10 @@ L1: e = de->semantic(sc); return e; } - else - { - VarExp *ve = new VarExp(e->loc, d, 1); - return ve; - } + VarExp *ve = new VarExp(e->loc, d, 1); + if (d->isVarDeclaration() && d->needThis()) + ve->type = d->type->addMod(e->type->mod); + return ve; } if (d->isDataseg()) @@ -8772,7 +8885,7 @@ MATCH TypeClass::implicitConvTo(Type *to) { if (cdto->scope) cdto->semantic(NULL); - if (cdto->isBaseOf(sym, NULL)) + if (cdto->isBaseOf(sym, NULL) && MODimplicitConv(mod, to->mod)) { //printf("'to' is base\n"); return MATCHconvert; } @@ -8867,7 +8980,7 @@ TypeTuple::TypeTuple(Parameters *arguments) { for (size_t i = 0; i < arguments->dim; i++) { - Parameter *arg = arguments->tdata()[i]; + Parameter *arg = (*arguments)[i]; assert(arg && arg->type); } } @@ -8887,11 +9000,11 @@ TypeTuple::TypeTuple(Expressions *exps) { arguments->setDim(exps->dim); for (size_t i = 0; i < exps->dim; i++) - { Expression *e = exps->tdata()[i]; + { Expression *e = (*exps)[i]; if (e->type->ty == Ttuple) e->error("cannot form tuple of tuples"); Parameter *arg = new Parameter(STCundefined, e->type, NULL, NULL); - arguments->tdata()[i] = arg; + (*arguments)[i] = arg; } } this->arguments = arguments; @@ -8958,8 +9071,8 @@ int TypeTuple::equals(Object *o) if (arguments->dim == tt->arguments->dim) { for (size_t i = 0; i < tt->arguments->dim; i++) - { Parameter *arg1 = arguments->tdata()[i]; - Parameter *arg2 = tt->arguments->tdata()[i]; + { Parameter *arg1 = (*arguments)[i]; + Parameter *arg2 = (*tt->arguments)[i]; if (!arg1->type->equals(arg2->type)) return 0; @@ -8976,7 +9089,7 @@ Type *TypeTuple::reliesOnTident(TemplateParameters *tparams) { for (size_t i = 0; i < arguments->dim; i++) { - Parameter *arg = arguments->tdata()[i]; + Parameter *arg = (*arguments)[i]; Type *t = arg->type->reliesOnTident(tparams); if (t) return t; @@ -8995,9 +9108,9 @@ Type *TypeTuple::makeConst() t->arguments = new Parameters(); t->arguments->setDim(arguments->dim); for (size_t i = 0; i < arguments->dim; i++) - { Parameter *arg = arguments->tdata()[i]; + { Parameter *arg = (*arguments)[i]; Parameter *narg = new Parameter(arg->storageClass, arg->type->constOf(), arg->ident, arg->defaultArg); - t->arguments->tdata()[i] = (Parameter *)narg; + (*t->arguments)[i] = (Parameter *)narg; } return t; } @@ -9090,11 +9203,11 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) TypeTuple *tt = (TypeTuple *)tbn; lwr = semanticLength(sc, tbn, lwr); - lwr = lwr->optimize(WANTvalue | WANTinterpret); + lwr = lwr->ctfeInterpret(); uinteger_t i1 = lwr->toUInteger(); upr = semanticLength(sc, tbn, upr); - upr = upr->optimize(WANTvalue | WANTinterpret); + upr = upr->ctfeInterpret(); uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) @@ -9105,7 +9218,7 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) Parameters *args = new Parameters; args->reserve(i2 - i1); for (size_t i = i1; i < i2; i++) - { Parameter *arg = tt->arguments->tdata()[i]; + { Parameter *arg = (*tt->arguments)[i]; args->push(arg); } @@ -9134,11 +9247,11 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->push(sym); lwr = lwr->semantic(sc); - lwr = lwr->optimize(WANTvalue | WANTinterpret); + lwr = lwr->ctfeInterpret(); uinteger_t i1 = lwr->toUInteger(); upr = upr->semantic(sc); - upr = upr->optimize(WANTvalue | WANTinterpret); + upr = upr->ctfeInterpret(); uinteger_t i2 = upr->toUInteger(); sc = sc->pop(); @@ -9161,7 +9274,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol objects->setDim(i2 - i1); for (size_t i = 0; i < objects->dim; i++) { - objects->tdata()[i] = td->objects->tdata()[(size_t)i1 + i]; + (*objects)[i] = (*td->objects)[(size_t)i1 + i]; } TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); @@ -9268,10 +9381,10 @@ Parameters *Parameter::arraySyntaxCopy(Parameters *args) a = new Parameters(); a->setDim(args->dim); for (size_t i = 0; i < a->dim; i++) - { Parameter *arg = args->tdata()[i]; + { Parameter *arg = (*args)[i]; arg = arg->syntaxCopy(); - a->tdata()[i] = arg; + (*a)[i] = arg; } } return a; @@ -9281,32 +9394,9 @@ char *Parameter::argsTypesToChars(Parameters *args, int varargs) { OutBuffer *buf = new OutBuffer(); -#if 1 HdrGenState hgs; argsToCBuffer(buf, &hgs, args, varargs); -#else - buf->writeByte('('); - if (args) - { OutBuffer argbuf; - HdrGenState hgs; - for (size_t i = 0; i < args->dim; i++) - { if (i) - buf->writeByte(','); - Parameter *arg = args->tdata()[i]; - argbuf.reset(); - arg->type->toCBuffer2(&argbuf, &hgs, 0); - buf->write(&argbuf); - } - if (varargs) - { - if (i && varargs == 1) - buf->writeByte(','); - buf->writestring("..."); - } - } - buf->writeByte(')'); -#endif return buf->toChars(); } @@ -9532,7 +9622,7 @@ int Parameter::foreach(Parameters *args, Parameter::ForeachDg dg, void *ctx, siz size_t n = pn ? *pn : 0; // take over index int result = 0; for (size_t i = 0; i < args->dim; i++) - { Parameter *arg = args->tdata()[i]; + { Parameter *arg = (*args)[i]; Type *t = arg->type->toBasetype(); if (t->ty == Ttuple) diff --git a/dmd2/mtype.h b/dmd2/mtype.h index 8a2b1a76..a35f9f5c 100644 --- a/dmd2/mtype.h +++ b/dmd2/mtype.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2010 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -48,7 +48,7 @@ struct HdrGenState; struct Parameter; // Back end -#if IN_GCC +#ifdef IN_GCC union tree_node; typedef union tree_node TYPE; typedef TYPE type; #endif @@ -215,6 +215,7 @@ struct Type : Object static ClassDeclaration *typeinfowild; static TemplateDeclaration *associativearray; + static TemplateDeclaration *rtinfo; static Type *basic[TMAX]; static unsigned char mangleChar[TMAX]; @@ -317,8 +318,8 @@ struct Type : Object virtual ClassDeclaration *isClassHandle(); virtual Expression *getProperty(Loc loc, Identifier *ident); virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + virtual structalign_t alignment(); Expression *noMember(Scope *sc, Expression *e, Identifier *ident); - virtual unsigned memalign(unsigned salign); virtual Expression *defaultInit(Loc loc = 0); virtual Expression *defaultInitLiteral(Loc loc); virtual Expression *voidInitLiteral(VarDeclaration *var); @@ -375,6 +376,7 @@ struct TypeError : Type Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + TypeTuple *toArgTypes(); }; struct TypeNext : Type @@ -409,7 +411,7 @@ struct TypeBasic : Type d_uns64 size(Loc loc); unsigned alignsize(); #if IN_LLVM - unsigned memalign(unsigned salign); + unsigned alignment(); #endif Expression *getProperty(Loc loc, Identifier *ident); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); @@ -488,7 +490,7 @@ struct TypeSArray : TypeArray Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int isString(); int isZeroInit(Loc loc); - unsigned memalign(unsigned salign); + structalign_t alignment(); MATCH constConv(Type *to); MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); @@ -567,6 +569,7 @@ struct TypeAArray : TypeArray int isZeroInit(Loc loc); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + Type *reliesOnTident(TemplateParameters *tparams); Expression *toExpression(); int hasPointers(); TypeTuple *toArgTypes(); @@ -778,6 +781,7 @@ struct TypeInstance : TypeQualified void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); Type *semantic(Loc loc, Scope *sc); Dsymbol *toDsymbol(Scope *sc); + Type *reliesOnTident(TemplateParameters *tparams = NULL); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); }; @@ -817,7 +821,7 @@ struct TypeStruct : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); - unsigned memalign(unsigned salign); + structalign_t alignment(); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); Expression *voidInitLiteral(VarDeclaration *var); @@ -907,6 +911,7 @@ struct TypeTypedef : Type void toDecoBuffer(OutBuffer *buf, int flag, bool mangle); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + structalign_t alignment(); Expression *getProperty(Loc loc, Identifier *ident); int isintegral(); int isfloating(); diff --git a/dmd2/opover.c b/dmd2/opover.c index bcf1828c..de57524a 100644 --- a/dmd2/opover.c +++ b/dmd2/opover.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -12,6 +12,7 @@ #include #include #include +#include // memset() #if _MSC_VER #include #else @@ -355,9 +356,11 @@ Expression *UnaExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - UnaExp *e = (UnaExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); + Expression *e = copy(); + ((UnaExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } #endif } @@ -374,7 +377,7 @@ Expression *ArrayExp::op_overload(Scope *sc) if (fd) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *x = arguments->tdata()[i]; + { Expression *x = (*arguments)[i]; // Create scope for '$' variable for this dimension ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, this); sym->loc = loc; @@ -393,7 +396,7 @@ Expression *ArrayExp::op_overload(Scope *sc) x = new CommaExp(0, av, x); x->semantic(sc); } - arguments->tdata()[i] = x; + (*arguments)[i] = x; sc = sc->pop(); } @@ -412,9 +415,11 @@ Expression *ArrayExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - UnaExp *e = (UnaExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); + Expression *e = copy(); + ((UnaExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } } return NULL; @@ -457,9 +462,11 @@ Expression *CastExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - UnaExp *e = (UnaExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); + Expression *e = copy(); + ((UnaExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } } return NULL; @@ -529,9 +536,9 @@ Expression *BinExp::op_overload(Scope *sc) */ args1.setDim(1); - args1.tdata()[0] = e1; + args1[0] = e1; args2.setDim(1); - args2.tdata()[0] = e2; + args2[0] = e2; argsset = 1; Match m; @@ -622,9 +629,9 @@ L1: if (!argsset) { args1.setDim(1); - args1.tdata()[0] = e1; + args1[0] = e1; args2.setDim(1); - args2.tdata()[0] = e2; + args2[0] = e2; } Match m; @@ -715,9 +722,11 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } // Try alias this on second operand @@ -730,9 +739,11 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); - return e->trySemantic(sc); + Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e2 = e2; + e = e->trySemantic(sc); + return e; } #endif return NULL; @@ -776,9 +787,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) Expressions args2; args1.setDim(1); - args1.tdata()[0] = e1; + args1[0] = e1; args2.setDim(1); - args2.tdata()[0] = e2; + args2[0] = e2; Match m; memset(&m, 0, sizeof(m)); @@ -884,9 +895,11 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } // Try alias this on second operand @@ -895,9 +908,11 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); - return e->trySemantic(sc); + Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e2 = e2; + e = e->trySemantic(sc); + return e; } return NULL; @@ -916,12 +931,20 @@ Expression *EqualExp::op_overload(Scope *sc) if (!(cd1->isCPPinterface() || cd2->isCPPinterface())) { /* Rewrite as: - * .object.opEquals(cast(Object)e1, cast(Object)e2) + * .object.opEquals(e1, e2) + */ + Expression *e1x = e1; + Expression *e2x = e2; + + /* * The explicit cast is necessary for interfaces, * see http://d.puremagic.com/issues/show_bug.cgi?id=4088 */ - Expression *e1x = new CastExp(loc, e1, ClassDeclaration::object->getType()); - Expression *e2x = new CastExp(loc, e2, ClassDeclaration::object->getType()); + Type *to = ClassDeclaration::object->getType(); + if (cd1->isInterfaceDeclaration()) + e1x = new CastExp(loc, e1, t1->isMutable() ? to : to->constOf()); + if (cd2->isInterfaceDeclaration()) + e2x = new CastExp(loc, e2, t2->isMutable() ? to : to->constOf()); Expression *e = new IdentifierExp(loc, Id::empty); e = new DotIdExp(loc, e, Id::object); @@ -968,7 +991,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) Expressions *a = new Expressions(); a->push(e2); for (size_t i = 0; i < ae->arguments->dim; i++) - a->push(ae->arguments->tdata()[i]); + a->push((*ae->arguments)[i]); Objects *targsi = opToArg(sc, op); Expression *e = new DotTemplateInstanceExp(loc, ae->e1, fd->ident, targsi); @@ -1085,7 +1108,7 @@ Expression *BinAssignExp::op_overload(Scope *sc) */ args2.setDim(1); - args2.tdata()[0] = e2; + args2[0] = e2; Match m; memset(&m, 0, sizeof(m)); @@ -1132,9 +1155,11 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); - return e->trySemantic(sc); + Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e1 = e1; + e = e->trySemantic(sc); + return e; } // Try alias this on second operand @@ -1144,9 +1169,11 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - BinExp *e = (BinExp *)syntaxCopy(); - e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); - return e->trySemantic(sc); + Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); + Expression *e = copy(); + ((BinExp *)e)->e2 = e2; + e = e->trySemantic(sc); + return e; } #endif return NULL; @@ -1209,7 +1236,7 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) { Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse; #if DMDV2 - Identifier *idhead = (op == TOKforeach) ? Id::Ffront : Id::Fback; + Identifier *idfront = (op == TOKforeach) ? Id::Ffront : Id::Fback; int sliced = 0; #endif Type *tab; @@ -1262,7 +1289,7 @@ int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply) } } - if (Dsymbol *shead = search_function(ad, idhead)) + if (Dsymbol *shead = ad->search(0, idfront, 0)) { // range aggregate break; } @@ -1316,7 +1343,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) if (sapply) // prefer opApply { for (size_t u = 0; u < arguments->dim; u++) - { Parameter *arg = arguments->tdata()[u]; + { Parameter *arg = (*arguments)[u]; if (arg->type) arg->type = arg->type->semantic(loc, sc); } @@ -1350,14 +1377,14 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) /* Return if no arguments need types. */ for (size_t u = 0; u < arguments->dim; u++) - { Parameter *arg = arguments->tdata()[u]; + { Parameter *arg = (*arguments)[u]; if (!arg->type) break; } AggregateDeclaration *ad; - Parameter *arg = arguments->tdata()[0]; + Parameter *arg = (*arguments)[0]; Type *taggr = aggr->type; assert(taggr); Type *tab = taggr->toBasetype(); @@ -1370,7 +1397,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) { if (!arg->type) arg->type = Type::tsize_t; // key type - arg = arguments->tdata()[1]; + arg = (*arguments)[1]; } if (!arg->type && tab->ty != Ttuple) arg->type = tab->nextOf(); // value type @@ -1383,7 +1410,7 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) { if (!arg->type) arg->type = taa->index; // key type - arg = arguments->tdata()[1]; + arg = (*arguments)[1]; } if (!arg->type) arg->type = taa->next; // value type @@ -1403,20 +1430,24 @@ int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) { if (!arg->type) { - /* Look for a head() or rear() overload + /* Look for a front() or back() overload */ Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback; - Dsymbol *s = search_function(ad, id); + Dsymbol *s = ad->search(0, id, 0); FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; - if (!fd) - { if (s && s->isTemplateDeclaration()) - break; - break; + if (fd) + { + // Resolve inout qualifier of front type + arg->type = fd->type->nextOf(); + if (arg->type) + arg->type = arg->type->substWildTo(tab->mod); } - // Resolve inout qualifier of front type - arg->type = fd->type->nextOf(); - if (arg->type) - arg->type = arg->type->substWildTo(tab->mod); + else if (s && s->isTemplateDeclaration()) + ; + else if (s && s->isDeclaration()) + arg->type = ((Declaration *)s)->type; + else + break; } break; } @@ -1522,7 +1553,7 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flag for (size_t u = 0; u < nparams; u++) { - Parameter *arg = arguments->tdata()[u]; + Parameter *arg = (*arguments)[u]; Parameter *param = Parameter::getNth(tf->parameters, u); if (arg->type) { if (!arg->type->equals(param->type)) @@ -1560,7 +1591,7 @@ void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments) } if (!td->parameters || td->parameters->dim != 1) continue; - TemplateParameter *tp = td->parameters->tdata()[0]; + TemplateParameter *tp = (*td->parameters)[0]; TemplateAliasParameter *tap = tp->isTemplateAliasParameter(); if (!tap || !tap->specType || tap->specType->ty != Tfunction) continue; diff --git a/dmd2/optimize.c b/dmd2/optimize.c index f007751c..16e30130 100644 --- a/dmd2/optimize.c +++ b/dmd2/optimize.c @@ -153,7 +153,6 @@ Expression *fromConstInitializer(int result, Expression *e1) if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); - int fwdref = (v && !v->originalType && v->scope); e = expandVar(result, v); if (e) { @@ -202,10 +201,10 @@ Expression *VarExp::optimize(int result) Expression *TupleExp::optimize(int result) { for (size_t i = 0; i < exps->dim; i++) - { Expression *e = exps->tdata()[i]; + { Expression *e = (*exps)[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); - exps->tdata()[i] = e; + (*exps)[i] = e; } return this; } @@ -215,10 +214,10 @@ Expression *ArrayLiteralExp::optimize(int result) if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand))); - elements->tdata()[i] = e; + (*elements)[i] = e; } } return this; @@ -228,14 +227,14 @@ Expression *AssocArrayLiteralExp::optimize(int result) { assert(keys->dim == values->dim); for (size_t i = 0; i < keys->dim; i++) - { Expression *e = keys->tdata()[i]; + { Expression *e = (*keys)[i]; e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand))); - keys->tdata()[i] = e; + (*keys)[i] = e; - e = values->tdata()[i]; + e = (*values)[i]; e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand))); - values->tdata()[i] = e; + (*values)[i] = e; } return this; } @@ -245,11 +244,11 @@ Expression *StructLiteralExp::optimize(int result) if (elements) { for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; if (!e) continue; e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand))); - elements->tdata()[i] = e; + (*elements)[i] = e; } } return this; @@ -495,20 +494,20 @@ Expression *NewExp::optimize(int result) if (newargs) { for (size_t i = 0; i < newargs->dim; i++) - { Expression *e = newargs->tdata()[i]; + { Expression *e = (*newargs)[i]; e = e->optimize(WANTvalue); - newargs->tdata()[i] = e; + (*newargs)[i] = e; } } if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = (*arguments)[i]; e = e->optimize(WANTvalue); - arguments->tdata()[i] = e; + (*arguments)[i] = e; } } if (result & WANTinterpret) @@ -527,10 +526,10 @@ Expression *CallExp::optimize(int result) if (arguments) { for (size_t i = 0; i < arguments->dim; i++) - { Expression *e = arguments->tdata()[i]; + { Expression *e = (*arguments)[i]; e = e->optimize(WANTvalue); - arguments->tdata()[i] = e; + (*arguments)[i] = e; } } diff --git a/dmd2/parse.c b/dmd2/parse.c index 6119ec54..8ad48ce7 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -12,6 +12,7 @@ #include #include +#include // strlen(),memcpy() #include "rmem.h" #include "lexer.h" @@ -454,7 +455,10 @@ Dsymbols *Parser::parseDeclDefs(int once) ((tk = peek(tk)), 1) && skipAttributes(tk, &tk) && (tk->value == TOKlparen || - tk->value == TOKlcurly) + tk->value == TOKlcurly || + tk->value == TOKin || + tk->value == TOKout || + tk->value == TOKbody) ) { a = parseDeclarations(storageClass, comment); @@ -512,7 +516,11 @@ Dsymbols *Parser::parseDeclDefs(int once) { nextToken(); if (token.value == TOKint32v && token.uns64value > 0) + { + if (token.uns64value & (token.uns64value - 1)) + error("align(%s) must be a power of 2", token.toChars()); n = (unsigned)token.uns64value; + } else { error("positive integer expected, not %s", token.toChars()); n = 1; @@ -535,7 +543,7 @@ Dsymbols *Parser::parseDeclDefs(int once) nextToken(); check(TOKlparen); if (token.value != TOKidentifier) - { error("pragma(identifier expected"); + { error("pragma(identifier) expected"); goto Lerror; } ident = token.ident; @@ -1370,7 +1378,8 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) default: Ldefault: { stc = storageClass & (STCin | STCout | STCref | STClazy); - if (stc & (stc - 1)) // if stc is not a power of 2 + if (stc & (stc - 1) && // if stc is not a power of 2 + !(stc == (STCin | STCref))) error("incompatible parameter storage classes"); if ((storageClass & (STCconst | STCout)) == (STCconst | STCout)) error("out cannot be const"); @@ -2860,7 +2869,10 @@ Dsymbols *Parser::parseDeclarations(StorageClass storage_class, unsigned char *c ((tk = peek(tk)), 1) && skipAttributes(tk, &tk) && (tk->value == TOKlparen || - tk->value == TOKlcurly) + tk->value == TOKlcurly || + tk->value == TOKin || + tk->value == TOKout || + tk->value == TOKbody) ) { ts = NULL; @@ -3347,7 +3359,15 @@ Initializer *Parser::parseInitializer() if (comma == 1) error("comma expected separating array initializers, not %s", token.toChars()); value = parseInitializer(); - ia->addInit(NULL, value); + if (token.value == TOKcolon) + { + nextToken(); + e = value->toExpression(); + value = parseInitializer(); + } + else + e = NULL; + ia->addInit(e, value); comma = 1; continue; @@ -3601,7 +3621,7 @@ Statement *Parser::parseStatement(int flags) as->reserve(a->dim); for (size_t i = 0; i < a->dim; i++) { - Dsymbol *d = a->tdata()[i]; + Dsymbol *d = (*a)[i]; s = new ExpStatement(loc, d); as->push(s); } @@ -3609,7 +3629,7 @@ Statement *Parser::parseStatement(int flags) } else if (a->dim == 1) { - Dsymbol *d = a->tdata()[0]; + Dsymbol *d = (*a)[0]; s = new ExpStatement(loc, d); } else @@ -3841,7 +3861,7 @@ Statement *Parser::parseStatement(int flags) Expression *aggr = parseExpression(); if (token.value == TOKslice && arguments->dim == 1) { - Parameter *a = arguments->tdata()[0]; + Parameter *a = (*arguments)[0]; delete arguments; nextToken(); Expression *upr = parseExpression(); @@ -4087,7 +4107,7 @@ Statement *Parser::parseStatement(int flags) // Keep cases in order by building the case statements backwards for (size_t i = cases.dim; i; i--) { - exp = cases.tdata()[i - 1]; + exp = cases[i - 1]; s = new CaseStatement(loc, exp, s); } } @@ -4242,7 +4262,7 @@ Statement *Parser::parseStatement(int flags) Loc loc = this->loc; nextToken(); - if (token.value == TOKlcurly) + if (token.value == TOKlcurly || token.value != TOKlparen) { t = NULL; id = NULL; @@ -5406,6 +5426,7 @@ Expression *Parser::parsePrimaryExp() token.value == TOKenum || token.value == TOKinterface || token.value == TOKargTypes || + token.value == TOKparameters || #if DMDV2 token.value == TOKconst && peek(&token)->value == TOKrparen || token.value == TOKinvariant && peek(&token)->value == TOKrparen || diff --git a/dmd2/readme.txt b/dmd2/readme.txt index e8109070..0d72c9be 100644 --- a/dmd2/readme.txt +++ b/dmd2/readme.txt @@ -12,7 +12,9 @@ of the D Programming Language defined in the documents at http://www.digitalmars.com/d/ These sources are free, they are redistributable and modifiable -under the terms of the GNU General Public License (attached as gpl.txt), +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 1, or (at your option) +any later version (attached as gpl.txt), or the Artistic License (attached as artistic.txt). The optimizer and code generator sources are diff --git a/dmd2/root/aav.c b/dmd2/root/aav.c index ca685d42..7a515a13 100644 --- a/dmd2/root/aav.c +++ b/dmd2/root/aav.c @@ -1,3 +1,12 @@ + +// Copyright (c) 2010-2012 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. + /** * Implementation of associative arrays. * diff --git a/dmd2/root/aav.h b/dmd2/root/aav.h index 266b5a83..201ca48f 100644 --- a/dmd2/root/aav.h +++ b/dmd2/root/aav.h @@ -1,4 +1,12 @@ +// Copyright (c) 2010-2012 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. + typedef void* Value; typedef void* Key; diff --git a/dmd2/root/array.c b/dmd2/root/array.c index f3440445..3ef48322 100644 --- a/dmd2/root/array.c +++ b/dmd2/root/array.c @@ -40,7 +40,6 @@ #include "port.h" #include "root.h" -#include "dchar.h" #include "rmem.h" diff --git a/dmd2/root/async.c b/dmd2/root/async.c index 78f17c68..92767c8e 100644 --- a/dmd2/root/async.c +++ b/dmd2/root/async.c @@ -1,4 +1,12 @@ +// Copyright (c) 2009-2012 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. + #define _MT 1 #include diff --git a/dmd2/root/dchar.c b/dmd2/root/dchar.c deleted file mode 100644 index 0b11a8a4..00000000 --- a/dmd2/root/dchar.c +++ /dev/null @@ -1,482 +0,0 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include -#include - -#include "dchar.h" -#include "rmem.h" - -#if M_UNICODE - -// Converts a char string to Unicode - -dchar *Dchar::dup(char *p) -{ - dchar *s; - size_t len; - - if (!p) - return NULL; - len = strlen(p); - s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); - for (unsigned i = 0; i < len; i++) - { - s[i] = (dchar)(p[i] & 0xFF); - } - s[len] = 0; - return s; -} - -dchar *Dchar::memchr(dchar *p, int c, int count) -{ - int u; - - for (u = 0; u < count; u++) - { - if (p[u] == c) - return p + u; - } - return NULL; -} - -#if _WIN32 && __DMC__ -__declspec(naked) -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - __asm - { - mov ECX,4[ESP] - mov EDX,8[ESP] - xor EAX,EAX - test EDX,EDX - je L92 - -LC8: cmp EDX,1 - je L98 - cmp EDX,2 - je LAE - - add EAX,[ECX] -// imul EAX,EAX,025h - lea EAX,[EAX][EAX*8] - add ECX,4 - sub EDX,2 - jmp LC8 - -L98: mov DX,[ECX] - and EDX,0FFFFh - add EAX,EDX - ret - -LAE: add EAX,[ECX] -L92: ret - } -} -#else -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str; - return hash; - - case 2: - hash += *(const uint32_t *)str; - return hash; - - default: - hash += *(const uint32_t *)str; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} -#endif - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str | 0x20; - return hash; - - case 2: - hash += *(const uint32_t *)str | 0x200020; - return hash; - - default: - hash += *(const uint32_t *)str | 0x200020; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} - -#elif MCBS - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str; - str += 4; - len -= 4; - break; - } - } -} - -#elif UTF8 - -// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 - -char Dchar::mblen[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1, -}; - -dchar *Dchar::dec(dchar *pstart, dchar *p) -{ - while ((p[-1] & 0xC0) == 0x80) - p--; - return p; -} - -int Dchar::get(dchar *p) -{ - unsigned c; - unsigned char *q = (unsigned char *)p; - - c = q[0]; - switch (mblen[c]) - { - case 2: - c = ((c - 0xC0) << 6) | - (q[1] - 0x80); - break; - - case 3: - c = ((c - 0xE0) << 12) | - ((q[1] - 0x80) << 6) | - (q[2] - 0x80); - break; - - case 4: - c = ((c - 0xF0) << 18) | - ((q[1] - 0x80) << 12) | - ((q[2] - 0x80) << 6) | - (q[3] - 0x80); - break; - - case 5: - c = ((c - 0xF8) << 24) | - ((q[1] - 0x80) << 18) | - ((q[2] - 0x80) << 12) | - ((q[3] - 0x80) << 6) | - (q[4] - 0x80); - break; - - case 6: - c = ((c - 0xFC) << 30) | - ((q[1] - 0x80) << 24) | - ((q[2] - 0x80) << 18) | - ((q[3] - 0x80) << 12) | - ((q[4] - 0x80) << 6) | - (q[5] - 0x80); - break; - } - return c; -} - -dchar *Dchar::put(dchar *p, unsigned c) -{ - if (c <= 0x7F) - { - *p++ = c; - } - else if (c <= 0x7FF) - { - p[0] = 0xC0 + (c >> 6); - p[1] = 0x80 + (c & 0x3F); - p += 2; - } - else if (c <= 0xFFFF) - { - p[0] = 0xE0 + (c >> 12); - p[1] = 0x80 + ((c >> 6) & 0x3F); - p[2] = 0x80 + (c & 0x3F); - p += 3; - } - else if (c <= 0x1FFFFF) - { - p[0] = 0xF0 + (c >> 18); - p[1] = 0x80 + ((c >> 12) & 0x3F); - p[2] = 0x80 + ((c >> 6) & 0x3F); - p[3] = 0x80 + (c & 0x3F); - p += 4; - } - else if (c <= 0x3FFFFFF) - { - p[0] = 0xF8 + (c >> 24); - p[1] = 0x80 + ((c >> 18) & 0x3F); - p[2] = 0x80 + ((c >> 12) & 0x3F); - p[3] = 0x80 + ((c >> 6) & 0x3F); - p[4] = 0x80 + (c & 0x3F); - p += 5; - } - else if (c <= 0x7FFFFFFF) - { - p[0] = 0xFC + (c >> 30); - p[1] = 0x80 + ((c >> 24) & 0x3F); - p[2] = 0x80 + ((c >> 18) & 0x3F); - p[3] = 0x80 + ((c >> 12) & 0x3F); - p[4] = 0x80 + ((c >> 6) & 0x3F); - p[5] = 0x80 + (c & 0x3F); - p += 6; - } - else - assert(0); // not a UCS-4 character - return p; -} - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if LITTLE_ENDIAN - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - - str += 4; - len -= 4; - break; - } - } -} - -#else // ascii - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if LITTLE_ENDIAN - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if LITTLE_ENDIAN - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - str += 4; - len -= 4; - break; - } - } -} - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]) | 0x202020; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str | 0x20202020; - str += 4; - len -= 4; - break; - } - } -} - -#endif - -#if 0 -#include - -void main() -{ - // Print out values to hardcode into Dchar::mblen[] - int c; - int s; - - for (c = 0; c < 256; c++) - { - s = 1; - if (c >= 0xC0 && c <= 0xDF) - s = 2; - if (c >= 0xE0 && c <= 0xEF) - s = 3; - if (c >= 0xF0 && c <= 0xF7) - s = 4; - if (c >= 0xF8 && c <= 0xFB) - s = 5; - if (c >= 0xFC && c <= 0xFD) - s = 6; - - printf("%d", s); - if ((c & 15) == 15) - printf(",\n"); - else - printf(","); - } -} -#endif diff --git a/dmd2/root/dchar.h b/dmd2/root/dchar.h deleted file mode 100644 index 6ac7994c..00000000 --- a/dmd2/root/dchar.h +++ /dev/null @@ -1,194 +0,0 @@ - -// Copyright (c) 1999-2011 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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 DCHAR_H -#define DCHAR_H - -#if __GNUC__ && !_WIN32 -#include "gnuc.h" -#endif - -#if _MSC_VER - // Disable useless warnings about unreferenced functions - #pragma warning (disable : 4514) -#endif - -//#include "root.h" -typedef size_t hash_t; - -#undef TEXT - -// NOTE: All functions accepting pointer arguments must not be NULL - -#if M_UNICODE - -#include -#include - -typedef wchar_t dchar; -#define TEXT(x) L##x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } - static int len(const dchar *p) { return wcslen(p); } - static dchar get(dchar *p) { return *p; } - static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } - static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) - { -#if __DMC__ - if (!*s1 && !*s2) // wcscmp is broken - return 0; -#endif - return wcscmp(s1, s2); -#if 0 - return (*s1 == *s2) - ? wcscmp(s1, s2) - : ((int)*s1 - (int)*s2); -#endif - } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return iswalpha(c); } - static int isUpper(dchar c) { return iswupper(c); } - static int isLower(dchar c) { return iswlower(c); } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } - static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory? - static dchar *dup(char *p); - static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } - static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); } - static dchar *memchr(dchar *p, int c, int count); - static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#elif MCBS - -#include -#include - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax MB_LEN_MAX - -#elif UTF8 - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 6 - -struct Dchar -{ - static char mblen[256]; - - static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } - static dchar *dec(dchar *pstart, dchar *p); - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p); - static int getprev(dchar *pstart, dchar *p) - { return *dec(pstart, p) & 0xFF; } - static dchar *put(dchar *p, unsigned c); - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } - static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; } - static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); } -}; - -#else - -#include - -#ifndef GCC_SAFE_DMD -#include -#endif - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p) { return *p & 0xFF; } - static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; } - static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } -#ifndef GCC_SAFE_DMD - static int isAlpha(dchar c) { return isalpha((unsigned char)c); } - static int isUpper(dchar c) { return isupper((unsigned char)c); } - static int isLower(dchar c) { return islower((unsigned char)c); } - static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); } - static int isLocaleLower(dchar c) { return islower((unsigned char)c); } - static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? -#endif - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions -#ifdef __GNUC__ - static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } -#else - static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } -#endif - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#endif -#endif - diff --git a/dmd2/root/gnuc.c b/dmd2/root/gnuc.c index 8f33d839..90358da1 100644 --- a/dmd2/root/gnuc.c +++ b/dmd2/root/gnuc.c @@ -1,4 +1,12 @@ +// Copyright (c) 2009-2012 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. + // Put functions in here missing from gnu C #include "gnuc.h" diff --git a/dmd2/root/gnuc.h b/dmd2/root/gnuc.h index 00c9851d..6b25fbf2 100644 --- a/dmd2/root/gnuc.h +++ b/dmd2/root/gnuc.h @@ -1,4 +1,12 @@ +// Copyright (c) 2009-2012 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + #ifndef _GNUC_H #define _GNUC_H 1 diff --git a/dmd2/root/lstring.c b/dmd2/root/lstring.c deleted file mode 100644 index a4e41ed5..00000000 --- a/dmd2/root/lstring.c +++ /dev/null @@ -1,63 +0,0 @@ -// lstring.c - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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 "dchar.h" -#include "rmem.h" -#include "lstring.h" - -#ifdef _MSC_VER // prevent compiler internal crash -Lstring Lstring::zero; -#else -Lstring Lstring::zero = LSTRING_EMPTY(); -#endif - -Lstring *Lstring::ctor(const dchar *p, unsigned length) -{ - Lstring *s; - - s = alloc(length); - memcpy(s->string, p, length * sizeof(dchar)); - return s; -} - -Lstring *Lstring::alloc(unsigned length) -{ - Lstring *s; - - s = (Lstring *)mem.malloc(size(length)); - s->length = length; - s->string[length] = 0; - return s; -} - -Lstring *Lstring::append(const Lstring *s) -{ - Lstring *t; - - if (!s->length) - return this; - t = alloc(length + s->length); - memcpy(t->string, string, length * sizeof(dchar)); - memcpy(t->string + length, s->string, s->length * sizeof(dchar)); - return t; -} - -Lstring *Lstring::substring(int start, int end) -{ - Lstring *t; - - if (start == end) - return &zero; - t = alloc(end - start); - memcpy(t->string, string + start, (end - start) * sizeof(dchar)); - return t; -} diff --git a/dmd2/root/lstring.h b/dmd2/root/lstring.h deleted file mode 100644 index 0c545790..00000000 --- a/dmd2/root/lstring.h +++ /dev/null @@ -1,74 +0,0 @@ - -// lstring.h -// length-prefixed strings - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// 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 LSTRING_H -#define LSTRING_H 1 - -#include "dchar.h" - -struct Lstring -{ - unsigned length; - -#ifndef IN_GCC - // Disable warning about nonstandard extension - #pragma warning (disable : 4200) -#endif - dchar string[]; - - static Lstring zero; // 0 length string - - // No constructors because we want to be able to statically - // initialize Lstring's, and Lstrings are of variable size. - - #if M_UNICODE - #define LSTRING(p,length) { length, L##p } - #else - #define LSTRING(p,length) { length, p } - #endif - -#if __GNUC__ - #define LSTRING_EMPTY() { 0 } -#else - #define LSTRING_EMPTY() LSTRING("", 0) -#endif - - static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } - static Lstring *ctor(const dchar *p, unsigned length); - static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } - static Lstring *alloc(unsigned length); - Lstring *clone(); - - unsigned len() { return length; } - - dchar *toDchars() { return string; } - - hash_t hash() { return Dchar::calcHash(string, length); } - hash_t ihash() { return Dchar::icalcHash(string, length); } - - static int cmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); - } - - static int icmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); - } - - Lstring *append(const Lstring *s); - Lstring *substring(int start, int end); -}; - -#endif diff --git a/dmd2/root/response.c b/dmd2/root/response.c index 31e35686..45f08662 100644 --- a/dmd2/root/response.c +++ b/dmd2/root/response.c @@ -109,6 +109,7 @@ int response_expand(int *pargc, char ***pargv) char *buffer; char *bufend; char *p; + int comment = 0; cp++; p = getenv(cp); @@ -171,15 +172,31 @@ int response_expand(int *pargc, char ***pargv) goto L2; case 0xD: + case '\n': + if (comment) + { + comment = 0; + } case 0: case ' ': case '\t': - case '\n': continue; // scan to start of argument + case '#': + comment = 1; + continue; + case '@': + if (comment) + { + continue; + } recurse = 1; default: /* start of new argument */ + if (comment) + { + continue; + } if (addargp(&n,p)) goto noexpand; instring = 0; diff --git a/dmd2/root/rmem.c b/dmd2/root/rmem.c index 2504ab93..fd202732 100644 --- a/dmd2/root/rmem.c +++ b/dmd2/root/rmem.c @@ -1,6 +1,11 @@ -/* Copyright (c) 2000 Digital Mars */ -/* All Rights Reserved */ +// Copyright (c) 2000-2012 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 diff --git a/dmd2/root/rmem.h b/dmd2/root/rmem.h index d22145a9..7307d97b 100644 --- a/dmd2/root/rmem.h +++ b/dmd2/root/rmem.h @@ -1,5 +1,11 @@ -// Copyright (C) 2000-2011 by Digital Mars + +// Copyright (c) 2000-2012 by Digital Mars // All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. #ifndef ROOT_MEM_H #define ROOT_MEM_H diff --git a/dmd2/root/root.c b/dmd2/root/root.c index 773a542a..d4697100 100644 --- a/dmd2/root/root.c +++ b/dmd2/root/root.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -18,6 +18,7 @@ #include #include #include +#include #if (defined (__SVR4) && defined (__sun)) #include @@ -49,7 +50,6 @@ #include "port.h" #include "root.h" -#include "dchar.h" #include "rmem.h" #if 0 //__SC__ //def DEBUG @@ -142,22 +142,6 @@ void error(const char *format, ...) exit(EXIT_FAILURE); } -#if M_UNICODE -void error(const dchar *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Error: "); - vwprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - exit(EXIT_FAILURE); -} -#endif - void error_mem() { error("out of memory"); @@ -206,15 +190,6 @@ char *Object::toChars() return (char *)"Object"; } -dchar *Object::toDchars() -{ -#if M_UNICODE - return L"Object"; -#else - return toChars(); -#endif -} - int Object::dyncast() { return 0; @@ -1609,30 +1584,6 @@ void OutBuffer::writestring(const char *string) write(string,strlen(string)); } -void OutBuffer::writedstring(const char *string) -{ -#if M_UNICODE - for (; *string; string++) - { - writedchar(*string); - } -#else - write(string,strlen(string)); -#endif -} - -void OutBuffer::writedstring(const wchar_t *string) -{ -#if M_UNICODE - write(string,wcslen(string) * sizeof(wchar_t)); -#else - for (; *string; string++) - { - writedchar(*string); - } -#endif -} - void OutBuffer::prependstring(const char *string) { unsigned len; @@ -1646,18 +1597,10 @@ void OutBuffer::prependstring(const char *string) void OutBuffer::writenl() { #if _WIN32 -#if M_UNICODE - write4(0x000A000D); // newline is CR,LF on Microsoft OS's -#else writeword(0x0A0D); // newline is CR,LF on Microsoft OS's -#endif -#else -#if M_UNICODE - writeword('\n'); #else writeByte('\n'); #endif -#endif } void OutBuffer::writeByte(unsigned b) @@ -1719,13 +1662,6 @@ void OutBuffer::writeUTF8(unsigned b) assert(0); } -void OutBuffer::writedchar(unsigned b) -{ - reserve(Dchar_mbmax * sizeof(dchar)); - offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) - - this->data; -} - void OutBuffer::prependbyte(unsigned b) { reserve(1); @@ -1873,46 +1809,6 @@ void OutBuffer::vprintf(const char *format, va_list args) write(p,count); } -#if M_UNICODE -void OutBuffer::vprintf(const wchar_t *format, va_list args) -{ - dchar buffer[128]; - dchar *p; - unsigned psize; - int count; - - WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format); - - p = buffer; - psize = sizeof(buffer) / sizeof(buffer[0]); - for (;;) - { -#if _WIN32 - count = _vsnwprintf(p,psize,format,args); - if (count != -1) - break; - psize *= 2; -#elif POSIX - va_list va; - va_copy(va, args); - count = vsnwprintf(p,psize,format,va); - va_end(va); - - if (count == -1) - psize *= 2; - else if (count >= psize) - psize = count + 1; - else - break; -#else - assert(0); -#endif - p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size - } - write(p,count * 2); -} -#endif - void OutBuffer::printf(const char *format, ...) { va_list ap; @@ -1921,16 +1817,6 @@ void OutBuffer::printf(const char *format, ...) va_end(ap); } -#if M_UNICODE -void OutBuffer::printf(const wchar_t *format, ...) -{ - va_list ap; - va_start(ap, format); - vprintf(format,ap); - va_end(ap); -} -#endif - void OutBuffer::bracket(char left, char right) { reserve(2); diff --git a/dmd2/root/root.h b/dmd2/root/root.h index 830ea43b..842222e3 100644 --- a/dmd2/root/root.h +++ b/dmd2/root/root.h @@ -1,5 +1,4 @@ - // Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -24,7 +23,6 @@ typedef size_t hash_t; #include "longdouble.h" -#include "dchar.h" char *wchar2ascii(wchar_t *); int wcharIsAscii(wchar_t *); @@ -92,7 +90,6 @@ struct Object virtual void print(); virtual char *toChars(); - virtual dchar *toDchars(); virtual void toBuffer(OutBuffer *buf); /** @@ -282,14 +279,11 @@ struct OutBuffer : Object void write(const void *data, unsigned nbytes); void writebstring(unsigned char *string); void writestring(const char *string); - void writedstring(const char *string); - void writedstring(const wchar_t *string); void prependstring(const char *string); void writenl(); // write newline void writeByte(unsigned b); void writebyte(unsigned b) { writeByte(b); } void writeUTF8(unsigned b); - void writedchar(unsigned b); void prependbyte(unsigned b); void writeword(unsigned w); void writeUTF16(unsigned w); @@ -300,10 +294,6 @@ struct OutBuffer : Object void align(unsigned size); void vprintf(const char *format, va_list args); void printf(const char *format, ...); -#if M_UNICODE - void vprintf(const unsigned short *format, va_list args); - void printf(const unsigned short *format, ...); -#endif void bracket(char left, char right); unsigned bracket(unsigned i, const char *left, unsigned j, const char *right); void spread(unsigned offset, unsigned nbytes); diff --git a/dmd2/root/speller.c b/dmd2/root/speller.c index 373baf6d..207b49c0 100644 --- a/dmd2/root/speller.c +++ b/dmd2/root/speller.c @@ -1,4 +1,12 @@ +// Copyright (c) 2010-2012 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 diff --git a/dmd2/root/speller.h b/dmd2/root/speller.h index bfffb739..5f4e28f4 100644 --- a/dmd2/root/speller.h +++ b/dmd2/root/speller.h @@ -1,4 +1,12 @@ +// Copyright (c) 2010-2012 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. + typedef void *(fp_speller_t)(void *, const char *); extern const char idchars[]; diff --git a/dmd2/root/stringtable.c b/dmd2/root/stringtable.c index f1c0044a..58dcd0b6 100644 --- a/dmd2/root/stringtable.c +++ b/dmd2/root/stringtable.c @@ -9,15 +9,70 @@ #include -#include +#include // uint{8|16|32}_t +#include // memcpy() #include #include "root.h" -#include "rmem.h" -#include "dchar.h" -#include "lstring.h" +#include "rmem.h" // mem #include "stringtable.h" +hash_t calcHash(const char *str, size_t len) +{ + hash_t hash = 0; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 37; + hash += *(const uint8_t *)str; + return hash; + + case 2: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint16_t *)str; +#else + hash += str[0] * 256 + str[1]; +#endif + return hash; + + case 3: + hash *= 37; +#if LITTLE_ENDIAN + hash += (*(const uint16_t *)str << 8) + + ((const uint8_t *)str)[2]; +#else + hash += (str[0] * 256 + str[1]) * 256 + str[2]; +#endif + return hash; + + default: + hash *= 37; +#if LITTLE_ENDIAN + hash += *(const uint32_t *)str; +#else + hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; +#endif + str += 4; + len -= 4; + break; + } + } +} + +void StringValue::ctor(const char *p, unsigned length) +{ + this->length = length; + this->lstring[length] = 0; + memcpy(this->lstring, p, length * sizeof(char)); +} + void StringTable::init(unsigned size) { table = (void **)mem.calloc(size, sizeof(void *)); @@ -46,21 +101,20 @@ struct StringEntry StringValue value; - static StringEntry *alloc(const dchar *s, unsigned len); + static StringEntry *alloc(const char *s, unsigned len); }; -StringEntry *StringEntry::alloc(const dchar *s, unsigned len) +StringEntry *StringEntry::alloc(const char *s, unsigned len) { StringEntry *se; - se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); - se->value.lstring.length = len; - se->hash = Dchar::calcHash(s,len); - memcpy(se->value.lstring.string, s, len * sizeof(dchar)); + se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) + len + 1); + se->value.ctor(s, len); + se->hash = calcHash(s,len); return se; } -void **StringTable::search(const dchar *s, unsigned len) +void **StringTable::search(const char *s, unsigned len) { hash_t hash; unsigned u; @@ -68,7 +122,7 @@ void **StringTable::search(const dchar *s, unsigned len) StringEntry **se; //printf("StringTable::search(%p,%d)\n",s,len); - hash = Dchar::calcHash(s,len); + hash = calcHash(s,len); u = hash % tabledim; se = (StringEntry **)&table[u]; //printf("\thash = %d, u = %d\n",hash,u); @@ -77,10 +131,10 @@ void **StringTable::search(const dchar *s, unsigned len) cmp = (*se)->hash - hash; if (cmp == 0) { - cmp = (*se)->value.lstring.len() - len; + cmp = (*se)->value.len() - len; if (cmp == 0) { - cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); + cmp = ::memcmp(s,(*se)->value.toDchars(),len); if (cmp == 0) break; } @@ -94,7 +148,7 @@ void **StringTable::search(const dchar *s, unsigned len) return (void **)se; } -StringValue *StringTable::lookup(const dchar *s, unsigned len) +StringValue *StringTable::lookup(const char *s, unsigned len) { StringEntry *se; se = *(StringEntry **)search(s,len); @@ -104,7 +158,7 @@ StringValue *StringTable::lookup(const dchar *s, unsigned len) return NULL; } -StringValue *StringTable::update(const dchar *s, unsigned len) +StringValue *StringTable::update(const char *s, unsigned len) { StringEntry **pse; StringEntry *se; @@ -118,7 +172,7 @@ StringValue *StringTable::update(const dchar *s, unsigned len) return &se->value; } -StringValue *StringTable::insert(const dchar *s, unsigned len) +StringValue *StringTable::insert(const char *s, unsigned len) { StringEntry **pse; StringEntry *se; @@ -133,7 +187,3 @@ StringValue *StringTable::insert(const dchar *s, unsigned len) } return &se->value; } - - - - diff --git a/dmd2/root/stringtable.h b/dmd2/root/stringtable.h index ce714587..170894e6 100644 --- a/dmd2/root/stringtable.h +++ b/dmd2/root/stringtable.h @@ -1,3 +1,4 @@ + // Copyright (c) 1999-2011 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -15,34 +16,56 @@ #endif #include "root.h" -#include "dchar.h" -#include "lstring.h" +struct StringEntry; + +// StringValue is a variable-length structure as indicated by the last array +// member with unspecified size. It has neither proper c'tors nor a factory +// method because the only thing which should be creating these is StringTable. struct StringValue { union - { int intvalue; + { void *ptrvalue; - dchar *string; + char *string; }; - Lstring lstring; +private: + unsigned length; + +#ifndef IN_GCC + // Disable warning about nonstandard extension + #pragma warning (disable : 4200) +#endif + char lstring[]; + +public: + unsigned len() const { return length; } + const char *toDchars() const { return lstring; } + +private: + friend struct StringEntry; + StringValue(); // not constructible + // This is more like a placement new c'tor + void ctor(const char *p, unsigned length); }; struct StringTable { +private: void **table; unsigned count; unsigned tabledim; +public: void init(unsigned size = 37); ~StringTable(); - StringValue *lookup(const dchar *s, unsigned len); - StringValue *insert(const dchar *s, unsigned len); - StringValue *update(const dchar *s, unsigned len); + StringValue *lookup(const char *s, unsigned len); + StringValue *insert(const char *s, unsigned len); + StringValue *update(const char *s, unsigned len); private: - void **search(const dchar *s, unsigned len); + void **search(const char *s, unsigned len); }; #endif diff --git a/dmd2/scope.c b/dmd2/scope.c index 010cdb1a..28f6b965 100644 --- a/dmd2/scope.c +++ b/dmd2/scope.c @@ -9,6 +9,7 @@ #include #include +#include // strlen() #include "root.h" #include "speller.h" diff --git a/dmd2/scope.h b/dmd2/scope.h index 4fee6539..2e54ab7b 100644 --- a/dmd2/scope.h +++ b/dmd2/scope.h @@ -87,7 +87,7 @@ struct Scope #define CSXreturn 0x20 // seen a return statement #define CSXany_ctor 0x40 // either this() or super() was called - unsigned structalign; // alignment for struct members + structalign_t structalign; // alignment for struct members enum LINK linkage; // linkage for external functions enum PROT protection; // protection for class members @@ -102,7 +102,7 @@ struct Scope #define SCOPEstaticassert 8 // inside static assert #define SCOPEdebug 0x10 // inside debug conditional -#if IN_GCC +#ifdef IN_GCC Expressions *attributes; // GCC decl/type attributes #endif diff --git a/dmd2/statement.c b/dmd2/statement.c index 66a32704..89d6194e 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -28,6 +28,7 @@ #include "parse.h" #include "template.h" #include "attrib.h" +#include "import.h" #if IN_LLVM #if defined(_MSC_VER) @@ -426,7 +427,7 @@ Statements *CompileStatement::flatten(Scope *sc) //printf("CompileStatement::flatten() %s\n", exp->toChars()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); - exp = exp->optimize(WANTvalue | WANTinterpret); + exp = exp->ctfeInterpret(); if (exp->op == TOKerror) return NULL; StringExp *se = exp->toString(); @@ -1585,6 +1586,10 @@ Statement *ForeachStatement::semantic(Scope *sc) return s; } + Type *argtype = (*arguments)[dim-1]->type; + if (argtype) + argtype = argtype->semantic(loc, sc); + TypeTuple *tuple = (TypeTuple *)tab; Statements *statements = new Statements(); //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars()); @@ -1599,9 +1604,8 @@ Statement *ForeachStatement::semantic(Scope *sc) ((DotVarExp *)(*te->exps)[0])->e1->isTemp()) { CommaExp *ce = (CommaExp *)((DotVarExp *)(*te->exps)[0])->e1; - - prelude = ce->e1; - ((DotVarExp *)(*te->exps)[0])->e1 = ce->e2; + prelude = ce->e1; + ((DotVarExp *)(*te->exps)[0])->e1 = ce->e2; } } else if (aggr->op == TOKtype) // type tuple @@ -1612,8 +1616,8 @@ Statement *ForeachStatement::semantic(Scope *sc) assert(0); for (size_t j = 0; j < n; j++) { size_t k = (op == TOKforeach) ? j : n - 1 - j; - Expression *e; - Type *t; + Expression *e = NULL; + Type *t = NULL; if (te) e = (*te->exps)[k]; else @@ -1664,14 +1668,20 @@ Statement *ForeachStatement::semantic(Scope *sc) var = new AliasDeclaration(loc, arg->ident, s); if (arg->storageClass & STCref) error("symbol %s cannot be ref", s->toChars()); + if (argtype && argtype->ty != Terror) + error("cannot specify element type for symbol %s", s->toChars()); } else if (e->op == TOKtype) { var = new AliasDeclaration(loc, arg->ident, e->type); + if (argtype && argtype->ty != Terror) + error("cannot specify element type for type %s", e->type->toChars()); } else { arg->type = e->type; + if (argtype && argtype->ty != Terror) + arg->type = argtype; Initializer *ie = new ExpInitializer(0, e); VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); if (arg->storageClass & STCref) @@ -1688,6 +1698,8 @@ Statement *ForeachStatement::semantic(Scope *sc) else { var = new AliasDeclaration(loc, arg->ident, t); + if (argtype && argtype->ty != Terror) + error("cannot specify element type for symbol %s", s->toChars()); } DeclarationExp *de = new DeclarationExp(loc, var); st->push(new ExpStatement(loc, de)); @@ -1757,23 +1769,47 @@ Lagain: Type *argtype = arg->type->semantic(loc, sc); VarDeclaration *var; - var = new VarDeclaration(loc, argtype, arg->ident, NULL); - var->storage_class |= STCforeach; - var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); - if (var->storage_class & (STCref | STCout)) - var->storage_class |= STCnodtor; if (dim == 2 && i == 0) - { key = var; - //var->storage_class |= STCfinal; + { +#if (BUG6652 == 1 || BUG6652 == 2) + var = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), NULL); + var->storage_class |= arg->storageClass & (STCin | STCout | STC_TYPECTOR); +#else + if (arg->storageClass & STCref) + var = new VarDeclaration(loc, argtype, arg->ident, NULL); + else + var = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), NULL); + var->storage_class |= arg->storageClass & (STCin | STCout | STC_TYPECTOR); +#endif + var->storage_class |= STCforeach; + if (var->storage_class & (STCref | STCout)) + var->storage_class |= STCnodtor; + + key = var; } else { + var = new VarDeclaration(loc, argtype, arg->ident, NULL); + var->storage_class |= STCforeach; + var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); + if (var->storage_class & (STCref | STCout)) + var->storage_class |= STCnodtor; + value = var; - /* Reference to immutable data should be marked as const - */ - if (var->storage_class & STCref && !tn->isMutable()) + if (var->storage_class & STCref) { - var->storage_class |= STCconst; + /* Reference to immutable data should be marked as const + */ + if (!tn->isMutable()) + var->storage_class |= STCconst; + + Type *t = tab->nextOf(); + if (!t->invariantOf()->equals(argtype->invariantOf()) || + !MODimplicitConv(t->mod, argtype->mod)) + { + error("argument type mismatch, %s to ref %s", + t->toChars(), argtype->toChars()); + } } } #if 0 @@ -1831,6 +1867,30 @@ Lagain: value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key))); Statement *ds = new ExpStatement(loc, value); + if (dim == 2) + { Parameter *arg = (*arguments)[0]; +#if (BUG6652 == 1 || BUG6652 == 2) + if ((*arguments)[0]->storageClass & STCref) + { + AliasDeclaration *v = new AliasDeclaration(loc, arg->ident, key); + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } + else + { + ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); + VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie); + v->storage_class |= STCforeach | STCref | STCbug6652; + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } +#else + if (!(arg->storageClass & STCref)) + { + ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); + VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie); + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } +#endif + } body = new CompoundStatement(loc, ds, body); s = new ForStatement(loc, forinit, cond, increment, body); @@ -1901,29 +1961,29 @@ Lagain: goto Lapply; { /* Look for range iteration, i.e. the properties - * .empty, .next, .retreat, .head and .rear + * .empty, .popFront, .popBack, .front and .back * foreach (e; aggr) { ... } * translates to: - * for (auto __r = aggr[]; !__r.empty; __r.next) - * { auto e = __r.head; + * for (auto __r = aggr[]; !__r.empty; __r.popFront) + * { auto e = __r.front; * ... * } */ AggregateDeclaration *ad = (tab->ty == Tclass) ? (AggregateDeclaration *)((TypeClass *)tab)->sym : (AggregateDeclaration *)((TypeStruct *)tab)->sym; - Identifier *idhead; - Identifier *idnext; + Identifier *idfront; + Identifier *idpopFront; if (op == TOKforeach) - { idhead = Id::Ffront; - idnext = Id::FpopFront; + { idfront = Id::Ffront; + idpopFront = Id::FpopFront; } else - { idhead = Id::Fback; - idnext = Id::FpopBack; + { idfront = Id::Fback; + idpopFront = Id::FpopBack; } - Dsymbol *shead = search_function(ad, idhead); - if (!shead) + Dsymbol *sfront = ad->search(0, idfront, 0); + if (!sfront) goto Lapply; /* Generate a temporary __r and initialize it with the aggregate. @@ -1939,13 +1999,13 @@ Lagain: // __r.next e = new VarExp(loc, r); - Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idnext)); + Expression *increment = new CallExp(loc, new DotIdExp(loc, e, idpopFront)); /* Declaration statement for e: - * auto e = __r.idhead; + * auto e = __r.idfront; */ e = new VarExp(loc, r); - Expression *einit = new DotIdExp(loc, e, idhead); + Expression *einit = new DotIdExp(loc, e, idfront); Statement *makeargs, *forbody; if (dim == 1) { @@ -1968,7 +2028,7 @@ Lagain: makeargs = new ExpStatement(loc, de); Expression *ve = new VarExp(loc, vd); - ve->type = shead->isDeclaration()->type; + ve->type = sfront->isDeclaration()->type; if (ve->type->toBasetype()->ty == Tfunction) ve->type = ve->type->toBasetype()->nextOf(); if (!ve->type || ve->type->ty == Terror) @@ -2046,18 +2106,6 @@ Lagain: Type *tret = func->type->nextOf(); - // Need a variable to hold value from any return statements in body. - if (!sc->func->vresult && tret && tret != Type::tvoid) - { - VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); - v->noscope = 1; - v->semantic(sc); - if (!sc->insert(v)) - assert(0); - v->parent = sc->func; - sc->func->vresult = v; - } - TypeFunction *tfld = NULL; if (sapply) { FuncDeclaration *fdapply = sapply->isFuncDeclaration(); @@ -2533,7 +2581,14 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) */ ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr); - key = new VarDeclaration(loc, arg->type, arg->ident, ie); +#if (BUG6652 == 1 || BUG6652 == 2) + key = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), ie); +#else + if (arg->storageClass & STCref) + key = new VarDeclaration(loc, arg->type, arg->ident, ie); + else + key = new VarDeclaration(loc, arg->type, Lexer::uniqueId("__key"), ie); +#endif Identifier *id = Lexer::uniqueId("__limit"); ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); @@ -2580,6 +2635,28 @@ Statement *ForeachRangeStatement::semantic(Scope *sc) //increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1)); increment = new PreExp(TOKpreplusplus, loc, new VarExp(loc, key)); +#if (BUG6652 == 1 || BUG6652 == 2) + if (arg->storageClass & STCref) + { + AliasDeclaration *v = new AliasDeclaration(loc, arg->ident, key); + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } + else + { + ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); + VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie); + v->storage_class |= STCforeach | STCref | STCbug6652; + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } +#else + if (!(arg->storageClass & STCref)) + { + ExpInitializer *ie = new ExpInitializer(loc, new IdentifierExp(loc, key->ident)); + VarDeclaration *v = new VarDeclaration(loc, NULL, arg->ident, ie); + body = new CompoundStatement(loc, new ExpStatement(loc, v), body); + } +#endif + ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body); s = fs->semantic(sc); return s; @@ -2971,8 +3048,8 @@ Statement *PragmaStatement::semantic(Scope *sc) Expression *e = (*args)[i]; e = e->semantic(sc); - if (e->op != TOKerror) - e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKerror && e->op != TOKtype) + e = e->ctfeInterpret(); if (e->op == TOKerror) { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); goto Lerror; @@ -3002,7 +3079,7 @@ Statement *PragmaStatement::semantic(Scope *sc) Expression *e = (*args)[0]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); (*args)[0] = e; StringExp *se = e->toString(); if (!se) @@ -3033,7 +3110,7 @@ Statement *PragmaStatement::semantic(Scope *sc) { Expression *e = (*args)[0]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) @@ -3171,6 +3248,10 @@ Statement *SwitchStatement::semantic(Scope *sc) condition = condition->semantic(sc); condition = resolveProperties(sc, condition); + TypeEnum *te = NULL; + // preserve enum type for final switches + if (condition->type->ty == Tenum) + te = (TypeEnum *)condition->type; if (condition->type->isString()) { // If it's not an array, cast it to one @@ -3235,8 +3316,8 @@ Statement *SwitchStatement::semantic(Scope *sc) { // Don't use toBasetype() because that will skip past enums t = ((TypeTypedef *)t)->sym->basetype; } - if (condition->type->ty == Tenum) - { TypeEnum *te = (TypeEnum *)condition->type; + if (te) + { EnumDeclaration *ed = te->toDsymbol(sc)->isEnumDeclaration(); assert(ed); size_t dim = ed->members->dim; @@ -3247,7 +3328,7 @@ Statement *SwitchStatement::semantic(Scope *sc) { for (size_t j = 0; j < cases->dim; j++) { CaseStatement *cs = (*cases)[j]; - if (cs->exp->equals(em->value)) + if (cs->exp->equals(em->value) || cs->exp->toInteger() == em->value->toInteger()) goto L1; } error("enum member %s not represented in final switch", em->toChars()); @@ -3397,7 +3478,7 @@ Statement *CaseStatement::semantic(Scope *sc) } } else - exp = exp->optimize(WANTvalue | WANTinterpret); + exp = exp->ctfeInterpret(); if (exp->op != TOKstring && exp->op != TOKint64 && exp->op != TOKerror) { @@ -3503,12 +3584,11 @@ Statement *CaseRangeStatement::semantic(Scope *sc) first = first->semantic(sc); first = first->implicitCastTo(sc, sw->condition->type); - first = first->optimize(WANTvalue | WANTinterpret); - + first = first->ctfeInterpret(); last = last->semantic(sc); last = last->implicitCastTo(sc, sw->condition->type); - last = last->optimize(WANTvalue | WANTinterpret); + last = last->ctfeInterpret(); if (first->op == TOKerror || last->op == TOKerror) return statement ? statement->semantic(sc) : NULL; @@ -3574,12 +3654,12 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s) : Statement(loc) { this->statement = s; -#if IN_GCC +#ifdef IN_GCC cblock = NULL; -#endif +#elif IN_LLVM bodyBB = NULL; - // LDC enclosingScopeExit = NULL; +#endif } Statement *DefaultStatement::syntaxCopy() @@ -3749,6 +3829,7 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp) : Statement(loc) { this->exp = exp; + this->implicit0 = 0; } Statement *ReturnStatement::syntaxCopy() @@ -3766,7 +3847,6 @@ Statement *ReturnStatement::semantic(Scope *sc) FuncDeclaration *fd = sc->parent->isFuncDeclaration(); Scope *scx = sc; - int implicit0 = 0; Expression *eorg = NULL; if (fd->fes) @@ -3810,8 +3890,11 @@ Statement *ReturnStatement::semantic(Scope *sc) { fd->hasReturnExp |= 1; + FuncLiteralDeclaration *fld = fd->isFuncLiteralDeclaration(); if (tret) exp = exp->inferType(tbret); + else if (fld && fld->treq && fld->treq->nextOf()) + exp = exp->inferType(fld->treq->nextOf()); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); if (!((TypeFunction *)fd->type)->isref) @@ -3984,11 +4067,14 @@ Statement *ReturnStatement::semantic(Scope *sc) // Construct: return vresult; if (!fd->vresult) { // Declare vresult + Scope *sco = fd->scout ? fd->scout : scx; VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); v->noscope = 1; v->storage_class |= STCresult; - v->semantic(scx); - if (!scx->insert(v)) + if (((TypeFunction *)fd->type)->isref) + v->storage_class |= STCref | STCforeach; + v->semantic(sco); + if (!sco->insert(v)) assert(0); v->parent = fd; fd->vresult = v; @@ -4027,7 +4113,7 @@ Statement *ReturnStatement::semantic(Scope *sc) if (fd->returnLabel && tbret->ty != Tvoid) { - assert(fd->vresult); + fd->buildResultVar(); VarExp *v = new VarExp(0, fd->vresult); assert(eorg); @@ -4357,9 +4443,16 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { /* Cast the interface to an object, as the object has the monitor, * not the interface. */ - Type *t = new TypeIdentifier(0, Id::Object); + if (!ClassDeclaration::object) + { + error("missing or corrupt object.d"); + fatal(); + } + + Type *t = ClassDeclaration::object->type; + t = t->semantic(0, sc)->toBasetype(); + assert(t->ty == Tclass); - t = t->semantic(0, sc); exp = new CastExp(loc, exp, t); exp = exp->semantic(sc); } @@ -5313,9 +5406,6 @@ LabelDsymbol::LabelDsymbol(Identifier *ident) : Dsymbol(ident) { statement = NULL; -#if IN_GCC - asmLabelNum = 0; -#endif } LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()? @@ -5410,9 +5500,29 @@ Statement *ImportStatement::syntaxCopy() Statement *ImportStatement::semantic(Scope *sc) { for (size_t i = 0; i < imports->dim; i++) - { Dsymbol *s = (*imports)[i]; + { Import *s = (*imports)[i]->isImport(); + + for (size_t i = 0; i < s->names.dim; i++) + { + Identifier *name = s->names[i]; + Identifier *alias = s->aliases[i]; + + if (!alias) + alias = name; + + TypeIdentifier *tname = new TypeIdentifier(s->loc, name); + AliasDeclaration *ad = new AliasDeclaration(s->loc, alias, tname); + + s->aliasdecls.push(ad); + } + s->semantic(sc); sc->insert(s); + + for (size_t i = 0; i < s->aliasdecls.dim; i++) + { + sc->insert(s->aliasdecls[i]); + } } return this; } diff --git a/dmd2/statement.h b/dmd2/statement.h index 2bd213dc..a06e79e2 100644 --- a/dmd2/statement.h +++ b/dmd2/statement.h @@ -79,7 +79,7 @@ struct DValue; typedef DValue elem; #endif -#if IN_GCC +#ifdef IN_GCC union tree_node; typedef union tree_node block; //union tree_node; typedef union tree_node elem; #else @@ -595,7 +595,7 @@ struct CaseRangeStatement : Statement struct DefaultStatement : Statement { Statement *statement; -#if IN_GCC +#ifdef IN_GCC block *cblock; // back end: label for the block #endif @@ -664,6 +664,7 @@ struct SwitchErrorStatement : Statement struct ReturnStatement : Statement { Expression *exp; + int implicit0; ReturnStatement(Loc loc, Expression *exp); Statement *syntaxCopy(); @@ -930,9 +931,6 @@ struct LabelStatement : Statement struct LabelDsymbol : Dsymbol { LabelStatement *statement; -#if IN_GCC - unsigned asmLabelNum; // GCC-specific -#endif LabelDsymbol(Identifier *ident); LabelDsymbol *isLabel(); diff --git a/dmd2/staticassert.c b/dmd2/staticassert.c index 8e3dcefa..6fa9606c 100644 --- a/dmd2/staticassert.c +++ b/dmd2/staticassert.c @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -59,10 +59,14 @@ void StaticAssert::semantic2(Scope *sc) ++sc->ignoreTemplates; Expression *e = exp->semantic(sc); sc = sc->pop(); - if (e->type == Type::terror) + if (!e->type->checkBoolean()) + { + if (e->type->toBasetype() != Type::terror) + exp->error("expression %s of type %s does not have a boolean value", exp->toChars(), e->type->toChars()); return; + } unsigned olderrs = global.errors; - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (global.errors != olderrs) { errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars()); @@ -74,7 +78,7 @@ void StaticAssert::semantic2(Scope *sc) OutBuffer buf; msg = msg->semantic(sc); - msg = msg->optimize(WANTvalue | WANTinterpret); + msg = msg->ctfeInterpret(); hgs.console = 1; msg->toCBuffer(&buf, &hgs); error("%s", buf.toChars()); diff --git a/dmd2/struct.c b/dmd2/struct.c index 51e6c3a7..0b3e9b97 100644 --- a/dmd2/struct.c +++ b/dmd2/struct.c @@ -37,7 +37,6 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) scope = 0; structsize = 0; // size of struct alignsize = 0; // size of struct for alignment purposes - structalign = 0; // struct member alignment in effect hasUnions = 0; sizeok = SIZEOKnone; // size not determined yet deferred = NULL; @@ -60,6 +59,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) noDefaultCtor = FALSE; #endif dtor = NULL; + getRTInfo = NULL; #if IN_LLVM availableExternally = true; // assume this unless proven otherwise @@ -83,7 +83,7 @@ void AggregateDeclaration::semantic2(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic2(sc); } sc->pop(); @@ -103,10 +103,25 @@ void AggregateDeclaration::semantic3(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic3(sc); } sc->pop(); + + if (!getRTInfo) + { // Evaluate: gcinfo!type + Objects *tiargs = new Objects(); + tiargs->push(type); + TemplateInstance *ti = new TemplateInstance(loc, Type::rtinfo, tiargs); + ti->semantic(sc); + ti->semantic2(sc); + ti->semantic3(sc); + Dsymbol *s = ti->toAlias(); + Expression *e = new DsymbolExp(0, s, 0); + e = e->semantic(ti->tempdecl->scope); + e = e->ctfeInterpret(); + getRTInfo = e; + } } } @@ -117,7 +132,7 @@ void AggregateDeclaration::inlineScan() { for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; //printf("inline scan aggregate symbol '%s'\n", s->toChars()); s->inlineScan(); } @@ -127,6 +142,8 @@ void AggregateDeclaration::inlineScan() unsigned AggregateDeclaration::size(Loc loc) { //printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope); + if (loc.linnum == 0) + loc = this->loc; if (!members) error(loc, "unknown size"); if (sizeok != SIZEOKdone && scope) @@ -196,20 +213,33 @@ int AggregateDeclaration::isExport() */ void AggregateDeclaration::alignmember( - unsigned salign, // struct alignment that is in effect - unsigned size, // alignment requirement of field + structalign_t alignment, // struct alignment that is in effect + unsigned size, // alignment requirement of field unsigned *poffset) { - //printf("salign = %d, size = %d, offset = %d\n",salign,size,offset); - if (salign > 1) + //printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset); + switch (alignment) { - assert(size != 3); - unsigned sa = size; - if (sa == 0 || salign < sa) - sa = salign; - *poffset = (*poffset + sa - 1) & ~(sa - 1); + case 1: + // No alignment + break; + + case STRUCTALIGN_DEFAULT: + { /* Must match what the corresponding C compiler's default + * alignment behavior is. + */ + assert(size != 3); + unsigned sa = (size == 0 || 8 < size) ? 8 : size; + *poffset = (*poffset + sa - 1) & ~(sa - 1); + break; + } + + default: + // Align on alignment boundary, which must be a positive power of 2 + assert(alignment > 0 && !(alignment & (alignment - 1))); + *poffset = (*poffset + alignment - 1) & ~(alignment - 1); + break; } - //printf("result = %d\n",offset); } /**************************************** @@ -221,25 +251,36 @@ unsigned AggregateDeclaration::placeField( unsigned *nextoffset, // next location in aggregate unsigned memsize, // size of member unsigned memalignsize, // size of member for alignment purposes - unsigned memalign, // alignment in effect for this member + structalign_t alignment, // alignment in effect for this member unsigned *paggsize, // size of aggregate (updated) unsigned *paggalignsize, // size of aggregate for alignment purposes (updated) bool isunion // the aggregate is a union ) { unsigned ofs = *nextoffset; - alignmember(memalign, memalignsize, &ofs); + alignmember(alignment, memalignsize, &ofs); unsigned memoffset = ofs; ofs += memsize; if (ofs > *paggsize) *paggsize = ofs; if (!isunion) *nextoffset = ofs; - if (global.params.is64bit && memalign == 8 && memalignsize == 16) - /* Not sure how to handle this */ - ; - else if (memalign < memalignsize) - memalignsize = memalign; + + if (alignment == STRUCTALIGN_DEFAULT) + { + if (global.params.is64bit && memalignsize == 16) + ; + else if (8 < memalignsize) + memalignsize = 8; + else if (alignment < memalignsize) + memalignsize = alignment; + } + else + { + if (memalignsize < alignment) + memalignsize = alignment; + } + if (*paggalignsize < memalignsize) *paggalignsize = memalignsize; @@ -265,13 +306,13 @@ int AggregateDeclaration::firstFieldInUnion(int indx) { if (isUnionDeclaration()) return 0; - VarDeclaration * vd = fields.tdata()[indx]; + VarDeclaration * vd = fields[indx]; int firstNonZero = indx; // first index in the union with non-zero size for (; ;) { if (indx == 0) return firstNonZero; - VarDeclaration * v = fields.tdata()[indx - 1]; + VarDeclaration * v = fields[indx - 1]; if (v->offset != vd->offset) return firstNonZero; --indx; @@ -290,7 +331,7 @@ int AggregateDeclaration::firstFieldInUnion(int indx) */ int AggregateDeclaration::numFieldsInUnion(int firstIndex) { - VarDeclaration * vd = fields.tdata()[firstIndex]; + VarDeclaration * vd = fields[firstIndex]; /* If it is a zero-length field, AND we can't find an earlier non-zero * sized field with the same offset, we assume it's not part of a union. */ @@ -300,7 +341,7 @@ int AggregateDeclaration::numFieldsInUnion(int firstIndex) int count = 1; for (size_t i = firstIndex+1; i < fields.dim; ++i) { - VarDeclaration * v = fields.tdata()[i]; + VarDeclaration * v = fields[i]; // If offsets are different, they are not in the same union if (v->offset != vd->offset) break; @@ -322,7 +363,10 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id) postblit = NULL; xeq = NULL; + alignment = 0; #endif + arg1type = NULL; + arg2type = NULL; // For forward references type = new TypeStruct(this); @@ -389,8 +433,8 @@ void StructDeclaration::semantic(Scope *sc) #else handle = type->pointerTo(); #endif - structalign = sc->structalign; protection = sc->protection; + alignment = sc->structalign; storage_class |= sc->stc; if (sc->stc & STCdeprecated) isdeprecated = true; @@ -403,7 +447,7 @@ void StructDeclaration::semantic(Scope *sc) int hasfunctions = 0; for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; //printf("adding member '%s' to '%s'\n", s->toChars(), this->toChars()); s->addMember(sc, this, 1); if (s->isFuncDeclaration()) @@ -452,6 +496,7 @@ void StructDeclaration::semantic(Scope *sc) sc2->inunion = 1; sc2->protection = PROTpublic; sc2->explicitProtection = 0; + sc2->structalign = STRUCTALIGN_DEFAULT; size_t members_dim = members->dim; @@ -507,7 +552,7 @@ void StructDeclaration::semantic(Scope *sc) fields.setDim(0); structsize = 0; alignsize = 0; - structalign = 0; +// structalign = 0; scope = scx ? scx : new Scope(*sc); scope->setNoFree(); @@ -631,6 +676,15 @@ void StructDeclaration::semantic(Scope *sc) aggNew = (NewDeclaration *)search(0, Id::classNew, 0); aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); + TypeTuple *tup = type->toArgTypes(); + size_t dim = tup->arguments->dim; + if (dim >= 1) + { assert(dim <= 2); + arg1type = (*tup->arguments)[0]->type; + if (dim == 2) + arg2type = (*tup->arguments)[1]->type; + } + if (sc->func) { semantic2(sc); @@ -667,6 +721,7 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) void StructDeclaration::finalizeSize(Scope *sc) { + //printf("StructDeclaration::finalizeSize() %s\n", toChars()); if (sizeok != SIZEOKnone) return; @@ -690,11 +745,56 @@ void StructDeclaration::finalizeSize(Scope *sc) // Round struct size up to next alignsize boundary. // This will ensure that arrays of structs will get their internals // aligned properly. - structsize = (structsize + alignsize - 1) & ~(alignsize - 1); + if (alignment == STRUCTALIGN_DEFAULT) + structsize = (structsize + alignsize - 1) & ~(alignsize - 1); + else + structsize = (structsize + alignment - 1) & ~(alignment - 1); sizeok = SIZEOKdone; } +/*************************************** + * Return true if struct is POD (Plain Old Data). + * This is defined as: + * not nested + * no postblits, constructors, destructors, or assignment operators + * no fields with with any of those + * The idea being these are compatible with C structs. + * + * Note that D struct constructors can mean POD, since there is always default + * construction with no ctor, but that interferes with OPstrpar which wants it + * on the stack in memory, not in registers. + */ +bool StructDeclaration::isPOD() +{ + if (isnested || cpctor || postblit || ctor || dtor) + return false; + + /* Recursively check any fields have a constructor. + * We should cache the results of this. + */ + for (size_t i = 0; i < fields.dim; i++) + { + Dsymbol *s = fields[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v && v->storage_class & STCfield); + if (v->storage_class & STCref) + continue; + Type *tv = v->type->toBasetype(); + while (tv->ty == Tsarray) + { TypeSArray *ta = (TypeSArray *)tv; + tv = tv->nextOf()->toBasetype(); + } + if (tv->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)tv; + StructDeclaration *sd = ts->sym; + if (!sd->isPOD()) + return false; + } + } + return true; +} + void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->printf("%s ", kind()); @@ -711,7 +811,7 @@ void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); diff --git a/dmd2/template.c b/dmd2/template.c index 2f8ce392..dd2a67fa 100644 --- a/dmd2/template.c +++ b/dmd2/template.c @@ -85,7 +85,7 @@ int isError(Object *o) return (t->ty == Terror); Expression *e = isExpression(o); if (e) - return (e->op == TOKerror); + return (e->op == TOKerror || !e->type || e->type->ty== Terror); Tuple *v = isTuple(o); if (v) return arrayObjectIsError(&v->objects); @@ -99,7 +99,7 @@ int arrayObjectIsError(Objects *args) { for (size_t i = 0; i < args->dim; i++) { - Object *o = args->tdata()[i]; + Object *o = (*args)[i]; if (isError(o)) return 1; } @@ -130,7 +130,12 @@ Dsymbol *getDsymbol(Object *oarg) if (ea->op == TOKvar) sa = ((VarExp *)ea)->var; else if (ea->op == TOKfunction) - sa = ((FuncExp *)ea)->fd; + { + if (((FuncExp *)ea)->td) + sa = ((FuncExp *)ea)->td; + else + sa = ((FuncExp *)ea)->fd; + } else sa = NULL; } @@ -243,8 +248,8 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) goto Lnomatch; for (size_t i = 0; i < u1->objects.dim; i++) { - if (!match(u1->objects.tdata()[i], - u2->objects.tdata()[i], + if (!match(u1->objects[i], + u2->objects[i], tempdecl, sc)) goto Lnomatch; } @@ -268,8 +273,8 @@ int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl, if (oa1->dim != oa2->dim) return 0; for (size_t j = 0; j < oa1->dim; j++) - { Object *o1 = oa1->tdata()[j]; - Object *o2 = oa2->tdata()[j]; + { Object *o1 = (*oa1)[j]; + Object *o2 = (*oa2)[j]; if (!match(o1, o2, tempdecl, sc)) { return 0; @@ -362,7 +367,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, #if 0 if (parameters) for (int i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = parameters->tdata()[i]; + { TemplateParameter *tp = (*parameters)[i]; //printf("\tparameter[%d] = %p\n", i, tp); TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); @@ -410,7 +415,7 @@ Dsymbol *TemplateDeclaration::syntaxCopy(Dsymbol *) p->setDim(parameters->dim); for (size_t i = 0; i < p->dim; i++) { TemplateParameter *tp = (*parameters)[i]; - p->tdata()[i] = tp->syntaxCopy(); + (*p)[i] = tp->syntaxCopy(); } } Expression *e = NULL; @@ -437,8 +442,13 @@ void TemplateDeclaration::semantic(Scope *sc) return; // semantic() already run semanticRun = PASSsemantic; - if (sc->module && sc->module->ident == Id::object && ident == Id::AssociativeArray) - { Type::associativearray = this; + // Remember templates defined in module object that we need to know about + if (sc->module && sc->module->ident == Id::object) + { + if (ident == Id::AssociativeArray) + Type::associativearray = this; + else if (ident == Id::RTInfo) + Type::rtinfo = this; } if (sc->func) @@ -465,7 +475,7 @@ void TemplateDeclaration::semantic(Scope *sc) } #if DMDV2 - if (/*global.params.useUnitTests &&*/ sc->module) + if (sc->module) { // Generate this function as it may be used // when template is instantiated in other modules @@ -499,13 +509,13 @@ void TemplateDeclaration::semantic(Scope *sc) for (size_t i = 0; i < parameters->dim; i++) { TemplateParameter *tp = (*parameters)[i]; - origParameters->tdata()[i] = tp->syntaxCopy(); + (*origParameters)[i] = tp->syntaxCopy(); } } for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; tp->declareParameter(paramscope); } @@ -576,8 +586,8 @@ int TemplateDeclaration::overloadInsert(Dsymbol *s) goto Lcontinue; for (size_t i = 0; i < f->parameters->dim; i++) - { TemplateParameter *p1 = f->parameters->tdata()[i]; - TemplateParameter *p2 = f2->parameters->tdata()[i]; + { TemplateParameter *p1 = (*f->parameters)[i]; + TemplateParameter *p2 = (*f2->parameters)[i]; if (!p1->overloadMatch(p2)) goto Lcontinue; @@ -622,7 +632,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E // Shouldn't run semantic on default arguments and return type. for (int i = 0; iparameters->dim; i++) - tf->parameters->tdata()[i]->defaultArg = NULL; + (*tf->parameters)[i]->defaultArg = NULL; tf->next = NULL; // Resolve parameter types and 'auto ref's. @@ -647,7 +657,7 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E } for (size_t i = 0; i < fparameters->dim; i++) { - Parameter *fparam = fparameters->tdata()[i]; + Parameter *fparam = (*fparameters)[i]; if (!fparam->ident) continue; // don't add it, if it has no name VarDeclaration *v = new VarDeclaration(loc, fparam->type, fparam->ident, NULL); @@ -688,7 +698,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, if (ti->tiargs->dim) printf("ti->tiargs->dim = %d, [0] = %p\n", ti->tiargs->dim, - ti->tiargs->tdata()[0]); + (*ti->tiargs)[0]); #endif dedtypes->zero(); @@ -721,7 +731,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, m = MATCHexact; for (size_t i = 0; i < dedtypes_dim; i++) { MATCH m2; - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; Declaration *sparam; //printf("\targument [%d]\n", i); @@ -759,9 +769,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, */ for (size_t i = 0; i < dedtypes_dim; i++) { - if (!dedtypes->tdata()[i]) + if (!(*dedtypes)[i]) { assert(i < ti->tiargs->dim); - dedtypes->tdata()[i] = (Type *)ti->tiargs->tdata()[i]; + (*dedtypes)[i] = (Type *)(*ti->tiargs)[i]; } } } @@ -796,12 +806,14 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, } e = e->semantic(sc); + if (e->op == TOKerror) + goto Lnomatch; if (fd && fd->vthis) fd->vthis = vthissave; sc->pop(); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (e->isBool(TRUE)) ; else if (e->isBool(FALSE)) @@ -822,16 +834,16 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, { for (size_t i = 0; i < dedtypes_dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; Object *oarg; printf(" [%d]", i); if (i < ti->tiargs->dim) - oarg = ti->tiargs->tdata()[i]; + oarg = (*ti->tiargs)[i]; else oarg = NULL; - tp->print(oarg, dedtypes->tdata()[i]); + tp->print(oarg, (*dedtypes)[i]); } } else @@ -888,11 +900,11 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi ti.tiargs->setDim(parameters->dim); for (size_t i = 0; i < ti.tiargs->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; Object *p = (Object *)tp->dummyArg(); if (p) - ti.tiargs->tdata()[i] = p; + (*ti.tiargs)[i] = p; else ti.tiargs->setDim(i); } @@ -935,6 +947,8 @@ MATCH TemplateDeclaration::leastAsSpecialized(TemplateDeclaration *td2, Expressi * dedargs Expression/Type deduced template arguments * Returns: * match level + * bit 0-3 Match template parameters by inferred template arguments + * bit 4-7 Match template parameters by initial template arguments */ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, @@ -947,18 +961,20 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec int fptupindex = -1; int tuple_dim = 0; MATCH match = MATCHexact; + MATCH matchTargsi = MATCHexact; FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration(); Parameters *fparameters; // function parameter list int fvarargs; // function varargs Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T unsigned wildmatch = 0; + TemplateParameters *inferparams = parameters; TypeFunction *tf = (TypeFunction *)fd->type; #if 0 printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars()); for (size_t i = 0; i < fargs->dim; i++) - { Expression *e = fargs->tdata()[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()); @@ -991,7 +1007,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec for (size_t i = 0; i < dedargs->dim; i++) { printf("\tdedarg[%d] = ", i); - Object *oarg = dedargs->tdata()[i]; + Object *oarg = (*dedargs)[i]; if (oarg) printf("%s", oarg->toChars()); printf("\n"); } @@ -1015,13 +1031,13 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec */ Tuple *t = new Tuple(); assert(parameters->dim); - dedargs->tdata()[parameters->dim - 1] = t; + (*dedargs)[parameters->dim - 1] = t; tuple_dim = nargsi - n; t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { - t->objects.tdata()[i] = targsi->tdata()[n + i]; + t->objects[i] = (*targsi)[n + i]; } declareParameter(paramscope, tp, t); tp_is_declared = 1; @@ -1033,7 +1049,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec for (size_t i = 0; i < n; i++) { assert(i < parameters->dim); - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; MATCH m; Declaration *sparam = NULL; @@ -1041,19 +1057,29 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec //printf("\tdeduceType m = %d\n", m); if (m == MATCHnomatch) goto Lnomatch; - if (m < match) - match = m; + if (m < matchTargsi) + matchTargsi = m; sparam->semantic(paramscope); if (!paramscope->insert(sparam)) goto Lnomatch; } + if (n < parameters->dim) + { + inferparams = new TemplateParameters(); + inferparams->setDim(parameters->dim - n); + memcpy(inferparams->tdata(), + parameters->tdata() + n, + inferparams->dim * sizeof(*inferparams->tdata())); + } + else + inferparams = NULL; } #if 0 for (size_t i = 0; i < dedargs->dim; i++) { printf("\tdedarg[%d] = ", i); - Object *oarg = dedargs->tdata()[i]; + Object *oarg = (*dedargs)[i]; if (oarg) printf("%s", oarg->toChars()); printf("\n"); } @@ -1077,7 +1103,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec goto L2; Tuple *t = new Tuple(); //printf("t = %p\n", t); - dedargs->tdata()[parameters->dim - 1] = t; + (*dedargs)[parameters->dim - 1] = t; declareParameter(paramscope, tp, t); goto L2; } @@ -1092,7 +1118,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec */ for (fptupindex = 0; fptupindex < nfparams; fptupindex++) { - Parameter *fparam = fparameters->tdata()[fptupindex]; + Parameter *fparam = (*fparameters)[fptupindex]; if (fparam->type->ty != Tident) continue; TypeIdentifier *tid = (TypeIdentifier *)fparam->type; @@ -1112,12 +1138,12 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec * now form the tuple argument. */ Tuple *t = new Tuple(); - dedargs->tdata()[parameters->dim - 1] = t; + (*dedargs)[parameters->dim - 1] = t; tuple_dim = nfargs - (nfparams - 1); t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) - { Expression *farg = fargs->tdata()[fptupindex + i]; + { Expression *farg = (*fargs)[fptupindex + i]; // Check invalid arguments to detect errors early. if (farg->op == TOKerror || farg->type->ty == Terror) @@ -1291,7 +1317,7 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec if (m < match) match = m; - t->objects.tdata()[i] = tt; + t->objects[i] = tt; } declareParameter(paramscope, tp, t); goto L2; @@ -1316,7 +1342,7 @@ L2: { // Match 'ethis' to any TemplateThisParameter's for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = parameters->tdata()[i]; + { TemplateParameter *tp = (*parameters)[i]; TemplateThisParameter *ttp = tp->isTemplateThisParameter(); if (ttp) { MATCH m; @@ -1331,7 +1357,7 @@ L2: } // Match attributes of ethis against attributes of fd - if (fd->type) + if (fd->type && !fd->isCtorDeclaration()) { Type *tthis = ethis->type; unsigned mod = fd->type->mod; @@ -1389,6 +1415,7 @@ L2: i += tuple_dim - 1; Parameter *fparam = Parameter::getNth(fparameters, parami); + Type *prmtype = fparam->type; if (i >= nfargs) // if not enough arguments { @@ -1401,7 +1428,7 @@ L2: } else { - Expression *farg = fargs->tdata()[i]; + Expression *farg = (*fargs)[i]; // Check invalid arguments to detect errors early. if (farg->op == TOKerror || farg->type->ty == Terror) @@ -1410,12 +1437,20 @@ L2: Lretry: #if 0 printf("\tfarg->type = %s\n", farg->type->toChars()); - printf("\tfparam->type = %s\n", fparam->type->toChars()); + printf("\tfparam->type = %s\n", prmtype->toChars()); #endif Type *argtype = farg->type; // Apply function parameter storage classes to parameter types - fparam->type = fparam->type->addStorageClass(fparam->storageClass); + 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(loc, paramscope); + } #if DMDV2 /* Allow string literals which are type [] to match with [dim] @@ -1423,7 +1458,7 @@ Lretry: if (farg->op == TOKstring) { StringExp *se = (StringExp *)farg; if (!se->committed && argtype->ty == Tarray && - fparam->type->toBasetype()->ty == Tsarray) + prmtype->toBasetype()->ty == Tsarray) { argtype = new TypeSArray(argtype->nextOf(), new IntegerExp(se->loc, se->len, Type::tindex)); argtype = argtype->semantic(se->loc, NULL); @@ -1435,7 +1470,7 @@ Lretry: */ if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; - Type *tp = fparam->type; + Type *tp = prmtype; Expression *e = fe->inferType(tp, 1, parameters); if (!e) goto Lvarargs; @@ -1461,20 +1496,26 @@ Lretry: goto Lvarargs; unsigned wm = 0; - MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, &wm); + MATCH m = argtype->deduceType(paramscope, prmtype, parameters, &dedtypes, &wm); //printf("\tdeduceType m = %d\n", m); //printf("\twildmatch = x%x m = %d\n", wildmatch, m); wildmatch |= wm; + /* If no match, see if the argument can be matched by using + * implicit conversions. + */ + if (!m) + m = farg->implicitConvTo(prmtype); + /* If no match, see if there's a conversion to a delegate */ if (!m) - { Type *tbp = fparam->type->toBasetype(); + { Type *tbp = prmtype->toBasetype(); Type *tba = farg->type->toBasetype(); AggregateDeclaration *ad; if (tbp->ty == Tdelegate) { - TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype(); + TypeDelegate *td = (TypeDelegate *)prmtype->toBasetype(); TypeFunction *tf = (TypeFunction *)td->next; if (!tf->varargs && Parameter::dim(tf->parameters) == 0) @@ -1532,7 +1573,7 @@ Lretry: { if (!farg->isLvalue()) goto Lnomatch; } - if (!m && (fparam->storageClass & STClazy) && fparam->type->ty == Tvoid && + if (!m && (fparam->storageClass & STClazy) && prmtype->ty == Tvoid && farg->type->ty != Tvoid) m = MATCHconvert; @@ -1552,7 +1593,7 @@ Lretry: /* Check for match with function parameter T... */ - Type *tb = fparam->type->toBasetype(); + Type *tb = prmtype->toBasetype(); switch (tb->ty) { // Perhaps we can do better with this, see TypeFunction::callMatch() @@ -1566,7 +1607,7 @@ Lretry: { TypeArray *ta = (TypeArray *)tb; for (; i < nfargs; i++) { - Expression *arg = fargs->tdata()[i]; + Expression *arg = (*fargs)[i]; assert(arg); if (arg->op == TOKfunction) @@ -1624,13 +1665,13 @@ Lmatch: for (size_t i = nargsi; i < dedargs->dim; i++) { - TemplateParameter *tparam = parameters->tdata()[i]; + TemplateParameter *tparam = (*parameters)[i]; //printf("tparam[%d] = %s\n", i, tparam->ident->toChars()); /* For T:T*, the dedargs is the T*, dedtypes is the T * But for function templates, we really need them to match */ - Object *oarg = dedargs->tdata()[i]; - Object *oded = dedtypes.tdata()[i]; + Object *oarg = (*dedargs)[i]; + Object *oded = dedtypes[i]; //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); //if (oarg) printf("oarg: %s\n", oarg->toChars()); //if (oded) printf("oded: %s\n", oded->toChars()); @@ -1643,14 +1684,14 @@ Lmatch: * the oded == oarg */ Declaration *sparam; - dedargs->tdata()[i] = oded; + (*dedargs)[i] = oded; MATCH m2 = tparam->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam); //printf("m2 = %d\n", m2); if (!m2) goto Lnomatch; if (m2 < match) match = m2; // pick worst match - if (dedtypes.tdata()[i] != oded) + if (dedtypes[i] != oded) error("specialization not allowed for deduced parameter %s", tparam->ident->toChars()); } } @@ -1669,7 +1710,7 @@ Lmatch: } } declareParameter(paramscope, tparam, oded); - dedargs->tdata()[i] = oded; + (*dedargs)[i] = oded; } } @@ -1738,8 +1779,10 @@ Lmatch: if (nerrors != global.errors) // if any errors from evaluating the constraint, no match goto Lnomatch; + if (e->op == TOKerror) + goto Lnomatch; - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (e->isBool(TRUE)) ; else if (e->isBool(FALSE)) @@ -1753,14 +1796,14 @@ Lmatch: #if 0 for (i = 0; i < dedargs->dim; i++) - { Type *t = dedargs->tdata()[i]; + { Type *t = (*dedargs)[i]; printf("\tdedargs[%d] = %d, %s\n", i, t->dyncast(), t->toChars()); } #endif paramscope->pop(); //printf("\tmatch %d\n", match); - return match; + return (MATCH)(match | (matchTargsi<<4)); Lnomatch: paramscope->pop(); @@ -1798,6 +1841,12 @@ void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Obj } } } + if (ea && ea->op == TOKtype) + targ = ea->type; + else if (ea && ea->op == TOKimport) + sa = ((ScopeExp *)ea)->sds; + else if (ea && (ea->op == TOKthis || ea->op == TOKsuper)) + sa = ((ThisExp *)ea)->var; if (targ) { @@ -1809,6 +1858,14 @@ void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Obj //printf("Alias %s %s;\n", sa->ident->toChars(), tp->ident->toChars()); s = new AliasDeclaration(0, tp->ident, sa); } + else if (ea && ea->op == TOKfunction) + { + if (((FuncExp *)ea)->td) + sa = ((FuncExp *)ea)->td; + else + sa = ((FuncExp *)ea)->fd; + s = new AliasDeclaration(0, tp->ident, sa); + } else if (ea) { // tdtypes.data[i] always matches ea here @@ -1847,7 +1904,7 @@ TemplateTupleParameter *isVariadic(TemplateParameters *parameters) TemplateTupleParameter *tp = NULL; if (dim) - tp = (parameters->tdata()[dim - 1])->isTemplateTupleParameter(); + tp = ((*parameters)[dim - 1])->isTemplateTupleParameter(); return tp; } @@ -1882,6 +1939,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags) { MATCH m_best = MATCHnomatch; + MATCH m_best2 = MATCHnomatch; TemplateDeclaration *td_ambig = NULL; TemplateDeclaration *td_best = NULL; Objects *tdargs = new Objects(); @@ -1893,13 +1951,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, printf(" targsi:\n"); if (targsi) { for (size_t i = 0; i < targsi->dim; i++) - { Object *arg = targsi->tdata()[i]; + { Object *arg = (*targsi)[i]; printf("\t%s\n", arg->toChars()); } } printf(" fargs:\n"); for (size_t i = 0; i < fargs->dim; i++) - { Expression *arg = fargs->tdata()[i]; + { Expression *arg = (*fargs)[i]; printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); //printf("\tty = %d\n", arg->type->ty); } @@ -1919,14 +1977,22 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, goto Lerror; } + MATCH m, m2; Objects dedargs; FuncDeclaration *fd = NULL; - MATCH m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); - //printf("deduceFunctionTemplateMatch = %d\n", m); + m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); + m2 = (MATCH)(m >> 4); + m = (MATCH)(m & 0xF); + //printf("deduceFunctionTemplateMatch = %d, m2 = %d\n", m, m2); if (!m) // if no match continue; + if (m2 < m_best2) + goto Ltd_best; + if (m2 > m_best2) + goto Ltd; + if (m < m_best) goto Ltd_best; if (m > m_best) @@ -1962,7 +2028,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, 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->isCtorDeclaration() ? ethis : NULL, fargs); + MATCH c2 = (MATCH) tf2->callMatch(fd_best->needThis() && !fd_best->isCtorDeclaration() ? ethis : NULL, fargs); //printf("2: c1 = %d, c2 = %d\n", c1, c2); if (c1 > c2) @@ -1997,6 +2063,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, td_best = td; fd_best = fd; m_best = m; + m_best2 = m2; tdargs->setDim(dedargs.dim); memcpy(tdargs->tdata(), dedargs.tdata(), tdargs->dim * sizeof(void *)); continue; @@ -2023,8 +2090,20 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, ti = new TemplateInstance(loc, td_best, tdargs); ti->semantic(sc, fargs); fd_best = ti->toAlias()->isFuncDeclaration(); - if (!fd_best || !((TypeFunction*)fd_best->type)->callMatch(ethis, fargs, flags)) + if (!fd_best) goto Lerror; + if (!((TypeFunction*)fd_best->type)->callMatch(fd_best->needThis() && !fd_best->isCtorDeclaration() ? ethis : NULL, fargs)) + goto Lerror; + + if (FuncLiteralDeclaration *fld = fd_best->isFuncLiteralDeclaration()) + { + // Inside template constraint, nested reference check doesn't work correctly. + if (!(sc->flags & SCOPEstaticif) && fld->tok == TOKreserved) + { // change to non-nested + fld->tok = TOKfunction; + fld->vthis = NULL; + } + } /* As Bugzilla 3682 shows, a template instance can be matched while instantiating * that same template. Thus, the function type can be incomplete. Complete it. @@ -2051,7 +2130,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, { if (i) bufa.writeByte(','); - Object *oarg = args->tdata()[i]; + Object *oarg = (*args)[i]; ObjectToCBuffer(&bufa, &hgs, oarg); } } @@ -2059,7 +2138,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, OutBuffer buf; argExpTypesToCBuffer(&buf, fargs, &hgs); if (this->overnext) - ::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)", + ::error(this->loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)", kind(), parent->toPrettyChars(), ident->toChars(), bufa.toChars(), buf.toChars()); else @@ -2161,9 +2240,9 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writeByte('('); for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; if (hgs->ddoc) - tp = origParameters->tdata()[i]; + tp = (*origParameters)[i]; if (i) buf->writeByte(','); tp->toCBuffer(buf, hgs); @@ -2185,7 +2264,7 @@ void TemplateDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->toCBuffer(buf, hgs); } buf->writebyte('}'); @@ -2204,7 +2283,7 @@ char *TemplateDeclaration::toChars() buf.writeByte('('); for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; if (i) buf.writeByte(','); tp->toCBuffer(&buf, &hgs); @@ -2231,7 +2310,7 @@ char *TemplateDeclaration::toChars() int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters) { for (size_t i = 0; i < parameters->dim; i++) - { TemplateParameter *tp = parameters->tdata()[i]; + { TemplateParameter *tp = (*parameters)[i]; if (tp->ident->equals(id)) return i; @@ -2294,7 +2373,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Loc loc; if (parameters->dim) { - TemplateParameter *tp = parameters->tdata()[0]; + TemplateParameter *tp = (*parameters)[0]; loc = tp->loc; } @@ -2306,13 +2385,13 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, return deduceType(sc, tparam, parameters, dedtypes, wildmatch); } - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; // Found the corresponding parameter tp if (!tp->isTemplateTypeParameter()) goto Lnomatch; Type *tt = this; - Type *at = (Type *)dedtypes->tdata()[i]; + Type *at = (Type *)(*dedtypes)[i]; // 7*7 == 49 cases @@ -2343,7 +2422,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, else *wildmatch |= (mod & ~MODshared); tt = mutableOf()->substWildTo(MODmutable); - dedtypes->tdata()[i] = tt; + (*dedtypes)[i] = tt; goto Lconst; } @@ -2357,13 +2436,13 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, } else if (tt->implicitConvTo(at->constOf())) { - dedtypes->tdata()[i] = at->constOf()->mutableOf(); + (*dedtypes)[i] = at->constOf()->mutableOf(); *wildmatch |= MODconst; goto Lconst; } else if (at->implicitConvTo(tt->constOf())) { - dedtypes->tdata()[i] = tt->constOf()->mutableOf(); + (*dedtypes)[i] = tt->constOf()->mutableOf(); *wildmatch |= MODconst; goto Lconst; } @@ -2391,7 +2470,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, // foo(U:U) wild(T) => wild(T) // foo(U:U) wild(shared(T)) => wild(shared(T)) if (!at) - { dedtypes->tdata()[i] = tt; + { (*dedtypes)[i] = tt; goto Lexact; } break; @@ -2410,7 +2489,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, // foo(U:wild(shared(U)) wild(shared(T)) => T tt = mutableOf()->unSharedOf(); if (!at) - { dedtypes->tdata()[i] = tt; + { (*dedtypes)[i] = tt; goto Lexact; } break; @@ -2428,7 +2507,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, // foo(U:const(U)) wild(shared(T)) => shared(T) tt = mutableOf(); if (!at) - { dedtypes->tdata()[i] = tt; + { (*dedtypes)[i] = tt; goto Lconst; } break; @@ -2441,7 +2520,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, // foo(U:shared(U)) wild(shared(T)) => wild(T) tt = unSharedOf(); if (!at) - { dedtypes->tdata()[i] = tt; + { (*dedtypes)[i] = tt; goto Lconst; } break; @@ -2538,7 +2617,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Loc loc; if (parameters->dim) { - TemplateParameter *tp = parameters->tdata()[0]; + TemplateParameter *tp = (*parameters)[0]; loc = tp->loc; } @@ -2658,11 +2737,11 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame int i = templateIdentifierLookup(id, parameters); if (i == -1) goto Lnomatch; - TemplateParameter *tprm = parameters->tdata()[i]; + TemplateParameter *tprm = (*parameters)[i]; TemplateValueParameter *tvp = tprm->isTemplateValueParameter(); if (!tvp) goto Lnomatch; - Expression *e = (Expression *)dedtypes->tdata()[i]; + Expression *e = (Expression *)(*dedtypes)[i]; if (e) { if (!dim->equals(e)) @@ -2674,7 +2753,7 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame MATCH m = (MATCH)dim->implicitConvTo(vt); if (!m) goto Lnomatch; - dedtypes->tdata()[i] = dim; + (*dedtypes)[i] = dim; } return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes, wildmatch); } @@ -2754,7 +2833,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para for (; 1; tupi++) { if (tupi == parameters->dim) goto L1; - TemplateParameter *t = parameters->tdata()[tupi]; + TemplateParameter *t = (*parameters)[tupi]; TemplateTupleParameter *tup = t->isTemplateTupleParameter(); if (tup && tup->ident->equals(tid->ident)) break; @@ -2767,7 +2846,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para /* See if existing tuple, and whether it matches or not */ - Object *o = dedtypes->tdata()[tupi]; + Object *o = (*dedtypes)[tupi]; if (o) { // Existing deduced argument must be a tuple, and must match Tuple *t = isTuple(o); @@ -2775,7 +2854,7 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para return MATCHnomatch; for (size_t i = 0; i < tuple_dim; i++) { Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i); - if (!arg->type->equals(t->objects.tdata()[i])) + if (!arg->type->equals(t->objects[i])) return MATCHnomatch; } } @@ -2785,9 +2864,9 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { Parameter *arg = Parameter::getNth(this->parameters, nfparams - 1 + i); - t->objects.tdata()[i] = arg->type; + t->objects[i] = arg->type; } - dedtypes->tdata()[tupi] = t; + (*dedtypes)[tupi] = t; } nfparams--; // don't consider the last parameter for type deduction goto L2; @@ -2818,8 +2897,8 @@ MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *pa for (size_t i = 0; i < idents.dim; i++) { - Identifier *id1 = idents.tdata()[i]; - Identifier *id2 = tp->idents.tdata()[i]; + Identifier *id1 = idents[i]; + Identifier *id2 = tp->idents[i]; if (!id1->equals(id2)) return MATCHnomatch; @@ -2857,7 +2936,19 @@ 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 */ - Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL); + TypeIdentifier *tid = new TypeIdentifier(0, tp->tempinst->name); + Type *t; + Expression *e; + Dsymbol *s; + tid->resolve(0, sc, &e, &t, &s); + if (t) + { + s = t->toDsymbol(sc); + if (s) + { TemplateInstance *ti = s->parent->isTemplateInstance(); + s = ti ? ti->tempdecl : NULL; + } + } if (s) { s = s->toAlias(); @@ -2867,7 +2958,7 @@ MATCH TypeInstance::deduceType(Scope *sc, } goto Lnomatch; } - TemplateParameter *tpx = parameters->tdata()[i]; + TemplateParameter *tpx = (*parameters)[i]; // This logic duplicates tpx->matchArg() TemplateAliasParameter *ta = tpx->isTemplateAliasParameter(); if (!ta) @@ -2877,14 +2968,14 @@ MATCH TypeInstance::deduceType(Scope *sc, goto Lnomatch; if (ta->specAlias && sa != ta->specAlias) goto Lnomatch; - if (dedtypes->tdata()[i]) + if ((*dedtypes)[i]) { // Must match already deduced symbol - Object *s = dedtypes->tdata()[i]; + Object *s = (*dedtypes)[i]; if (s != sa) goto Lnomatch; } - dedtypes->tdata()[i] = sa; + (*dedtypes)[i] = sa; } } else if (tempinst->tempdecl != tp->tempinst->tempdecl) @@ -2895,22 +2986,66 @@ MATCH TypeInstance::deduceType(Scope *sc, for (size_t i = 0; 1; i++) { //printf("\ttest: tempinst->tiargs[%d]\n", i); - Object *o1; + Object *o1 = NULL; if (i < tempinst->tiargs->dim) - o1 = tempinst->tiargs->tdata()[i]; + o1 = (*tempinst->tiargs)[i]; else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim) // Pick up default arg - o1 = tempinst->tdtypes.tdata()[i]; - else + o1 = tempinst->tdtypes[i]; + else if (i >= tp->tempinst->tiargs->dim) break; if (i >= tp->tempinst->tiargs->dim) goto Lnomatch; - Object *o2 = tp->tempinst->tiargs->tdata()[i]; + Object *o2 = (*tp->tempinst->tiargs)[i]; + Type *t2 = isType(o2); + + int j; + if (t2 && + t2->ty == Tident && + i == tp->tempinst->tiargs->dim - 1 && + (j = templateParameterLookup(t2, parameters), j != -1) && + j == parameters->dim - 1 && + (*parameters)[j]->isTemplateTupleParameter()) + { + /* Given: + * struct A(B...) {} + * alias A!(int, float) X; + * static if (is(X Y == A!(Z), Z...)) {} + * deduce that Z is a tuple(int, float) + */ + + /* Create tuple from remaining args + */ + Tuple *vt = new Tuple(); + size_t vtdim = (tempinst->tempdecl->isVariadic() + ? tempinst->tiargs->dim : tempinst->tdtypes.dim) - i; + vt->objects.setDim(vtdim); + for (size_t k = 0; k < vtdim; k++) + { + Object *o; + if (k < tempinst->tiargs->dim) + o = (*tempinst->tiargs)[i + k]; + else // Pick up default arg + o = tempinst->tdtypes[i + k]; + vt->objects[k] = o; + } + + Tuple *v = (Tuple *)(*dedtypes)[j]; + if (v) + { + if (!match(v, vt, tempinst->tempdecl, sc)) + goto Lnomatch; + } + else + (*dedtypes)[j] = vt; + break; //return MATCHexact; + } + else if (!o1) + break; Type *t1 = isType(o1); - Type *t2 = isType(o2); Expression *e1 = isExpression(o1); Expression *e2 = isExpression(o2); @@ -2931,44 +3066,6 @@ MATCH TypeInstance::deduceType(Scope *sc, if (v2) printf("v2 = %s\n", v2->toChars()); #endif - TemplateTupleParameter *ttp; - int j; - if (t2 && - t2->ty == Tident && - i == tp->tempinst->tiargs->dim - 1 && - i == tempinst->tempdecl->parameters->dim - 1 && - (ttp = tempinst->tempdecl->isVariadic()) != NULL) - { - /* Given: - * struct A(B...) {} - * alias A!(int, float) X; - * static if (!is(X Y == A!(Z), Z)) - * deduce that Z is a tuple(int, float) - */ - - j = templateParameterLookup(t2, parameters); - if (j == -1) - goto Lnomatch; - - /* Create tuple from remaining args - */ - Tuple *vt = new Tuple(); - size_t vtdim = tempinst->tiargs->dim - i; - vt->objects.setDim(vtdim); - for (size_t k = 0; k < vtdim; k++) - vt->objects.tdata()[k] = tempinst->tiargs->tdata()[i + k]; - - Tuple *v = (Tuple *)dedtypes->tdata()[j]; - if (v) - { - if (!match(v, vt, tempinst->tempdecl, sc)) - goto Lnomatch; - } - else - dedtypes->tdata()[j] = vt; - break; //return MATCHexact; - } - if (t1 && t2) { if (!t1->deduceType(sc, t2, parameters, dedtypes, wildmatch)) @@ -2976,6 +3073,12 @@ MATCH TypeInstance::deduceType(Scope *sc, } else if (e1 && e2) { + Le: + e1 = e1->ctfeInterpret(); + e2 = e2->ctfeInterpret(); + + //printf("e1 = %s, type = %s %d\n", e1->toChars(), e1->type->toChars(), e1->type->ty); + //printf("e2 = %s, type = %s %d\n", e2->toChars(), e2->type->toChars(), e2->type->ty); if (!e1->equals(e2)) { if (e2->op == TOKvar) { @@ -2985,7 +3088,13 @@ MATCH TypeInstance::deduceType(Scope *sc, j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters); goto L1; } - goto Lnomatch; + if (!e2->implicitConvTo(e1->type)) + goto Lnomatch; + + e2 = e2->implicitCastTo(sc, e1->type); + e2 = e2->ctfeInterpret(); + if (!e1->equals(e2)) + goto Lnomatch; } } else if (e1 && t2 && t2->ty == Tident) @@ -2993,13 +3102,18 @@ MATCH TypeInstance::deduceType(Scope *sc, j = templateParameterLookup(t2, parameters); L1: if (j == -1) + { + t2->resolve(loc, sc, &e2, &t2, &s2); + if (e2) + goto Le; goto Lnomatch; - TemplateParameter *tp = parameters->tdata()[j]; + } + TemplateParameter *tp = (*parameters)[j]; // BUG: use tp->matchArg() instead of the following TemplateValueParameter *tv = tp->isTemplateValueParameter(); if (!tv) goto Lnomatch; - Expression *e = (Expression *)dedtypes->tdata()[j]; + Expression *e = (Expression *)(*dedtypes)[j]; if (e) { if (!e1->equals(e)) @@ -3010,20 +3124,31 @@ MATCH TypeInstance::deduceType(Scope *sc, MATCH m = (MATCH)e1->implicitConvTo(vt); if (!m) goto Lnomatch; - dedtypes->tdata()[j] = e1; + (*dedtypes)[j] = e1; } } + else if (s1 && s2) + { + Ls: + if (!s1->equals(s2)) + goto Lnomatch; + } else if (s1 && t2 && t2->ty == Tident) { j = templateParameterLookup(t2, parameters); if (j == -1) + { + t2->resolve(loc, sc, &e2, &t2, &s2); + if (s2) + goto Ls; goto Lnomatch; - TemplateParameter *tp = parameters->tdata()[j]; + } + TemplateParameter *tp = (*parameters)[j]; // BUG: use tp->matchArg() instead of the following TemplateAliasParameter *ta = tp->isTemplateAliasParameter(); if (!ta) goto Lnomatch; - Dsymbol *s = (Dsymbol *)dedtypes->tdata()[j]; + Dsymbol *s = (Dsymbol *)(*dedtypes)[j]; if (s) { if (!s1->equals(s)) @@ -3031,15 +3156,9 @@ MATCH TypeInstance::deduceType(Scope *sc, } else { - dedtypes->tdata()[j] = s1; + (*dedtypes)[j] = s1; } } - else if (s1 && s2) - { - if (!s1->equals(s2)) - goto Lnomatch; - } - // BUG: Need to handle tuple parameters else goto Lnomatch; } @@ -3076,7 +3195,7 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame */ TypeInstance *tpi = (TypeInstance *)tparam; if (tpi->idents.dim) - { Identifier *id = tpi->idents.tdata()[tpi->idents.dim - 1]; + { Identifier *id = tpi->idents[tpi->idents.dim - 1]; if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) { Type *tparent = sym->parent->getType(); @@ -3171,8 +3290,8 @@ void deduceBaseClassParameters(BaseClass *b, { // If we've found more than one possible type for a parameter, // mark it as unknown. - if (tmpdedtypes->tdata()[k] != best->tdata()[k]) - best->tdata()[k] = dedtypes->tdata()[k]; + if ((*tmpdedtypes)[k] != (*best)[k]) + (*best)[k] = (*dedtypes)[k]; } ++numBaseClassMatches; } @@ -3214,7 +3333,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet */ TypeInstance *tpi = (TypeInstance *)tparam; if (tpi->idents.dim) - { Identifier *id = tpi->idents.tdata()[tpi->idents.dim - 1]; + { Identifier *id = tpi->idents[tpi->idents.dim - 1]; if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) { Type *tparent = sym->parent->getType(); @@ -3250,7 +3369,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet while(s && s->baseclasses->dim > 0) { // Test the base class - deduceBaseClassParameters((s->baseclasses->tdata()[0]), + deduceBaseClassParameters((*s->baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches); @@ -3261,7 +3380,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet deduceBaseClassParameters(b, sc, tparam, parameters, dedtypes, best, numBaseClassMatches); } - s = ((s->baseclasses->tdata()[0]))->base; + s = (*s->baseclasses)[0]->base; } if (numBaseClassMatches == 0) @@ -3420,14 +3539,14 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs, Type *ta; if (i < tiargs->dim) - oarg = tiargs->tdata()[i]; + oarg = (*tiargs)[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes->dim); // It might have already been deduced - oarg = dedtypes->tdata()[i]; + oarg = (*dedtypes)[i]; if (!oarg) { goto Lnomatch; @@ -3457,14 +3576,14 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs, if (m2 < m) m = m2; - if (dedtypes->tdata()[i]) - ta = (Type *)dedtypes->tdata()[i]; + if ((*dedtypes)[i]) + ta = (Type *)(*dedtypes)[i]; } else { - if (dedtypes->tdata()[i]) + if ((*dedtypes)[i]) { // Must match already deduced type - Type *t = (Type *)dedtypes->tdata()[i]; + Type *t = (Type *)(*dedtypes)[i]; if (!t->equals(ta)) { //printf("t = %s ta = %s\n", t->toChars(), ta->toChars()); @@ -3477,7 +3596,7 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs, m = MATCHconvert; } } - dedtypes->tdata()[i] = ta; + (*dedtypes)[i] = ta; *psparam = new AliasDeclaration(loc, ident, ta); //printf("\tm = %d\n", m); @@ -3647,7 +3766,7 @@ Object *aliasParameterSemantic(Loc loc, Scope *sc, Object *o) else if (ea) { ea = ea->semantic(sc); - o = ea->optimize(WANTvalue | WANTinterpret); + o = ea->ctfeInterpret(); } } return o; @@ -3694,20 +3813,25 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs, //printf("TemplateAliasParameter::matchArg()\n"); if (i < tiargs->dim) - oarg = tiargs->tdata()[i]; + oarg = (*tiargs)[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes->dim); // It might have already been deduced - oarg = dedtypes->tdata()[i]; + oarg = (*dedtypes)[i]; if (!oarg) goto Lnomatch; } } sa = getDsymbol(oarg); + ea = isExpression(oarg); + if (ea && (ea->op == TOKthis || ea->op == TOKsuper)) + sa = ((ThisExp *)ea)->var; + else if (ea && ea->op == TOKimport) + sa = ((ScopeExp *)ea)->sds; if (sa) { /* specType means the alias must be a declaration with a type @@ -3724,7 +3848,6 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs, else { sa = oarg; - ea = isExpression(oarg); if (ea) { if (specType) { @@ -3740,17 +3863,26 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs, { if (sa == sdummy) goto Lnomatch; - if (sa != specAlias) - goto Lnomatch; + if (sa != specAlias && isDsymbol(sa)) + { + TemplateInstance *ti = isDsymbol(sa)->isTemplateInstance(); + Type *ta = isType(specAlias); + if (!ti || !ta) + goto Lnomatch; + Type *t = new TypeInstance(0, ti); + MATCH m = t->deduceType(sc, ta, parameters, dedtypes); + if (m == MATCHnomatch) + goto Lnomatch; + } } - else if (dedtypes->tdata()[i]) + else if ((*dedtypes)[i]) { // Must match already deduced symbol - Object *si = dedtypes->tdata()[i]; + Object *si = (*dedtypes)[i]; if (!sa || si != sa) goto Lnomatch; } - dedtypes->tdata()[i] = sa; + (*dedtypes)[i] = sa; s = isDsymbol(sa); if (s) @@ -3912,7 +4044,7 @@ void TemplateValueParameter::semantic(Scope *sc) e = e->semantic(sc); e = e->implicitCastTo(sc, valType); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (e->op == TOKint64 || e->op == TOKfloat64 || e->op == TOKcomplex80 || e->op == TOKnull || e->op == TOKstring) specValue = e; @@ -3924,7 +4056,7 @@ void TemplateValueParameter::semantic(Scope *sc) e = e->semantic(sc); e = e->implicitCastTo(sc, valType); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); if (e->op == TOKint64) defaultValue = e; //e->toInteger(); @@ -3968,14 +4100,14 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Object *oarg; if (i < tiargs->dim) - oarg = tiargs->tdata()[i]; + oarg = (*tiargs)[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes->dim); // It might have already been deduced - oarg = dedtypes->tdata()[i]; + oarg = (*dedtypes)[i]; if (!oarg) goto Lnomatch; } @@ -3989,7 +4121,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, if (ei && ei->op == TOKvar) { // Resolve const variables that we had skipped earlier - ei = ei->optimize(WANTvalue | WANTinterpret); + ei = ei->ctfeInterpret(); } //printf("\tvalType: %s, ty = %d\n", valType->toChars(), valType->ty); @@ -4014,12 +4146,12 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, e = e->semantic(sc); e = e->implicitCastTo(sc, vt); - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); ei = ei->syntaxCopy(); ei = ei->semantic(sc); ei = ei->implicitCastTo(sc, vt); - ei = ei->optimize(WANTvalue | WANTinterpret); + ei = ei->ctfeInterpret(); //printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars()); //printf("\te : %s, %s\n", e->toChars(), e->type->toChars()); if (!ei->equals(e)) @@ -4027,9 +4159,9 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, } else { - if (dedtypes->tdata()[i]) + if ((*dedtypes)[i]) { // Must match already deduced value - Expression *e = (Expression *)dedtypes->tdata()[i]; + Expression *e = (Expression *)(*dedtypes)[i]; if (!ei || !ei->equals(e)) goto Lnomatch; @@ -4037,10 +4169,10 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, else if (m != MATCHexact) { ei = ei->implicitCastTo(sc, vt); - ei = ei->optimize(WANTvalue | WANTinterpret); + ei = ei->ctfeInterpret(); } } - dedtypes->tdata()[i] = ei; + (*dedtypes)[i] = ei; init = new ExpInitializer(loc, ei); sparam = new VarDeclaration(loc, vt, ident, init); @@ -4176,11 +4308,11 @@ MATCH TemplateTupleParameter::matchArg(Scope *sc, Objects *tiargs, assert(i + 1 == dedtypes->dim); // must be the last one Tuple *ovar; - if (dedtypes->tdata()[i] && isTuple(dedtypes->tdata()[i])) + if ((*dedtypes)[i] && isTuple((*dedtypes)[i])) // It was already been deduced - ovar = isTuple(dedtypes->tdata()[i]); - else if (i + 1 == tiargs->dim && isTuple(tiargs->tdata()[i])) - ovar = isTuple(tiargs->tdata()[i]); + ovar = isTuple((*dedtypes)[i]); + else if (i + 1 == tiargs->dim && isTuple((*tiargs)[i])) + ovar = isTuple((*tiargs)[i]); else { ovar = new Tuple(); @@ -4190,11 +4322,11 @@ MATCH TemplateTupleParameter::matchArg(Scope *sc, Objects *tiargs, //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim); ovar->objects.setDim(tiargs->dim - i); for (size_t j = 0; j < ovar->objects.dim; j++) - ovar->objects.tdata()[j] = tiargs->tdata()[i + j]; + ovar->objects[j] = (*tiargs)[i + j]; } } *psparam = new TupleDeclaration(loc, ident, &ovar->objects); - dedtypes->tdata()[i] = ovar; + (*dedtypes)[i] = ovar; return MATCHexact; } @@ -4211,7 +4343,7 @@ void TemplateTupleParameter::print(Object *oarg, Object *oded) if (i) printf(", "); - Object *o = v->objects.tdata()[i]; + Object *o = v->objects[i]; Dsymbol *sa = isDsymbol(o); if (sa) @@ -4332,7 +4464,7 @@ Objects *TemplateInstance::arraySyntaxCopy(Objects *objs) a->setDim(objs->dim); for (size_t i = 0; i < objs->dim; i++) { - a->tdata()[i] = objectSyntaxCopy(objs->tdata()[i]); + (*a)[i] = objectSyntaxCopy((*objs)[i]); } } return a; @@ -4367,7 +4499,7 @@ void TemplateInstance::expandMembers(Scope *sc2) } for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + 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) @@ -4506,21 +4638,34 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } else { - /* Run semantic on each argument, place results in tiargs[] - * (if we havetempdecl, then tiargs is already evaluated) + /* Find template declaration first. */ - semanticTiargs(sc); - if (arrayObjectIsError(tiargs)) - { inst = this; + 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) + inst = this; + //printf("error return %p, %d\n", tempdecl, global.errors); + if (inst) + ++inst->errors; + return; // error recovery + } + unsigned errs = global.errors; - tempdecl = findTemplateDeclaration(sc); - if (tempdecl) - tempdecl = findBestMatch(sc, fargs); + tempdecl = findBestMatch(sc, fargs); if (!tempdecl || (errs != global.errors)) - { inst = this; + { if (!sc->parameterSpecialization) + inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); return; // error recovery } @@ -4538,7 +4683,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) for (size_t i = 0; i < tempdecl->instances.dim; i++) { - TemplateInstance *ti = tempdecl->instances.tdata()[i]; + TemplateInstance *ti = tempdecl->instances[i]; #if LOG printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti->toChars()); #endif @@ -4567,7 +4712,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) size_t nfparams = Parameter::dim(fparameters); // Num function parameters for (size_t j = 0; j < nfparams && j < fargs->dim; j++) { Parameter *fparam = Parameter::getNth(fparameters, j); - Expression *farg = fargs->tdata()[j]; + Expression *farg = (*fargs)[j]; if (fparam->storageClass & STCauto) // if "auto ref" { if (farg->isLvalue()) @@ -4695,7 +4840,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) a->push(this); break; } - if (this == a->tdata()[i]) // if already in Array + if (this == (*a)[i]) // if already in Array break; } } @@ -4732,7 +4877,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) int memnum = 0; for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; #if LOG printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s->toChars(), s, s->kind(), this->toChars(), memnum); #endif @@ -4805,7 +4950,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) * or semantic3() yet. */ for (size_t i = 0; i < Module::deferred.dim; i++) - { Dsymbol *sd = Module::deferred.tdata()[i]; + { Dsymbol *sd = Module::deferred[i]; if (sd->parent == this) { @@ -4879,7 +5024,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) { // Because we added 'this' in the last position above, we // should be able to remove it without messing other indices up. - assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); + assert((*target_symbol_list)[target_symbol_list_idx] == this); target_symbol_list->remove(target_symbol_list_idx); } semanticRun = PASSinit; @@ -4915,12 +5060,12 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f return; for (size_t j = 0; j < tiargs->dim; j++) { - Object *o = tiargs->tdata()[j]; + Object *o = (*tiargs)[j]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); - //printf("1: tiargs->tdata()[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta); + //printf("1: (*tiargs)[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta); if (ta) { //printf("type %s\n", ta->toChars()); @@ -4937,13 +5082,13 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f if (flags & 1) // only used by __traits, must not interpret the args ea = ea->optimize(WANTvalue); else if (ea->op != TOKvar) - ea = ea->optimize(WANTvalue | WANTinterpret); - tiargs->tdata()[j] = ea; + ea = ea->ctfeInterpret(); + (*tiargs)[j] = ea; } else if (sa) { Ldsym: - tiargs->tdata()[j] = sa; + (*tiargs)[j] = sa; TupleDeclaration *d = sa->toAlias()->isTupleDeclaration(); if (d) { @@ -4964,19 +5109,19 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f if (dim) { tiargs->reserve(dim); for (size_t i = 0; i < dim; i++) - { Parameter *arg = tt->arguments->tdata()[i]; + { Parameter *arg = (*tt->arguments)[i]; tiargs->insert(j + i, arg->type); } } j--; } else - tiargs->tdata()[j] = ta; + (*tiargs)[j] = ta; } else { assert(global.errors); - tiargs->tdata()[j] = Type::terror; + (*tiargs)[j] = Type::terror; } } else if (ea) @@ -4989,9 +5134,12 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f ea = ea->semantic(sc); if (flags & 1) // only used by __traits, must not interpret the args ea = ea->optimize(WANTvalue); - else if (ea->op != TOKvar && ea->op != TOKtuple) - ea = ea->optimize(WANTvalue | WANTinterpret); - tiargs->tdata()[j] = ea; + else if (ea->op != TOKvar && ea->op != TOKtuple && + ea->op != TOKimport && ea->op != TOKtype && + ea->op != TOKfunction && ea->op != TOKerror && + ea->op != TOKthis && ea->op != TOKsuper) + ea = ea->ctfeInterpret(); + (*tiargs)[j] = ea; if (ea->op == TOKtype) { ta = ea->type; goto Ltype; @@ -5000,6 +5148,18 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { sa = ((ScopeExp *)ea)->sds; goto Ldsym; } + if (ea->op == TOKfunction) + { FuncExp *fe = (FuncExp *)ea; + /* A function literal, that is passed to template and + * already semanticed as function pointer, never requires + * outer frame. So convert it to global function is valid. + */ + if (fe->fd->tok == TOKreserved && fe->type->ty == Tpointer) + { // change to non-nested + fe->fd->tok = TOKfunction; + fe->fd->vthis = NULL; + } + } if (ea->op == TOKtuple) { // Expand tuple TupleExp *te = (TupleExp *)ea; @@ -5008,7 +5168,7 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f if (dim) { tiargs->reserve(dim); for (size_t i = 0; i < dim; i++) - tiargs->insert(j + i, te->exps->tdata()[i]); + tiargs->insert(j + i, (*te->exps)[i]); } j--; } @@ -5023,13 +5183,13 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f { assert(0); } - //printf("1: tiargs->tdata()[%d] = %p\n", j, tiargs->tdata()[j]); + //printf("1: (*tiargs)[%d] = %p\n", j, (*tiargs)[j]); } #if 0 printf("-TemplateInstance::semanticTiargs()\n"); for (size_t j = 0; j < tiargs->dim; j++) { - Object *o = tiargs->tdata()[j]; + Object *o = (*tiargs)[j]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); @@ -5075,7 +5235,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc) if (os) { s = NULL; for (size_t i = 0; i < os->a.dim; i++) - { Dsymbol *s2 = os->a.tdata()[i]; + { Dsymbol *s2 = os->a[i]; if (s2->isTemplateDeclaration()) { if (s) @@ -5199,7 +5359,7 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far { MATCH m; -//if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, tiargs->tdata()[0]); +//if (tiargs->dim) printf("2: tiargs->dim = %d, data[0] = %p\n", tiargs->dim, (*tiargs)[0]); // If more arguments than parameters, // then this is no match. @@ -5279,17 +5439,17 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far /* Cast any value arguments to be same type as value parameter */ for (size_t i = 0; i < tiargs->dim; i++) - { Object *o = tiargs->tdata()[i]; + { Object *o = (*tiargs)[i]; Expression *ea = isExpression(o); // value argument - TemplateParameter *tp = tempdecl->parameters->tdata()[i]; + TemplateParameter *tp = (*tempdecl->parameters)[i]; assert(tp); TemplateValueParameter *tvp = tp->isTemplateValueParameter(); if (tvp) { assert(ea); ea = ea->castTo(tvp->valType); - ea = ea->optimize(WANTvalue | WANTinterpret); - tiargs->tdata()[i] = (Object *)ea; + ea = ea->ctfeInterpret(); + (*tiargs)[i] = (Object *)ea; } } #endif @@ -5314,7 +5474,7 @@ int TemplateInstance::hasNestedArgs(Objects *args) * symbol that is on the stack. */ for (size_t i = 0; i < args->dim; i++) - { Object *o = args->tdata()[i]; + { Object *o = (*args)[i]; Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); Tuple *va = isTuple(o); @@ -5332,7 +5492,10 @@ int TemplateInstance::hasNestedArgs(Objects *args) } if (ea->op == TOKfunction) { - sa = ((FuncExp *)ea)->fd; + if (((FuncExp *)ea)->td) + sa = ((FuncExp *)ea)->td; + else + sa = ((FuncExp *)ea)->fd; goto Lsa; } } @@ -5404,7 +5567,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) char *id = tempdecl->ident->toChars(); buf.printf("__T%llu%s", (ulonglong)strlen(id), id); for (size_t i = 0; i < args->dim; i++) - { Object *o = args->tdata()[i]; + { Object *o = (*args)[i]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); @@ -5442,7 +5605,10 @@ Identifier *TemplateInstance::genIdent(Objects *args) } if (ea->op == TOKfunction) { - sa = ((FuncExp *)ea)->fd; + if (((FuncExp *)ea)->td) + sa = ((FuncExp *)ea)->td; + else + sa = ((FuncExp *)ea)->fd; ea = NULL; goto Lsa; } @@ -5453,7 +5619,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) } // Now that we know it is not an alias, we MUST obtain a value unsigned olderr = global.errors; - ea = ea->optimize(WANTvalue | WANTinterpret); + ea = ea->ctfeInterpret(); if (ea->op == TOKerror || olderr != global.errors) continue; #if 1 @@ -5462,7 +5628,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) buf.writestring(ea->type->deco); #else // Use type of parameter, not type of argument - TemplateParameter *tp = tempdecl->parameters->tdata()[i]; + TemplateParameter *tp = (*tempdecl->parameters)[i]; assert(tp); TemplateValueParameter *tvp = tp->isTemplateValueParameter(); assert(tvp); @@ -5528,9 +5694,9 @@ void TemplateInstance::declareParameters(Scope *sc) //printf("TemplateInstance::declareParameters()\n"); for (size_t i = 0; i < tdtypes.dim; i++) { - TemplateParameter *tp = tempdecl->parameters->tdata()[i]; - //Object *o = tiargs->tdata()[i]; - Object *o = tdtypes.tdata()[i]; // initializer for tp + TemplateParameter *tp = (*tempdecl->parameters)[i]; + //Object *o = (*tiargs)[i]; + Object *o = tdtypes[i]; // initializer for tp //printf("\ttdtypes[%d] = %p\n", i, o); tempdecl->declareParameter(sc, tp, o); @@ -5566,7 +5732,7 @@ int TemplateInstance::needsTypeInference(Scope *sc) } for (size_t i = 0; i < td->parameters->dim; i++) - if (td->parameters->tdata()[i]->isTemplateThisParameter()) + if ((*td->parameters)[i]->isTemplateThisParameter()) return TRUE; /* Determine if the instance arguments, tiargs, are all that is necessary @@ -5627,7 +5793,7 @@ void TemplateInstance::semantic2(Scope *sc) sc->tinst = this; for (i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; #if LOG printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); #endif @@ -5669,7 +5835,7 @@ void TemplateInstance::semantic3(Scope *sc) olderrors = global.startGagging(); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic3(sc); if (speculative && global.errors != olderrors) break; @@ -5777,7 +5943,7 @@ void TemplateInstance::toObjFile(int multiobj) { for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->toObjFile(multiobj); } } @@ -5795,7 +5961,7 @@ void TemplateInstance::inlineScan() { for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->inlineScan(); } } @@ -5937,7 +6103,7 @@ void TemplateInstance::printInstantiationTrace() TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Identifiers *idents, Objects *tiargs) - : TemplateInstance(loc, idents->tdata()[idents->dim - 1]) + : TemplateInstance(loc, (*idents)[idents->dim - 1]) { //printf("TemplateMixin(ident = '%s')\n", ident ? ident->toChars() : ""); this->ident = ident; @@ -5953,7 +6119,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) ids->setDim(idents->dim); for (size_t i = 0; i < idents->dim; i++) { // Matches TypeQualified::syntaxCopyHelper() - Identifier *id = idents->tdata()[i]; + Identifier *id = (*idents)[i]; if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; @@ -5961,7 +6127,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s) ti = (TemplateInstance *)ti->syntaxCopy(NULL); id = (Identifier *)ti; } - ids->tdata()[i] = id; + (*ids)[i] = id; } tm = new TemplateMixin(loc, ident, @@ -6022,7 +6188,7 @@ void TemplateMixin::semantic(Scope *sc) else { i = 1; - id = idents->tdata()[0]; + id = (*idents)[0]; switch (id->dyncast()) { case DYNCAST_IDENTIFIER: @@ -6045,7 +6211,7 @@ void TemplateMixin::semantic(Scope *sc) { if (!s) break; - id = idents->tdata()[i]; + id = (*idents)[i]; s = s->searchX(loc, sc, id); } if (!s) @@ -6301,7 +6467,7 @@ void TemplateMixin::semantic3(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic3(sc); } sc = sc->pop(); @@ -6359,10 +6525,14 @@ int TemplateMixin::hasPointers() void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { + //printf("TemplateMixin::setFieldOffset() %s\n", toChars()); + if (scope) // if fwd reference + semantic(NULL); // try to resolve it if (members) { for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; + //printf("\t%s\n", s->toChars()); s->setFieldOffset(ad, poffset, isunion); } } @@ -6385,7 +6555,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("mixin "); for (size_t i = 0; i < idents->dim; i++) - { Identifier *id = idents->tdata()[i]; + { Identifier *id = (*idents)[i]; if (i) buf->writeByte('.'); @@ -6397,7 +6567,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs) for (size_t i = 0; i < tiargs->dim; i++) { if (i) buf->writebyte(','); - Object *oarg = tiargs->tdata()[i]; + Object *oarg = (*tiargs)[i]; Type *t = isType(oarg); Expression *e = isExpression(oarg); Dsymbol *s = isDsymbol(oarg); diff --git a/dmd2/traits.c b/dmd2/traits.c index 68f7b2a1..7a678920 100644 --- a/dmd2/traits.c +++ b/dmd2/traits.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -89,7 +89,7 @@ Expression *TraitsExp::semantic(Scope *sc) #define ISTYPE(cond) \ for (size_t i = 0; i < dim; i++) \ - { Type *t = getType(args->tdata()[i]); \ + { Type *t = getType((*args)[i]); \ if (!t) \ goto Lfalse; \ if (!(cond)) \ @@ -101,7 +101,7 @@ Expression *TraitsExp::semantic(Scope *sc) #define ISDSYMBOL(cond) \ for (size_t i = 0; i < dim; i++) \ - { Dsymbol *s = getDsymbol(args->tdata()[i]); \ + { Dsymbol *s = getDsymbol((*args)[i]); \ if (!s) \ goto Lfalse; \ if (!(cond)) \ @@ -196,7 +196,7 @@ Expression *TraitsExp::semantic(Scope *sc) if (dim != 1) goto Ldimerror; - Object *o = args->tdata()[0]; + Object *o = (*args)[0]; Dsymbol *s = getDsymbol(o); if (!s || !s->ident) { @@ -210,7 +210,7 @@ Expression *TraitsExp::semantic(Scope *sc) { if (dim != 1) goto Ldimerror; - Object *o = args->tdata()[0]; + Object *o = (*args)[0]; Dsymbol *s = getDsymbol(o); if (s) s = s->toParent(); @@ -231,13 +231,13 @@ Expression *TraitsExp::semantic(Scope *sc) { if (dim != 2) goto Ldimerror; - Object *o = args->tdata()[0]; - Expression *e = isExpression(args->tdata()[1]); + Object *o = (*args)[0]; + Expression *e = isExpression((*args)[1]); if (!e) { error("expression expected as second argument of __traits %s", ident->toChars()); goto Lfalse; } - e = e->optimize(WANTvalue | WANTinterpret); + e = e->ctfeInterpret(); StringExp *se = e->toString(); if (!se || se->length() == 0) { error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars()); @@ -336,7 +336,7 @@ Expression *TraitsExp::semantic(Scope *sc) { if (dim != 1) goto Ldimerror; - Object *o = args->tdata()[0]; + Object *o = (*args)[0]; Dsymbol *s = getDsymbol(o); ClassDeclaration *cd; if (!s || (cd = s->isClassDeclaration()) == NULL) @@ -350,7 +350,7 @@ Expression *TraitsExp::semantic(Scope *sc) { if (dim != 1) goto Ldimerror; - Object *o = args->tdata()[0]; + Object *o = (*args)[0]; Dsymbol *s = getDsymbol(o); ScopeDsymbol *sd; if (!s) @@ -380,7 +380,7 @@ Expression *TraitsExp::semantic(Scope *sc) /* Skip if already present in idents[] */ for (size_t j = 0; j < idents->dim; j++) - { Identifier *id = idents->tdata()[j]; + { Identifier *id = (*idents)[j]; if (id == sm->ident) return 0; #ifdef DEBUG @@ -421,9 +421,9 @@ Expression *TraitsExp::semantic(Scope *sc) assert(sizeof(Expressions) == sizeof(Identifiers)); Expressions *exps = (Expressions *)idents; for (size_t i = 0; i < idents->dim; i++) - { Identifier *id = idents->tdata()[i]; + { Identifier *id = (*idents)[i]; StringExp *se = new StringExp(loc, id->toChars()); - exps->tdata()[i] = se; + (*exps)[i] = se; } #if DMDV1 @@ -448,7 +448,7 @@ Expression *TraitsExp::semantic(Scope *sc) goto Lfalse; for (size_t i = 0; i < dim; i++) - { Object *o = args->tdata()[i]; + { Object *o = (*args)[i]; Expression *e; unsigned errors = global.startGagging(); @@ -491,8 +491,8 @@ Expression *TraitsExp::semantic(Scope *sc) if (dim != 2) goto Ldimerror; TemplateInstance::semanticTiargs(loc, sc, args, 0); - Object *o1 = args->tdata()[0]; - Object *o2 = args->tdata()[1]; + Object *o1 = (*args)[0]; + Object *o2 = (*args)[1]; Dsymbol *s1 = getDsymbol(o1); Dsymbol *s2 = getDsymbol(o2); diff --git a/dmd2/unialpha.c b/dmd2/unialpha.c deleted file mode 100644 index 5c407180..00000000 --- a/dmd2/unialpha.c +++ /dev/null @@ -1,323 +0,0 @@ - -// Copyright (c) 2003 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include - -/******************************* - * Return !=0 if unicode alpha. - * Use table from C99 Appendix D. - */ - -int isUniAlpha(unsigned u) -{ - static unsigned short table[][2] = - { - { 0x00AA, 0x00AA }, - { 0x00B5, 0x00B5 }, - { 0x00B7, 0x00B7 }, - { 0x00BA, 0x00BA }, - { 0x00C0, 0x00D6 }, - { 0x00D8, 0x00F6 }, - { 0x00F8, 0x01F5 }, - { 0x01FA, 0x0217 }, - { 0x0250, 0x02A8 }, - { 0x02B0, 0x02B8 }, - { 0x02BB, 0x02BB }, - { 0x02BD, 0x02C1 }, - { 0x02D0, 0x02D1 }, - { 0x02E0, 0x02E4 }, - { 0x037A, 0x037A }, - { 0x0386, 0x0386 }, - { 0x0388, 0x038A }, - { 0x038C, 0x038C }, - { 0x038E, 0x03A1 }, - { 0x03A3, 0x03CE }, - { 0x03D0, 0x03D6 }, - { 0x03DA, 0x03DA }, - { 0x03DC, 0x03DC }, - { 0x03DE, 0x03DE }, - { 0x03E0, 0x03E0 }, - { 0x03E2, 0x03F3 }, - { 0x0401, 0x040C }, - { 0x040E, 0x044F }, - { 0x0451, 0x045C }, - { 0x045E, 0x0481 }, - { 0x0490, 0x04C4 }, - { 0x04C7, 0x04C8 }, - { 0x04CB, 0x04CC }, - { 0x04D0, 0x04EB }, - { 0x04EE, 0x04F5 }, - { 0x04F8, 0x04F9 }, - { 0x0531, 0x0556 }, - { 0x0559, 0x0559 }, - { 0x0561, 0x0587 }, - { 0x05B0, 0x05B9 }, - { 0x05BB, 0x05BD }, - { 0x05BF, 0x05BF }, - { 0x05C1, 0x05C2 }, - { 0x05D0, 0x05EA }, - { 0x05F0, 0x05F2 }, - { 0x0621, 0x063A }, - { 0x0640, 0x0652 }, - { 0x0660, 0x0669 }, - { 0x0670, 0x06B7 }, - { 0x06BA, 0x06BE }, - { 0x06C0, 0x06CE }, - { 0x06D0, 0x06DC }, - { 0x06E5, 0x06E8 }, - { 0x06EA, 0x06ED }, - { 0x06F0, 0x06F9 }, - { 0x0901, 0x0903 }, - { 0x0905, 0x0939 }, - { 0x093D, 0x093D }, - { 0x093E, 0x094D }, - { 0x0950, 0x0952 }, - { 0x0958, 0x0963 }, - { 0x0966, 0x096F }, - { 0x0981, 0x0983 }, - { 0x0985, 0x098C }, - { 0x098F, 0x0990 }, - { 0x0993, 0x09A8 }, - { 0x09AA, 0x09B0 }, - { 0x09B2, 0x09B2 }, - { 0x09B6, 0x09B9 }, - { 0x09BE, 0x09C4 }, - { 0x09C7, 0x09C8 }, - { 0x09CB, 0x09CD }, - { 0x09DC, 0x09DD }, - { 0x09DF, 0x09E3 }, - { 0x09E6, 0x09EF }, - { 0x09F0, 0x09F1 }, - { 0x0A02, 0x0A02 }, - { 0x0A05, 0x0A0A }, - { 0x0A0F, 0x0A10 }, - { 0x0A13, 0x0A28 }, - { 0x0A2A, 0x0A30 }, - { 0x0A32, 0x0A33 }, - { 0x0A35, 0x0A36 }, - { 0x0A38, 0x0A39 }, - { 0x0A3E, 0x0A42 }, - { 0x0A47, 0x0A48 }, - { 0x0A4B, 0x0A4D }, - { 0x0A59, 0x0A5C }, - { 0x0A5E, 0x0A5E }, - { 0x0A66, 0x0A6F }, - { 0x0A74, 0x0A74 }, - { 0x0A81, 0x0A83 }, - { 0x0A85, 0x0A8B }, - { 0x0A8D, 0x0A8D }, - { 0x0A8F, 0x0A91 }, - { 0x0A93, 0x0AA8 }, - { 0x0AAA, 0x0AB0 }, - { 0x0AB2, 0x0AB3 }, - { 0x0AB5, 0x0AB9 }, - { 0x0ABD, 0x0AC5 }, - { 0x0AC7, 0x0AC9 }, - { 0x0ACB, 0x0ACD }, - { 0x0AD0, 0x0AD0 }, - { 0x0AE0, 0x0AE0 }, - { 0x0AE6, 0x0AEF }, - { 0x0B01, 0x0B03 }, - { 0x0B05, 0x0B0C }, - { 0x0B0F, 0x0B10 }, - { 0x0B13, 0x0B28 }, - { 0x0B2A, 0x0B30 }, - { 0x0B32, 0x0B33 }, - { 0x0B36, 0x0B39 }, - { 0x0B3D, 0x0B3D }, - { 0x0B3E, 0x0B43 }, - { 0x0B47, 0x0B48 }, - { 0x0B4B, 0x0B4D }, - { 0x0B5C, 0x0B5D }, - { 0x0B5F, 0x0B61 }, - { 0x0B66, 0x0B6F }, - { 0x0B82, 0x0B83 }, - { 0x0B85, 0x0B8A }, - { 0x0B8E, 0x0B90 }, - { 0x0B92, 0x0B95 }, - { 0x0B99, 0x0B9A }, - { 0x0B9C, 0x0B9C }, - { 0x0B9E, 0x0B9F }, - { 0x0BA3, 0x0BA4 }, - { 0x0BA8, 0x0BAA }, - { 0x0BAE, 0x0BB5 }, - { 0x0BB7, 0x0BB9 }, - { 0x0BBE, 0x0BC2 }, - { 0x0BC6, 0x0BC8 }, - { 0x0BCA, 0x0BCD }, - { 0x0BE7, 0x0BEF }, - { 0x0C01, 0x0C03 }, - { 0x0C05, 0x0C0C }, - { 0x0C0E, 0x0C10 }, - { 0x0C12, 0x0C28 }, - { 0x0C2A, 0x0C33 }, - { 0x0C35, 0x0C39 }, - { 0x0C3E, 0x0C44 }, - { 0x0C46, 0x0C48 }, - { 0x0C4A, 0x0C4D }, - { 0x0C60, 0x0C61 }, - { 0x0C66, 0x0C6F }, - { 0x0C82, 0x0C83 }, - { 0x0C85, 0x0C8C }, - { 0x0C8E, 0x0C90 }, - { 0x0C92, 0x0CA8 }, - { 0x0CAA, 0x0CB3 }, - { 0x0CB5, 0x0CB9 }, - { 0x0CBE, 0x0CC4 }, - { 0x0CC6, 0x0CC8 }, - { 0x0CCA, 0x0CCD }, - { 0x0CDE, 0x0CDE }, - { 0x0CE0, 0x0CE1 }, - { 0x0CE6, 0x0CEF }, - { 0x0D02, 0x0D03 }, - { 0x0D05, 0x0D0C }, - { 0x0D0E, 0x0D10 }, - { 0x0D12, 0x0D28 }, - { 0x0D2A, 0x0D39 }, - { 0x0D3E, 0x0D43 }, - { 0x0D46, 0x0D48 }, - { 0x0D4A, 0x0D4D }, - { 0x0D60, 0x0D61 }, - { 0x0D66, 0x0D6F }, - { 0x0E01, 0x0E3A }, - { 0x0E40, 0x0E5B }, -// { 0x0E50, 0x0E59 }, - { 0x0E81, 0x0E82 }, - { 0x0E84, 0x0E84 }, - { 0x0E87, 0x0E88 }, - { 0x0E8A, 0x0E8A }, - { 0x0E8D, 0x0E8D }, - { 0x0E94, 0x0E97 }, - { 0x0E99, 0x0E9F }, - { 0x0EA1, 0x0EA3 }, - { 0x0EA5, 0x0EA5 }, - { 0x0EA7, 0x0EA7 }, - { 0x0EAA, 0x0EAB }, - { 0x0EAD, 0x0EAE }, - { 0x0EB0, 0x0EB9 }, - { 0x0EBB, 0x0EBD }, - { 0x0EC0, 0x0EC4 }, - { 0x0EC6, 0x0EC6 }, - { 0x0EC8, 0x0ECD }, - { 0x0ED0, 0x0ED9 }, - { 0x0EDC, 0x0EDD }, - { 0x0F00, 0x0F00 }, - { 0x0F18, 0x0F19 }, - { 0x0F20, 0x0F33 }, - { 0x0F35, 0x0F35 }, - { 0x0F37, 0x0F37 }, - { 0x0F39, 0x0F39 }, - { 0x0F3E, 0x0F47 }, - { 0x0F49, 0x0F69 }, - { 0x0F71, 0x0F84 }, - { 0x0F86, 0x0F8B }, - { 0x0F90, 0x0F95 }, - { 0x0F97, 0x0F97 }, - { 0x0F99, 0x0FAD }, - { 0x0FB1, 0x0FB7 }, - { 0x0FB9, 0x0FB9 }, - { 0x10A0, 0x10C5 }, - { 0x10D0, 0x10F6 }, - { 0x1E00, 0x1E9B }, - { 0x1EA0, 0x1EF9 }, - { 0x1F00, 0x1F15 }, - { 0x1F18, 0x1F1D }, - { 0x1F20, 0x1F45 }, - { 0x1F48, 0x1F4D }, - { 0x1F50, 0x1F57 }, - { 0x1F59, 0x1F59 }, - { 0x1F5B, 0x1F5B }, - { 0x1F5D, 0x1F5D }, - { 0x1F5F, 0x1F7D }, - { 0x1F80, 0x1FB4 }, - { 0x1FB6, 0x1FBC }, - { 0x1FBE, 0x1FBE }, - { 0x1FC2, 0x1FC4 }, - { 0x1FC6, 0x1FCC }, - { 0x1FD0, 0x1FD3 }, - { 0x1FD6, 0x1FDB }, - { 0x1FE0, 0x1FEC }, - { 0x1FF2, 0x1FF4 }, - { 0x1FF6, 0x1FFC }, - { 0x203F, 0x2040 }, - { 0x207F, 0x207F }, - { 0x2102, 0x2102 }, - { 0x2107, 0x2107 }, - { 0x210A, 0x2113 }, - { 0x2115, 0x2115 }, - { 0x2118, 0x211D }, - { 0x2124, 0x2124 }, - { 0x2126, 0x2126 }, - { 0x2128, 0x2128 }, - { 0x212A, 0x2131 }, - { 0x2133, 0x2138 }, - { 0x2160, 0x2182 }, - { 0x3005, 0x3007 }, - { 0x3021, 0x3029 }, - { 0x3041, 0x3093 }, - { 0x309B, 0x309C }, - { 0x30A1, 0x30F6 }, - { 0x30FB, 0x30FC }, - { 0x3105, 0x312C }, - { 0x4E00, 0x9FA5 }, - { 0xAC00, 0xD7A3 }, - }; - -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - //printf("%x\n", table[i][0]); - assert(table[i][0] <= table[i][1]); - if (i < sizeof(table) / sizeof(table[0]) - 1) - assert(table[i][1] < table[i + 1][0]); - } -#endif - - if (u > 0xD7A3) - goto Lisnot; - - // Binary search - int mid; - int low; - int high; - - low = 0; - high = sizeof(table) / sizeof(table[0]) - 1; - while (low <= high) - { - mid = (low + high) >> 1; - if (u < table[mid][0]) - high = mid - 1; - else if (u > table[mid][1]) - low = mid + 1; - else - goto Lis; - } - -Lisnot: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - assert(u < table[i][0] || u > table[i][1]); - } -#endif - return 0; - -Lis: -#ifdef DEBUG - for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) - { - if (u >= table[i][0] && u <= table[i][1]) - return 1; - } - assert(0); // should have been in table -#endif - return 1; -} - diff --git a/dmd2/unittests.c b/dmd2/unittests.c index 1b3c2770..3cadebe5 100644 --- a/dmd2/unittests.c +++ b/dmd2/unittests.c @@ -1,4 +1,12 @@ +// Copyright (c) 2010-2012 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 "mars.h" diff --git a/dmd2/utf.c b/dmd2/utf.c index 78f8cd4a..c74f0770 100644 --- a/dmd2/utf.c +++ b/dmd2/utf.c @@ -1,5 +1,5 @@ // utf.c -// Copyright (c) 2003-2009 by Digital Mars +// Copyright (c) 2003-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -7,22 +7,32 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. -// Description of UTF-8 at: -// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 +/// Description of UTF-8 in [1]. Unicode non-characters and private-use +/// code points described in [2],[4]. +/// +/// References: +/// [1] http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 +/// [2] http://en.wikipedia.org/wiki/Unicode +/// [3] http://unicode.org/faq/utf_bom.html +/// [4] http://www.unicode.org/versions/Unicode6.1.0/ch03.pdf -#include -#include #include #include "utf.h" -int utf_isValidDchar(dchar_t c) +namespace { - return c < 0xD800 || - (c > 0xDFFF && c <= 0x10FFFF && c != 0xFFFE && c != 0xFFFF); -} -static const unsigned char UTF8stride[256] = +/* The following encodings are valid, except for the 5 and 6 byte + * combinations: + * 0xxxxxxx + * 110xxxxx 10xxxxxx + * 1110xxxx 10xxxxxx 10xxxxxx + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + */ +const unsigned UTF8_STRIDE[256] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -42,237 +52,73 @@ static const unsigned char UTF8stride[256] = 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF, }; -/** - * stride() returns the length of a UTF-8 sequence starting at index i - * in string s. - * Returns: - * The number of bytes in the UTF-8 sequence or - * 0xFF meaning s[i] is not the start of of UTF-8 sequence. - */ +} // namespace -unsigned stride(unsigned char* s, size_t i) +namespace Unicode { - unsigned result = UTF8stride[s[i]]; - return result; + +// 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"; +char const UTF8_DECODE_OVERLONG[] = "Overlong UTF-8 sequence"; +char const UTF8_DECODE_INVALID_TRAILER[] = "Invalid trailing code unit"; +char const UTF8_DECODE_INVALID_CODE_POINT[] = "Invalid code point decoded"; + +// UTF-16 decoding errors +char const UTF16_DECODE_TRUNCATED_SEQUENCE[]= "Truncated UTF-16 sequence"; +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). +bool utf_isValidDchar(dchar_t c) +{ + // TODO: Whether non-char code points should be rejected is pending review + return c <= 0x10FFFF // largest character code point + && !(0xD800 <= c && c <= 0xDFFF) // surrogate pairs + && (c & 0xFFFFFE) != 0x00FFFE // non-characters +// && (c & 0xFFFE) != 0xFFFE // non-characters +// && !(0x00FDD0 <= c && c <= 0x00FDEF) // non-characters + ; } -/******************************************** - * Decode a single UTF-8 character sequence. - * Returns: - * NULL success - * !=NULL error message string +/******************************* + * Return !=0 if unicode alpha. + * Use table from C99 Appendix D. */ -const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult) +bool isUniAlpha(dchar_t c) { - dchar_t V; - size_t i = *pidx; - unsigned char u = s[i]; - - //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); - - assert(i >= 0 && i < len); - - if (u & 0x80) - { unsigned n; - unsigned char u2; - - /* The following encodings are valid, except for the 5 and 6 byte - * combinations: - * 0xxxxxxx - * 110xxxxx 10xxxxxx - * 1110xxxx 10xxxxxx 10xxxxxx - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - */ - for (n = 1; ; n++) - { - if (n > 4) - goto Lerr; // only do the first 4 of 6 encodings - if (((u << n) & 0x80) == 0) - { - if (n == 1) - goto Lerr; - break; - } - } - - // Pick off (7 - n) significant bits of B from first byte of octet - V = (dchar_t)(u & ((1 << (7 - n)) - 1)); - - if (i + (n - 1) >= len) - goto Lerr; // off end of string - - /* The following combinations are overlong, and illegal: - * 1100000x (10xxxxxx) - * 11100000 100xxxxx (10xxxxxx) - * 11110000 1000xxxx (10xxxxxx 10xxxxxx) - * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) - * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) - */ - u2 = s[i + 1]; - if ((u & 0xFE) == 0xC0 || - (u == 0xE0 && (u2 & 0xE0) == 0x80) || - (u == 0xF0 && (u2 & 0xF0) == 0x80) || - (u == 0xF8 && (u2 & 0xF8) == 0x80) || - (u == 0xFC && (u2 & 0xFC) == 0x80)) - goto Lerr; // overlong combination - - for (unsigned j = 1; j != n; j++) - { - u = s[i + j]; - if ((u & 0xC0) != 0x80) - goto Lerr; // trailing bytes are 10xxxxxx - V = (V << 6) | (u & 0x3F); - } - if (!utf_isValidDchar(V)) - goto Lerr; - i += n; - } - else + static size_t const END = sizeof(ALPHA_TABLE) / sizeof(ALPHA_TABLE[0]); + size_t high = END - 1; + // Shortcut search if c is out of range + size_t low + = (c < ALPHA_TABLE[0][0] || ALPHA_TABLE[high][1] < c) ? high + 1 : 0; + // Binary search + while (low <= high) { - V = (dchar_t) u; - i++; - } - - assert(utf_isValidDchar(V)); - *pidx = i; - *presult = V; - return NULL; - - Lerr: - *presult = (dchar_t) s[i]; - *pidx = i + 1; - return "invalid UTF-8 sequence"; -} - -/*************************************************** - * Validate a UTF-8 string. - * Returns: - * NULL success - * !=NULL error message string - */ - -const char *utf_validateString(unsigned char *s, size_t len) -{ - size_t idx; - const char *err = NULL; - dchar_t dc; - - for (idx = 0; idx < len; ) - { - err = utf_decodeChar(s, len, &idx, &dc); - if (err) - break; - } - return err; -} - - -/******************************************** - * Decode a single UTF-16 character sequence. - * Returns: - * NULL success - * !=NULL error message string - */ - - -const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult) -{ - const char *msg; - size_t i = *pidx; - unsigned u = s[i]; - - assert(i >= 0 && i < len); - if (u & ~0x7F) - { if (u >= 0xD800 && u <= 0xDBFF) - { unsigned u2; - - if (i + 1 == len) - { msg = "surrogate UTF-16 high value past end of string"; - goto Lerr; - } - u2 = s[i + 1]; - if (u2 < 0xDC00 || u2 > 0xDFFF) - { msg = "surrogate UTF-16 low value out of range"; - goto Lerr; - } - u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); - i += 2; - } - else if (u >= 0xDC00 && u <= 0xDFFF) - { msg = "unpaired surrogate UTF-16 value"; - goto Lerr; - } - else if (u == 0xFFFE || u == 0xFFFF) - { msg = "illegal UTF-16 value"; - goto Lerr; - } + size_t mid = (low + high) >> 1; + if (c < ALPHA_TABLE[mid][0]) + high = mid - 1; + else if (ALPHA_TABLE[mid][1] < c) + low = mid + 1; else - i++; + { + assert(ALPHA_TABLE[mid][0] <= c && c <= ALPHA_TABLE[mid][1]); + return true; + } } - else - { - i++; - } - - assert(utf_isValidDchar(u)); - *pidx = i; - *presult = (dchar_t)u; - return NULL; - - Lerr: - *presult = (dchar_t)s[i]; - *pidx = i + 1; - return msg; + return false; } -void utf_encodeChar(unsigned char *s, dchar_t c) -{ - if (c <= 0x7F) - { - s[0] = (char) c; - } - else if (c <= 0x7FF) - { - s[0] = (char)(0xC0 | (c >> 6)); - s[1] = (char)(0x80 | (c & 0x3F)); - } - else if (c <= 0xFFFF) - { - s[0] = (char)(0xE0 | (c >> 12)); - s[1] = (char)(0x80 | ((c >> 6) & 0x3F)); - s[2] = (char)(0x80 | (c & 0x3F)); - } - else if (c <= 0x10FFFF) - { - s[0] = (char)(0xF0 | (c >> 18)); - s[1] = (char)(0x80 | ((c >> 12) & 0x3F)); - s[2] = (char)(0x80 | ((c >> 6) & 0x3F)); - s[3] = (char)(0x80 | (c & 0x3F)); - } - else - assert(0); -} - -void utf_encodeWchar(unsigned short *s, dchar_t c) -{ - if (c <= 0xFFFF) - { - s[0] = (wchar_t) c; - } - else - { - s[0] = (wchar_t) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - s[1] = (wchar_t) (((c - 0x10000) & 0x3FF) + 0xDC00); - } -} - - /** - * Returns the code length of c in the encoding. - * The code is returned in character count, not in bytes. + * Returns the code length of c in code units. */ int utf_codeLengthChar(dchar_t c) @@ -291,10 +137,10 @@ int utf_codeLengthWchar(dchar_t c) } /** - * Returns the code length of c in the encoding. + * Returns the code length of c in code units for the encoding. * sz is the encoding: 1 = utf8, 2 = utf16, 4 = utf32. - * The code is returned in character count, not in bytes. */ + int utf_codeLength(int sz, dchar_t c) { if (sz == 1) @@ -305,16 +151,161 @@ int utf_codeLength(int sz, dchar_t c) return 1; } -void utf_encode(int sz, void *s, dchar_t c) +void utf_encodeChar(utf8_t *s, dchar_t c) { - if (sz == 1) - utf_encodeChar((unsigned char *)s, c); - else if (sz == 2) - utf_encodeWchar((unsigned short *)s, c); + assert(s != NULL); + assert(utf_isValidDchar(c)); + if (c <= 0x7F) + { + s[0] = static_cast(c); + } + else if (c <= 0x07FF) + { + s[0] = static_cast(0xC0 | (c >> 6)); + s[1] = static_cast(0x80 | (c & 0x3F)); + } + else if (c <= 0xFFFF) + { + s[0] = static_cast(0xE0 | (c >> 12)); + s[1] = static_cast(0x80 | ((c >> 6) & 0x3F)); + s[2] = static_cast(0x80 | (c & 0x3F)); + } + else if (c <= 0x10FFFF) + { + s[0] = static_cast(0xF0 | (c >> 18)); + s[1] = static_cast(0x80 | ((c >> 12) & 0x3F)); + s[2] = static_cast(0x80 | ((c >> 6) & 0x3F)); + s[3] = static_cast(0x80 | (c & 0x3F)); + } + else + assert(0); +} + +void utf_encodeWchar(utf16_t *s, dchar_t c) +{ + assert(s != NULL); + assert(utf_isValidDchar(c)); + if (c <= 0xFFFF) + { + s[0] = static_cast(c); + } else { - assert(sz == 4); - memcpy((unsigned char *)s, &c, sz); + s[0] = static_cast((((c - 0x010000) >> 10) & 0x03FF) + 0xD800); + s[1] = static_cast(((c - 0x010000) & 0x03FF) + 0xDC00); } } +void utf_encode(int sz, void *s, dchar_t c) +{ + if (sz == 1) + utf_encodeChar((utf8_t *)s, c); + else if (sz == 2) + utf_encodeWchar((utf16_t *)s, c); + else + { + assert(sz == 4); + *((utf32_t *)s) = c; + } +} + +/******************************************** + * Decode a UTF-8 sequence as a single UTF-32 code point. + * Returns: + * NULL success + * !=NULL error message string + */ + +const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult) +{ + assert(s != NULL); + assert(pidx != NULL); + assert(presult != NULL); + size_t i = (*pidx)++; + assert(i < len); + utf8_t u = s[i]; + // Pre-stage results for ASCII and error cases + *presult = u; + + //printf("utf_decodeChar(s = %02x, %02x, %02x len = %d)\n", u, s[1], s[2], len); + + // Get expected sequence length + unsigned n = UTF8_STRIDE[u]; + switch (n) + { + case 1: // ASCII + return UTF8_DECODE_OK; + case 2: case 3: case 4: // multi-byte UTF-8 + break; + default: // 5- or 6-byte sequence + return UTF8_DECODE_OUTSIDE_CODE_SPACE; + } + if (len < i + n) // source too short + return UTF8_DECODE_TRUNCATED_SEQUENCE; + + // Pick off 7 - n low bits from first code unit + utf32_t c = u & ((1 << (7 - n)) - 1); + /* The following combinations are overlong, and illegal: + * 1100000x (10xxxxxx) + * 11100000 100xxxxx (10xxxxxx) + * 11110000 1000xxxx (10xxxxxx 10xxxxxx) + * 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) + * 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) + */ + utf8_t u2 = s[++i]; + if ((u & 0xFE) == 0xC0 || // overlong combination + (u == 0xE0 && (u2 & 0xE0) == 0x80) || + (u == 0xF0 && (u2 & 0xF0) == 0x80) || + (u == 0xF8 && (u2 & 0xF8) == 0x80) || + (u == 0xFC && (u2 & 0xFC) == 0x80)) + return UTF8_DECODE_OVERLONG; + // Decode remaining bits + for (n += i - 1; i != n; ++i) + { + u = s[i]; + if ((u & 0xC0) != 0x80) // trailing bytes are 10xxxxxx + return UTF8_DECODE_INVALID_TRAILER; + c = (c << 6) | (u & 0x3F); + } + if (!utf_isValidDchar(c)) + return UTF8_DECODE_INVALID_CODE_POINT; + *pidx = i; + *presult = c; + return UTF8_DECODE_OK; +} + +/******************************************** + * Decode a UTF-16 sequence as a single UTF-32 code point. + * Returns: + * NULL success + * !=NULL error message string + */ + +const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult) +{ + assert(s != NULL); + assert(pidx != NULL); + assert(presult != NULL); + size_t i = (*pidx)++; + assert(i < len); + // Pre-stage results for ASCII and error cases + utf32_t u = *presult = s[i]; + + if (u < 0x80) // ASCII + return UTF16_DECODE_OK; + if (0xD800 <= u && u <= 0xDBFF) // Surrogate pair + { if (len <= i + 1) + return UTF16_DECODE_TRUNCATED_SEQUENCE; + utf16_t u2 = s[i + 1]; + if (u2 < 0xDC00 || 0xDFFF < u) + return UTF16_DECODE_INVALID_SURROGATE; + u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00); + ++*pidx; + } + else if (0xDC00 <= u && u <= 0xDFFF) + return UTF16_DECODE_UNPAIRED_SURROGATE; + if (!utf_isValidDchar(u)) + return UTF16_DECODE_INVALID_CODE_POINT; + *presult = u; + return UTF16_DECODE_OK; +} diff --git a/dmd2/utf.h b/dmd2/utf.h index 22d8d3eb..e48ffaab 100644 --- a/dmd2/utf.h +++ b/dmd2/utf.h @@ -11,25 +11,114 @@ #ifndef DMD_UTF_H #define DMD_UTF_H +#include -typedef unsigned dchar_t; +/// A UTF-8 code unit +typedef unsigned char utf8_t; +/// A UTF-16 code unit +typedef unsigned short utf16_t; +/// A UTF-32 code unit +typedef unsigned int utf32_t; +typedef utf32_t dchar_t; -int utf_isValidDchar(dchar_t c); +namespace Unicode +{ -const char *utf_decodeChar(unsigned char *s, size_t len, size_t *pidx, dchar_t *presult); -const char *utf_decodeWchar(unsigned short *s, size_t len, size_t *pidx, dchar_t *presult); +static utf16_t const ALPHA_TABLE[][2] = +{ + { 0x00AA, 0x00AA }, { 0x00B5, 0x00B5 }, { 0x00B7, 0x00B7 }, { 0x00BA, 0x00BA }, + { 0x00C0, 0x00D6 }, { 0x00D8, 0x00F6 }, { 0x00F8, 0x01F5 }, { 0x01FA, 0x0217 }, + { 0x0250, 0x02A8 }, { 0x02B0, 0x02B8 }, { 0x02BB, 0x02BB }, { 0x02BD, 0x02C1 }, + { 0x02D0, 0x02D1 }, { 0x02E0, 0x02E4 }, { 0x037A, 0x037A }, { 0x0386, 0x0386 }, + { 0x0388, 0x038A }, { 0x038C, 0x038C }, { 0x038E, 0x03A1 }, { 0x03A3, 0x03CE }, + { 0x03D0, 0x03D6 }, { 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE }, + { 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C }, { 0x040E, 0x044F }, + { 0x0451, 0x045C }, { 0x045E, 0x0481 }, { 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 }, + { 0x04CB, 0x04CC }, { 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 }, + { 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0587 }, { 0x05B0, 0x05B9 }, + { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05D0, 0x05EA }, + { 0x05F0, 0x05F2 }, { 0x0621, 0x063A }, { 0x0640, 0x0652 }, { 0x0660, 0x0669 }, + { 0x0670, 0x06B7 }, { 0x06BA, 0x06BE }, { 0x06C0, 0x06CE }, { 0x06D0, 0x06DC }, + { 0x06E5, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x06F0, 0x06F9 }, { 0x0901, 0x0903 }, + { 0x0905, 0x0939 }, { 0x093D, 0x094D }, { 0x0950, 0x0952 }, { 0x0958, 0x0963 }, + { 0x0966, 0x096F }, { 0x0981, 0x0983 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 }, + { 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 }, { 0x09B6, 0x09B9 }, + { 0x09BE, 0x09C4 }, { 0x09C7, 0x09C8 }, { 0x09CB, 0x09CD }, { 0x09DC, 0x09DD }, + { 0x09DF, 0x09E3 }, { 0x09E6, 0x09F1 }, { 0x0A02, 0x0A02 }, { 0x0A05, 0x0A0A }, + { 0x0A0F, 0x0A10 }, { 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 }, + { 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A3E, 0x0A42 }, { 0x0A47, 0x0A48 }, + { 0x0A4B, 0x0A4D }, { 0x0A59, 0x0A5C }, { 0x0A5E, 0x0A5E }, { 0x0A66, 0x0A6F }, + { 0x0A74, 0x0A74 }, { 0x0A81, 0x0A83 }, { 0x0A85, 0x0A8B }, { 0x0A8D, 0x0A8D }, + { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 }, { 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 }, + { 0x0AB5, 0x0AB9 }, { 0x0ABD, 0x0AC5 }, { 0x0AC7, 0x0AC9 }, { 0x0ACB, 0x0ACD }, + { 0x0AD0, 0x0AD0 }, { 0x0AE0, 0x0AE0 }, { 0x0AE6, 0x0AEF }, { 0x0B01, 0x0B03 }, + { 0x0B05, 0x0B0C }, { 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 }, + { 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B43 }, { 0x0B47, 0x0B48 }, + { 0x0B4B, 0x0B4D }, { 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B66, 0x0B6F }, + { 0x0B82, 0x0B83 }, { 0x0B85, 0x0B8A }, { 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 }, + { 0x0B99, 0x0B9A }, { 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 }, + { 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 }, { 0x0BBE, 0x0BC2 }, + { 0x0BC6, 0x0BC8 }, { 0x0BCA, 0x0BCD }, { 0x0BE7, 0x0BEF }, { 0x0C01, 0x0C03 }, + { 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 }, { 0x0C2A, 0x0C33 }, + { 0x0C35, 0x0C39 }, { 0x0C3E, 0x0C44 }, { 0x0C46, 0x0C48 }, { 0x0C4A, 0x0C4D }, + { 0x0C60, 0x0C61 }, { 0x0C66, 0x0C6F }, { 0x0C82, 0x0C83 }, { 0x0C85, 0x0C8C }, + { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 }, { 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 }, + { 0x0CBE, 0x0CC4 }, { 0x0CC6, 0x0CC8 }, { 0x0CCA, 0x0CCD }, { 0x0CDE, 0x0CDE }, + { 0x0CE0, 0x0CE1 }, { 0x0CE6, 0x0CEF }, { 0x0D02, 0x0D03 }, { 0x0D05, 0x0D0C }, + { 0x0D0E, 0x0D10 }, { 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D3E, 0x0D43 }, + { 0x0D46, 0x0D48 }, { 0x0D4A, 0x0D4D }, { 0x0D60, 0x0D61 }, { 0x0D66, 0x0D6F }, + { 0x0E01, 0x0E3A }, { 0x0E40, 0x0E5B }, /* { 0x0E50, 0x0E59 }, */ { 0x0E81, 0x0E82 }, + { 0x0E84, 0x0E84 }, { 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D }, + { 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 }, { 0x0EA5, 0x0EA5 }, + { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB }, { 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB9 }, + { 0x0EBB, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0EC6, 0x0EC6 }, { 0x0EC8, 0x0ECD }, + { 0x0ED0, 0x0ED9 }, { 0x0EDC, 0x0EDD }, { 0x0F00, 0x0F00 }, { 0x0F18, 0x0F19 }, + { 0x0F20, 0x0F33 }, { 0x0F35, 0x0F35 }, { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, + { 0x0F3E, 0x0F47 }, { 0x0F49, 0x0F69 }, { 0x0F71, 0x0F84 }, { 0x0F86, 0x0F8B }, + { 0x0F90, 0x0F95 }, { 0x0F97, 0x0F97 }, { 0x0F99, 0x0FAD }, { 0x0FB1, 0x0FB7 }, + { 0x0FB9, 0x0FB9 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 }, { 0x1E00, 0x1E9B }, + { 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D }, { 0x1F20, 0x1F45 }, + { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 }, { 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B }, + { 0x1F5D, 0x1F5D }, { 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC }, + { 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC }, { 0x1FD0, 0x1FD3 }, + { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC }, { 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC }, + { 0x203F, 0x2040 }, { 0x207F, 0x207F }, { 0x2102, 0x2102 }, { 0x2107, 0x2107 }, + { 0x210A, 0x2113 }, { 0x2115, 0x2115 }, { 0x2118, 0x211D }, { 0x2124, 0x2124 }, + { 0x2126, 0x2126 }, { 0x2128, 0x2128 }, { 0x212A, 0x2131 }, { 0x2133, 0x2138 }, + { 0x2160, 0x2182 }, { 0x3005, 0x3007 }, { 0x3021, 0x3029 }, { 0x3041, 0x3093 }, + { 0x309B, 0x309C }, { 0x30A1, 0x30F6 }, { 0x30FB, 0x30FC }, { 0x3105, 0x312C }, + { 0x4E00, 0x9FA5 }, { 0xAC00, 0xD7A3 }, +}; -const char *utf_validateString(unsigned char *s, size_t len); +char const *const UTF8_DECODE_OK = NULL; +extern char const UTF8_DECODE_OUTSIDE_CODE_SPACE[]; +extern char const UTF8_DECODE_TRUNCATED_SEQUENCE[]; +extern char const UTF8_DECODE_OVERLONG[]; +extern char const UTF8_DECODE_INVALID_TRAILER[]; +extern char const UTF8_DECODE_INVALID_CODE_POINT[]; -extern int isUniAlpha(dchar_t); +char const *const UTF16_DECODE_OK = NULL; +extern char const UTF16_DECODE_TRUNCATED_SEQUENCE[]; +extern char const UTF16_DECODE_INVALID_SURROGATE[]; +extern char const UTF16_DECODE_UNPAIRED_SURROGATE[]; +extern char const UTF16_DECODE_INVALID_CODE_POINT[]; -void utf_encodeChar(unsigned char *s, dchar_t c); -void utf_encodeWchar(unsigned short *s, dchar_t c); +} // namespace Unicode + +/// \return true if \a c is a valid, non-private UTF-32 code point +bool utf_isValidDchar(dchar_t c); + +bool isUniAlpha(dchar_t c); int utf_codeLengthChar(dchar_t c); int utf_codeLengthWchar(dchar_t c); - int utf_codeLength(int sz, dchar_t c); + +void utf_encodeChar(utf8_t *s, dchar_t c); +void utf_encodeWchar(utf16_t *s, dchar_t c); void utf_encode(int sz, void *s, dchar_t c); -#endif +const char *utf_decodeChar(utf8_t const *s, size_t len, size_t *pidx, dchar_t *presult); +const char *utf_decodeWchar(utf16_t const *s, size_t len, size_t *pidx, dchar_t *presult); + +#endif // DMD_UTF_H diff --git a/driver/main.cpp b/driver/main.cpp index e570907a..13f4ee68 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -23,6 +23,11 @@ #include "rmem.h" #include "root.h" +// stricmp +#if __GNUC__ && !_WIN32 +#include "gnuc.h" +#endif + #include "mars.h" #include "module.h" #include "mtype.h" @@ -834,10 +839,7 @@ int main(int argc, char** argv) #endif if (stricmp(ext, global.mars_ext) == 0 || - stricmp(ext, global.hdr_ext) == 0 || - stricmp(ext, "htm") == 0 || - stricmp(ext, "html") == 0 || - stricmp(ext, "xhtml") == 0) + stricmp(ext, global.hdr_ext) == 0) { ext--; // skip onto '.' assert(*ext == '.'); diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 3c36a1f8..63d55c54 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -384,5 +384,5 @@ if(PHOBOS2_DIR) install(DIRECTORY ${PHOBOS2_DIR}/etc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.d") install(FILES ${PHOBOS2_DIR}/crc32.d DESTINATION ${INCLUDE_INSTALL_DIR}) endif(PHOBOS2_DIR) -install(FILES ${RUNTIME_DIR}/import/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) +install(FILES ${RUNTIME_DIR}/src/object.di DESTINATION ${INCLUDE_INSTALL_DIR}/ldc) install(DIRECTORY ${RUNTIME_DIR}/import/ldc DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.di") diff --git a/runtime/druntime b/runtime/druntime index 6ac9475a..a1cb86b9 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 6ac9475aa22924887d5010f41a4dc577836fbbdf +Subproject commit a1cb86b9e1e91eae50494e6904e47d11aa869540 diff --git a/runtime/phobos b/runtime/phobos index 52b15ed3..e05ad809 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 52b15ed3c0abf1d8af58bc5371c90636e01c1073 +Subproject commit e05ad809add2722d4f6492d1a4f43dd26091bdb9