Mercurial > projects > ldc
diff dmd2/mtype.c @ 1452:638d16625da2
LDC 2 compiles again.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Sat, 30 May 2009 17:23:32 +0100 |
parents | 442ab244c455 |
children | a5526b7a5ae6 |
line wrap: on
line diff
--- a/dmd2/mtype.c Thu May 28 00:07:21 2009 +0200 +++ b/dmd2/mtype.c Sat May 30 17:23:32 2009 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars +// Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -8,8 +8,13 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +#define __C99FEATURES__ 1 // Needed on Solaris for NaN and more #define __USE_ISOC99 1 // so signbit() gets defined +#if (defined (__SVR4) && defined (__sun)) +#include <alloca.h> +#endif + #ifdef __DMC__ #include <math.h> #else @@ -20,10 +25,6 @@ #include <assert.h> #include <float.h> -#ifdef __DMC__ -#include <fp.h> -#endif - #if _MSC_VER #include <malloc.h> #include <complex> @@ -32,19 +33,10 @@ #include <complex.h> #elif __MINGW32__ #include <malloc.h> -#else -//#define signbit 56 #endif -#if __GNUC__ -#if !(defined (__SVR4) && defined (__sun)) -#include <bits/nan.h> -#include <bits/mathdef.h> -#endif -#endif -static double zero = 0; - -#include "mem.h" +#include "rmem.h" +#include "port.h" #include "dsymbol.h" #include "mtype.h" @@ -60,7 +52,11 @@ #include "aggregate.h" #include "hdrgen.h" -#include "gen/tollvm.h" +#if IN_LLVM +//#include "gen/tollvm.h" +Ir* Type::sir = NULL; +unsigned GetTypeAlignment(Ir* ir, Type* t); +#endif FuncDeclaration *hasThis(Scope *sc); @@ -76,19 +72,34 @@ */ int PTRSIZE = 4; -#if IN_LLVM -int REALSIZE = 8; -int REALPAD = 0; -#elif TARGET_LINUX + +/* REALSIZE = size a real consumes in memory + * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE + * REALALIGNSIZE = alignment for reals + */ +#if TARGET_OSX +int REALSIZE = 16; +int REALPAD = 6; +int REALALIGNSIZE = 16; +#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS int REALSIZE = 12; int REALPAD = 2; +int REALALIGNSIZE = 4; #else int REALSIZE = 10; int REALPAD = 0; +int REALALIGNSIZE = 2; #endif + int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; +#if _WIN32 && !defined __MINGW32__ +static double zero = 0; +double Port::nan = NAN; +double Port::infinity = 1/zero; +#endif + /***************************** Type *****************************/ ClassDeclaration *Type::typeinfo; @@ -106,6 +117,7 @@ ClassDeclaration *Type::typeinfotypelist; ClassDeclaration *Type::typeinfoconst; ClassDeclaration *Type::typeinfoinvariant; +ClassDeclaration *Type::typeinfoshared; Type *Type::tvoidptr; Type *Type::basic[TMAX]; @@ -113,21 +125,34 @@ unsigned char Type::sizeTy[TMAX]; StringTable Type::stringtable; - -Type::Type(TY ty) +#if IN_LLVM +StringTable Type::deco_stringtable; +#endif + + +Type::Type(TY ty/*, Type *next*/) { this->ty = ty; this->mod = 0; + //this->next = next; this->deco = NULL; #if DMDV2 this->cto = NULL; this->ito = NULL; + this->sto = NULL; + this->scto = NULL; #endif this->pto = NULL; this->rto = NULL; this->arrayof = NULL; this->vtinfo = NULL; +#if IN_DMD this->ctype = NULL; +#endif + +#if IN_LLVM + this->irtype = NULL; +#endif } Type *Type::syntaxCopy() @@ -159,7 +184,11 @@ return 'M'; // name mangling prefix for functions needing 'this' } +#if IN_LLVM +void Type::init(Ir* _sir) +#else void Type::init() +#endif { int i; int j; @@ -256,6 +285,9 @@ tvoidptr = tvoid->pointerTo(); + // LDC + sir = _sir; + // set size_t / ptrdiff_t types and pointer size if (global.params.is64bit) { @@ -265,6 +297,17 @@ } else { + PTRSIZE = 4; +#if TARGET_OSX + REALSIZE = 16; + REALPAD = 6; +#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS + REALSIZE = 12; + REALPAD = 2; +#else + REALSIZE = 10; + REALPAD = 0; +#endif Tsize_t = Tuns32; Tptrdiff_t = Tint32; PTRSIZE = 4; @@ -309,6 +352,20 @@ return merge(); } +Type *Type::trySemantic(Loc loc, Scope *sc) +{ + unsigned errors = global.errors; + global.gag++; // suppress printing of error messages + Type *t = semantic(loc, sc); + global.gag--; + if (errors != global.errors) // if any errors happened + { + global.errors = errors; + t = NULL; + } + return t; +} + /******************************* * Determine if converting 'this' to 'to' is an identity operation, * a conversion to const operation, or the types aren't the same. @@ -327,8 +384,13 @@ return MATCHnomatch; } +/******************************** + * Convert to 'const'. + */ + Type *Type::constOf() { +#if 0 //printf("Type::constOf() %p %s\n", this, toChars()); if (isConst()) return this; @@ -342,10 +404,29 @@ //if (t->nextOf()) assert(t->nextOf()->isConst()); //printf("-Type::constOf() %p %s\n", t, toChars()); return t; -} +#else + //printf("Type::constOf() %p %s\n", this, toChars()); + if (mod == MODconst) + return this; + if (cto) + { assert(cto->mod == MODconst); + return cto; + } + Type *t = makeConst(); + t = t->merge(); + t->fixTo(this); + //printf("-Type::constOf() %p %s\n", t, toChars()); + return t; +#endif +} + +/******************************** + * Convert to 'immutable'. + */ Type *Type::invariantOf() { +#if 0 //printf("Type::invariantOf() %p %s\n", this, toChars()); if (isInvariant()) { @@ -370,10 +451,32 @@ #endif //printf("\t%p\n", t); return t; -} +#else + //printf("Type::invariantOf() %p %s\n", this, toChars()); + if (isInvariant()) + { + return this; + } + if (ito) + { + assert(ito->isInvariant()); + return ito; + } + Type *t = makeInvariant(); + t = t->merge(); + t->fixTo(this); + //printf("\t%p\n", t); + return t; +#endif +} + +/******************************** + * Make type mutable. + */ Type *Type::mutableOf() { +#if 0 //printf("Type::mutableOf() %p, %s\n", this, toChars()); Type *t = this; if (isConst()) @@ -396,6 +499,8 @@ t->rto = NULL; t->cto = NULL; t->ito = NULL; + t->sto = NULL; + t->scto = NULL; t->vtinfo = NULL; if (ty == Tsarray) { TypeSArray *ta = (TypeSArray *)t; @@ -416,6 +521,307 @@ } } return t; +#else + //printf("Type::mutableOf() %p, %s\n", this, toChars()); + Type *t = this; + if (isConst()) + { if (isShared()) + t = sto; // shared const => shared + else + t = cto; + assert(!t || t->isMutable()); + } + else if (isInvariant()) + { t = ito; + assert(!t || (t->isMutable() && !t->isShared())); + } + if (!t) + { + unsigned sz = sizeTy[ty]; + t = (Type *)mem.malloc(sz); + memcpy(t, this, sz); + t->mod = 0; + t->deco = NULL; + t->arrayof = NULL; + t->pto = NULL; + t->rto = NULL; + t->cto = NULL; + t->ito = NULL; + t->sto = NULL; + t->scto = NULL; + t->vtinfo = NULL; + t = t->merge(); + + t->fixTo(this); + + switch (mod) + { + case MODconst: + t->cto = this; + break; + + case MODinvariant: + t->ito = this; + break; + + case MODshared: + t->sto = this; + break; + + case MODshared | MODconst: + t->scto = this; + break; + + default: + assert(0); + } + } + return t; +#endif +} + +Type *Type::sharedOf() +{ + //printf("Type::sharedOf() %p, %s\n", this, toChars()); + if (mod == MODshared) + { + return this; + } + if (sto) + { + assert(sto->isShared()); + return sto; + } + Type *t = makeShared(); + t = t->merge(); + t->fixTo(this); + //printf("\t%p\n", t); + return t; +} + +Type *Type::sharedConstOf() +{ + //printf("Type::sharedConstOf() %p, %s\n", this, toChars()); + if (mod == (MODshared | MODconst)) + { + return this; + } + if (scto) + { + assert(scto->mod == (MODshared | MODconst)); + return scto; + } + Type *t = makeSharedConst(); + t = t->merge(); + t->fixTo(this); + //printf("\t%p\n", t); + return t; +} + + +/********************************** + * For our new type 'this', which is type-constructed from t, + * fill in the cto, ito, sto, scto shortcuts. + */ + +void Type::fixTo(Type *t) +{ + ito = t->ito; +#if 0 + /* Cannot do these because these are not fully transitive: + * there can be a shared ptr to immutable, for example. + * Immutable subtypes are always immutable, though. + */ + cto = t->cto; + sto = t->sto; + scto = t->scto; +#endif + + assert(mod != t->mod); +#define X(m, n) (((m) << 3) | (n)) + switch (X(mod, t->mod)) + { + case X(0, MODconst): + cto = t; + break; + + case X(0, MODinvariant): + ito = t; + break; + + case X(0, MODshared): + sto = t; + break; + + case X(0, MODshared | MODconst): + scto = t; + break; + + + case X(MODconst, 0): + cto = NULL; + goto L2; + + case X(MODconst, MODinvariant): + ito = t; + goto L2; + + case X(MODconst, MODshared): + sto = t; + goto L2; + + case X(MODconst, MODshared | MODconst): + scto = t; + L2: + t->cto = this; + break; + + + case X(MODinvariant, 0): + ito = NULL; + goto L3; + + case X(MODinvariant, MODconst): + cto = t; + goto L3; + + case X(MODinvariant, MODshared): + sto = t; + goto L3; + + case X(MODinvariant, MODshared | MODconst): + scto = t; + L3: + t->ito = this; + if (t->cto) t->cto->ito = this; + if (t->sto) t->sto->ito = this; + if (t->scto) t->scto->ito = this; + break; + + + case X(MODshared, 0): + sto = NULL; + goto L4; + + case X(MODshared, MODconst): + cto = t; + goto L4; + + case X(MODshared, MODinvariant): + ito = t; + goto L4; + + case X(MODshared, MODshared | MODconst): + scto = t; + L4: + t->sto = this; + break; + + + case X(MODshared | MODconst, 0): + scto = NULL; + break; + + case X(MODshared | MODconst, MODconst): + cto = t; + break; + + case X(MODshared | MODconst, MODinvariant): + ito = t; + break; + + case X(MODshared | MODconst, MODshared): + sto = t; + L5: + t->scto = this; + break; + + default: + assert(0); + } +#undef X + + check(); + t->check(); + //printf("fixTo: %s, %s\n", toChars(), t->toChars()); +} + +/*************************** + * Look for bugs in constructing types. + */ + +void Type::check() +{ + switch (mod) + { + case 0: + if (cto) assert(cto->mod == MODconst); + if (ito) assert(ito->mod == MODinvariant); + if (sto) assert(sto->mod == MODshared); + if (scto) assert(scto->mod == (MODshared | MODconst)); + break; + + case MODconst: + if (cto) assert(cto->mod == 0); + if (ito) assert(ito->mod == MODinvariant); + if (sto) assert(sto->mod == MODshared); + if (scto) assert(scto->mod == (MODshared | MODconst)); + break; + + case MODinvariant: + if (cto) assert(cto->mod == MODconst); + if (ito) assert(ito->mod == 0); + if (sto) assert(sto->mod == MODshared); + if (scto) assert(scto->mod == (MODshared | MODconst)); + break; + + case MODshared: + if (cto) assert(cto->mod == MODconst); + if (ito) assert(ito->mod == MODinvariant); + if (sto) assert(sto->mod == 0); + if (scto) assert(scto->mod == (MODshared | MODconst)); + break; + + case MODshared | MODconst: + if (cto) assert(cto->mod == MODconst); + if (ito) assert(ito->mod == MODinvariant); + if (sto) assert(sto->mod == MODshared); + if (scto) assert(scto->mod == 0); + break; + + default: + assert(0); + } + + Type *tn = nextOf(); + if (tn && ty != Tfunction && ty != Tdelegate) + { // Verify transitivity + switch (mod) + { + case 0: + break; + + case MODconst: + assert(tn->mod & MODinvariant || tn->mod & MODconst); + break; + + case MODinvariant: + assert(tn->mod == MODinvariant); + break; + + case MODshared: + assert(tn->mod & MODinvariant || tn->mod & MODshared); + break; + + case MODshared | MODconst: + assert(tn->mod & MODinvariant || tn->mod & (MODshared | MODconst)); + break; + + default: + assert(0); + } + tn->check(); + } } Type *Type::makeConst() @@ -433,6 +839,8 @@ t->rto = NULL; t->cto = NULL; t->ito = NULL; + t->sto = NULL; + t->scto = NULL; t->vtinfo = NULL; //printf("-Type::makeConst() %p, %s\n", t, toChars()); return t; @@ -452,10 +860,155 @@ t->rto = NULL; t->cto = NULL; t->ito = NULL; + t->sto = NULL; + t->scto = NULL; + t->vtinfo = NULL; + return t; +} + +Type *Type::makeShared() +{ + if (sto) + return sto; + unsigned sz = sizeTy[ty]; + Type *t = (Type *)mem.malloc(sz); + memcpy(t, this, sz); + t->mod = MODshared; + t->deco = NULL; + t->arrayof = NULL; + t->pto = NULL; + t->rto = NULL; + t->cto = NULL; + t->ito = NULL; + t->sto = NULL; + t->scto = NULL; + t->vtinfo = NULL; + return t; +} + +Type *Type::makeSharedConst() +{ + if (scto) + return scto; + unsigned sz = sizeTy[ty]; + Type *t = (Type *)mem.malloc(sz); + memcpy(t, this, sz); + t->mod = MODshared | MODconst; + t->deco = NULL; + t->arrayof = NULL; + t->pto = NULL; + t->rto = NULL; + t->cto = NULL; + t->ito = NULL; + t->sto = NULL; + t->scto = NULL; t->vtinfo = NULL; return t; } +/************************************ + * Apply MODxxxx bits to existing type. + */ + +Type *Type::castMod(unsigned mod) +{ Type *t; + + switch (mod) + { + case 0: + t = mutableOf(); + break; + + case MODconst: + t = constOf(); + break; + + case MODinvariant: + t = invariantOf(); + break; + + case MODshared: + t = sharedOf(); + break; + + case MODshared | MODconst: + t = sharedConstOf(); + break; + + default: + assert(0); + } + return t; +} + +/************************************ + * Add MODxxxx bits to existing type. + * We're adding, not replacing, so adding const to + * a shared type => "shared const" + */ + +Type *Type::addMod(unsigned mod) +{ Type *t = this; + + /* Add anything to immutable, and it remains immutable + */ + if (!t->isInvariant()) + { + switch (mod) + { + case 0: + break; + + case MODconst: + if (isShared()) + t = sharedConstOf(); + else + t = constOf(); + break; + + case MODinvariant: + t = invariantOf(); + break; + + case MODshared: + if (isConst()) + t = sharedConstOf(); + else + t = sharedOf(); + break; + + case MODshared | MODconst: + t = sharedConstOf(); + break; + + default: + assert(0); + } + } + return t; +} + +/************************************ + * Add storage class modifiers to type. + */ + +Type *Type::addStorageClass(unsigned stc) +{ + /* Just translate to MOD bits and let addMod() do the work + */ + unsigned mod = 0; + + if (stc & STCimmutable) + mod = MODinvariant; + else + { if (stc & (STCconst | STCin)) + mod = MODconst; + if (stc & STCshared) + mod |= MODshared; + } + return addMod(mod); +} + /************************** * Return type with the top level of it being mutable. */ @@ -520,7 +1073,7 @@ * flag 0x100 do not do const/invariant */ -void Type::toDecoBuffer(OutBuffer *buf, int flag) +void Type::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) // Possible conflict from merge { if (flag != mod && flag != 0x100) { @@ -574,7 +1127,7 @@ if (mod != this->mod) { const char *p; - if (mod & MODshared) + if (this->mod & MODshared) buf->writestring("shared("); switch (this->mod & (MODconst | MODinvariant)) { @@ -585,7 +1138,7 @@ p = "const("; goto L1; case MODinvariant: - p = "invariant("; + p = "immutable("; L1: buf->writestring(p); toCBuffer2(buf, hgs, this->mod); buf->writeByte(')'); @@ -593,7 +1146,7 @@ default: assert(0); } - if (mod & MODshared) + if (this->mod & MODshared) buf->writeByte(')'); } } @@ -614,7 +1167,7 @@ //if (next) //next = next->merge(); - toDecoBuffer(&buf); + toDecoBuffer(&buf, false); sv = stringtable.update((char *)buf.data, buf.offset); if (sv->ptrvalue) { t = (Type *) sv->ptrvalue; @@ -624,13 +1177,51 @@ else { sv->ptrvalue = this; - deco = sv->lstring.string; + + // we still need deco strings to be unique + // or Type::equals fails, which breaks a bunch of stuff, + // like covariant member function overloads. + OutBuffer mangle; + toDecoBuffer(&mangle, true); + StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset); + if (sv2->ptrvalue) + { Type* t2 = (Type *) sv2->ptrvalue; + assert(t2->deco); + deco = t2->deco; + } + else + { + sv2->ptrvalue = this; + deco = (char *)sv2->lstring.string; + } //printf("new value, deco = '%s' %p\n", t->deco, t->deco); } } return t; } +/************************************* + * This version does a merge even if the deco is already computed. + * Necessary for types that have a deco, but are not merged. + */ +Type *Type::merge2() +{ + //printf("merge2(%s)\n", toChars()); + Type *t = this; + assert(t); + if (!t->deco) + return t->merge(); + + StringValue *sv = deco_stringtable.lookup((char *)t->deco, strlen(t->deco)); + if (sv && sv->ptrvalue) + { t = (Type *) sv->ptrvalue; + assert(t->deco); + } + else + assert(0); + return t; +} + int Type::isintegral() { return FALSE; @@ -719,7 +1310,7 @@ return NULL; } -int Type::isZeroInit() +int Type::isZeroInit(Loc loc) { return 0; // assume not } @@ -759,7 +1350,7 @@ else if (ident == Id::size) { error(loc, ".size property should be replaced with .sizeof"); - e = new IntegerExp(loc, size(loc), Type::tsize_t); + e = new ErrorExp(); } else if (ident == Id::alignof) { @@ -778,9 +1369,14 @@ e = defaultInit(loc); } else if (ident == Id::mangleof) - { - assert(deco); - e = new StringExp(loc, deco, strlen(deco), 'c'); + { const char *s; + if (!deco) + { s = toChars(); + error(loc, "forward reference of type %s.mangleof", s); + } + else + s = deco; + e = new StringExp(loc, (char *)s, strlen(s), 'c'); Scope sc; e = e->semantic(&sc); } @@ -793,7 +1389,7 @@ else { error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars()); - e = new IntegerExp(loc, 1, Type::tint32); + e = new ErrorExp(); } return e; } @@ -896,6 +1492,17 @@ va_end( ap ); } +void Type::warning(Loc loc, const char *format, ...) +{ + if (global.params.warnings && !global.gag) + { + va_list ap; + va_start(ap, format); + ::vwarning(loc, format, ap); + va_end( ap ); + } +} + Identifier *Type::getTypeInfoIdent(int internal) { // _init_10TypeInfo_%s @@ -910,11 +1517,16 @@ buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]); } else - toDecoBuffer(&buf); + toDecoBuffer(&buf, true); len = buf.offset; name = (char *)alloca(19 + sizeof(len) * 3 + len + 1); buf.writeByte(0); +#if TARGET_OSX + // The LINKc will prepend the _ + sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data); +#else sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data); +#endif // LDC // it is not clear where the underscore that's stripped here is added back in // if (global.params.isWindows) @@ -987,12 +1599,12 @@ this->next = next; } -void TypeNext::toDecoBuffer(OutBuffer *buf, int flag) -{ - Type::toDecoBuffer(buf, flag); +void TypeNext::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) +{ + Type::toDecoBuffer(buf, flag, mangle); assert(next != this); //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty); - next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); + next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle); } void TypeNext::checkDeprecated(Loc loc, Scope *sc) @@ -1016,11 +1628,17 @@ { //printf("TypeNext::makeConst() %p, %s\n", this, toChars()); if (cto) + { assert(cto->mod == MODconst); return cto; + } TypeNext *t = (TypeNext *)Type::makeConst(); if (ty != Tfunction && ty != Tdelegate && next->deco && - !next->isInvariant()) - t->next = next->constOf(); + !next->isInvariant() && !next->isConst()) + { if (next->isShared()) + t->next = next->sharedConstOf(); + else + t->next = next->constOf(); + } //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars()); return t; } @@ -1033,12 +1651,50 @@ return ito; } TypeNext *t = (TypeNext *)Type::makeInvariant(); - if (ty != Tfunction && ty != Tdelegate && next->deco) + if (ty != Tfunction && ty != Tdelegate && next->deco && + !next->isInvariant()) { t->next = next->invariantOf(); } return t; } +Type *TypeNext::makeShared() +{ + //printf("TypeNext::makeShared() %s\n", toChars()); + if (sto) + { assert(sto->mod == MODshared); + return sto; + } + TypeNext *t = (TypeNext *)Type::makeShared(); + if (ty != Tfunction && ty != Tdelegate && next->deco && + !next->isInvariant() && !next->isShared()) + { + if (next->isConst()) + t->next = next->sharedConstOf(); + else + t->next = next->sharedOf(); + } + //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars()); + return t; +} + +Type *TypeNext::makeSharedConst() +{ + //printf("TypeNext::makeSharedConst() %s\n", toChars()); + if (scto) + { assert(scto->mod == (MODshared | MODconst)); + return scto; + } + TypeNext *t = (TypeNext *)Type::makeSharedConst(); + if (ty != Tfunction && ty != Tdelegate && next->deco && + !next->isInvariant() && !next->isSharedConst()) + { + t->next = next->sharedConstOf(); + } + //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars()); + return t; +} + MATCH TypeNext::constConv(Type *to) { MATCH m = Type::constConv(to); @@ -1049,6 +1705,13 @@ } +void TypeNext::transitive() +{ + /* Invoke transitivity of type attributes + */ + next = next->addMod(mod); +} + /* ============================= TypeBasic =========================== */ TypeBasic::TypeBasic(TY ty) @@ -1234,7 +1897,24 @@ { if (ty == Tvoid) return 1; - return getABITypeAlign(DtoType(this)); + return GetTypeAlignment(sir, this); +#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS + case Tint64: + case Tuns64: + case Tfloat64: + case Timaginary64: + case Tcomplex32: + case Tcomplex64: + sz = 4; + break; +#endif +#if IN_DMD + default: + sz = size(0); + break; + } + return sz; +#endif } @@ -1319,24 +1999,7 @@ case Tfloat64: case Tfloat80: { -#if IN_GCC - // mode doesn't matter, will be converted in RealExp anyway - fvalue = real_t::getnan(real_t::LongDouble); -#elif __GNUC__ - // gcc nan's have the sign bit set by default, so turn it off - // Need the volatile to prevent gcc from doing incorrect - // constant folding. - volatile d_float80 foo; - foo = NAN; - if (std::signbit(foo)) // signbit sometimes, not always, set - foo = -foo; // turn off sign bit - fvalue = foo; -#elif _MSC_VER - unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF }; - fvalue = *(double*)nan; -#else - fvalue = NAN; -#endif + fvalue = Port::nan; goto Lfvalue; } } @@ -1354,15 +2017,7 @@ case Tfloat32: case Tfloat64: case Tfloat80: -#if IN_GCC - fvalue = real_t::getinfinity(); -#elif __GNUC__ - fvalue = 1 / zero; -#elif _MSC_VER - fvalue = std::numeric_limits<long double>::infinity(); -#else - fvalue = INFINITY; -#endif + fvalue = Port::infinity; goto Lfvalue; } } @@ -1579,16 +2234,29 @@ } Expression *TypeBasic::defaultInit(Loc loc) -{ integer_t value = 0; +{ dinteger_t value = 0; + +#if SNAN_DEFAULT_INIT + /* + * Use a payload which is different from the machine NaN, + * so that uninitialised variables can be + * detected even if exceptions are disabled. + */ + unsigned short snan[8] = { 0, 0, 0, 0xA000, 0x7FFF }; + /* + * Although long doubles are 10 bytes long, some + * C ABIs pad them out to 12 or even 16 bytes, so + * leave enough space in the snan array. + */ + assert(REALSIZE <= sizeof(snan)); + d_float80 fvalue = *(long double*)snan; +#endif #if LOGDEFAULTINIT printf("TypeBasic::defaultInit() '%s'\n", toChars()); #endif switch (ty) { - case Tvoid: - return new IntegerExp(loc, value, Type::tbool); - case Tchar: value = 0xFF; break; @@ -1604,15 +2272,33 @@ case Tfloat32: case Tfloat64: case Tfloat80: +#if SNAN_DEFAULT_INIT + return new RealExp(loc, fvalue, this); +#else + return getProperty(loc, Id::nan); +#endif + case Tcomplex32: case Tcomplex64: case Tcomplex80: +#if SNAN_DEFAULT_INIT + { // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN). + complex_t cvalue; + ((real_t *)&cvalue)[0] = fvalue; + ((real_t *)&cvalue)[1] = fvalue; + return new ComplexExp(loc, cvalue, this); + } +#else return getProperty(loc, Id::nan); +#endif + + case Tvoid: + error(loc, "void does not have a default initializer"); } return new IntegerExp(loc, value, this); } -int TypeBasic::isZeroInit() +int TypeBasic::isZeroInit(Loc loc) { switch (ty) { @@ -1869,7 +2555,7 @@ if (ident == Id::idup) { Type *einv = next->invariantOf(); if (next->implicitConvTo(einv) < MATCHconst) - error(e->loc, "cannot implicitly convert element type %s to invariant", next->toChars()); + error(e->loc, "cannot implicitly convert element type %s to immutable", next->toChars()); e->type = einv->arrayOf(); } else @@ -1909,10 +2595,11 @@ e = new CastExp(e->loc, e, e->type); e->type = Type::tvoid->arrayOf(); } - arguments->push(e); - - arguments->push(n->getTypeInfo(sc)); // LDC, we don't support the getInternalTypeInfo - // optimization arbitrarily, not yet at least... + arguments->push(e); + + if (next->ty != Tbit) + arguments->push(n->getTypeInfo(sc)); // LDC, we don't support the getInternalTypeInfo + // optimization arbitrarily, not yet at least... e = new CallExp(e->loc, ec, arguments); e->type = next->arrayOf(); } @@ -1924,7 +2611,6 @@ } - /***************************** TypeSArray *****************************/ TypeSArray::TypeSArray(Type *t, Expression *dim) @@ -1944,13 +2630,13 @@ } d_uns64 TypeSArray::size(Loc loc) -{ integer_t sz; +{ dinteger_t sz; if (!dim) return Type::size(loc); sz = dim->toInteger(); - { integer_t n, n2; + { dinteger_t n, n2; n = next->size(); n2 = n * sz; @@ -1961,7 +2647,7 @@ return sz; Loverflow: - error(loc, "index %lld overflow for static array", sz); + error(loc, "index %jd overflow for static array", sz); return 1; } @@ -2028,7 +2714,7 @@ sc = sc->pop(); if (d >= td->objects->dim) - { error(loc, "tuple index %llu exceeds %u", d, td->objects->dim); + { error(loc, "tuple index %ju exceeds %u", d, td->objects->dim); goto Ldefault; } Object *o = (Object *)td->objects->data[(size_t)d]; @@ -2082,7 +2768,7 @@ uinteger_t d = dim->toUInteger(); if (d >= sd->objects->dim) - { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim); + { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); return Type::terror; } Object *o = (Object *)sd->objects->data[(size_t)d]; @@ -2095,15 +2781,12 @@ } next = next->semantic(loc,sc); - if (mod == MODconst && !next->isInvariant()) - next = next->constOf(); - else if (mod == MODinvariant) - next = next->invariantOf(); + transitive(); Type *tbn = next->toBasetype(); if (dim) - { integer_t n, n2; + { dinteger_t n, n2; dim = semanticLength(sc, tbn, dim); @@ -2116,10 +2799,10 @@ */ return this; } - integer_t d1 = dim->toInteger(); + dinteger_t d1 = dim->toInteger(); dim = dim->castTo(sc, tsize_t); dim = dim->optimize(WANTvalue); - integer_t d2 = dim->toInteger(); + dinteger_t d2 = dim->toInteger(); if (d1 != d2) goto Loverflow; @@ -2144,7 +2827,7 @@ if (n && n2 / n != d2) { Loverflow: - error(loc, "index %lld overflow for static array", d1); + error(loc, "index %jd overflow for static array", d1); dim = new IntegerExp(0, 1, tsize_t); } } @@ -2158,12 +2841,18 @@ uinteger_t d = dim->toUInteger(); if (d >= tt->arguments->dim) - { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim); + { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); return Type::terror; } Argument *arg = (Argument *)tt->arguments->data[(size_t)d]; return arg->type; } + case Tstruct: + { TypeStruct *ts = (TypeStruct *)tbn; + if (ts->sym->isnested) + error(loc, "cannot have array of inner structs %s", ts->toChars()); + break; + } case Tfunction: case Tnone: error(loc, "can't have array of %s", tbn->toChars()); @@ -2175,18 +2864,18 @@ return merge(); } -void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag) -{ - Type::toDecoBuffer(buf, flag); +void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) +{ + Type::toDecoBuffer(buf, flag, mangle); if (dim) - buf->printf("%llu", dim->toInteger()); + buf->printf("%ju", dim->toInteger()); if (next) /* Note that static arrays are value types, so * for a parameter, propagate the 0x100 to the next * level, since for T[4][3], any const should apply to the T, * not the [4]. */ - next->toDecoBuffer(buf, (flag & 0x100) ? flag : mod); + next->toDecoBuffer(buf, (flag & 0x100) ? flag : mod, mangle); } void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -2307,9 +2996,9 @@ return next->defaultInit(loc); } -int TypeSArray::isZeroInit() -{ - return next->isZeroInit(); +int TypeSArray::isZeroInit(Loc loc) +{ + return next->isZeroInit(loc); } @@ -2375,24 +3064,26 @@ error(loc, "can't have array of %s", tbn->toChars()); tn = next = tint32; break; + case Tstruct: + { TypeStruct *ts = (TypeStruct *)tbn; + if (ts->sym->isnested) + error(loc, "cannot have array of inner structs %s", ts->toChars()); + break; + } } if (tn->isauto()) error(loc, "cannot have array of auto %s", tn->toChars()); - if (mod == MODconst && !tn->isInvariant()) - tn = tn->constOf(); - else if (mod == MODinvariant) - tn = tn->invariantOf(); - next = tn; + transitive(); return merge(); } -void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag) -{ - Type::toDecoBuffer(buf, flag); +void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) +{ + Type::toDecoBuffer(buf, flag, mangle); if (next) - next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); + next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle); } void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -2511,7 +3202,7 @@ return e; } -int TypeDArray::isZeroInit() +int TypeDArray::isZeroInit(Loc loc) { return 1; } @@ -2585,6 +3276,16 @@ if (index->nextOf() && !index->nextOf()->isInvariant()) { index = index->constOf()->mutableOf(); +#if 0 +printf("index is %p %s\n", index, index->toChars()); +index->check(); +printf("index->mod = x%x\n", index->mod); +printf("index->ito = x%x\n", index->ito); +if (index->ito) { +printf("index->ito->mod = x%x\n", index->ito->mod); +printf("index->ito->ito = x%x\n", index->ito->ito); +} +#endif } switch (index->toBasetype()->ty) @@ -2597,10 +3298,7 @@ break; } next = next->semantic(loc,sc); - if (mod == MODconst && !next->isInvariant()) - next = next->constOf(); - else if (mod == MODinvariant) - next = next->invariantOf(); + transitive(); switch (next->toBasetype()->ty) { @@ -2666,7 +3364,7 @@ arguments = new Expressions(); arguments->push(e); e = new CallExp(e->loc, ec, arguments); - e->type = ((TypeFunction *)aaLen_fd->type)->next; + e->type = aaLen_fd->type->nextOf(); } else if (ident == Id::keys) { @@ -2733,7 +3431,7 @@ ec = new VarExp(0, aaRehash_fd); arguments = new Expressions(); arguments->push(e->addressOf(sc)); - arguments->push(index->getInternalTypeInfo(sc)); + arguments->push(index->getInternalTypeInfo(sc)); // LDC doesn't support getInternalTypeInfo, see above e = new CallExp(e->loc, ec, arguments); e->type = this; } @@ -2744,11 +3442,11 @@ return e; } -void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag) -{ - Type::toDecoBuffer(buf, flag); - index->toDecoBuffer(buf); - next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod); +void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) +{ + Type::toDecoBuffer(buf, flag, mangle); + index->toDecoBuffer(buf, mangle); + next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod, mangle); } void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) @@ -2774,7 +3472,7 @@ return e; } -int TypeAArray::isZeroInit() +int TypeAArray::isZeroInit(Loc loc) { return TRUE; } @@ -2865,10 +3563,7 @@ if (n != next) deco = NULL; next = n; - if (mod == MODconst && !next->isInvariant()) - next = next->constOf(); - else if (mod == MODinvariant) - next = next->invariantOf(); + transitive(); return merge(); } @@ -2943,7 +3638,7 @@ return e; } -int TypePointer::isZeroInit() +int TypePointer::isZeroInit(Loc loc) { return 1; } @@ -2981,10 +3676,7 @@ if (n != next) deco = NULL; next = n; - if (mod == MODconst && !next->isInvariant()) - next = next->constOf(); - else if (mod == MODinvariant) - next = next->invariantOf(); + transitive(); return merge(); } @@ -3024,7 +3716,7 @@ return e; } -int TypeReference::isZeroInit() +int TypeReference::isZeroInit(Loc loc) { return 1; } @@ -3046,8 +3738,9 @@ this->ispure = false; this->isref = false; - // LDC - this->fty = NULL; +#if IN_LLVM + this->funcdecl = NULL; +#endif } Type *TypeFunction::syntaxCopy() @@ -3077,6 +3770,7 @@ printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars()); printf("deco = %p, %p\n", deco, t->deco); // printf("ty = %d\n", next->ty); + printf("mod = %x, %x\n", mod, t->mod); #endif int inoutmismatch = 0; @@ -3154,6 +3848,16 @@ goto Lnotcovariant; Lcovariant: + /* Can convert mutable to const + */ + if (t1->mod != t2->mod) + { + if (!(t1->mod & MODconst) && (t2->mod & MODconst)) + goto Lnotcovariant; + if (!(t1->mod & MODshared) && (t2->mod & MODshared)) + goto Lnotcovariant; + } + /* Can convert pure to impure, and nothrow to throw */ if (!t1->ispure && t2->ispure) @@ -3177,7 +3881,7 @@ return 2; } -void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag) +void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { unsigned char mc; //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars()); @@ -3210,6 +3914,7 @@ assert(0); } buf->writeByte(mc); +// Possible conflict from merge if (ispure || isnothrow || isref) { if (ispure) @@ -3220,16 +3925,16 @@ buf->writestring("Nc"); } // Write argument types - Argument::argsToDecoBuffer(buf, parameters); + Argument::argsToDecoBuffer(buf, parameters, mangle); //if (buf->data[buf->offset - 1] == '@') halt(); buf->writeByte('Z' - varargs); // mark end of arg list - next->toDecoBuffer(buf); + next->toDecoBuffer(buf, mangle); inuse--; } void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs) { - //printf("TypeFunction::toCBuffer() this = %p %s\n", this, toChars()); + //printf("TypeFunction::toCBuffer() this = %p\n", this); const char *p = NULL; if (inuse) @@ -3243,7 +3948,7 @@ if (mod & MODconst) buf->writestring("const "); if (mod & MODinvariant) - buf->writestring("invariant "); + buf->writestring("immutable "); if (mod & MODshared) buf->writestring("shared "); @@ -3286,7 +3991,7 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod) { - //printf("TypeFunction::toCBuffer2() this = %p %s\n", this, toChars()); + //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref); const char *p = NULL; if (inuse) @@ -3348,6 +4053,7 @@ return this; } //printf("TypeFunction::semantic() this = %p\n", this); + //printf("TypeFunction::semantic() %s, sc->stc = %x\n", toChars(), sc->stc); TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction)); memcpy(tf, this, sizeof(TypeFunction)); @@ -3388,7 +4094,7 @@ tf->next = Type::terror; } if (tf->next->isauto() && !(sc->flags & SCOPEctor)) - error(loc, "functions cannot return auto %s", tf->next->toChars()); + error(loc, "functions cannot return scope %s", tf->next->toChars()); if (tf->parameters) { size_t dim = Argument::dim(tf->parameters); @@ -3400,20 +4106,14 @@ arg->type = arg->type->semantic(loc,sc); if (tf->inuse == 1) tf->inuse--; - if (arg->storageClass & (STCconst | STCin)) - { - if (!arg->type->isInvariant()) - arg->type = arg->type->constOf(); - } - else if (arg->storageClass & STCinvariant) - arg->type = arg->type->invariantOf(); + arg->type = arg->type->addStorageClass(arg->storageClass); if (arg->storageClass & (STCauto | STCalias | STCstatic)) { if (!arg->type) continue; } - +// Possible merge conflict Type *t = arg->type->toBasetype(); if (arg->storageClass & (STCout | STCref | STClazy)) @@ -3531,7 +4231,7 @@ if (varargs == 2 && u + 1 == nparams) // if last varargs param { Type *tb = p->type->toBasetype(); TypeSArray *tsa; - integer_t sz; + dinteger_t sz; switch (tb->ty) { @@ -3719,7 +4419,7 @@ return e; } -int TypeDelegate::isZeroInit() +int TypeDelegate::isZeroInit(Loc loc) { return 1; } @@ -3986,7 +4686,7 @@ } } if (t->ty == Ttuple) - *pt = t->syntaxCopy(); + *pt = t; else *pt = t->merge(); } @@ -4015,11 +4715,11 @@ return t; } -void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag) +void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { unsigned len; char *name; - Type::toDecoBuffer(buf, flag); + Type::toDecoBuffer(buf, flag, mangle); name = ident->toChars(); len = strlen(name); buf->printf("%d%s", len, name); @@ -4050,13 +4750,8 @@ //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars()); s = sc->search(loc, ident, &scopesym); resolveHelper(loc, sc, s, scopesym, pe, pt, ps); - if (*pt && mod) - { - if (mod & MODconst) - *pt = (*pt)->constOf(); - else if (mod & MODinvariant) - *pt = (*pt)->invariantOf(); - } + if (*pt) + (*pt) = (*pt)->addMod(mod); } /***************************************** @@ -4106,10 +4801,7 @@ if (tt->sym->sem == 1) error(loc, "circular reference of typedef %s", tt->toChars()); } - if (isConst()) - t = t->constOf(); - else if (isInvariant()) - t = t->invariantOf(); + t = t->addMod(mod); } else { @@ -4200,13 +4892,8 @@ if (s) s->semantic(sc); resolveHelper(loc, sc, s, NULL, pe, pt, ps); - if (*pt && mod) - { - if (mod & MODconst) - *pt = (*pt)->constOf(); - else if (mod & MODinvariant) - *pt = (*pt)->invariantOf(); - } + if (*pt) + *pt = (*pt)->addMod(mod); //printf("pt = '%s'\n", (*pt)->toChars()); } @@ -4246,6 +4933,34 @@ return t; } +Dsymbol *TypeInstance::toDsymbol(Scope *sc) +{ + Type *t; + Expression *e; + Dsymbol *s; + + //printf("TypeInstance::semantic(%s)\n", toChars()); + + if (sc->parameterSpecialization) + { + unsigned errors = global.errors; + global.gag++; + + resolve(loc, sc, &e, &t, &s); + + global.gag--; + if (errors != global.errors) + { if (global.gag == 0) + global.errors = errors; + return NULL; + } + } + else + resolve(loc, sc, &e, &t, &s); + + return s; +} + /***************************** TypeTypeof *****************************/ @@ -4257,6 +4972,7 @@ Type *TypeTypeof::syntaxCopy() { + //printf("TypeTypeof::syntaxCopy() %s\n", toChars()); TypeTypeof *t; t = new TypeTypeof(loc, exp->syntaxCopy()); @@ -4363,7 +5079,6 @@ */ //t = t->toHeadMutable(); } - if (idents.dim) { Dsymbol *s = t->toDsymbol(sc); @@ -4374,6 +5089,7 @@ Identifier *id = (Identifier *)idents.data[i]; s = s->searchX(loc, sc, id); } + if (s) { t = s->getType(); @@ -4434,11 +5150,7 @@ goto Lerr; } t = sc->func->type->nextOf(); - - if (mod & MODinvariant) - t = t->invariantOf(); - else if (mod & MODconst) - t = t->constOf(); + t = t->addMod(mod); if (idents.dim) { @@ -4548,10 +5260,10 @@ return sym->memtype->toBasetype(); } -void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag) +void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { const char *name = sym->mangle(); - Type::toDecoBuffer(buf, flag); + Type::toDecoBuffer(buf, flag, mangle); buf->printf("%s", name); } @@ -4572,7 +5284,16 @@ Dsymbol *s = sym->search(e->loc, ident, 0); if (!s) { - return getProperty(e->loc, ident); + if (ident == Id::max || + ident == Id::min || + ident == Id::init || + ident == Id::stringof || + !sym->memtype + ) + { + return getProperty(e->loc, ident); + } + return sym->memtype->dotExp(sc, e, ident); } EnumMember *m = s->isEnumMember(); Expression *em = m->value->copy(); @@ -4613,7 +5334,7 @@ Lfwd: error(loc, "forward reference of %s.%s", toChars(), ident->toChars()); - return new IntegerExp(0, 0, this); + return new ErrorExp(); } int TypeEnum::isintegral() @@ -4671,13 +5392,21 @@ if (!sym->defaultval) { error(loc, "forward reference of %s.init", toChars()); - return new IntegerExp(0, 0, this); + return new ErrorExp(); } return sym->defaultval; } -int TypeEnum::isZeroInit() -{ +int TypeEnum::isZeroInit(Loc loc) +{ + if (!sym->defaultval) + { +#ifdef DEBUG + printf("3: "); +#endif + error(loc, "enum %s is forward referenced", sym->toChars()); + return 0; + } return sym->defaultval->isBool(FALSE); } @@ -4739,9 +5468,9 @@ return mutableOf(); } -void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag) -{ - Type::toDecoBuffer(buf, flag); +void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) +{ + Type::toDecoBuffer(buf, flag, mangle); const char *name = sym->mangle(); buf->printf("%s", name); } @@ -4839,10 +5568,7 @@ sym->inuse = 1; Type *t = sym->basetype->toBasetype(); sym->inuse = 0; - if (mod == MODconst && !t->isInvariant()) - t = t->constOf(); - else if (mod == MODinvariant) - t = t->invariantOf(); + t = t->addMod(mod); return t; } @@ -4896,7 +5622,7 @@ return e; } -int TypeTypedef::isZeroInit() +int TypeTypedef::isZeroInit(Loc loc) { if (sym->init) { @@ -4913,7 +5639,7 @@ sym->basetype = Type::terror; } sym->inuse = 1; - int result = sym->basetype->isZeroInit(); + int result = sym->basetype->isZeroInit(loc); sym->inuse = 0; return result; } @@ -4984,11 +5710,11 @@ return sym; } -void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag) +void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { const char *name = sym->mangle(); //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name); - Type::toDecoBuffer(buf, flag); + Type::toDecoBuffer(buf, flag, mangle); buf->printf("%s", name); } @@ -5008,7 +5734,6 @@ Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident) { unsigned offset; - Expression *b; VarDeclaration *v; Dsymbol *s; DotVarExp *de; @@ -5020,7 +5745,7 @@ if (!sym->members) { error(e->loc, "struct %s is forward referenced", sym->toChars()); - return new IntegerExp(e->loc, 0, Type::tint32); + return new ErrorExp(); } /* If e.tupleof @@ -5072,6 +5797,17 @@ ident != Id::stringof && ident != Id::offsetof) { + /* See if we should forward to the alias this. + */ + if (sym->aliasthis) + { /* Rewrite e.ident as: + * e.aliasthis.ident + */ + e = new DotIdExp(e->loc, e, sym->aliasthis->ident); + e = new DotIdExp(e->loc, e, ident); + return e->semantic(sc); + } + /* Look for overloaded opDot() to see if we should forward request * to it. */ @@ -5143,6 +5879,33 @@ return de; } + Import *timp = s->isImport(); + if (timp) + { + e = new DsymbolExp(e->loc, s, 0); + e = e->semantic(sc); + return e; + } + + OverloadSet *o = s->isOverloadSet(); + if (o) + { /* We really should allow this, triggered by: + * template c() + * { + * void a(); + * void b () { this.a(); } + * } + * struct S + * { + * mixin c; + * mixin c; + * } + * alias S e; + */ + error(e->loc, "overload set for %s.%s not allowed in struct declaration", e->toChars(), ident->toChars()); + return new ErrorExp(); + } + d = s->isDeclaration(); #ifdef DEBUG if (!d) @@ -5153,18 +5916,18 @@ if (e->op == TOKtype) { FuncDeclaration *fd = sc->func; + if (d->isTupleDeclaration()) + { + e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = e->semantic(sc); + return e; + } if (d->needThis() && fd && fd->vthis) { e = new DotVarExp(e->loc, new ThisExp(e->loc), d); e = e->semantic(sc); return e; } - if (d->isTupleDeclaration()) - { - e = new TupleExp(e->loc, d->isTupleDeclaration()); - e = e->semantic(sc); - return e; - } return new VarExp(e->loc, d, 1); } @@ -5187,19 +5950,13 @@ // *(&e + offset) accessCheck(e->loc, sc, e, d); - -// LDC we don't want dot exprs turned into pointer arithmetic. it complicates things for no apparent gain -#ifndef IN_LLVM - b = new AddrExp(e->loc, e); +#if 0 + Expression *b = new AddrExp(e->loc, e); b->type = e->type->pointerTo(); b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32)); b->type = v->type->pointerTo(); b = new PtrExp(e->loc, b); - b->type = v->type; - if (e->type->isConst()) - b->type = b->type->constOf(); - else if (e->type->isInvariant()) - b->type = b->type->invariantOf(); + b->type = v->type->addMod(e->type->mod); return b; #endif } @@ -5226,7 +5983,7 @@ return new VarExp(sym->loc, d); } -int TypeStruct::isZeroInit() +int TypeStruct::isZeroInit(Loc loc) { return sym->zeroInit; } @@ -5257,7 +6014,8 @@ for (size_t i = 0; i < s->fields.dim; i++) { Dsymbol *sm = (Dsymbol *)s->fields.data[i]; - if (sm->hasPointers()) + Declaration *d = sm->isDeclaration(); + if (d->storage_class & STCref || d->hasPointers()) return TRUE; } return FALSE; @@ -5283,20 +6041,10 @@ assert(v && v->storage_class & STCfield); // 'from' type - Type *tvf = v->type; - if (mod == MODconst) - tvf = tvf->constOf(); - else if (mod == MODinvariant) - tvf = tvf->invariantOf(); + Type *tvf = v->type->addMod(mod); // 'to' type - Type *tv = v->type; - if (to->mod == 0) - tv = tv->mutableOf(); - else - { assert(to->mod == MODinvariant); - tv = tv->invariantOf(); - } + 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) @@ -5306,6 +6054,16 @@ } } } + else if (sym->aliasthis) + { + m = MATCHnomatch; + Declaration *d = sym->aliasthis->isDeclaration(); + if (d) + { assert(d->type); + Type *t = d->type->addMod(mod); + m = t->implicitConvTo(to); + } + } else m = MATCHnomatch; // no match return m; @@ -5365,11 +6123,11 @@ return sym; } -void TypeClass::toDecoBuffer(OutBuffer *buf, int flag) +void TypeClass::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { const char *name = sym->mangle(); //printf("TypeClass::toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name); - Type::toDecoBuffer(buf, flag); + Type::toDecoBuffer(buf, flag, mangle); buf->printf("%s", name); } @@ -5568,6 +6326,17 @@ ident != Id::stringof && ident != Id::offsetof) { + /* See if we should forward to the alias this. + */ + if (sym->aliasthis) + { /* Rewrite e.ident as: + * e.aliasthis.ident + */ + e = new DotIdExp(e->loc, e, sym->aliasthis->ident); + e = new DotIdExp(e->loc, e, ident); + return e->semantic(sc); + } + /* Look for overloaded opDot() to see if we should forward request * to it. */ @@ -5641,11 +6410,19 @@ return de; } + OverloadSet *o = s->isOverloadSet(); + if (o) + { /* We really should allow this + */ + error(e->loc, "overload set for %s.%s not allowed in struct declaration", e->toChars(), ident->toChars()); + return new ErrorExp(); + } + Declaration *d = s->isDeclaration(); if (!d) { e->error("%s.%s is not a declaration", e->toChars(), ident->toChars()); - return new IntegerExp(e->loc, 1, Type::tint32); + return new ErrorExp(); } if (e->op == TOKtype) @@ -5653,7 +6430,13 @@ /* It's: * Class.d */ - if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration())) + if (d->isTupleDeclaration()) + { + e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = e->semantic(sc); + return e; + } + else if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration())) { if (sc->func) { @@ -5685,12 +6468,6 @@ e = de->semantic(sc); return e; } - else if (d->isTupleDeclaration()) - { - e = new TupleExp(e->loc, d->isTupleDeclaration()); - e = e->semantic(sc); - return e; - } else { VarExp *ve = new VarExp(e->loc, d, 1); @@ -5766,7 +6543,18 @@ return MATCHconvert; } - return MATCHnomatch; + m = MATCHnomatch; + if (sym->aliasthis) + { + Declaration *d = sym->aliasthis->isDeclaration(); + if (d) + { assert(d->type); + Type *t = d->type->addMod(mod); + m = t->implicitConvTo(to); + } + } + + return m; } MATCH TypeClass::constConv(Type *to) @@ -5795,7 +6583,7 @@ return e; } -int TypeClass::isZeroInit() +int TypeClass::isZeroInit(Loc loc) { return 1; } @@ -5939,12 +6727,12 @@ Argument::argsToCBuffer(buf, hgs, arguments, 0); } -void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag) +void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag, bool mangle) { //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars()); - Type::toDecoBuffer(buf, flag); + Type::toDecoBuffer(buf, flag, mangle); OutBuffer buf2; - Argument::argsToDecoBuffer(&buf2, arguments); + Argument::argsToDecoBuffer(&buf2, arguments, mangle); unsigned len = buf2.offset; buf->printf("%d%.*s", len, len, (char *)buf2.extractData()); } @@ -5962,7 +6750,7 @@ else { error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars()); - e = new IntegerExp(loc, 1, Type::tint32); + e = new ErrorExp(); } return e; } @@ -5990,10 +6778,7 @@ { //printf("TypeSlice::semantic() %s\n", toChars()); next = next->semantic(loc, sc); - if (mod == MODconst && !next->isInvariant()) - next = next->constOf(); - else if (mod == MODinvariant) - next = next->invariantOf(); + transitive(); //printf("next: %s\n", next->toChars()); Type *tbn = next->toBasetype(); @@ -6012,7 +6797,7 @@ uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) - { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim); + { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim); return Type::terror; } @@ -6057,7 +6842,7 @@ sc = sc->pop(); if (!(i1 <= i2 && i2 <= td->objects->dim)) - { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim); + { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim); goto Ldefault; } @@ -6198,15 +6983,12 @@ else if (arg->storageClass & STCauto) buf->writestring("auto "); - if (arg->storageClass & STCscope) - buf->writestring("scope "); - - if (arg->storageClass & STCconst) - buf->writestring("const "); - if (arg->storageClass & STCinvariant) - buf->writestring("invariant "); - if (arg->storageClass & STCshared) - buf->writestring("shared "); + unsigned stc = arg->storageClass; + if (arg->type && arg->type->mod & MODshared) + stc &= ~STCshared; + + StorageClassDeclaration::stcToCBuffer(buf, + stc & (STCconst | STCimmutable | STCshared | STCscope)); argbuf.reset(); if (arg->storageClass & STCalias) @@ -6233,7 +7015,7 @@ } -void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments) +void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle) { //printf("Argument::argsToDecoBuffer()\n"); @@ -6244,7 +7026,7 @@ for (size_t i = 0; i < dim; i++) { Argument *arg = Argument::getNth(arguments, i); - arg->toDecoBuffer(buf); + arg->toDecoBuffer(buf, mangle); } } } @@ -6301,7 +7083,7 @@ return NULL; } -void Argument::toDecoBuffer(OutBuffer *buf) +void Argument::toDecoBuffer(OutBuffer *buf, bool mangle) { if (storageClass & STCscope) buf->writeByte('M'); @@ -6331,7 +7113,7 @@ type->toDecoBuffer(buf, mod); #else //type->toHeadMutable()->toDecoBuffer(buf, 0); - type->toDecoBuffer(buf, 0); + type->toDecoBuffer(buf, 0, mangle); #endif }