Merge dmd-1.074 into ldc.

This commit is contained in:
kai
2012-04-13 21:07:31 +02:00
parent f1998a6110
commit 1c6ff32d50
54 changed files with 5533 additions and 4034 deletions

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -51,6 +51,13 @@ namespace llvm
} }
#endif #endif
enum Sizeok
{
SIZEOKnone, // size of aggregate is not computed yet
SIZEOKdone, // size of aggregate is set correctly
SIZEOKfwd, // error in computing size of aggregate
};
struct AggregateDeclaration : ScopeDsymbol struct AggregateDeclaration : ScopeDsymbol
{ {
Type *type; Type *type;
@@ -62,10 +69,7 @@ struct AggregateDeclaration : ScopeDsymbol
unsigned structalign; // struct member alignment in effect unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields int hasUnions; // set if aggregate has overlapping fields
VarDeclarations fields; // VarDeclaration fields VarDeclarations fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data enum Sizeok sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated int isdeprecated; // !=0 if deprecated
#if DMDV2 #if DMDV2
@@ -89,7 +93,8 @@ struct AggregateDeclaration : ScopeDsymbol
FuncDeclaration *dtor; // aggregate destructor FuncDeclaration *dtor; // aggregate destructor
#ifdef IN_GCC #ifdef IN_GCC
Array methods; // flat list of all methods for debug information Expressions *attributes; // GCC decl/type attributes
FuncDeclarations methods; // flat list of all methods for debug information
#endif #endif
AggregateDeclaration(Loc loc, Identifier *id); AggregateDeclaration(Loc loc, Identifier *id);
@@ -98,8 +103,10 @@ struct AggregateDeclaration : ScopeDsymbol
void inlineScan(); void inlineScan();
unsigned size(Loc loc); unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset); static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
static unsigned placeField(unsigned *nextoffset,
unsigned memsize, unsigned memalignsize, unsigned memalign,
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
Type *getType(); Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int firstFieldInUnion(int indx); // first field in union that includes indx int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index int numFieldsInUnion(int firstIndex); // #fields in union starting at index
int isDeprecated(); // is aggregate deprecated? int isDeprecated(); // is aggregate deprecated?
@@ -163,14 +170,19 @@ struct StructDeclaration : AggregateDeclaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle(); char *mangle();
const char *kind(); const char *kind();
void finalizeSize(Scope *sc);
#if DMDV1 #if DMDV1
Expression *cloneMembers(); Expression *cloneMembers();
#endif #endif
#if DMDV2 #if DMDV2
int needOpAssign(); int needOpAssign();
int needOpEquals();
FuncDeclaration *buildOpAssign(Scope *sc); FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc); FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc); FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
#endif #endif
void toDocBuffer(OutBuffer *buf); void toDocBuffer(OutBuffer *buf);
@@ -222,7 +234,8 @@ struct BaseClass
}; };
#if DMDV2 #if DMDV2
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size #define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#else #else
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size #define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size #define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
return decl; return decl;
} }
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
{
Dsymbols *d = include(NULL, NULL);
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
if (s)
{
if (s->apply(fp, param))
return 1;
}
}
}
return 0;
}
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{ {
int m = 0; int m = 0;
@@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
m |= s->addMember(sc, sd, m | memnum); m |= s->addMember(sc, sd, m | memnum);
} }
@@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection; newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign; newsc->structalign = structalign;
} }
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i]; { Dsymbol *s = (*decl)[i];
s->setScope(newsc); // yes, the only difference from semanticNewSc() s->setScope(newsc); // yes, the only difference from semanticNewSc()
} }
@@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection; newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign; newsc->structalign = structalign;
} }
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i]; { Dsymbol *s = (*decl)[i];
s->semantic(newsc); s->semantic(newsc);
} }
@@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc)
{ {
for (size_t i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ {
Dsymbol *s = d->tdata()[i]; Dsymbol *s = (*d)[i];
s->semantic(sc); s->semantic(sc);
} }
@@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc)
if (d) if (d)
{ {
for (size_t i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->semantic2(sc); s->semantic2(sc);
} }
} }
@@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc)
if (d) if (d)
{ {
for (size_t i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->semantic3(sc); s->semantic3(sc);
} }
} }
@@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan()
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::inlineScan %s\n", s->toChars()); //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
s->inlineScan(); s->inlineScan();
} }
@@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment)
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::addComment %s\n", s->toChars()); //printf("AttribDeclaration::addComment %s\n", s->toChars());
s->addComment(comment); s->addComment(comment);
} }
@@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc)
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::emitComment %s\n", s->toChars()); //printf("AttribDeclaration::emitComment %s\n", s->toChars());
s->emitComment(sc); s->emitComment(sc);
} }
@@ -246,32 +264,27 @@ void AttribDeclaration::toObjFile(int multiobj)
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->toObjFile(multiobj); s->toObjFile(multiobj);
} }
} }
} }
int AttribDeclaration::cvMember(unsigned char *p) #endif
void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{ {
int nwritten = 0;
int n;
Dsymbols *d = include(NULL, NULL); Dsymbols *d = include(NULL, NULL);
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
n = s->cvMember(p); s->setFieldOffset(ad, poffset, isunion);
if (p)
p += n;
nwritten += n;
} }
} }
return nwritten;
} }
#endif
int AttribDeclaration::hasPointers() int AttribDeclaration::hasPointers()
{ {
@@ -281,7 +294,7 @@ int AttribDeclaration::hasPointers()
{ {
for (size_t i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ {
Dsymbol *s = d->tdata()[i]; Dsymbol *s = (*d)[i];
if (s->hasPointers()) if (s->hasPointers())
return 1; return 1;
} }
@@ -323,8 +336,8 @@ void AttribDeclaration::checkCtorConstInit()
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->checkCtorConstInit(); s->checkCtorConstInit();
} }
} }
@@ -339,8 +352,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->addLocalClass(aclasses); s->addLocalClass(aclasses);
} }
} }
@@ -354,15 +367,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (decl->dim == 0) if (decl->dim == 0)
buf->writestring("{}"); buf->writestring("{}");
else if (decl->dim == 1) else if (decl->dim == 1)
(decl->tdata()[0])->toCBuffer(buf, hgs); ((*decl)[0])->toCBuffer(buf, hgs);
else else
{ {
buf->writenl(); buf->writenl();
buf->writeByte('{'); buf->writeByte('{');
buf->writenl(); buf->writenl();
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
buf->writestring(" "); buf->writestring(" ");
s->toCBuffer(buf, hgs); s->toCBuffer(buf, hgs);
@@ -467,6 +480,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCout, TOKout }, { STCout, TOKout },
{ STCin, TOKin }, { STCin, TOKin },
#if DMDV2 #if DMDV2
{ STCmanifest, TOKenum },
{ STCimmutable, TOKimmutable }, { STCimmutable, TOKimmutable },
{ STCshared, TOKshared }, { STCshared, TOKshared },
{ STCnothrow, TOKnothrow }, { STCnothrow, TOKnothrow },
@@ -474,10 +488,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCref, TOKref }, { STCref, TOKref },
{ STCtls, TOKtls }, { STCtls, TOKtls },
{ STCgshared, TOKgshared }, { STCgshared, TOKgshared },
{ STCproperty, TOKat }, { STCproperty, TOKat, Id::property },
{ STCsafe, TOKat }, { STCsafe, TOKat, Id::safe },
{ STCtrusted, TOKat }, { STCtrusted, TOKat, Id::trusted },
{ STCdisable, TOKat }, { STCsystem, TOKat, Id::system },
{ STCdisable, TOKat, Id::disable },
#endif #endif
}; };
@@ -488,20 +503,9 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
enum TOK tok = table[i].tok; enum TOK tok = table[i].tok;
#if DMDV2 #if DMDV2
if (tok == TOKat) if (tok == TOKat)
{ Identifier *id; {
if (stc & STCproperty)
id = Id::property;
else if (stc & STCsafe)
id = Id::safe;
else if (stc & STCtrusted)
id = Id::trusted;
else if (stc & STCdisable)
id = Id::disable;
else
assert(0);
buf->writeByte('@'); buf->writeByte('@');
buf->writestring(id->toChars()); buf->writestring(table[i].id->toChars());
} }
else else
#endif #endif
@@ -560,9 +564,9 @@ void LinkDeclaration::semantic3(Scope *sc)
{ enum LINK linkage_save = sc->linkage; { enum LINK linkage_save = sc->linkage;
sc->linkage = linkage; sc->linkage = linkage;
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
s->semantic3(sc); s->semantic3(sc);
} }
@@ -738,6 +742,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
: AttribDeclaration(decl) : AttribDeclaration(decl)
{ {
this->loc = loc; this->loc = loc;
this->alignment = 0;
this->isunion = isunion; this->isunion = isunion;
this->sem = 0; this->sem = 0;
} }
@@ -755,21 +760,6 @@ void AnonDeclaration::semantic(Scope *sc)
{ {
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
if (sem == 1)
{ //printf("already completed\n");
scope = NULL;
return; // semantic() already completed
}
Scope *scx = NULL;
if (scope)
{ sc = scope;
scx = scope;
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
assert(sc->parent); assert(sc->parent);
Dsymbol *parent = sc->parent->pastMixin(); Dsymbol *parent = sc->parent->pastMixin();
@@ -781,106 +771,85 @@ void AnonDeclaration::semantic(Scope *sc)
return; return;
} }
alignment = sc->structalign;
if (decl) if (decl)
{ {
AnonymousAggregateDeclaration aad;
int adisunion;
if (sc->anonAgg)
{ ad = sc->anonAgg;
adisunion = sc->inunion;
}
else
adisunion = ad->isUnionDeclaration() != NULL;
// printf("\tsc->anonAgg = %p\n", sc->anonAgg);
// printf("\tad = %p\n", ad);
// printf("\taad = %p\n", &aad);
sc = sc->push(); sc = sc->push();
sc->anonAgg = &aad;
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
sc->inunion = isunion; sc->inunion = isunion;
sc->offset = 0; sc->offset = 0;
sc->flags = 0; sc->flags = 0;
aad.structalign = sc->structalign;
aad.parent = ad;
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
s->semantic(sc); s->semantic(sc);
if (isunion)
sc->offset = 0;
if (aad.sizeok == 2)
{
break;
}
} }
sc = sc->pop(); sc = sc->pop();
}
}
// If failed due to forward references, unwind and try again later
if (aad.sizeok == 2) void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
//printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
if (decl)
{
/* This works by treating an AnonDeclaration as an aggregate 'member',
* so in order to place that member we need to compute the member's
* size and alignment.
*/
size_t fieldstart = ad->fields.dim;
/* Hackishly hijack ad's structsize and alignsize fields
* for use in our fake anon aggregate member.
*/
unsigned savestructsize = ad->structsize;
unsigned savealignsize = ad->alignsize;
ad->structsize = 0;
ad->alignsize = 0;
unsigned offset = 0;
for (size_t i = 0; i < decl->dim; i++)
{ {
ad->sizeok = 2; Dsymbol *s = (*decl)[i];
//printf("\tsetting ad->sizeok %p to 2\n", ad);
if (!sc->anonAgg) s->setFieldOffset(ad, &offset, this->isunion);
{ if (this->isunion)
scope = scx ? scx : new Scope(*sc); offset = 0;
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
Module::dprogress = dprogress_save;
//printf("\tforward reference %p\n", this);
return;
} }
if (sem == 0)
{ Module::dprogress++; unsigned anonstructsize = ad->structsize;
sem = 1; unsigned anonalignsize = ad->alignsize;
//printf("\tcompleted %p\n", this); ad->structsize = savestructsize;
} ad->alignsize = savealignsize;
else
;//printf("\talready completed %p\n", this);
// 0 sized structs are set to 1 byte // 0 sized structs are set to 1 byte
if (aad.structsize == 0) if (anonstructsize == 0)
{ {
aad.structsize = 1; anonstructsize = 1;
aad.alignsize = 1; anonalignsize = 1;
} }
// Align size of anonymous aggregate /* Given the anon 'member's size and alignment,
//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); * go ahead and place it.
ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); */
//ad->structsize = sc->offset; unsigned anonoffset = AggregateDeclaration::placeField(
//printf("sc->offset = %d\n", sc->offset); poffset,
anonstructsize, anonalignsize, alignment,
&ad->structsize, &ad->alignsize,
isunion);
// Add members of aad to ad // Add to the anon fields the base offset of this anonymous aggregate
//printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars()); //printf("anon fields, anonoffset = %d\n", anonoffset);
for (unsigned i = 0; i < aad.fields.dim; i++) for (size_t i = fieldstart; i < ad->fields.dim; i++)
{ {
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; VarDeclaration *v = ad->fields[i];
//printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
v->offset += sc->offset; v->offset += anonoffset;
ad->fields.push(v);
} }
// Add size of aad to ad
if (adisunion)
{
if (aad.structsize > ad->structsize)
ad->structsize = aad.structsize;
sc->offset = 0;
}
else
{
ad->structsize = sc->offset + aad.structsize;
sc->offset = ad->structsize;
}
if (ad->alignsize < aad.alignsize)
ad->alignsize = aad.alignsize;
} }
} }
@@ -891,9 +860,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("\n{\n"); buf->writestring("\n{\n");
if (decl) if (decl)
{ {
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
//buf->writestring(" "); //buf->writestring(" ");
s->toCBuffer(buf, hgs); s->toCBuffer(buf, hgs);
@@ -953,10 +922,10 @@ void PragmaDeclaration::setScope(Scope *sc)
} }
else else
{ {
Expression *e = args->tdata()[0]; Expression *e = (*args)[0];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e; (*args)[0] = e;
StringExp* se = e->toString(); StringExp* se = e->toString();
if (!se) if (!se)
{ {
@@ -991,7 +960,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{ {
for (size_t i = 0; i < args->dim; i++) for (size_t i = 0; i < args->dim; i++)
{ {
Expression *e = args->tdata()[i]; Expression *e = (*args)[i];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
@@ -1013,11 +982,11 @@ void PragmaDeclaration::semantic(Scope *sc)
error("string expected for library name"); error("string expected for library name");
else else
{ {
Expression *e = args->tdata()[0]; Expression *e = (*args)[0];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e; (*args)[0] = e;
if (e->op == TOKerror) if (e->op == TOKerror)
goto Lnodecl; goto Lnodecl;
StringExp *se = e->toString(); StringExp *se = e->toString();
@@ -1045,7 +1014,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Declaration *d = NULL; Declaration *d = NULL;
StringExp *s = NULL; StringExp *s = NULL;
e = (Expression *)args->data[0]; e = (*args)[0];
e = e->semantic(sc); e = e->semantic(sc);
if (e->op == TOKvar) if (e->op == TOKvar)
{ {
@@ -1056,14 +1025,14 @@ void PragmaDeclaration::semantic(Scope *sc)
if (!d) if (!d)
error("first argument of GNU_asm must be a function or variable declaration"); error("first argument of GNU_asm must be a function or variable declaration");
e = args->tdata()[1]; e = (*args)[1];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue); e = e->optimize(WANTvalue);
e = e->toString(); e = e->toString();
if (e && ((StringExp *)e)->sz == 1) if (e && ((StringExp *)e)->sz == 1)
s = ((StringExp *)e); s = ((StringExp *)e);
else else
error("second argument of GNU_asm must be a char string"); error("second argument of GNU_asm must be a character string");
if (d && s) if (d && s)
d->c_ident = Lexer::idPool((char*) s->string); d->c_ident = Lexer::idPool((char*) s->string);
@@ -1078,10 +1047,10 @@ void PragmaDeclaration::semantic(Scope *sc)
error("function name expected for start address"); error("function name expected for start address");
else else
{ {
Expression *e = (Expression *)args->data[0]; Expression *e = (*args)[0];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
args->data[0] = (void *)e; (*args)[0] = e;
Dsymbol *sa = getDsymbol(e); Dsymbol *sa = getDsymbol(e);
if (!sa || !sa->isFuncDeclaration()) if (!sa || !sa->isFuncDeclaration())
error("function name expected for start address, not '%s'", e->toChars()); error("function name expected for start address, not '%s'", e->toChars());
@@ -1111,11 +1080,13 @@ void PragmaDeclaration::semantic(Scope *sc)
{ {
for (size_t i = 0; i < args->dim; i++) for (size_t i = 0; i < args->dim; i++)
{ {
#if IN_LLVM
// ignore errors in ignored pragmas. // ignore errors in ignored pragmas.
global.gag++; global.gag++;
unsigned errors_save = global.errors; unsigned errors_save = global.errors;
#endif
Expression *e = (Expression *)args->data[i]; Expression *e = (*args)[i];
e = e->semantic(sc); e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
if (i == 0) if (i == 0)
@@ -1124,9 +1095,11 @@ void PragmaDeclaration::semantic(Scope *sc)
printf(","); printf(",");
printf("%s", e->toChars()); printf("%s", e->toChars());
#if IN_LLVM
// restore error state. // restore error state.
global.gag--; global.gag--;
global.errors = errors_save; global.errors = errors_save;
#endif
} }
if (args->dim) if (args->dim)
printf(")"); printf(")");
@@ -1141,9 +1114,9 @@ void PragmaDeclaration::semantic(Scope *sc)
Ldecl: Ldecl:
if (decl) if (decl)
{ {
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
s->semantic(sc); s->semantic(sc);
@@ -1180,7 +1153,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
{ {
assert(args && args->dim == 1); assert(args && args->dim == 1);
Expression *e = (Expression *)args->data[0]; Expression *e = (*args)[0];
assert(e->op == TOKstring); assert(e->op == TOKstring);
@@ -1208,7 +1181,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
else if (ident == Id::startaddress) else if (ident == Id::startaddress)
{ {
assert(args && args->dim == 1); assert(args && args->dim == 1);
Expression *e = (Expression *)args->data[0]; Expression *e = (*args)[0];
Dsymbol *sa = getDsymbol(e); Dsymbol *sa = getDsymbol(e);
FuncDeclaration *f = sa->isFuncDeclaration(); FuncDeclaration *f = sa->isFuncDeclaration();
assert(f); assert(f);
@@ -1285,8 +1258,8 @@ void ConditionalDeclaration::emitComment(Scope *sc)
* a template, then include(NULL, NULL) will fail. * a template, then include(NULL, NULL) will fail.
*/ */
Dsymbols *d = decl ? decl : elsedecl; Dsymbols *d = decl ? decl : elsedecl;
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i]; { Dsymbol *s = (*d)[i];
s->emitComment(sc); s->emitComment(sc);
} }
} }
@@ -1308,9 +1281,9 @@ void ConditionalDeclaration::setScope(Scope *sc)
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d); //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ {
Dsymbol *s = d->tdata()[i]; Dsymbol *s = (*d)[i];
s->setScope(sc); s->setScope(sc);
} }
@@ -1324,9 +1297,9 @@ void ConditionalDeclaration::importAll(Scope *sc)
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ {
Dsymbol *s = d->tdata()[i]; Dsymbol *s = (*d)[i];
s->importAll(sc); s->importAll(sc);
} }
@@ -1349,10 +1322,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment)
{ {
if (d) if (d)
{ {
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s; { Dsymbol *s = (*d)[i];
s = d->tdata()[i];
//printf("ConditionalDeclaration::addComment %s\n", s->toChars()); //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
s->addComment(comment); s->addComment(comment);
} }
@@ -1372,9 +1343,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl(); buf->writenl();
if (decl) if (decl)
{ {
for (unsigned i = 0; i < decl->dim; i++) for (size_t i = 0; i < decl->dim; i++)
{ {
Dsymbol *s = decl->tdata()[i]; Dsymbol *s = (*decl)[i];
buf->writestring(" "); buf->writestring(" ");
s->toCBuffer(buf, hgs); s->toCBuffer(buf, hgs);
@@ -1388,9 +1359,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl(); buf->writenl();
buf->writeByte('{'); buf->writeByte('{');
buf->writenl(); buf->writenl();
for (unsigned i = 0; i < elsedecl->dim; i++) for (size_t i = 0; i < elsedecl->dim; i++)
{ {
Dsymbol *s = elsedecl->tdata()[i]; Dsymbol *s = (*elsedecl)[i];
buf->writestring(" "); buf->writestring(" ");
s->toCBuffer(buf, hgs); s->toCBuffer(buf, hgs);
@@ -1474,9 +1445,9 @@ void StaticIfDeclaration::semantic(Scope *sc)
addisdone = 1; addisdone = 1;
} }
for (unsigned i = 0; i < d->dim; i++) for (size_t i = 0; i < d->dim; i++)
{ {
Dsymbol *s = d->tdata()[i]; Dsymbol *s = (*d)[i];
s->semantic(sc); s->semantic(sc);
} }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol
AttribDeclaration(Dsymbols *decl); AttribDeclaration(Dsymbols *decl);
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s); virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
int apply(Dsymbol_apply_ft_t fp, void *param);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum); int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc, void setScopeNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
@@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol
void emitComment(Scope *sc); void emitComment(Scope *sc);
const char *kind(); const char *kind();
int oneMember(Dsymbol **ps); int oneMember(Dsymbol **ps);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
int hasPointers(); int hasPointers();
bool hasStaticCtorOrDtor(); bool hasStaticCtorOrDtor();
void checkCtorConstInit(); void checkCtorConstInit();
@@ -58,7 +60,6 @@ struct AttribDeclaration : Dsymbol
#if IN_DMD #if IN_DMD
void toObjFile(int multiobj); // compile to .obj file void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
#endif #endif
#if IN_LLVM #if IN_LLVM
@@ -119,12 +120,14 @@ struct AlignDeclaration : AttribDeclaration
struct AnonDeclaration : AttribDeclaration struct AnonDeclaration : AttribDeclaration
{ {
int isunion; bool isunion;
unsigned alignment;
int sem; // 1 if successful semantic() int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s); Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc); void semantic(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind(); const char *kind();
}; };

View File

@@ -1166,17 +1166,16 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *DelegateExp::castTo(Scope *sc, Type *t)
{ {
Type *tb;
#if 0 #if 0
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars()); toChars(), type->toChars(), t->toChars());
#endif #endif
Expression *e = this;
static char msg[] = "cannot form delegate due to covariant return type"; static char msg[] = "cannot form delegate due to covariant return type";
tb = t->toBasetype(); Expression *e = this;
Type *tb = t->toBasetype();
type = type->toBasetype(); type = type->toBasetype();
if (tb != type) if (tb != type || hasOverloads)
{ {
// Look for delegates to functions where the functions are overloaded. // Look for delegates to functions where the functions are overloaded.
FuncDeclaration *f; FuncDeclaration *f;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -228,9 +228,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
cd->baseclasses->setDim(this->baseclasses->dim); cd->baseclasses->setDim(this->baseclasses->dim);
for (size_t i = 0; i < cd->baseclasses->dim; i++) for (size_t i = 0; i < cd->baseclasses->dim; i++)
{ {
BaseClass *b = (BaseClass *)this->baseclasses->data[i]; BaseClass *b = this->baseclasses->tdata()[i];
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
cd->baseclasses->data[i] = b2; cd->baseclasses->tdata()[i] = b2;
} }
ScopeDsymbol::syntaxCopy(cd); ScopeDsymbol::syntaxCopy(cd);
@@ -264,7 +264,7 @@ void ClassDeclaration::semantic(Scope *sc)
return; return;
} }
if (symtab) if (symtab)
{ if (sizeok == 1 || !scope) { if (sizeok == SIZEOKdone || !scope)
{ //printf("\tsemantic for '%s' is already completed\n", toChars()); { //printf("\tsemantic for '%s' is already completed\n", toChars());
return; // semantic() already completed return; // semantic() already completed
} }
@@ -290,7 +290,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[] // Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; ) for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = (BaseClass *)baseclasses->data[i]; { BaseClass *b = baseclasses->tdata()[i];
b->type = b->type->semantic(loc, sc); b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype(); Type *tb = b->type->toBasetype();
@@ -315,11 +315,12 @@ void ClassDeclaration::semantic(Scope *sc)
BaseClass *b; BaseClass *b;
Type *tb; Type *tb;
b = (BaseClass *)baseclasses->data[0]; b = baseclasses->tdata()[0];
//b->type = b->type->semantic(loc, sc); //b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype(); tb = b->type->toBasetype();
if (tb->ty != Tclass) if (tb->ty != Tclass)
{ error("base type must be class or interface, not %s", b->type->toChars()); { if (b->type != Type::terror)
error("base type must be class or interface, not %s", b->type->toChars());
baseclasses->remove(0); baseclasses->remove(0);
} }
else else
@@ -331,7 +332,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!isDeprecated()) if (!isDeprecated())
{ {
// Deriving from deprecated class makes this one deprecated too // Deriving from deprecated class makes this one deprecated too
isdeprecated = 1; isdeprecated = true;
tc->checkDeprecated(loc, sc); tc->checkDeprecated(loc, sc);
} }
@@ -350,12 +351,12 @@ void ClassDeclaration::semantic(Scope *sc)
goto L7; goto L7;
} }
} }
if (!tc->sym->symtab || tc->sym->sizeok == 0) if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
{ // Try to resolve forward reference { // Try to resolve forward reference
if (/*sc->mustsemantic &&*/ tc->sym->scope) if (/*sc->mustsemantic &&*/ tc->sym->scope)
tc->sym->semantic(NULL); tc->sym->semantic(NULL);
} }
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
{ {
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars()); //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
//error("forward reference of base class %s", baseClass->toChars()); //error("forward reference of base class %s", baseClass->toChars());
@@ -384,7 +385,7 @@ void ClassDeclaration::semantic(Scope *sc)
BaseClass *b; BaseClass *b;
Type *tb; Type *tb;
b = (BaseClass *)baseclasses->data[i]; b = baseclasses->tdata()[i];
b->type = b->type->semantic(loc, sc); b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype(); tb = b->type->toBasetype();
if (tb->ty == Tclass) if (tb->ty == Tclass)
@@ -392,7 +393,7 @@ void ClassDeclaration::semantic(Scope *sc)
else else
tc = NULL; tc = NULL;
if (!tc || !tc->sym->isInterfaceDeclaration()) if (!tc || !tc->sym->isInterfaceDeclaration())
{ { if (b->type != Type::terror)
error("base type must be interface, not %s", b->type->toChars()); error("base type must be interface, not %s", b->type->toChars());
baseclasses->remove(i); baseclasses->remove(i);
continue; continue;
@@ -404,7 +405,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!isDeprecated()) if (!isDeprecated())
{ {
// Deriving from deprecated class makes this one deprecated too // Deriving from deprecated class makes this one deprecated too
isdeprecated = 1; isdeprecated = true;
tc->checkDeprecated(loc, sc); tc->checkDeprecated(loc, sc);
} }
@@ -413,7 +414,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces // Check for duplicate interfaces
for (size_t j = (baseClass ? 1 : 0); j < i; j++) for (size_t j = (baseClass ? 1 : 0); j < i; j++)
{ {
BaseClass *b2 = (BaseClass *)baseclasses->data[j]; BaseClass *b2 = baseclasses->tdata()[j];
if (b2->base == tc->sym) if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars()); error("inherits from duplicate interface %s", b2->base->toChars());
} }
@@ -467,7 +468,7 @@ void ClassDeclaration::semantic(Scope *sc)
} }
interfaces_dim = baseclasses->dim; interfaces_dim = baseclasses->dim;
interfaces = (BaseClass **)baseclasses->data; interfaces = baseclasses->tdata();
if (baseClass) if (baseClass)
@@ -480,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Copy vtbl[] from base class // Copy vtbl[] from base class
vtbl.setDim(baseClass->vtbl.dim); vtbl.setDim(baseClass->vtbl.dim);
memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim); memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
// Inherit properties from base class // Inherit properties from base class
com = baseClass->isCOMclass(); com = baseClass->isCOMclass();
@@ -503,7 +504,7 @@ void ClassDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = (*members)[i];
s->addMember(sc, this, 1); s->addMember(sc, this, 1);
} }
@@ -606,17 +607,20 @@ void ClassDeclaration::semantic(Scope *sc)
structsize = sc->offset; structsize = sc->offset;
Scope scsave = *sc; Scope scsave = *sc;
size_t members_dim = members->dim; size_t members_dim = members->dim;
sizeok = 0; sizeok = SIZEOKnone;
/* Set scope so if there are forward references, we still might be able to /* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums. * resolve individual members like enums.
*/ */
for (size_t i = 0; i < members_dim; i++) for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i]; { Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because /* There are problems doing this in the general case because
* Scope keeps track of things like 'offset' * Scope keeps track of things like 'offset'
*/ */
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) if (s->isEnumDeclaration() ||
(s->isAggregateDeclaration() && s->ident) ||
s->isTemplateMixin() ||
s->isAliasDeclaration())
{ {
//printf("setScope %s %s\n", s->kind(), s->toChars()); //printf("setScope %s %s\n", s->kind(), s->toChars());
s->setScope(sc); s->setScope(sc);
@@ -624,13 +628,35 @@ void ClassDeclaration::semantic(Scope *sc)
} }
for (size_t i = 0; i < members_dim; i++) for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = (Dsymbol *)members->data[i]; { Dsymbol *s = (*members)[i];
s->semantic(sc); s->semantic(sc);
} }
if (sizeok == 2) // Set the offsets of the fields and determine the size of the class
{ // semantic() failed because of forward references.
unsigned offset = structsize;
bool isunion = isUnionDeclaration() != NULL;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setFieldOffset(this, &offset, false);
}
sc->offset = structsize;
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
type = Type::terror;
}
if (sizeok == 2) // failed due to forward references
{ // semantic() failed due to forward references
// Unwind what we did, and defer it for later // Unwind what we did, and defer it for later
for (size_t i = 0; i < fields.dim; i++)
{ Dsymbol *s = fields[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd)
vd->offset = 0;
}
fields.setDim(0); fields.setDim(0);
structsize = 0; structsize = 0;
alignsize = 0; alignsize = 0;
@@ -650,7 +676,6 @@ void ClassDeclaration::semantic(Scope *sc)
//printf("\tsemantic('%s') successful\n", toChars()); //printf("\tsemantic('%s') successful\n", toChars());
structsize = sc->offset;
//members->print(); //members->print();
/* Look for special member functions. /* Look for special member functions.
@@ -683,7 +708,6 @@ void ClassDeclaration::semantic(Scope *sc)
members->push(ctor); members->push(ctor);
ctor->addMember(sc, this, 1); ctor->addMember(sc, this, 1);
*sc = scsave; // why? What about sc->nofree? *sc = scsave; // why? What about sc->nofree?
sc->offset = structsize;
ctor->semantic(sc); ctor->semantic(sc);
this->ctor = ctor; this->ctor = ctor;
defaultCtor = ctor; defaultCtor = ctor;
@@ -699,9 +723,10 @@ void ClassDeclaration::semantic(Scope *sc)
#endif #endif
// Allocate instance of each new interface // Allocate instance of each new interface
sc->offset = structsize;
for (size_t i = 0; i < vtblInterfaces->dim; i++) for (size_t i = 0; i < vtblInterfaces->dim; i++)
{ {
BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; BaseClass *b = (*vtblInterfaces)[i];
unsigned thissize = PTRSIZE; unsigned thissize = PTRSIZE;
alignmember(structalign, thissize, &sc->offset); alignmember(structalign, thissize, &sc->offset);
@@ -720,7 +745,7 @@ void ClassDeclaration::semantic(Scope *sc)
alignsize = thissize; alignsize = thissize;
} }
structsize = sc->offset; structsize = sc->offset;
sizeok = 1; sizeok = SIZEOKdone;
Module::dprogress++; Module::dprogress++;
dtor = buildDtor(sc); dtor = buildDtor(sc);
@@ -731,7 +756,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Fill in base class vtbl[]s // Fill in base class vtbl[]s
for (i = 0; i < vtblInterfaces->dim; i++) for (i = 0; i < vtblInterfaces->dim; i++)
{ {
BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; BaseClass *b = vtblInterfaces->tdata()[i];
//b->fillVtbl(this, &b->vtbl, 1); //b->fillVtbl(this, &b->vtbl, 1);
} }
@@ -750,7 +775,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
} }
for (size_t i = 0; i < baseclasses->dim; i++) for (size_t i = 0; i < baseclasses->dim; i++)
{ {
BaseClass *b = (BaseClass *)baseclasses->data[i]; BaseClass *b = baseclasses->tdata()[i];
if (i) if (i)
buf->writeByte(','); buf->writeByte(',');
@@ -764,7 +789,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl(); buf->writenl();
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = members->tdata()[i];
buf->writestring(" "); buf->writestring(" ");
s->toCBuffer(buf, hgs); s->toCBuffer(buf, hgs);
@@ -799,7 +824,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
return 0; return 0;
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
for (size_t i = 0; i < cd->baseclasses->dim; i++) for (size_t i = 0; i < cd->baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)cd->baseclasses->data[i]; { BaseClass *b = cd->baseclasses->tdata()[i];
if (b->base == this || isBaseOf2(b->base)) if (b->base == this || isBaseOf2(b->base))
return 1; return 1;
@@ -845,7 +870,7 @@ int ClassDeclaration::isBaseInfoComplete()
if (!baseClass) if (!baseClass)
return ident == Id::Object; return ident == Id::Object;
for (size_t i = 0; i < baseclasses->dim; i++) for (size_t i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses->data[i]; { BaseClass *b = baseclasses->tdata()[i];
if (!b->base || !b->base->isBaseInfoComplete()) if (!b->base || !b->base->isBaseInfoComplete())
return 0; return 0;
} }
@@ -860,7 +885,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
if (scope && !symtab) if (scope && !symtab)
{ Scope *sc = scope; { Scope *sc = scope;
sc->mustsemantic++; sc->mustsemantic++;
// If speculatively gagged, ungag now.
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging())
global.gag = 0;
semantic(sc); semantic(sc);
global.gag = oldgag;
sc->mustsemantic--; sc->mustsemantic--;
} }
@@ -878,7 +908,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
for (size_t i = 0; i < baseclasses->dim; i++) for (size_t i = 0; i < baseclasses->dim; i++)
{ {
BaseClass *b = (BaseClass *)baseclasses->data[i]; BaseClass *b = baseclasses->tdata()[i];
if (b->base) if (b->base)
{ {
@@ -1178,12 +1208,12 @@ void InterfaceDeclaration::semantic(Scope *sc)
if (sc->stc & STCdeprecated) if (sc->stc & STCdeprecated)
{ {
isdeprecated = 1; isdeprecated = true;
} }
// Expand any tuples in baseclasses[] // Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; ) for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = (BaseClass *)baseclasses->data[0]; { BaseClass *b = (*baseclasses)[0];
b->type = b->type->semantic(loc, sc); b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype(); Type *tb = b->type->toBasetype();
@@ -1208,7 +1238,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
BaseClass *b; BaseClass *b;
Type *tb; Type *tb;
b = (BaseClass *)baseclasses->data[i]; b = baseclasses->tdata()[i];
b->type = b->type->semantic(loc, sc); b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype(); tb = b->type->toBasetype();
if (tb->ty == Tclass) if (tb->ty == Tclass)
@@ -1216,7 +1246,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
else else
tc = NULL; tc = NULL;
if (!tc || !tc->sym->isInterfaceDeclaration()) if (!tc || !tc->sym->isInterfaceDeclaration())
{ { if (b->type != Type::terror)
error("base type must be interface, not %s", b->type->toChars()); error("base type must be interface, not %s", b->type->toChars());
baseclasses->remove(i); baseclasses->remove(i);
continue; continue;
@@ -1226,7 +1256,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Check for duplicate interfaces // Check for duplicate interfaces
for (size_t j = 0; j < i; j++) for (size_t j = 0; j < i; j++)
{ {
BaseClass *b2 = (BaseClass *)baseclasses->data[j]; BaseClass *b2 = baseclasses->tdata()[j];
if (b2->base == tc->sym) if (b2->base == tc->sym)
error("inherits from duplicate interface %s", b2->base->toChars()); error("inherits from duplicate interface %s", b2->base->toChars());
} }
@@ -1311,10 +1341,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->explicitProtection = 0; sc->explicitProtection = 0;
structalign = sc->structalign; structalign = sc->structalign;
sc->offset = PTRSIZE * 2; sc->offset = PTRSIZE * 2;
structsize = sc->offset;
inuse++; inuse++;
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ { Dsymbol *s = (*members)[i];
Dsymbol *s = (*members)[i];
s->semantic(sc); s->semantic(sc);
} }
inuse--; inuse--;
@@ -1408,7 +1438,7 @@ int InterfaceDeclaration::isBaseInfoComplete()
{ {
assert(!baseClass); assert(!baseClass);
for (size_t i = 0; i < baseclasses->dim; i++) for (size_t i = 0; i < baseclasses->dim; i++)
{ BaseClass *b = (BaseClass *)baseclasses->data[i]; { BaseClass *b = baseclasses->tdata()[i];
if (!b->base || !b->base->isBaseInfoComplete ()) if (!b->base || !b->base->isBaseInfoComplete ())
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -225,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
: Condition(loc) : Condition(loc)
{ {
this->exp = exp; this->exp = exp;
this->nest = 0;
} }
Condition *StaticIfCondition::syntaxCopy() Condition *StaticIfCondition::syntaxCopy()
@@ -235,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy()
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s) int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{ {
#if 0 #if 0
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s); printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc);
if (s) if (s)
{ {
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind()); printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
@@ -243,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
#endif #endif
if (inc == 0) if (inc == 0)
{ {
if (exp->op == TOKerror || nest > 100)
{
error(loc, (nest > 1000) ? "unresolvable circular static if expression"
: "error evaluating static if expression");
if (!global.gag)
inc = 2; // so we don't see the error message again
return 0;
}
if (!sc) if (!sc)
{ {
error(loc, "static if conditional cannot be at global scope"); error(loc, "static if conditional cannot be at global scope");
@@ -250,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
return 0; return 0;
} }
++nest;
sc = sc->push(sc->scopesym); sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember() sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif; sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc); Expression *e = exp->semantic(sc);
sc->pop(); sc->pop();
e = e->optimize(WANTvalue | WANTinterpret); e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(TRUE)) --nest;
if (e->op == TOKerror)
{ exp = e;
inc = 0;
}
else if (e->isBool(TRUE))
inc = 1; inc = 1;
else if (e->isBool(FALSE)) else if (e->isBool(FALSE))
inc = 2; inc = 2;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -36,6 +36,7 @@ struct Condition
virtual Condition *syntaxCopy() = 0; virtual Condition *syntaxCopy() = 0;
virtual int include(Scope *sc, ScopeDsymbol *s) = 0; virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
virtual DebugCondition *isDebugCondition() { return NULL; }
}; };
struct DVCondition : Condition struct DVCondition : Condition
@@ -59,6 +60,7 @@ struct DebugCondition : DVCondition
int include(Scope *sc, ScopeDsymbol *s); int include(Scope *sc, ScopeDsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
DebugCondition *isDebugCondition() { return this; }
}; };
struct VersionCondition : DVCondition struct VersionCondition : DVCondition
@@ -77,6 +79,7 @@ struct VersionCondition : DVCondition
struct StaticIfCondition : Condition struct StaticIfCondition : Condition
{ {
Expression *exp; Expression *exp;
int nest; // limit circular dependencies
StaticIfCondition(Loc loc, Expression *exp); StaticIfCondition(Loc loc, Expression *exp);
Condition *syntaxCopy(); Condition *syntaxCopy();

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -530,7 +530,8 @@ void AliasDeclaration::semantic(Scope *sc)
goto L2; goto L2;
} }
else else
{ error("cannot alias an expression %s", e->toChars()); { if (e->op != TOKerror)
error("cannot alias an expression %s", e->toChars());
t = e->type; t = e->type;
} }
} }
@@ -543,7 +544,7 @@ void AliasDeclaration::semantic(Scope *sc)
ScopeDsymbol::multiplyDefined(0, this, overnext); ScopeDsymbol::multiplyDefined(0, this, overnext);
this->inSemantic = 0; this->inSemantic = 0;
if (errors != global.errors) if (global.gag && errors != global.errors)
type = savedtype; type = savedtype;
return; return;
@@ -580,7 +581,7 @@ void AliasDeclaration::semantic(Scope *sc)
assert(global.errors); assert(global.errors);
s = NULL; s = NULL;
} }
if (errors != global.errors) if (global.gag && errors != global.errors)
{ {
type = savedtype; type = savedtype;
overnext = savedovernext; overnext = savedovernext;
@@ -728,6 +729,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
#if DMDV1 #if DMDV1
nestedref = 0; nestedref = 0;
#endif #endif
alignment = 0;
ctorinit = 0; ctorinit = 0;
aliassym = NULL; aliassym = NULL;
onstack = 0; onstack = 0;
@@ -767,6 +769,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
sv->storage_class = storage_class; sv->storage_class = storage_class;
} }
// Syntax copy for header file // Syntax copy for header file
if (!htype) // Don't overwrite original if (!htype) // Don't overwrite original
{ if (type) // Make copy for both old and new instances { if (type) // Make copy for both old and new instances
@@ -955,9 +958,7 @@ void VarDeclaration::semantic(Scope *sc)
} }
else else
{ {
AggregateDeclaration *aad = sc->anonAgg; AggregateDeclaration *aad = parent->isAggregateDeclaration();
if (!aad)
aad = parent->isAggregateDeclaration();
if (aad) if (aad)
{ {
#if DMDV2 #if DMDV2
@@ -970,7 +971,15 @@ void VarDeclaration::semantic(Scope *sc)
} }
else else
#endif #endif
aad->addField(sc, this); {
storage_class |= STCfield;
alignment = sc->structalign;
#if DMDV2
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
aad->noDefaultCtor = TRUE;
#endif
}
} }
InterfaceDeclaration *id = parent->isInterfaceDeclaration(); InterfaceDeclaration *id = parent->isInterfaceDeclaration();
@@ -1305,6 +1314,31 @@ ExpInitializer *VarDeclaration::getExpInitializer()
void VarDeclaration::semantic2(Scope *sc) void VarDeclaration::semantic2(Scope *sc)
{ {
//printf("VarDeclaration::semantic2('%s')\n", toChars()); //printf("VarDeclaration::semantic2('%s')\n", toChars());
// Inside unions, default to void initializers
if (!init && sc->inunion && !toParent()->isFuncDeclaration())
{
AggregateDeclaration *aad = parent->isAggregateDeclaration();
if (aad)
{
if (aad->fields[0] == this)
{
int hasinit = 0;
for (size_t i = 1; i < aad->fields.dim; i++)
{
if (aad->fields[i]->init &&
!aad->fields[i]->init->isVoidInitializer())
{
hasinit = 1;
break;
}
}
if (!hasinit)
init = new ExpInitializer(loc, type->defaultInitLiteral(loc));
}
else
init = new VoidInitializer(loc);
}
}
if (init && !toParent()->isFuncDeclaration()) if (init && !toParent()->isFuncDeclaration())
{ inuse++; { inuse++;
#if 0 #if 0
@@ -1330,6 +1364,82 @@ void VarDeclaration::semantic3(Scope *sc)
Declaration::semantic3(sc); Declaration::semantic3(sc);
} }
void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
//printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars());
if (aliassym)
{ // If this variable was really a tuple, set the offsets for the tuple fields
TupleDeclaration *v2 = aliassym->isTupleDeclaration();
assert(v2);
for (size_t i = 0; i < v2->objects->dim; i++)
{ Object *o = (*v2->objects)[i];
assert(o->dyncast() == DYNCAST_EXPRESSION);
Expression *e = (Expression *)o;
assert(e->op == TOKdsymbol);
DsymbolExp *se = (DsymbolExp *)e;
se->s->setFieldOffset(ad, poffset, isunion);
}
return;
}
if (!(storage_class & STCfield))
return;
assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
/* Fields that are tuples appear both as part of TupleDeclarations and
* as members. That means ignore them if they are already a field.
*/
if (offset)
return; // already a field
for (size_t i = 0; i < ad->fields.dim; i++)
{
if (ad->fields[i] == this)
return; // already a field
}
// Check for forward referenced types which will fail the size() call
Type *t = type->toBasetype();
if (storage_class & STCref)
{ // References are the size of a pointer
t = Type::tvoidptr;
}
if (t->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)t;
#if DMDV2
if (ts->sym == ad)
{
ad->error("cannot have field %s with same struct type", toChars());
}
#endif
if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope)
ts->sym->semantic(NULL);
if (ts->sym->sizeok != SIZEOKdone)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
}
if (t->ty == Tident)
{
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
return;
}
unsigned memsize = t->size(loc); // size of member
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
unsigned memalign = t->memalign(alignment); // alignment boundaries
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign,
&ad->structsize, &ad->alignsize, isunion);
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize);
ad->fields.push(this);
}
const char *VarDeclaration::kind() const char *VarDeclaration::kind()
{ {
return "variable"; return "variable";

View File

@@ -279,6 +279,7 @@ struct VarDeclaration : Declaration
#else #else
int nestedref; // referenced by a lexically nested function int nestedref; // referenced by a lexically nested function
#endif #endif
unsigned short alignment;
int ctorinit; // it has been initialized in a ctor int ctorinit; // it has been initialized in a ctor
int onstack; // 1: it has been allocated on the stack int onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway // 2: on stack, run destructor anyway
@@ -305,6 +306,7 @@ struct VarDeclaration : Declaration
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *); Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc); void semantic(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
void semantic2(Scope *sc); void semantic2(Scope *sc);
const char *kind(); const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -795,6 +797,7 @@ struct FuncDeclaration : Declaration
int isAbstract(); int isAbstract();
int isCodeseg(); int isCodeseg();
int isOverloadable(); int isOverloadable();
int hasOverloads();
int isPure(); int isPure();
int isSafe(); int isSafe();
int isTrusted(); int isTrusted();

View File

@@ -261,6 +261,9 @@ void Module::gendocfile()
Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
} }
char *srcfilename = srcfile->toChars();
Macro::define(&macrotable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
char *docfilename = docfile->toChars(); char *docfilename = docfile->toChars();
Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -50,6 +50,7 @@ Dsymbol::Dsymbol()
this->loc = 0; this->loc = 0;
this->comment = NULL; this->comment = NULL;
this->scope = NULL; this->scope = NULL;
this->errors = false;
#if IN_LLVM #if IN_LLVM
this->llvmInternal = LLVMnone; this->llvmInternal = LLVMnone;
this->irsym = NULL; this->irsym = NULL;
@@ -69,6 +70,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->loc = 0; this->loc = 0;
this->comment = NULL; this->comment = NULL;
this->scope = NULL; this->scope = NULL;
this->errors = false;
#if IN_LLVM #if IN_LLVM
this->llvmInternal = LLVMnone; this->llvmInternal = LLVMnone;
this->irsym = NULL; this->irsym = NULL;
@@ -169,6 +171,10 @@ bool Dsymbol::hasStaticCtorOrDtor()
return FALSE; return FALSE;
} }
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
}
char *Dsymbol::toChars() char *Dsymbol::toChars()
{ {
return ident ? ident->toChars() : (char *)"__anonymous"; return ident ? ident->toChars() : (char *)"__anonymous";
@@ -283,6 +289,23 @@ TemplateInstance *Dsymbol::inTemplateInstance()
return NULL; return NULL;
} }
// Check if this function is a member of a template which has only been
// instantiated speculatively, eg from inside is(typeof()).
// Return the speculative template instance it is part of,
// or NULL if not speculative.
TemplateInstance *Dsymbol::isSpeculative()
{
Dsymbol * par = parent;
while (par)
{
TemplateInstance *ti = par->isTemplateInstance();
if (ti && ti->speculative)
return ti;
par = par->toParent();
}
return NULL;
}
int Dsymbol::isAnonymous() int Dsymbol::isAnonymous()
{ {
return ident ? 0 : 1; return ident ? 0 : 1;
@@ -367,11 +390,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
void *symbol_search_fp(void *arg, const char *seed) void *symbol_search_fp(void *arg, const char *seed)
{ {
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return NULL;
StringValue *sv = Lexer::stringtable.lookup(seed, len);
if (!sv)
return NULL;
Identifier *id = (Identifier *)sv->ptrvalue;
assert(id);
Dsymbol *s = (Dsymbol *)arg; Dsymbol *s = (Dsymbol *)arg;
Identifier id(seed, 0);
Module::clearCache(); Module::clearCache();
s = s->search(0, &id, 4|2); return s->search(0, id, 4|2);
return s;
} }
Dsymbol *Dsymbol::search_correct(Identifier *ident) Dsymbol *Dsymbol::search_correct(Identifier *ident)
@@ -409,7 +442,13 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
id = ti->name; id = ti->name;
sm = s->search(loc, id, 0); sm = s->search(loc, id, 0);
if (!sm) if (!sm)
{ error("template identifier %s is not a member of %s %s", {
sm = s->search_correct(id);
if (sm)
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
else
error("template identifier '%s' is not a member of '%s %s'",
id->toChars(), s->kind(), s->toChars()); id->toChars(), s->kind(), s->toChars());
return NULL; return NULL;
} }
@@ -495,6 +534,11 @@ int Dsymbol::isOverloadable()
} }
#endif #endif
int Dsymbol::hasOverloads()
{
return 0;
}
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
{ {
return NULL; return NULL;
@@ -518,6 +562,11 @@ int Dsymbol::needThis()
return FALSE; return FALSE;
} }
int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
{
return (*fp)(this, param);
}
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{ {
//printf("Dsymbol::addMember('%s')\n", toChars()); //printf("Dsymbol::addMember('%s')\n", toChars());
@@ -634,19 +683,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
Module *Dsymbol::getModule() Module *Dsymbol::getModule()
{ {
Module *m;
Dsymbol *s;
//printf("Dsymbol::getModule()\n"); //printf("Dsymbol::getModule()\n");
TemplateDeclaration *td = getFuncTemplateDecl(this); TemplateDeclaration *td = getFuncTemplateDecl(this);
if (td) if (td)
return td->getModule(); return td->getModule();
s = this; Dsymbol *s = this;
while (s) while (s)
{ {
//printf("\ts = '%s'\n", s->toChars()); //printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
m = s->isModule(); Module *m = s->isModule();
if (m) if (m)
return m; return m;
s = s->parent; s = s->parent;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -128,6 +128,8 @@ enum PASS
PASSobj, // toObjFile() run PASSobj, // toObjFile() run
}; };
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
struct Dsymbol : Object struct Dsymbol : Object
{ {
Identifier *ident; Identifier *ident;
@@ -140,6 +142,7 @@ struct Dsymbol : Object
unsigned char *comment; // documentation comment for this Dsymbol unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic() Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
Dsymbol(); Dsymbol();
Dsymbol(Identifier *); Dsymbol(Identifier *);
@@ -157,6 +160,7 @@ struct Dsymbol : Object
Dsymbol *toParent(); Dsymbol *toParent();
Dsymbol *toParent2(); Dsymbol *toParent2();
TemplateInstance *inTemplateInstance(); TemplateInstance *inTemplateInstance();
TemplateInstance *isSpeculative();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
@@ -165,6 +169,7 @@ struct Dsymbol : Object
virtual const char *toPrettyChars(); virtual const char *toPrettyChars();
virtual const char *kind(); virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias(); // resolve real symbol
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc); virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc); virtual void importAll(Scope *sc);
@@ -193,6 +198,7 @@ struct Dsymbol : Object
#if DMDV2 #if DMDV2
virtual int isOverloadable(); virtual int isOverloadable();
#endif #endif
virtual int hasOverloads();
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
virtual Type *getType(); // is this a type? virtual Type *getType(); // is this a type?
@@ -202,6 +208,7 @@ struct Dsymbol : Object
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps); virtual int oneMember(Dsymbol **ps);
static int oneMembers(Dsymbols *members, Dsymbol **ps); static int oneMembers(Dsymbols *members, Dsymbol **ps);
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
virtual int hasPointers(); virtual int hasPointers();
virtual bool hasStaticCtorOrDtor(); virtual bool hasStaticCtorOrDtor();
virtual void addLocalClass(ClassDeclarations *) { } virtual void addLocalClass(ClassDeclarations *) { }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -345,10 +345,10 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
*/ */
Type *t0 = NULL; Type *t0 = NULL;
for (size_t i = 0; i < exps->dim; i++) for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i]; { Expression *e = (*exps)[i];
if (!e->type) if (!e->type)
{ error("%s has no value", e->toChars()); { error(e->loc, "%s has no value", e->toChars());
e = new ErrorExp(); e = new ErrorExp();
} }
e = resolveProperties(sc, e); e = resolveProperties(sc, e);
@@ -357,7 +357,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
t0 = e->type; t0 = e->type;
else else
e = e->implicitCastTo(sc, t0); e = e->implicitCastTo(sc, t0);
exps->data[i] = (void *)e; (*exps)[i] = e;
} }
if (!t0) if (!t0)
@@ -384,11 +384,11 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
Expression *e0; Expression *e0;
int j0; int j0;
for (size_t i = 0; i < exps->dim; i++) for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i]; { Expression *e = (*exps)[i];
e = resolveProperties(sc, e); e = resolveProperties(sc, e);
if (!e->type) if (!e->type)
{ error("%s has no value", e->toChars()); { e->error("%s has no value", e->toChars());
e = new ErrorExp(); e = new ErrorExp();
} }
@@ -401,8 +401,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
condexp.type = NULL; condexp.type = NULL;
condexp.e1 = e0; condexp.e1 = e0;
condexp.e2 = e; condexp.e2 = e;
condexp.loc = e->loc;
condexp.semantic(sc); condexp.semantic(sc);
exps->data[j0] = (void *)condexp.e1; (*exps)[j0] = condexp.e1;
e = condexp.e2; e = condexp.e2;
j0 = i; j0 = i;
e0 = e; e0 = e;
@@ -414,15 +415,15 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
e0 = e; e0 = e;
t0 = e->type; t0 = e->type;
} }
exps->data[i] = (void *)e; (*exps)[i] = e;
} }
if (t0) if (t0)
{ {
for (size_t i = 0; i < exps->dim; i++) for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i]; { Expression *e = (*exps)[i];
e = e->implicitCastTo(sc, t0); e = e->implicitCastTo(sc, t0);
exps->data[i] = (void *)e; (*exps)[i] = e;
} }
} }
else else
@@ -525,23 +526,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
} }
#endif #endif
// Check if this function is a member of a template which has only been
// instantiated speculatively, eg from inside is(typeof()).
// Return the speculative template instance it is part of,
// or NULL if not speculative.
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd)
{
Dsymbol * par = fd->parent;
while (par)
{
TemplateInstance *ti = par->isTemplateInstance();
if (ti && ti->speculative)
return ti;
par = par->toParent();
}
return NULL;
}
/**************************************** /****************************************
* Now that we know the exact type of the function we're calling, * Now that we know the exact type of the function we're calling,
* the arguments[] need to be adjusted: * the arguments[] need to be adjusted:
@@ -565,7 +549,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
// If inferring return type, and semantic3() needs to be run if not already run // If inferring return type, and semantic3() needs to be run if not already run
if (!tf->next && fd->inferRetType) if (!tf->next && fd->inferRetType)
{ {
TemplateInstance *spec = isSpeculativeFunction(fd); TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors; int olderrs = global.errors;
fd->semantic3(fd->scope); fd->semantic3(fd->scope);
// Update the template instantiation with the number // Update the template instantiation with the number
@@ -583,10 +567,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
Expression *arg; Expression *arg;
if (i < nargs) if (i < nargs)
arg = (Expression *)arguments->data[i]; arg = (*arguments)[i];
else else
arg = NULL; arg = NULL;
Type *tb;
if (i < nparams) if (i < nparams)
{ {
@@ -613,12 +596,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
if (tf->varargs == 2 && i + 1 == nparams) if (tf->varargs == 2 && i + 1 == nparams)
{ {
//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
if (arg->implicitConvTo(p->type)) MATCH m;
if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch)
{ {
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf())) if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
goto L2; goto L2;
else if (nargs != nparams) else if (nargs != nparams)
{ error(loc, "expected %zu function arguments, not %zu", nparams, nargs); { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
return; return;
} }
goto L1; goto L1;
@@ -661,9 +645,6 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
Expression *e = new VarExp(loc, v); Expression *e = new VarExp(loc, v);
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
AssignExp *ae = new AssignExp(loc, e, a); AssignExp *ae = new AssignExp(loc, e, a);
#if DMDV2
ae->op = TOKconstruct;
#endif
if (c) if (c)
c = new CommaExp(loc, c, ae); c = new CommaExp(loc, c, ae);
else else
@@ -723,7 +704,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
// LDC we don't want this! // LDC we don't want this!
#if !IN_LLVM #if !IN_LLVM
// Convert static arrays to pointers // Convert static arrays to pointers
tb = arg->type->toBasetype(); Type *tb = arg->type->toBasetype();
if (tb->ty == Tsarray) if (tb->ty == Tsarray)
{ {
arg = arg->checkToPointer(); arg = arg->checkToPointer();
@@ -732,7 +713,19 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
#if DMDV2 #if DMDV2
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
{ {
arg = callCpCtor(loc, sc, arg); if (arg->op == TOKcall)
{
/* 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 #endif
@@ -801,7 +794,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
} }
// Convert static arrays to dynamic arrays // Convert static arrays to dynamic arrays
tb = arg->type->toBasetype(); // BUG: I don't think this is right for D2
Type *tb = arg->type->toBasetype();
if (tb->ty == Tsarray) if (tb->ty == Tsarray)
{ TypeSArray *ts = (TypeSArray *)tb; { TypeSArray *ts = (TypeSArray *)tb;
Type *ta = ts->next->arrayOf(); Type *ta = ts->next->arrayOf();
@@ -2222,6 +2216,7 @@ Lagain:
if (em) if (em)
{ {
e = em->value->copy(); e = em->value->copy();
e->loc = loc;
e = e->semantic(sc); e = e->semantic(sc);
return e; return e;
} }
@@ -2234,8 +2229,8 @@ Lagain:
v->semantic(v->scope); v->semantic(v->scope);
type = v->type; type = v->type;
if (!v->type) if (!v->type)
{ error("forward reference of %s", v->toChars()); { error("forward reference of %s %s", v->kind(), v->toChars());
type = Type::terror; return new ErrorExp();
} }
} }
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray) if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray)
@@ -2245,8 +2240,7 @@ Lagain:
if (v->inuse) if (v->inuse)
{ {
error("circular reference to '%s'", v->toChars()); error("circular reference to '%s'", v->toChars());
type = Type::tint32; return new ErrorExp();
return this;
} }
ExpInitializer *ei = v->init->isExpInitializer(); ExpInitializer *ei = v->init->isExpInitializer();
if (ei) if (ei)
@@ -2282,13 +2276,19 @@ Lagain:
{ //printf("'%s' is a function\n", f->toChars()); { //printf("'%s' is a function\n", f->toChars());
if (!f->originalType && f->scope) // semantic not yet run if (!f->originalType && f->scope) // semantic not yet run
{
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !f->isSpeculative())
global.gag = 0;
f->semantic(f->scope); f->semantic(f->scope);
global.gag = oldgag;
}
#if DMDV2 #if DMDV2
// if inferring return type, sematic3 needs to be run // if inferring return type, sematic3 needs to be run
if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
{ {
TemplateInstance *spec = isSpeculativeFunction(f); TemplateInstance *spec = f->isSpeculative();
int olderrs = global.errors; int olderrs = global.errors;
f->semantic3(f->scope); f->semantic3(f->scope);
// Update the template instantiation with the number // Update the template instantiation with the number
@@ -2362,10 +2362,10 @@ Lagain:
} }
TemplateInstance *ti = s->isTemplateInstance(); TemplateInstance *ti = s->isTemplateInstance();
if (ti && !global.errors) if (ti)
{ if (!ti->semanticRun) { if (!ti->semanticRun)
ti->semantic(sc); ti->semantic(sc);
s = ti->inst->toAlias(); s = ti->toAlias();
if (!s->isTemplateInstance()) if (!s->isTemplateInstance())
goto Lagain; goto Lagain;
e = new ScopeExp(loc, ti); e = new ScopeExp(loc, ti);
@@ -3224,6 +3224,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
#endif #endif
if (type)
return this;
// Run semantic() on each element // Run semantic() on each element
arrayExpressionSemantic(keys, sc); arrayExpressionSemantic(keys, sc);
arrayExpressionSemantic(values, sc); arrayExpressionSemantic(values, sc);
@@ -3232,8 +3235,7 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
if (keys->dim != values->dim) if (keys->dim != values->dim)
{ {
error("number of keys is %u, must match number of values %u", keys->dim, values->dim); error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
keys->setDim(0); return new ErrorExp();
values->setDim(0);
} }
Type *tkey = NULL; Type *tkey = NULL;
@@ -3241,6 +3243,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
keys = arrayExpressionToCommonType(sc, keys, &tkey); keys = arrayExpressionToCommonType(sc, keys, &tkey);
values = arrayExpressionToCommonType(sc, values, &tvalue); values = arrayExpressionToCommonType(sc, values, &tvalue);
if (tkey == Type::terror || tvalue == Type::terror)
return new ErrorExp;
type = new TypeAArray(tvalue, tkey); type = new TypeAArray(tvalue, tkey);
type = type->semantic(loc, sc); type = type->semantic(loc, sc);
return this; return this;
@@ -3629,8 +3634,9 @@ Expression *ScopeExp::semantic(Scope *sc)
#endif #endif
Lagain: Lagain:
ti = sds->isTemplateInstance(); ti = sds->isTemplateInstance();
if (ti && !global.errors) if (ti && !ti->errors)
{ {
unsigned olderrs = global.errors;
if (!ti->semanticRun) if (!ti->semanticRun)
ti->semantic(sc); ti->semantic(sc);
if (ti->inst) if (ti->inst)
@@ -3660,7 +3666,7 @@ Lagain:
} }
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
} }
if (global.errors) if (olderrs != global.errors)
return new ErrorExp(); return new ErrorExp();
} }
else else
@@ -5471,6 +5477,32 @@ void BinExp::incompatibleTypes()
/************************************************************/ /************************************************************/
Expression *BinAssignExp::semantic(Scope *sc)
{ Expression *e;
//printf("BinAssignExp::semantic()\n");
if (type)
return this;
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
e = op_overload(sc);
if (e)
return e;
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
e2 = e2->castTo(sc, Type::tshiftcnt);
return this;
}
/************************************************************/
CompileExp::CompileExp(Loc loc, Expression *e) CompileExp::CompileExp(Loc loc, Expression *e)
: UnaExp(loc, TOKmixin, sizeof(CompileExp), e) : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
{ {
@@ -5921,7 +5953,9 @@ Expression *DotIdExp::semantic(Scope *sc)
if (tup) if (tup)
{ {
if (eleft) if (eleft)
error("cannot have e.tuple"); { error("cannot have e.tuple");
return new ErrorExp();
}
e = new TupleExp(loc, tup); e = new TupleExp(loc, tup);
e = e->semantic(sc); e = e->semantic(sc);
return e; return e;
@@ -5959,7 +5993,12 @@ Expression *DotIdExp::semantic(Scope *sc)
e = e->semantic(sc); e = e->semantic(sc);
return e; return e;
} }
error("undefined identifier %s", toChars()); s = ie->sds->search_correct(ident);
if (s)
error("undefined identifier '%s', did you mean '%s %s'?",
ident->toChars(), s->kind(), s->toChars());
else
error("undefined identifier '%s'", ident->toChars());
return new ErrorExp(); return new ErrorExp();
} }
else if (e1->type->ty == Tpointer && else if (e1->type->ty == Tpointer &&
@@ -6239,8 +6278,8 @@ L1:
return e; return e;
if (e->op == TOKdottd) if (e->op == TOKdottd)
{ {
if (global.errors) if (ti->errors)
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway return new ErrorExp();
DotTemplateExp *dte = (DotTemplateExp *)e; DotTemplateExp *dte = (DotTemplateExp *)e;
TemplateDeclaration *td = dte->td; TemplateDeclaration *td = dte->td;
eleft = dte->e1; eleft = dte->e1;
@@ -6248,8 +6287,8 @@ L1:
#if DMDV2 #if DMDV2
if (ti->needsTypeInference(sc)) if (ti->needsTypeInference(sc))
{ {
e = new CallExp(loc, this); e1 = eleft; // save result of semantic()
return e->semantic(sc); return this;
} }
else else
#endif #endif
@@ -6451,6 +6490,7 @@ DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f)
: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
{ {
this->func = f; this->func = f;
this->hasOverloads = 0;
m = NULL; m = NULL;
} }
@@ -6828,6 +6868,17 @@ Lagain:
arrayExpressionSemantic(arguments, sc); arrayExpressionSemantic(arguments, sc);
preFunctionParameters(loc, sc, arguments); preFunctionParameters(loc, sc, arguments);
// If there was an error processing any template argument,
// return an error without trying to resolve the template.
if (targsi && targsi->dim)
{
for (size_t k = 0; k < targsi->dim; k++)
{ Object *o = targsi->tdata()[k];
if (isError(o))
return new ErrorExp();
}
}
if (e1->op == TOKdotvar && t1->ty == Tfunction || if (e1->op == TOKdotvar && t1->ty == Tfunction ||
e1->op == TOKdottd) e1->op == TOKdottd)
{ {
@@ -7336,11 +7387,24 @@ Expression *AddrExp::semantic(Scope *sc)
return this; return this;
} }
if (f && f->isNested()) if (f)
{ {
Expression *e = new DelegateExp(loc, e1, f); if (f->isNested())
e = e->semantic(sc); {
return e; if (f->isFuncLiteralDeclaration())
{
if (!f->FuncDeclaration::isNested())
{ /* Supply a 'null' for a this pointer if no this is available
*/
Expression *e = new DelegateExp(loc, new NullExp(loc, Type::tvoidptr), f);
e = e->semantic(sc);
return e;
}
}
Expression *e = new DelegateExp(loc, e1, f);
e = e->semantic(sc);
return e;
}
} }
} }
else if (e1->op == TOKarray) else if (e1->op == TOKarray)
@@ -8554,10 +8618,11 @@ Expression *AssignExp::semantic(Scope *sc)
if (e1->op == TOKarray) if (e1->op == TOKarray)
{ {
ArrayExp *ae = (ArrayExp *)e1; ArrayExp *ae = (ArrayExp *)e1;
AggregateDeclaration *ad; AggregateDeclaration *ad = NULL;
Identifier *id = Id::index; Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc); ae->e1 = ae->e1->semantic(sc);
ae->e1 = resolveProperties(sc, ae->e1);
Type *t1 = ae->e1->type->toBasetype(); Type *t1 = ae->e1->type->toBasetype();
if (t1->ty == Tstruct) if (t1->ty == Tstruct)
{ {
@@ -8585,7 +8650,9 @@ Expression *AssignExp::semantic(Scope *sc)
{ Expression *e = new DotIdExp(loc, ae->e1, id); { Expression *e = new DotIdExp(loc, ae->e1, id);
if (1 || !global.params.useDeprecated) if (1 || !global.params.useDeprecated)
error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); { error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
return new ErrorExp();
}
e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
e = e->semantic(sc); e = e->semantic(sc);
@@ -8601,7 +8668,7 @@ Expression *AssignExp::semantic(Scope *sc)
if (e1->op == TOKslice) if (e1->op == TOKslice)
{ Type *t1; { Type *t1;
SliceExp *ae = (SliceExp *)e1; SliceExp *ae = (SliceExp *)e1;
AggregateDeclaration *ad; AggregateDeclaration *ad = NULL;
Identifier *id = Id::index; Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc); ae->e1 = ae->e1->semantic(sc);
@@ -8697,8 +8764,9 @@ Expression *AssignExp::semantic(Scope *sc)
* check for operator overloading. * check for operator overloading.
*/ */
if (t1->ty == Tclass || t1->ty == Tstruct) if (t1->ty == Tclass || t1->ty == Tstruct)
{ { // Disallow assignment operator overloads for same type
if (!e2->type->implicitConvTo(e1->type)) if (/*op == TOKassign &&*/ // construction shouldn't be allowed, but OK to avoid breaking existing code
!e2->implicitConvTo(e1->type))
{ {
Expression *e = op_overload(sc); Expression *e = op_overload(sc);
if (e) if (e)
@@ -8725,8 +8793,16 @@ Expression *AssignExp::semantic(Scope *sc)
e1 = e1->modifiableLvalue(sc, e1old); e1 = e1->modifiableLvalue(sc, e1old);
} }
// If it is a array, get the element type. Note that it may be
// multi-dimensional.
Type *telem = t1;
while (telem->ty == Tarray)
telem = telem->nextOf();
// Check for block assignment. If it is of type void[], void[][], etc,
// '= null' is the only allowable block assignment (Bug 7493)
if (e1->op == TOKslice && if (e1->op == TOKslice &&
t1->nextOf() && t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) &&
e2->implicitConvTo(t1->nextOf()) e2->implicitConvTo(t1->nextOf())
// !(t1->nextOf()->equals(e2->type->nextOf())) // !(t1->nextOf()->equals(e2->type->nextOf()))
) )
@@ -8792,7 +8868,7 @@ ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
/************************************************************/ /************************************************************/
AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
{ {
} }
@@ -8903,7 +8979,7 @@ Expression *AddAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
{ {
} }
@@ -8957,7 +9033,7 @@ Expression *MinAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
{ {
} }
@@ -8981,6 +9057,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
} }
e1 = e1->modifiableLvalue(sc, e1); e1 = e1->modifiableLvalue(sc, e1);
if (e1->op == TOKerror)
return e1;
Type *tb1 = e1->type->toBasetype(); Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype(); Type *tb2 = e2->type->toBasetype();
@@ -9039,13 +9117,15 @@ Expression *CatAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
{ {
} }
Expression *MulAssignExp::semantic(Scope *sc) Expression *MulAssignExp::semantic(Scope *sc)
{ Expression *e; { Expression *e;
if (type)
return this;
BinExp::semantic(sc); BinExp::semantic(sc);
e2 = resolveProperties(sc, e2); e2 = resolveProperties(sc, e2);
@@ -9117,13 +9197,15 @@ Expression *MulAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
{ {
} }
Expression *DivAssignExp::semantic(Scope *sc) Expression *DivAssignExp::semantic(Scope *sc)
{ Expression *e; { Expression *e;
if (type)
return this;
BinExp::semantic(sc); BinExp::semantic(sc);
e2 = resolveProperties(sc, e2); e2 = resolveProperties(sc, e2);
@@ -9198,12 +9280,14 @@ Expression *DivAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
{ {
} }
Expression *ModAssignExp::semantic(Scope *sc) Expression *ModAssignExp::semantic(Scope *sc)
{ {
if (type)
return this;
BinExp::semantic(sc); BinExp::semantic(sc);
checkComplexMulAssign(); checkComplexMulAssign();
return commonSemanticAssign(sc); return commonSemanticAssign(sc);
@@ -9212,104 +9296,28 @@ Expression *ModAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
{ {
} }
Expression *ShlAssignExp::semantic(Scope *sc)
{ Expression *e;
//printf("ShlAssignExp::semantic()\n");
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
e = op_overload(sc);
if (e)
return e;
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
/************************************************************/ /************************************************************/
ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
{ {
} }
Expression *ShrAssignExp::semantic(Scope *sc)
{ Expression *e;
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
e = op_overload(sc);
if (e)
return e;
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
/************************************************************/ /************************************************************/
UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
{ {
} }
Expression *UshrAssignExp::semantic(Scope *sc)
{ Expression *e;
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
e = op_overload(sc);
if (e)
return e;
e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
typeCombine(sc);
e1->checkIntegral();
e2 = e2->checkIntegral();
#if !IN_LLVM
e2 = e2->castTo(sc, Type::tshiftcnt);
#else
e2 = e2->castTo(sc, e1->type);
#endif
return this;
}
/************************************************************/ /************************************************************/
AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
{ {
} }
@@ -9321,7 +9329,7 @@ Expression *AndAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
{ {
} }
@@ -9333,7 +9341,7 @@ Expression *OrAssignExp::semantic(Scope *sc)
/************************************************************/ /************************************************************/
XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
{ {
} }

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -932,8 +932,12 @@ struct BinExp : Expression
struct BinAssignExp : BinExp struct BinAssignExp : BinExp
{ {
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2); BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
int checkSideEffect(int flag); : BinExp(loc, op, size, e1, e2)
{
}
Expression *semantic(Scope *sc);
}; };
/****************************************************************/ /****************************************************************/
@@ -1031,6 +1035,7 @@ struct DelegateExp : UnaExp
{ {
FuncDeclaration *func; FuncDeclaration *func;
Module* m; // starting point for overload resolution Module* m; // starting point for overload resolution
int hasOverloads;
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
Expression *semantic(Scope *sc); Expression *semantic(Scope *sc);
@@ -1446,10 +1451,10 @@ struct ConstructExp : AssignExp
#endif #endif
#define ASSIGNEXP(op) \ #define ASSIGNEXP(op) \
struct op##AssignExp : BinExp \ struct op##AssignExp : BinAssignExp \
{ \ { \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
Expression *semantic(Scope *sc); \ S(Expression *semantic(Scope *sc);) \
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
X(Expression *buildArrayLoop(Parameters *fparams);) \ X(Expression *buildArrayLoop(Parameters *fparams);) \
@@ -1460,6 +1465,7 @@ struct op##AssignExp : BinExp \
}; };
#define X(a) a #define X(a) a
#define S(a) a
ASSIGNEXP(Add) ASSIGNEXP(Add)
ASSIGNEXP(Min) ASSIGNEXP(Min)
ASSIGNEXP(Mul) ASSIGNEXP(Mul)
@@ -1468,15 +1474,28 @@ ASSIGNEXP(Mod)
ASSIGNEXP(And) ASSIGNEXP(And)
ASSIGNEXP(Or) ASSIGNEXP(Or)
ASSIGNEXP(Xor) ASSIGNEXP(Xor)
#undef S
#if DMDV2
#define S(a) a
ASSIGNEXP(Pow)
#undef S
#endif
#undef X #undef X
#define X(a) #define X(a)
#define S(a)
ASSIGNEXP(Shl) ASSIGNEXP(Shl)
ASSIGNEXP(Shr) ASSIGNEXP(Shr)
ASSIGNEXP(Ushr) ASSIGNEXP(Ushr)
#undef S
#define S(a) a
ASSIGNEXP(Cat) ASSIGNEXP(Cat)
#undef S
#undef X #undef X
#undef ASSIGNEXP #undef ASSIGNEXP
#undef ASSIGNEXP_TOELEM #undef ASSIGNEXP_TOELEM

View File

@@ -1,5 +1,5 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -306,7 +306,7 @@ void FuncDeclaration::semantic(Scope *sc)
(pd = toParent2()) != NULL && (pd = toParent2()) != NULL &&
(id = pd->isInterfaceDeclaration()) != NULL) (id = pd->isInterfaceDeclaration()) != NULL)
{ {
error("template member function not allowed in interface %s", id->toChars()); error("template member functions are not allowed in interface %s", id->toChars());
} }
cd = parent->isClassDeclaration(); cd = parent->isClassDeclaration();
@@ -362,6 +362,9 @@ void FuncDeclaration::semantic(Scope *sc)
//printf("\tnot virtual\n"); //printf("\tnot virtual\n");
goto Ldone; goto Ldone;
} }
// Suppress further errors if the return type is an error
if (type->nextOf() == Type::terror)
goto Ldone;
/* Find index of existing function in base class's vtbl[] to override /* Find index of existing function in base class's vtbl[] to override
* (the index will be the same as in cd's current vtbl[]) * (the index will be the same as in cd's current vtbl[])
@@ -407,7 +410,7 @@ void FuncDeclaration::semantic(Scope *sc)
break; break;
case -2: // can't determine because of fwd refs case -2: // can't determine because of fwd refs
cd->sizeok = 2; // can't finish due to forward reference cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save; Module::dprogress = dprogress_save;
return; return;
@@ -488,18 +491,26 @@ void FuncDeclaration::semantic(Scope *sc)
break; break;
case -2: case -2:
cd->sizeok = 2; // can't finish due to forward reference cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save; Module::dprogress = dprogress_save;
return; return;
default: default:
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi]; { FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
Type *ti = NULL; Type *ti = NULL;
/* Remember which functions this overrides /* Remember which functions this overrides
*/ */
foverrides.push(fdv); foverrides.push(fdv);
#if DMDV2
/* Should we really require 'override' when implementing
* an interface function?
*/
//if (!isOverride())
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
#endif
if (fdv->tintro) if (fdv->tintro)
ti = fdv->tintro; ti = fdv->tintro;
else if (!type->equals(fdv->type)) else if (!type->equals(fdv->type))
@@ -513,7 +524,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (global.endGagging(errors)) if (global.endGagging(errors))
{ {
// any error in isBaseOf() is a forward reference error, so we bail out // any error in isBaseOf() is a forward reference error, so we bail out
cd->sizeok = 2; // can't finish due to forward reference cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save; Module::dprogress = dprogress_save;
return; return;
} }
@@ -524,10 +535,15 @@ void FuncDeclaration::semantic(Scope *sc)
} }
if (ti) if (ti)
{ {
if (tintro && !tintro->equals(ti)) if (tintro)
{
if (!tintro->nextOf()->equals(ti->nextOf()) &&
!tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
!ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
{ {
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
} }
}
tintro = ti; tintro = ti;
} }
goto L2; goto L2;
@@ -601,7 +617,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (f->varargs) if (f->varargs)
{ {
Lmainerr: Lmainerr:
error("parameters must be main() or main(char[][] args)"); error("parameters must be main() or main(string[] args)");
} }
} }
@@ -2508,6 +2524,10 @@ int FuncDeclaration::isCodeseg()
return TRUE; // functions are always in the code segment return TRUE; // functions are always in the code segment
} }
int FuncDeclaration::hasOverloads()
{
return overnext != NULL;
}
// Determine if function needs // Determine if function needs
// a static frame pointer to its lexically enclosing function // a static frame pointer to its lexically enclosing function
@@ -3175,7 +3195,7 @@ int StaticCtorDeclaration::addPostInvariant()
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ {
if (hgs->hdrgen) if (hgs->hdrgen && !hgs->tpltMember)
{ buf->writestring("static this();"); { buf->writestring("static this();");
buf->writenl(); buf->writenl();
return; return;

View File

@@ -104,15 +104,15 @@ void Html::error(const char *format, ...)
{ {
if (!global.gag) if (!global.gag)
{ {
printf("%s(%d) : HTML Error: ", sourcename, linnum); fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum);
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
vprintf(format, ap); vfprintf(stderr, format, ap);
va_end(ap); va_end(ap);
printf("\n"); fprintf(stderr, "\n");
fflush(stdout); fflush(stderr);
} }
global.errors++; global.errors++;

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -79,7 +79,16 @@ void Import::load(Scope *sc)
// See if existing module // See if existing module
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg); DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (pkg && pkg->isModule())
{
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
pkg->toChars(), pkg->toPrettyChars(), id->toChars());
mod = pkg->isModule(); // Error recovery - treat as import of that module
return;
}
#endif
Dsymbol *s = dst->lookup(id); Dsymbol *s = dst->lookup(id);
if (s) if (s)
{ {
@@ -89,7 +98,8 @@ void Import::load(Scope *sc)
if (s->isModule()) if (s->isModule())
mod = (Module *)s; mod = (Module *)s;
else else
error("package and module have the same name"); ::error(loc, "can only import from a module, not from package %s.%s",
pkg->toPrettyChars(), id->toChars());
#endif #endif
} }
@@ -97,11 +107,14 @@ void Import::load(Scope *sc)
{ {
// Load module // Load module
mod = Module::load(loc, packages, id); mod = Module::load(loc, packages, id);
if (mod)
{
dst->insert(id, mod); // id may be different from mod->ident, dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias // if so then insert alias
if (!mod->importedFrom) if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
} }
}
if (!pkg) if (!pkg)
pkg = mod; pkg = mod;
@@ -151,7 +164,8 @@ void Import::semantic(Scope *sc)
// Load if not already done so // Load if not already done so
if (!mod) if (!mod)
{ load(sc); { load(sc);
mod->importAll(0); if (mod)
mod->importAll(0);
} }
if (mod) if (mod)
@@ -200,7 +214,9 @@ void Import::semantic(Scope *sc)
} }
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg); //printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
if (global.params.moduleDeps != NULL) if (global.params.moduleDeps != NULL &&
// object self-imports itself, so skip that (Bugzilla 7547)
!(id == Id::object && sc->module->ident == Id::object))
{ {
/* The grammar of the file is: /* The grammar of the file is:
* ImportDeclaration * ImportDeclaration

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
a = new Initializers(); a = new Initializers();
a->setDim(ai->dim); a->setDim(ai->dim);
for (size_t i = 0; i < a->dim; i++) for (size_t i = 0; i < a->dim; i++)
{ Initializer *e = (Initializer *)ai->data[i]; { Initializer *e = (*ai)[i];
e = e->syntaxCopy(); e = e->syntaxCopy();
a->data[i] = e; (*a)[i] = e;
} }
} }
return a; return a;
@@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy()
ai->value.setDim(value.dim); ai->value.setDim(value.dim);
for (size_t i = 0; i < field.dim; i++) for (size_t i = 0; i < field.dim; i++)
{ {
ai->field.data[i] = field.data[i]; ai->field[i] = field[i];
Initializer *init = (Initializer *)value.data[i]; Initializer *init = value[i];
init = init->syntaxCopy(); init = init->syntaxCopy();
ai->value.data[i] = init; ai->value[i] = init;
} }
return ai; return ai;
} }
@@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
s = ad->search(loc, id, 0); s = ad->search(loc, id, 0);
if (!s) if (!s)
{ {
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); s = ad->search_correct(id);
if (s)
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
id->toChars(), t->toChars(), s->kind(), s->toChars());
else
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
errors = 1; errors = 1;
continue; continue;
} }
@@ -212,8 +217,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
if (s && (v = s->isVarDeclaration()) != NULL) if (s && (v = s->isVarDeclaration()) != NULL)
{ {
val = val->semantic(sc, v->type, needInterpret); val = val->semantic(sc, v->type, needInterpret);
value.data[i] = (void *)val; value[i] = val;
vars.data[i] = (void *)v; vars[i] = v;
} }
else else
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
@@ -273,7 +278,7 @@ Expression *StructInitializer::toExpression()
elements->setDim(nfields); elements->setDim(nfields);
for (size_t i = 0; i < elements->dim; i++) for (size_t i = 0; i < elements->dim; i++)
{ {
elements->data[i] = NULL; (*elements)[i] = NULL;
} }
unsigned fieldi = 0; unsigned fieldi = 0;
for (size_t i = 0; i < value.dim; i++) for (size_t i = 0; i < value.dim; i++)
@@ -305,37 +310,37 @@ Expression *StructInitializer::toExpression()
{ error(loc, "too many initializers for '%s'", ad->toChars()); { error(loc, "too many initializers for '%s'", ad->toChars());
goto Lno; goto Lno;
} }
Initializer *iz = (Initializer *)value.data[i]; Initializer *iz = value[i];
if (!iz) if (!iz)
goto Lno; goto Lno;
Expression *ex = iz->toExpression(); Expression *ex = iz->toExpression();
if (!ex) if (!ex)
goto Lno; goto Lno;
if (elements->data[fieldi]) if ((*elements)[fieldi])
{ error(loc, "duplicate initializer for field '%s'", { error(loc, "duplicate initializer for field '%s'",
((Dsymbol *)ad->fields.data[fieldi])->toChars()); ad->fields[fieldi]->toChars());
goto Lno; goto Lno;
} }
elements->data[fieldi] = ex; (*elements)[fieldi] = ex;
++fieldi; ++fieldi;
} }
// Now, fill in any missing elements with default initializers. // Now, fill in any missing elements with default initializers.
// We also need to validate any anonymous unions // We also need to validate any anonymous unions
for (size_t i = 0; i < elements->dim; ) for (size_t i = 0; i < elements->dim; )
{ {
VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration(); VarDeclaration * vd = ad->fields[i]->isVarDeclaration();
int unionSize = ad->numFieldsInUnion(i); int unionSize = ad->numFieldsInUnion(i);
if (unionSize == 1) if (unionSize == 1)
{ // Not a union -- default initialize if missing { // Not a union -- default initialize if missing
if (!elements->data[i]) if (!(*elements)[i])
elements->data[i] = vd->type->defaultInit(); (*elements)[i] = vd->type->defaultInit();
} }
else else
{ // anonymous union -- check for errors { // anonymous union -- check for errors
int found = -1; // index of the first field with an initializer int found = -1; // index of the first field with an initializer
for (int j = i; j < i + unionSize; ++j) for (size_t j = i; j < i + unionSize; ++j)
{ {
if (!elements->data[j]) if (!(*elements)[j])
continue; continue;
if (found >= 0) if (found >= 0)
{ {
@@ -375,13 +380,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ {
if (i > 0) if (i > 0)
buf->writebyte(','); buf->writebyte(',');
Identifier *id = (Identifier *)field.data[i]; Identifier *id = field[i];
if (id) if (id)
{ {
buf->writestring(id->toChars()); buf->writestring(id->toChars());
buf->writebyte(':'); buf->writebyte(':');
} }
Initializer *iz = (Initializer *)value.data[i]; Initializer *iz = value[i];
if (iz) if (iz)
iz->toCBuffer(buf, hgs); iz->toCBuffer(buf, hgs);
} }
@@ -408,14 +413,14 @@ Initializer *ArrayInitializer::syntaxCopy()
ai->index.setDim(index.dim); ai->index.setDim(index.dim);
ai->value.setDim(value.dim); ai->value.setDim(value.dim);
for (size_t i = 0; i < ai->value.dim; i++) for (size_t i = 0; i < ai->value.dim; i++)
{ Expression *e = (Expression *)index.data[i]; { Expression *e = index[i];
if (e) if (e)
e = e->syntaxCopy(); e = e->syntaxCopy();
ai->index.data[i] = e; ai->index[i] = e;
Initializer *init = (Initializer *)value.data[i]; Initializer *init = value[i];
init = init->syntaxCopy(); init = init->syntaxCopy();
ai->value.data[i] = init; ai->value[i] = init;
} }
return ai; return ai;
} }
@@ -532,7 +537,7 @@ Expression *ArrayInitializer::toExpression()
for (size_t i = 0, j = 0; i < value.dim; i++, j++) for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{ {
if (index[i]) if (index[i])
j = (index[i])->toInteger(); j = index[i]->toInteger();
if (j >= edim) if (j >= edim)
edim = j + 1; edim = j + 1;
} }
@@ -584,6 +589,7 @@ Lno:
return new ErrorExp(); return new ErrorExp();
} }
/******************************** /********************************
* If possible, convert array initializer to associative array initializer. * If possible, convert array initializer to associative array initializer.
*/ */
@@ -601,18 +607,18 @@ Initializer *ArrayInitializer::toAssocArrayInitializer()
for (size_t i = 0; i < value.dim; i++) for (size_t i = 0; i < value.dim; i++)
{ {
e = index.tdata()[i]; e = index[i];
if (!e) if (!e)
goto Lno; goto Lno;
keys->tdata()[i] = e; (*keys)[i] = e;
Initializer *iz = value.tdata()[i]; Initializer *iz = value[i];
if (!iz) if (!iz)
goto Lno; goto Lno;
e = iz->toExpression(); e = iz->toExpression();
if (!e) if (!e)
goto Lno; goto Lno;
values->tdata()[i] = e; (*values)[i] = e;
} }
e = new AssocArrayLiteralExp(loc, keys, values); e = new AssocArrayLiteralExp(loc, keys, values);
return new ExpInitializer(loc, e); return new ExpInitializer(loc, e);
@@ -668,13 +674,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ {
if (i > 0) if (i > 0)
buf->writebyte(','); buf->writebyte(',');
Expression *ex = index.tdata()[i]; Expression *ex = index[i];
if (ex) if (ex)
{ {
ex->toCBuffer(buf, hgs); ex->toCBuffer(buf, hgs);
buf->writebyte(':'); buf->writebyte(':');
} }
Initializer *iz = value.tdata()[i]; Initializer *iz = value[i];
if (iz) if (iz)
iz->toCBuffer(buf, hgs); iz->toCBuffer(buf, hgs);
} }
@@ -707,7 +713,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
return this; // Failed, suppress duplicate error messages return this; // Failed, suppress duplicate error messages
if (exp->op == TOKtype) if (exp->op == TOKtype)
error("initializer must be an expression, not '%s'", exp->toChars()); exp->error("initializer must be an expression, not '%s'", exp->toChars());
Type *tb = t->toBasetype(); Type *tb = t->toBasetype();
/* Look for case of initializing a static array with a too-short /* Look for case of initializing a static array with a too-short
@@ -767,7 +773,7 @@ Type *ExpInitializer::inferType(Scope *sc)
// Give error for overloaded function addresses // Give error for overloaded function addresses
if (exp->op == TOKdelegate) if (exp->op == TOKdelegate)
{ DelegateExp *se = (DelegateExp *)exp; { DelegateExp *se = (DelegateExp *)exp;
if ( if (se->hasOverloads &&
se->func->isFuncDeclaration() && se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique()) !se->func->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -196,6 +196,8 @@ int lambdaInlineCost(Expression *e, void *param)
int expressionInlineCost(Expression *e, InlineCostState *ics) int expressionInlineCost(Expression *e, InlineCostState *ics)
{ {
//printf("expressionInlineCost()\n");
//e->dump(0);
ICS2 ics2; ICS2 ics2;
ics2.cost = 0; ics2.cost = 0;
ics2.ics = ics; ics2.ics = ics;
@@ -340,6 +342,7 @@ struct InlineDoState
Dsymbols from; // old Dsymbols Dsymbols from; // old Dsymbols
Dsymbols to; // parallel array of new Dsymbols Dsymbols to; // parallel array of new Dsymbols
Dsymbol *parent; // new parent Dsymbol *parent; // new parent
FuncDeclaration *fd; // function being inlined (old parent)
}; };
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@@ -1486,6 +1489,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
if ( if (
!fbody || !fbody ||
ident == Id::ensure || // ensure() has magic properties the inliner loses ident == Id::ensure || // ensure() has magic properties the inliner loses
(ident == Id::require && // require() has magic properties too
toParent()->isFuncDeclaration() && // see bug 7699
toParent()->isFuncDeclaration()->needThis()) ||
!hdrscan && !hdrscan &&
( (
#if 0 #if 0
@@ -1600,6 +1606,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
memset(&ids, 0, sizeof(ids)); memset(&ids, 0, sizeof(ids));
ids.parent = iss->fd; ids.parent = iss->fd;
ids.fd = this;
if (ps) if (ps)
as = new Statements(); as = new Statements();
@@ -1786,6 +1793,18 @@ Expression *Expression::inlineCopy(Scope *sc)
*/ */
return copy(); return copy();
#else #else
if (op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)this;
if (de->func->isNested())
{ /* See Bugzilla 4820
* Defer checking until later if we actually need the 'this' pointer
*/
Expression *e = de->copy();
return e;
}
}
InlineCostState ics; InlineCostState ics;
memset(&ics, 0, sizeof(ics)); memset(&ics, 0, sizeof(ics));
@@ -1802,3 +1821,4 @@ Expression *Expression::inlineCopy(Scope *sc)
return e; return e;
#endif #endif
} }

View File

@@ -27,7 +27,6 @@
#include "attrib.h" // for AttribDeclaration #include "attrib.h" // for AttribDeclaration
#include "template.h" #include "template.h"
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd);
#define LOG 0 #define LOG 0
@@ -45,6 +44,10 @@ private:
together with the VarDeclaration, and the previous together with the VarDeclaration, and the previous
stack address of that variable, so that we can restore it stack address of that variable, so that we can restore it
when we leave the stack frame. when we leave the stack frame.
Note that when a function is forward referenced, the interpreter must
run semantic3, and that may start CTFE again with a NULL istate. Thus
the stack might not be empty when CTFE begins.
Ctfe Stack addresses are just 0-based integers, but we save Ctfe Stack addresses are just 0-based integers, but we save
them as 'void *' because ArrayBase can only do pointers. them as 'void *' because ArrayBase can only do pointers.
*/ */
@@ -143,7 +146,11 @@ public:
} }
void saveGlobalConstant(VarDeclaration *v, Expression *e) void saveGlobalConstant(VarDeclaration *v, Expression *e)
{ {
assert(v->isDataseg() && !v->isCTFE()); #if DMDV2
assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE());
#else
assert( v->init && v->isConst() && !v->isCTFE());
#endif
v->ctfeAdrOnStack = globalValues.dim; v->ctfeAdrOnStack = globalValues.dim;
globalValues.push(e); globalValues.push(e);
} }
@@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval);
bool needToCopyLiteral(Expression *expr); bool needToCopyLiteral(Expression *expr);
Expression *copyLiteral(Expression *e); Expression *copyLiteral(Expression *e);
Expression *paintTypeOntoLiteral(Type *type, Expression *lit); Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2); Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
Expression *evaluateIfBuiltin(InterState *istate, Loc loc, Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
FuncDeclaration *fd, Expressions *arguments, Expression *pthis); FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
Expression *scrubReturnValue(Loc loc, Expression *e); Expression *scrubReturnValue(Loc loc, Expression *e);
@@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression
{ {
return value->sd->isClassDeclaration(); return value->sd->isClassDeclaration();
} }
VarDeclaration *getFieldAt(int index)
{
ClassDeclaration *cd = originalClass();
size_t fieldsSoFar = 0;
while (index - fieldsSoFar >= cd->fields.dim)
{ fieldsSoFar += cd->fields.dim;
cd = cd->baseClass;
}
return cd->fields.tdata()[index - fieldsSoFar];
}
// Return index of the field, or -1 if not found // Return index of the field, or -1 if not found
int getFieldIndex(Type *fieldtype, size_t fieldoffset) int getFieldIndex(Type *fieldtype, size_t fieldoffset)
{ {
@@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression
} }
}; };
struct VoidInitExp : Expression
{
VarDeclaration *var;
VoidInitExp(VarDeclaration *var, Type *type)
: Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
{
this->var = var;
this->type = var->type;
}
char *toChars()
{
return (char *)"void";
}
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue)
{
error("CTFE internal error: trying to read uninitialized variable");
assert(0);
return EXP_CANT_INTERPRET;
}
};
// Return index of the field, or -1 if not found // Return index of the field, or -1 if not found
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration // Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
@@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0)
* arguments function arguments * arguments function arguments
* thisarg 'this', if a needThis() function, NULL if not. * thisarg 'this', if a needThis() function, NULL if not.
* *
* Return result expression if successful, EXP_CANT_INTERPRET if not. * Return result expression if successful, EXP_CANT_INTERPRET if not,
* or EXP_VOID_INTERPRET if function returned void.
*/ */
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
@@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
*/ */
int olderrors = global.errors; int olderrors = global.errors;
int oldgag = global.gag; int oldgag = global.gag;
TemplateInstance *spec = isSpeculativeFunction(this); TemplateInstance *spec = isSpeculative();
if (global.gag && !spec) if (global.gag && !spec)
global.gag = 0; global.gag = 0;
semantic3(scope); semantic3(scope);
@@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
--evaluatingArgs; --evaluatingArgs;
if (earg == EXP_CANT_INTERPRET) if (earg == EXP_CANT_INTERPRET)
return earg; return earg;
/* Struct literals are passed by value, but we don't need to
* copy them if they are passed as const
*/
if (earg->op == TOKstructliteral
#if DMDV2
&& !(arg->storageClass & (STCconst | STCimmutable))
#endif
)
earg = copyLiteral(earg);
} }
if (earg->op == TOKthrownexception) if (earg->op == TOKthrownexception)
{ {
@@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
// If fell off the end of a void function, return void // If fell off the end of a void function, return void
if (!e && type->toBasetype()->nextOf()->ty == Tvoid) if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
return EXP_VOID_INTERPRET; return EXP_VOID_INTERPRET;
// If result is void, return void
if (e == EXP_VOID_INTERPRET)
return e;
// If it generated an exception, return it // If it generated an exception, return it
if (exceptionOrCantInterpret(e)) if (exceptionOrCantInterpret(e))
{ {
@@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
((ThrownExceptionExp *)e)->generateUncaughtError(); ((ThrownExceptionExp *)e)->generateUncaughtError();
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
// If we're about to leave CTFE, make sure we don't crash the
// compiler by returning a CTFE-internal expression.
if (!istate && !evaluatingArgs) if (!istate && !evaluatingArgs)
{ {
e = scrubReturnValue(loc, e); e = scrubReturnValue(loc, e);
@@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e)
} }
// As Equal, but resolves slices before comparing // As Equal, but resolves slices before comparing
Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2)
{ {
if (e1->op == TOKslice) if (e1->op == TOKslice)
e1 = resolveSlice(e1); e1 = resolveSlice(e1);
if (e2->op == TOKslice) if (e2->op == TOKslice)
e2 = resolveSlice(e2); e2 = resolveSlice(e2);
return Equal(op, type, e1, 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) Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
@@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
return Cat(type, e1, e2); return Cat(type, e1, e2);
} }
void scrubArray(Loc loc, Expressions *elems); bool scrubArray(Loc loc, Expressions *elems, bool structlit = false);
/* All results destined for use outside of CTFE need to have their CTFE-specific /* All results destined for use outside of CTFE need to have their CTFE-specific
* features removed. * features removed.
@@ -986,6 +1046,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
if (e->op == TOKvoid)
{
error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
e = new ErrorExp();
}
if (e->op == TOKslice) if (e->op == TOKslice)
{ {
e = resolveSlice(e); e = resolveSlice(e);
@@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
{ {
StructLiteralExp *se = (StructLiteralExp *)e; StructLiteralExp *se = (StructLiteralExp *)e;
se->ownedByCtfe = false; se->ownedByCtfe = false;
scrubArray(loc, se->elements); if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
} }
if (e->op == TOKstring) if (e->op == TOKstring)
{ {
@@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
if (e->op == TOKarrayliteral) if (e->op == TOKarrayliteral)
{ {
((ArrayLiteralExp *)e)->ownedByCtfe = false; ((ArrayLiteralExp *)e)->ownedByCtfe = false;
scrubArray(loc, ((ArrayLiteralExp *)e)->elements); if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
return EXP_CANT_INTERPRET;
} }
if (e->op == TOKassocarrayliteral) if (e->op == TOKassocarrayliteral)
{ {
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
aae->ownedByCtfe = false; aae->ownedByCtfe = false;
scrubArray(loc, aae->keys); if (!scrubArray(loc, aae->keys))
scrubArray(loc, aae->values); return EXP_CANT_INTERPRET;
if (!scrubArray(loc, aae->values))
return EXP_CANT_INTERPRET;
} }
return e; return e;
} }
// Scrub all members of an array // Scrub all members of an array. Return false if error
void scrubArray(Loc loc, Expressions *elems) bool scrubArray(Loc loc, Expressions *elems, bool structlit)
{ {
for (size_t i = 0; i < elems->dim; i++) for (size_t i = 0; i < elems->dim; i++)
{ {
Expression *m = elems->tdata()[i]; Expression *m = elems->tdata()[i];
if (!m) if (!m)
continue; continue;
m = scrubReturnValue(loc, m); if (m && m->op == TOKvoid && structlit)
m = NULL;
if (m)
m = scrubReturnValue(loc, m);
if (m == EXP_CANT_INTERPRET)
return false;
elems->tdata()[i] = m; elems->tdata()[i] = m;
} }
return true;
} }
@@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate)
Expression * caseExp = cs->exp->interpret(istate); Expression * caseExp = cs->exp->interpret(istate);
if (exceptionOrCantInterpret(caseExp)) if (exceptionOrCantInterpret(caseExp))
return caseExp; return caseExp;
e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp); e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp);
if (exceptionOrCantInterpret(e)) if (exceptionOrCantInterpret(e))
return e; return e;
if (e->isBool(TRUE)) if (e->isBool(TRUE))
@@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate)
ThrownExceptionExp *ex = (ThrownExceptionExp *)e; ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
Type *extype = ex->thrown->originalClass()->type; Type *extype = ex->thrown->originalClass()->type;
// Search for an appropriate catch clause. // Search for an appropriate catch clause.
for (size_t i = 0; i < catches->dim; i++) for (size_t i = 0; i < catches->dim; i++)
{ {
#if DMDV1 #if DMDV1
Catch *ca = (Catch *)catches->data[i]; Catch *ca = (Catch *)catches->data[i];
#else #else
Catch *ca = catches->tdata()[i]; Catch *ca = catches->tdata()[i];
#endif #endif
Type *catype = ca->type; Type *catype = ca->type;
if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler { // Execute the handler
if (ca->var) if (ca->var)
{ {
ctfeStack.push(ca->var); ctfeStack.push(ca->var);
ca->var->setValue(ex->thrown); ca->var->setValue(ex->thrown);
} }
return ca->handler->interpret(istate); return ca->handler ? ca->handler->interpret(istate) : NULL;
}
} }
}
return e; return e;
} }
@@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
} }
Type *pointee = ((TypePointer *)type)->next; Type *pointee = ((TypePointer *)type)->next;
Expression *val = getVarExp(loc, istate, var, goal); Expression *val = getVarExp(loc, istate, var, goal);
if (val == EXP_CANT_INTERPRET)
return val;
if (val->type->ty == Tarray || val->type->ty == Tsarray) if (val->type->ty == Tarray || val->type->ty == Tsarray)
{ {
// Check for unsupported type painting operations // Check for unsupported type painting operations
@@ -1907,10 +1984,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception)
{ {
e = copyLiteral(e); e = copyLiteral(e);
if (v->isDataseg()) ctfeStack.saveGlobalConstant(v, e);
ctfeStack.saveGlobalConstant(v, e);
else
v->setValueWithoutChecking(e);
} }
} }
else if (v->isCTFE() && !v->hasValue()) else if (v->isCTFE() && !v->hasValue())
@@ -1919,11 +1993,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
{ {
if (v->init->isVoidInitializer()) if (v->init->isVoidInitializer())
{ {
error(loc, "variable %s is used before initialization", v->toChars()); // var should have been initialized when it was created
return EXP_CANT_INTERPRET; error(loc, "CTFE internal error - trying to access uninitialized var");
assert(0);
e = EXP_CANT_INTERPRET;
}
else
{
e = v->init->toExpression();
e = e->interpret(istate);
} }
e = v->init->toExpression();
e = e->interpret(istate);
} }
else else
e = v->type->defaultInitLiteral(loc); e = v->type->defaultInitLiteral(loc);
@@ -1939,7 +2018,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
e = EXP_CANT_INTERPRET; e = EXP_CANT_INTERPRET;
} }
else if (!e) else if (!e)
error(loc, "variable %s is used before initialization", v->toChars()); {
assert(0);
assert(v->init && v->init->isVoidInitializer());
e = v->type->voidInitLiteral(v);
}
else if (exceptionOrCantInterpret(e)) else if (exceptionOrCantInterpret(e))
return e; return e;
else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex) else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex)
@@ -1958,6 +2041,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|| e->op == TOKassocarrayliteral || e->op == TOKslice || e->op == TOKassocarrayliteral || e->op == TOKslice
|| e->type->toBasetype()->ty == Tpointer) || e->type->toBasetype()->ty == Tpointer)
return e; // it's already an Lvalue return e; // it's already an Lvalue
else if (e->op == TOKvoid)
{
VoidInitExp *ve = (VoidInitExp *)e;
error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars());
errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars());
e = EXP_CANT_INTERPRET;
}
else else
e = e->interpret(istate, goal); e = e->interpret(istate, goal);
} }
@@ -1971,10 +2061,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
if (s->dsym->toInitializer() == s->sym) if (s->dsym->toInitializer() == s->sym)
{ {
#endif #endif
e = s->dsym->type->defaultInitLiteral(); e = s->dsym->type->defaultInitLiteral(loc);
e = e->semantic(NULL); e = e->semantic(NULL);
if (e->op == TOKerror) if (e->op == TOKerror)
e = EXP_CANT_INTERPRET; e = EXP_CANT_INTERPRET;
else // Convert NULL to VoidExp
e = e->interpret(istate, goal);
#if !IN_LLVM #if !IN_LLVM
} }
else else
@@ -2045,7 +2137,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
if (ie) if (ie)
e = ie->exp->interpret(istate); e = ie->exp->interpret(istate);
else if (v->init->isVoidInitializer()) else if (v->init->isVoidInitializer())
e = NULL; {
e = v->type->voidInitLiteral(v);
// There is no AssignExp for void initializers,
// so set it here.
v->setValue(e);
}
else else
{ {
error("Declaration %s is not yet implemented in CTFE", toChars()); error("Declaration %s is not yet implemented in CTFE", toChars());
@@ -2274,7 +2371,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
ekey = resolveSlice(ekey); ekey = resolveSlice(ekey);
for (size_t j = i; j < keysx->dim; j++) for (size_t j = i; j < keysx->dim; j++)
{ Expression *ekey2 = keysx->tdata()[j]; { Expression *ekey2 = keysx->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2);
if (ex == EXP_CANT_INTERPRET) if (ex == EXP_CANT_INTERPRET)
goto Lerr; goto Lerr;
if (ex->isBool(TRUE)) // if a match if (ex->isBool(TRUE)) // if a match
@@ -2448,10 +2545,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
if (elemType->ty == Tchar || elemType->ty == Twchar if (elemType->ty == Tchar || elemType->ty == Twchar
|| elemType->ty == Tdchar) || elemType->ty == Tdchar)
return createBlockDuplicatedStringLiteral(loc, newtype, return createBlockDuplicatedStringLiteral(loc, newtype,
(unsigned)(elemType->defaultInitLiteral()->toInteger()), (unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
len, elemType->size()); len, elemType->size());
return createBlockDuplicatedArrayLiteral(loc, newtype, return createBlockDuplicatedArrayLiteral(loc, newtype,
elemType->defaultInitLiteral(), elemType->defaultInitLiteral(loc),
len); len);
} }
@@ -2465,7 +2562,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
if (newtype->toBasetype()->ty == Tstruct) if (newtype->toBasetype()->ty == Tstruct)
{ {
Expression *se = newtype->defaultInitLiteral(); Expression *se = newtype->defaultInitLiteral(loc);
#if DMDV2 #if DMDV2
if (member) if (member)
{ {
@@ -2502,7 +2599,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
Dsymbol *s = c->fields.tdata()[i]; Dsymbol *s = c->fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration(); VarDeclaration *v = s->isVarDeclaration();
assert(v); assert(v);
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(); Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc);
if (exceptionOrCantInterpret(m)) if (exceptionOrCantInterpret(m))
return m; return m;
elems->tdata()[fieldsSoFar+i] = copyLiteral(m); elems->tdata()[fieldsSoFar+i] = copyLiteral(m);
@@ -2672,7 +2769,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
} }
if (indx < 0 || indx > len) if (indx < 0 || indx > len)
{ {
error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -2974,7 +3071,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi
for (size_t j = valuesx->dim; j; ) for (size_t j = valuesx->dim; j; )
{ j--; { j--;
Expression *ekey = aae->keys->tdata()[j]; Expression *ekey = aae->keys->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
if (exceptionOrCantInterpret(ex)) if (exceptionOrCantInterpret(ex))
return ex; return ex;
if (ex->isBool(TRUE)) if (ex->isBool(TRUE))
@@ -3144,7 +3241,7 @@ Expression *copyLiteral(Expression *e)
assert(v); assert(v);
// If it is a void assignment, use the default initializer // If it is a void assignment, use the default initializer
if (!m) if (!m)
m = v->type->defaultInitLiteral(e->loc); m = v->type->voidInitLiteral(v);
if (m->op == TOKslice) if (m->op == TOKslice)
m = resolveSlice(m); m = resolveSlice(m);
if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
@@ -3171,7 +3268,8 @@ Expression *copyLiteral(Expression *e)
|| e->op == TOKsymoff || e->op == TOKnull || e->op == TOKsymoff || e->op == TOKnull
|| e->op == TOKvar || e->op == TOKvar
|| e->op == TOKint64 || e->op == TOKfloat64 || e->op == TOKint64 || e->op == TOKfloat64
|| e->op == TOKchar || e->op == TOKcomplex80) || e->op == TOKchar || e->op == TOKcomplex80
|| e->op == TOKvoid)
{ // Simple value types { // Simple value types
Expression *r = e->syntaxCopy(); Expression *r = e->syntaxCopy();
r->type = e->type; r->type = e->type;
@@ -3341,7 +3439,7 @@ void assignInPlace(Expression *dest, Expression *src)
assert(o->op == e->op); assert(o->op == e->op);
assignInPlace(o, e); assignInPlace(o, e);
} }
else if (e->type->ty == Tsarray && o->type->ty == Tsarray) else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid)
{ {
assignInPlace(o, e); assignInPlace(o, e);
} }
@@ -3636,7 +3734,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
Type *elemType= NULL; Type *elemType= NULL;
elemType = ((TypeArray *)t)->next; elemType = ((TypeArray *)t)->next;
assert(elemType); assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral(); Expression *defaultElem = elemType->defaultInitLiteral(loc);
Expressions *elements = new Expressions(); Expressions *elements = new Expressions();
elements->setDim(newlen); elements->setDim(newlen);
@@ -3744,7 +3842,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
// only modifying part of the variable. So we need to make sure // only modifying part of the variable. So we need to make sure
// that the parent variable exists. // that the parent variable exists.
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc)));
// --------------------------------------- // ---------------------------------------
// Deal with reference assignment // Deal with reference assignment
@@ -3822,7 +3920,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
indx = resolveSlice(indx); indx = resolveSlice(indx);
// Look up this index in it up in the existing AA, to get the next level of AA. // Look up this index in it up in the existing AA, to get the next level of AA.
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx); AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx);
if (exceptionOrCantInterpret(newAA)) if (exceptionOrCantInterpret(newAA))
return newAA; return newAA;
if (!newAA) if (!newAA)
@@ -3968,14 +4066,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
? (StructLiteralExp *)exx ? (StructLiteralExp *)exx
: ((ClassReferenceExp *)exx)->value; : ((ClassReferenceExp *)exx)->value;
int fieldi = exx->op == TOKstructliteral int fieldi = exx->op == TOKstructliteral
? se->getFieldIndex(member->type, member->offset) ? findFieldIndexByName(se->sd, member)
: ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset); : ((ClassReferenceExp *)exx)->findFieldIndexByName(member);
if (fieldi == -1) if (fieldi == -1)
{ {
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars()); error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
assert(fieldi>=0 && fieldi < se->elements->dim); assert(fieldi >= 0 && fieldi < se->elements->dim);
// If it's a union, set all other members of this union to void
if (exx->op == TOKstructliteral)
{
assert(se->sd);
int unionStart = se->sd->firstFieldInUnion(fieldi);
int unionSize = se->sd->numFieldsInUnion(fieldi);
for(int i = unionStart; i < unionStart + unionSize; ++i)
{ if (i == fieldi)
continue;
Expression **el = &se->elements->tdata()[i];
if ((*el)->op != TOKvoid)
*el = (*el)->type->voidInitLiteral(member);
}
}
if (newval->op == TOKstructliteral) if (newval->op == TOKstructliteral)
assignInPlace(se->elements->tdata()[fieldi], newval); assignInPlace(se->elements->tdata()[fieldi], newval);
else else
@@ -4050,6 +4163,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
} }
aggregate = getAggregateFromPointer(aggregate, &ofs); aggregate = getAggregateFromPointer(aggregate, &ofs);
indexToModify += ofs; indexToModify += ofs;
if (aggregate->op != TOKslice && aggregate->op != TOKstring &&
aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral)
{
if (indexToModify != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]", indexToModify);
return EXP_CANT_INTERPRET;
}
// It is equivalent to *aggregate = newval.
// Aggregate could be varexp, a dotvar, ...
// TODO: we could support this
error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead",
ie->e1->toChars(), e2->toChars());
return EXP_CANT_INTERPRET;
}
destarraylen = resolveArrayLength(aggregate); destarraylen = resolveArrayLength(aggregate);
} }
if (indexToModify >= destarraylen) if (indexToModify >= destarraylen)
@@ -4075,7 +4203,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{ {
IndexExp *ix = (IndexExp *)aggregate; IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate) if (!aggregate)
{ {
error("key %s not found in associative array %s", error("key %s not found in associative array %s",
@@ -4177,6 +4305,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (isPointer(oldval->type)) if (isPointer(oldval->type))
{ // Slicing a pointer { // Slicing a pointer
oldval = oldval->interpret(istate, ctfeNeedLvalue); oldval = oldval->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(oldval))
return oldval;
dinteger_t ofs; dinteger_t ofs;
oldval = getAggregateFromPointer(oldval, &ofs); oldval = getAggregateFromPointer(oldval, &ofs);
assignmentToSlicedPointer = true; assignmentToSlicedPointer = true;
@@ -4186,7 +4316,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
&& oldval->op != TOKslice && oldval->op != TOKnull) && oldval->op != TOKslice && oldval->op != TOKnull)
{ {
error("CTFE ICE: cannot resolve array length"); if (assignmentToSlicedPointer)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
sexp->e1->toChars());
}
else
error("CTFE ICE: cannot resolve array length");
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
uinteger_t dollar = resolveArrayLength(oldval); uinteger_t dollar = resolveArrayLength(oldval);
@@ -4249,7 +4385,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{ {
IndexExp *ix = (IndexExp *)aggregate; IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate) if (!aggregate)
{ {
error("key %s not found in associative array %s", error("key %s not found in associative array %s",
@@ -4273,7 +4409,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
firstIndex = lowerbound + sexpold->lwr->toInteger(); firstIndex = lowerbound + sexpold->lwr->toInteger();
if (hi > sexpold->upr->toInteger()) if (hi > sexpold->upr->toInteger())
{ {
error("slice [%d..%d] exceeds array bounds [0..%jd]", error("slice [%d..%d] exceeds array bounds [0..%lld]",
lowerbound, upperbound, lowerbound, upperbound,
sexpold->upr->toInteger() - sexpold->lwr->toInteger()); sexpold->upr->toInteger() - sexpold->lwr->toInteger());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
@@ -4285,11 +4421,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
dinteger_t ofs; dinteger_t ofs;
aggregate = getAggregateFromPointer(aggregate, &ofs); aggregate = getAggregateFromPointer(aggregate, &ofs);
if (aggregate->op == TOKnull)
{
error("cannot slice null pointer %s", sexp->e1->toChars());
return EXP_CANT_INTERPRET;
}
dinteger_t hi = upperbound + ofs; dinteger_t hi = upperbound + ofs;
firstIndex = lowerbound + ofs; firstIndex = lowerbound + ofs;
if (firstIndex < 0 || hi > dim) if (firstIndex < 0 || hi > dim)
{ {
error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", error("slice [lld..%lld] exceeds memory block bounds [0..%lld]",
firstIndex, hi, dim); firstIndex, hi, dim);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -4430,9 +4571,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
else else
{ {
error("%s cannot be evaluated at compile time", toChars()); error("%s cannot be evaluated at compile time", toChars());
#ifdef DEBUG
dump(0);
#endif
} }
return returnValue; return returnValue;
} }
@@ -4812,6 +4950,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
if (!global.gag) if (!global.gag)
showCtfeBackTrace(istate, this, fd); showCtfeBackTrace(istate, this, fd);
} }
else if (eresult == EXP_VOID_INTERPRET)
;
else
eresult->loc = loc;
return eresult; return eresult;
} }
@@ -4830,7 +4972,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
InterState istateComma; InterState istateComma;
if (!istate && firstComma->e1->op == TOKdeclaration) if (!istate && firstComma->e1->op == TOKdeclaration)
{ {
assert(ctfeStack.stackPointer() == 0);
ctfeStack.startFrame(); ctfeStack.startFrame();
istate = &istateComma; istate = &istateComma;
} }
@@ -4848,7 +4989,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
ctfeStack.push(v); ctfeStack.push(v);
if (!v->init && !v->getValue()) if (!v->init && !v->getValue())
{ {
v->setValue(copyLiteral(v->type->defaultInitLiteral())); v->setValue(copyLiteral(v->type->defaultInitLiteral(loc)));
} }
if (!v->getValue()) { if (!v->getValue()) {
Expression *newval = v->init->toExpression(); Expression *newval = v->init->toExpression();
@@ -4944,7 +5085,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal)
* Return ae[e2] if present, or NULL if not found. * Return ae[e2] if present, or NULL if not found.
* Return EXP_CANT_INTERPRET on error. * Return EXP_CANT_INTERPRET on error.
*/ */
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
{ {
/* Search the keys backwards, in case there are duplicate keys /* Search the keys backwards, in case there are duplicate keys
*/ */
@@ -4952,13 +5093,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
{ {
i--; i--;
Expression *ekey = ae->keys->tdata()[i]; Expression *ekey = ae->keys->tdata()[i];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2);
if (ex == EXP_CANT_INTERPRET) if (ex == EXP_CANT_INTERPRET)
{
error("cannot evaluate %s==%s at compile time",
ekey->toChars(), e2->toChars());
return ex; return ex;
}
if (ex->isBool(TRUE)) if (ex->isBool(TRUE))
{ {
return ae->values->tdata()[i]; return ae->values->tdata()[i];
@@ -5013,23 +5150,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
if (exceptionOrCantInterpret(e2)) if (exceptionOrCantInterpret(e2))
return e2; return e2;
dinteger_t indx = e2->toInteger(); dinteger_t indx = e2->toInteger();
dinteger_t ofs; dinteger_t ofs;
Expression *agg = getAggregateFromPointer(e1, &ofs); Expression *agg = getAggregateFromPointer(e1, &ofs);
if (agg->op == TOKnull) if (agg->op == TOKnull)
{ {
error("cannot index null pointer %s", this->e1->toChars()); error("cannot index null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
assert(agg->op == TOKarrayliteral || agg->op == TOKstring); if ( agg->op == TOKarrayliteral || agg->op == TOKstring)
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
Type *pointee = ((TypePointer *)agg->type)->next;
if ((indx + ofs) < 0 || (indx+ofs) > len)
{ {
error("pointer index [%jd] exceeds allocated memory block [0..%jd]", dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
indx+ofs, len); Type *pointee = ((TypePointer *)agg->type)->next;
return EXP_CANT_INTERPRET; if ((indx + ofs) < 0 || (indx+ofs) > len)
{
error("pointer index [%lld] exceeds allocated memory block [0..%lld]",
indx+ofs, len);
return EXP_CANT_INTERPRET;
}
return ctfeIndex(loc, type, agg, indx+ofs);
}
else
{ // Pointer to a non-array variable
if ((indx + ofs) != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]",
indx+ofs);
return EXP_CANT_INTERPRET;
}
return agg->interpret(istate);
} }
return ctfeIndex(loc, type, agg, indx+ofs);
} }
e1 = this->e1; e1 = this->e1;
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe)) if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
@@ -5070,7 +5221,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
if (indx > iup - ilo) if (indx > iup - ilo)
{ {
error("index %ju exceeds array length %ju", indx, iup - ilo); error("index %llu exceeds array length %llu", indx, iup - ilo);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
indx += ilo; indx += ilo;
@@ -5091,7 +5242,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
{ {
if (e2->op == TOKslice) if (e2->op == TOKslice)
e2 = resolveSlice(e2); e2 = resolveSlice(e2);
e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2);
if (!e) if (!e)
{ {
error("key %s not found in associative array %s", error("key %s not found in associative array %s",
@@ -5112,6 +5263,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
return e; return e;
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
e = e->interpret(istate); e = e->interpret(istate);
if (goal == ctfeNeedRvalue && e->op == TOKvoid)
{
error("%s is used before initialized", toChars());
errorSupplemental(e->loc, "originally uninitialized here");
return EXP_CANT_INTERPRET;
}
e = paintTypeOntoLiteral(type, e); e = paintTypeOntoLiteral(type, e);
return e; return e;
} }
@@ -5166,12 +5323,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
error("cannot slice null pointer %s", this->e1->toChars()); error("cannot slice null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
if (agg->op != TOKarrayliteral && agg->op != TOKstring)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
this->e1->toChars());
return EXP_CANT_INTERPRET;
}
assert(agg->op == TOKarrayliteral || agg->op == TOKstring); assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); 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) if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
{ {
error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]",
ilwr+ofs, iupr+ofs, len); ilwr+ofs, iupr+ofs, len);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -5235,7 +5398,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{ {
if (ilwr== 0 && iupr == 0) if (ilwr== 0 && iupr == 0)
return e1; return e1;
e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
if (e1->op == TOKslice) if (e1->op == TOKslice)
@@ -5247,7 +5410,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
uinteger_t up1 = se->upr->toInteger(); uinteger_t up1 = se->upr->toInteger();
if (ilwr > iupr || iupr > up1 - lo1) if (ilwr > iupr || iupr > up1 - lo1)
{ {
error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]",
ilwr, iupr, lo1, up1); ilwr, iupr, lo1, up1);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -5264,7 +5427,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{ {
if (iupr < ilwr || ilwr < 0 || iupr > dollar) if (iupr < ilwr || ilwr < 0 || iupr > dollar)
{ {
error("slice [%jd..%jd] exceeds array bounds [0..%jd]", error("slice [%lld..%lld] exceeds array bounds [0..%lld]",
ilwr, iupr, dollar); ilwr, iupr, dollar);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -5295,7 +5458,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
} }
if (e1->op == TOKslice) if (e1->op == TOKslice)
e1 = resolveSlice(e1); e1 = resolveSlice(e1);
e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1);
if (exceptionOrCantInterpret(e)) if (exceptionOrCantInterpret(e))
return e; return e;
if (!e) if (!e)
@@ -5354,8 +5517,12 @@ bool isAssocArray(Type *t)
if (t->ty != Tstruct) if (t->ty != Tstruct)
return false; return false;
StructDeclaration *sym = ((TypeStruct *)t)->sym; StructDeclaration *sym = ((TypeStruct *)t)->sym;
if (sym->ident == Id::AssociativeArray) if (sym->ident == Id::AssociativeArray && sym->parent &&
sym->parent->parent &&
sym->parent->parent->ident == Id::object)
{
return true; return true;
}
#endif #endif
return false; return false;
} }
@@ -5510,9 +5677,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
e->type = type; e->type = type;
return e; return e;
} }
error("pointer cast from %s to %s is not supported at compile time",
// Check if we have a null pointer (eg, inside a struct)
e1 = e1->interpret(istate);
if (e1->op != TOKnull)
{
error("pointer cast from %s to %s is not supported at compile time",
e1->type->toChars(), to->toChars()); e1->type->toChars(), to->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
}
} }
if (to->ty == Tarray && e1->op == TOKslice) if (to->ty == Tarray && e1->op == TOKslice)
{ {
@@ -5660,7 +5833,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
assert(indx >=0 && indx <= len); // invalid pointer assert(indx >=0 && indx <= len); // invalid pointer
if (indx == len) if (indx == len)
{ {
error("dereference of pointer %s one past end of memory block limits [0..%jd]", error("dereference of pointer %s one past end of memory block limits [0..%lld]",
toChars(), len); toChars(), len);
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
@@ -5705,7 +5878,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
} }
else if (e->op == TOKaddress) else if (e->op == TOKaddress)
e = ((AddrExp*)e)->e1; // *(&x) ==> x e = ((AddrExp*)e)->e1; // *(&x) ==> x
if (e->op == TOKnull) else if (e->op == TOKnull)
{ {
error("dereference of null pointer '%s'", e1->toChars()); error("dereference of null pointer '%s'", e1->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
@@ -5794,6 +5967,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
if (e->op == TOKstructliteral || e->op == TOKarrayliteral || if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
e->op == TOKassocarrayliteral || e->op == TOKstring) e->op == TOKassocarrayliteral || e->op == TOKstring)
return e; return e;
if (e->op == TOKvoid)
{
VoidInitExp *ve = (VoidInitExp *)e;
error("cannot read uninitialized variable %s in ctfe", toChars());
ve->var->error("was uninitialized and used before set");
return EXP_CANT_INTERPRET;
}
if ( isPointer(type) ) if ( isPointer(type) )
{ {
return paintTypeOntoLiteral(type, e); return paintTypeOntoLiteral(type, e);
@@ -5838,7 +6018,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal)
size_t removed = 0; size_t removed = 0;
for (size_t j = 0; j < valuesx->dim; ++j) for (size_t j = 0; j < valuesx->dim; ++j)
{ Expression *ekey = keysx->tdata()[j]; { Expression *ekey = keysx->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
if (exceptionOrCantInterpret(ex)) if (exceptionOrCantInterpret(ex))
return ex; return ex;
if (ex->isBool(TRUE)) if (ex->isBool(TRUE))
@@ -6017,7 +6197,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
else if (str->op == TOKarrayliteral) else if (str->op == TOKarrayliteral)
ale = (ArrayLiteralExp *)str; ale = (ArrayLiteralExp *)str;
else else
{ error("CTFE internal error: cannot foreach %s", str->toChars()); { str->error("CTFE internal error: cannot foreach %s", str->toChars());
return EXP_CANT_INTERPRET; return EXP_CANT_INTERPRET;
} }
Expressions args; Expressions args;
@@ -6472,6 +6652,10 @@ bool isCtfeValueValid(Expression *newval)
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe); assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
return true; return true;
} }
if (newval->op == TOKvoid)
{
return true;
}
newval->error("CTFE internal error: illegal value %s\n", newval->toChars()); newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
return false; return false;
} }
@@ -6504,3 +6688,29 @@ void VarDeclaration::setValue(Expression *newval)
assert(isCtfeValueValid(newval)); assert(isCtfeValueValid(newval));
ctfeStack.setValue(this, newval); ctfeStack.setValue(this, newval);
} }
Expression *Type::voidInitLiteral(VarDeclaration *var)
{
return new VoidInitExp(var, this);
}
Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
{
return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger());
}
Expression *TypeStruct::voidInitLiteral(VarDeclaration *var)
{
Expressions *exps = new Expressions();
exps->setDim(sym->fields.dim);
for (size_t i = 0; i < sym->fields.dim; i++)
{
//(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
(*exps)[i] = sym->fields[i]->type->voidInitLiteral(var);
}
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
se->type = this;
se->ownedByCtfe = true;
return se;
}

View File

@@ -304,7 +304,7 @@ void Lexer::error(const char *format, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
verror(loc, format, ap); verror(tokenLoc(), format, ap);
va_end(ap); va_end(ap);
} }
@@ -2870,6 +2870,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
return c; return c;
} }
/*******************************************
* Search actual location of current token
* even when infinite look-ahead was done.
*/
Loc Lexer::tokenLoc()
{
Loc result = this->loc;
Token* last = &token;
while (last->next)
last = last->next;
unsigned char* start = token.ptr;
unsigned char* stop = last->ptr;
for (unsigned char* p = start; p < stop; ++p)
{
switch (*p)
{
case '\n':
result.linnum--;
break;
case '\r':
if (p[1] != '\n')
result.linnum--;
break;
default:
break;
}
}
return result;
}
/******************************************** /********************************************
* Create an identifier in the string table. * Create an identifier in the string table.
*/ */

View File

@@ -312,6 +312,8 @@ struct Lexer
static int isValidIdentifier(char *p); static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
Loc tokenLoc();
}; };
#endif /* DMD_LEXER_H */ #endif /* DMD_LEXER_H */

View File

@@ -72,7 +72,7 @@ Global::Global()
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen"; copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
written = "written by Walter Bright and Tomas Lindquist Olsen"; written = "written by Walter Bright and Tomas Lindquist Olsen";
version = "v1.073"; version = "v1.074";
ldc_version = "LDC trunk"; ldc_version = "LDC trunk";
llvm_version = "LLVM 3.0"; llvm_version = "LLVM 3.0";
global.structalign = 8; global.structalign = 8;
@@ -102,6 +102,11 @@ bool Global::endGagging(unsigned oldGagged)
return anyErrs; return anyErrs;
} }
bool Global::isSpeculativeGagging()
{
return gag && gag == speculativeGag;
}
char *Loc::toChars() const char *Loc::toChars() const
{ {

View File

@@ -347,6 +347,12 @@ struct Global
unsigned gag; // !=0 means gag reporting of errors & warnings unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned gaggedErrors; // number of errors reported while gagged unsigned gaggedErrors; // number of errors reported while gagged
/* Gagging can either be speculative (is(typeof()), etc)
* or because of forward references
*/
unsigned speculativeGag; // == gag means gagging is for is(typeof);
bool isSpeculativeGagging();
// Start gagging. Return the current number of gagged errors // Start gagging. Return the current number of gagged errors
unsigned startGagging(); unsigned startGagging();

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -387,7 +387,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
} }
m->read(loc); if (!m->read(loc))
return NULL;
m->parse(); m->parse();
#ifdef IN_GCC #ifdef IN_GCC
@@ -397,7 +399,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
return m; return m;
} }
void Module::read(Loc loc) bool Module::read(Loc loc)
{ {
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
if (srcfile->read()) if (srcfile->read())
@@ -415,9 +417,11 @@ void Module::read(Loc loc)
} }
else else
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
fatal();
} }
fatal(); return false;
} }
return true;
} }
inline unsigned readwordLE(unsigned short *p) inline unsigned readwordLE(unsigned short *p)
@@ -684,7 +688,15 @@ void Module::parse()
if (md) if (md)
{ this->ident = md->id; { this->ident = md->id;
dst = Package::resolve(md->packages, &this->parent, NULL); this->safe = md->safe;
Package *ppack = NULL;
dst = Package::resolve(md->packages, &this->parent, &ppack);
if (ppack && ppack->isModule())
{
error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s",
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
dst = modules;
}
} }
else else
{ {
@@ -709,7 +721,7 @@ void Module::parse()
{ {
Package *pkg = prev->isPackage(); Package *pkg = prev->isPackage();
assert(pkg); assert(pkg);
error(loc, "from file %s conflicts with package name %s", error(pkg->loc, "from file %s conflicts with package name %s",
srcname, pkg->toChars()); srcname, pkg->toChars());
} }
} }
@@ -1216,19 +1228,24 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
else else
{ {
assert(p->isPackage()); assert(p->isPackage());
#if TARGET_NET //dot net needs modules and packages with same name // It might already be a module, not a package, but that needs
#else // to be checked at a higher level, where a nice error message
if (p->isModule()) // can be generated.
{ p->error("module and package have the same name"); // dot net needs modules and packages with same name
fatal();
break;
}
#endif
} }
parent = p; parent = p;
dst = ((Package *)p)->symtab; dst = ((Package *)p)->symtab;
if (ppkg && !*ppkg) if (ppkg && !*ppkg)
*ppkg = (Package *)p; *ppkg = (Package *)p;
#if TARGET_NET
#else
if (p->isModule())
{ // Return the module so that a nice error message can be generated
if (ppkg)
*ppkg = (Package *)p;
break;
}
#endif
} }
if (pparent) if (pparent)
{ {

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -134,10 +134,11 @@ struct Module : Package
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toJsonBuffer(OutBuffer *buf); void toJsonBuffer(OutBuffer *buf);
const char *kind(); const char *kind();
void read(Loc loc); // read file bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
#if IN_LLVM #if IN_LLVM
void parse(bool gen_docs = false); // syntactic parse void parse(bool gen_docs = false); // syntactic parse
#elif IN_GCC #elif IN_GCC
void setDocfile(); // set docfile member
void parse(bool dump_source = false); // syntactic parse void parse(bool dump_source = false); // syntactic parse
#else #else
void parse(); // syntactic parse void parse(); // syntactic parse

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -1451,7 +1451,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Timaginary64: t = tfloat64; goto L2; case Timaginary64: t = tfloat64; goto L2;
case Timaginary80: t = tfloat80; goto L2; case Timaginary80: t = tfloat80; goto L2;
L2: L2:
e = new RealExp(0, 0.0, t); e = new RealExp(e->loc, 0.0, t);
break; break;
default: default:
@@ -1481,7 +1481,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Tfloat32: case Tfloat32:
case Tfloat64: case Tfloat64:
case Tfloat80: case Tfloat80:
e = new RealExp(0, 0.0, this); e = new RealExp(e->loc, 0.0, this);
break; break;
default: default:
@@ -2645,6 +2645,22 @@ int TypeAArray::checkBoolean()
return TRUE; return TRUE;
} }
Expression *TypeAArray::toExpression()
{
Expression *e = next->toExpression();
if (e)
{
Expression *ei = index->toExpression();
if (ei)
{
Expressions *arguments = new Expressions();
arguments->push(ei);
return new ArrayExp(0, e, arguments);
}
}
return NULL;
}
int TypeAArray::hasPointers() int TypeAArray::hasPointers()
{ {
return TRUE; return TRUE;
@@ -3184,13 +3200,25 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
error(loc, "cannot have parameter of type %s", fparam->type->toChars()); error(loc, "cannot have parameter of type %s", fparam->type->toChars());
if (fparam->defaultArg) if (fparam->defaultArg)
{ { Expression *e = fparam->defaultArg;
fparam->defaultArg = fparam->defaultArg->semantic(argsc); e = e->semantic(argsc);
fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg); e = resolveProperties(argsc, e);
fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type); if (e->op == TOKfunction) // see Bugzilla 4820
{ FuncExp *fe = (FuncExp *)e;
if (fe->fd)
{ // 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);
e = new AddrExp(e->loc, e);
e = e->semantic(argsc);
}
}
e = e->implicitCastTo(argsc, fparam->type);
fparam->defaultArg = e;
} }
/* If arg turns out to be a tuple, the number of parameters may /* If fparam after semantic() turns out to be a tuple, the number of parameters may
* change. * change.
*/ */
if (t->ty == Ttuple) if (t->ty == Ttuple)
@@ -3650,7 +3678,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
else else
{ {
Lerror: Lerror:
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); if (id->dyncast() == DYNCAST_DSYMBOL)
{ // searchX already handles errors for template instances
assert(global.errors);
}
else
{
sm = s->search_correct(id);
if (sm)
error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?",
id->toChars(), toChars(), sm->kind(), sm->toChars());
else
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
}
*pe = new ErrorExp(); *pe = new ErrorExp();
} }
return; return;
@@ -4131,14 +4171,19 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
else else
#endif #endif
{ {
sc->intypeof++; Scope *sc2 = sc->push();
exp = exp->semantic(sc); sc2->intypeof++;
unsigned oldspecgag = global.speculativeGag;
if (global.gag)
global.speculativeGag = global.gag;
exp = exp->semantic(sc2);
global.speculativeGag = oldspecgag;
#if DMDV2 #if DMDV2
if (exp->type && exp->type->ty == Tfunction && if (exp->type && exp->type->ty == Tfunction &&
((TypeFunction *)exp->type)->isproperty) ((TypeFunction *)exp->type)->isproperty)
exp = resolveProperties(sc, exp); exp = resolveProperties(sc2, exp);
#endif #endif
sc->intypeof--; sc2->pop();
if (exp->op == TOKtype) if (exp->op == TOKtype)
{ {
error(loc, "argument %s to typeof is not an expression", exp->toChars()); error(loc, "argument %s to typeof is not an expression", exp->toChars());
@@ -4959,8 +5004,8 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
e = vd->init->toExpression(); e = vd->init->toExpression();
} }
else else
e = vd->type->defaultInitLiteral(); e = vd->type->defaultInitLiteral(loc);
structelems->tdata()[j] = e; (*structelems)[j] = e;
} }
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
// Why doesn't the StructLiteralExp constructor do this, when // Why doesn't the StructLiteralExp constructor do this, when

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -254,7 +254,8 @@ struct Type : Object
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
virtual unsigned memalign(unsigned salign); virtual unsigned memalign(unsigned salign);
virtual Expression *defaultInit(Loc loc = 0); virtual Expression *defaultInit(Loc loc = 0);
virtual Expression *defaultInitLiteral(Loc loc = 0); virtual Expression *defaultInitLiteral(Loc loc);
virtual Expression *voidInitLiteral(VarDeclaration *var);
virtual int isZeroInit(Loc loc = 0); // if initializer is 0 virtual int isZeroInit(Loc loc = 0); // if initializer is 0
#if IN_DMD #if IN_DMD
virtual dt_t **toDt(dt_t **pdt); virtual dt_t **toDt(dt_t **pdt);
@@ -391,6 +392,7 @@ struct TypeSArray : TypeArray
MATCH implicitConvTo(Type *to); MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc); Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
#if IN_DMD #if IN_DMD
dt_t **toDt(dt_t **pdt); dt_t **toDt(dt_t **pdt);
dt_t **toDtElem(dt_t **pdt, Expression *e); dt_t **toDtElem(dt_t **pdt, Expression *e);
@@ -451,6 +453,7 @@ struct TypeAArray : TypeArray
int isZeroInit(Loc loc); int isZeroInit(Loc loc);
int checkBoolean(); int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration(); TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *toExpression();
int hasPointers(); int hasPointers();
TypeTuple *toArgTypes(); TypeTuple *toArgTypes();
@@ -644,6 +647,7 @@ struct TypeStruct : Type
unsigned memalign(unsigned salign); unsigned memalign(unsigned salign);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc); Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
int isZeroInit(Loc loc); int isZeroInit(Loc loc);
int checkBoolean(); int checkBoolean();
#if IN_DMD #if IN_DMD

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -129,7 +129,7 @@ Dsymbols *Parser::parseModule()
decldefs = parseDeclDefs(0); decldefs = parseDeclDefs(0);
if (token.value != TOKeof) if (token.value != TOKeof)
{ error("unrecognized declaration"); { error(loc, "unrecognized declaration");
goto Lerr; goto Lerr;
} }
return decldefs; return decldefs;
@@ -5565,6 +5565,7 @@ void initPrecedence()
precedence[TOKtraits] = PREC_primary; precedence[TOKtraits] = PREC_primary;
precedence[TOKdefault] = PREC_primary; precedence[TOKdefault] = PREC_primary;
precedence[TOKoverloadset] = PREC_primary; precedence[TOKoverloadset] = PREC_primary;
precedence[TOKvoid] = PREC_primary;
#endif #endif
// post // post

View File

@@ -1,188 +1,188 @@
/** /**
* Implementation of associative arrays. * Implementation of associative arrays.
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "aav.h" #include "aav.h"
static const size_t prime_list[] = { static const size_t prime_list[] = {
31UL, 31UL,
97UL, 389UL, 97UL, 389UL,
1543UL, 6151UL, 1543UL, 6151UL,
24593UL, 98317UL, 24593UL, 98317UL,
393241UL, 1572869UL, 393241UL, 1572869UL,
6291469UL, 25165843UL, 6291469UL, 25165843UL,
100663319UL, 402653189UL, 100663319UL, 402653189UL,
1610612741UL, 4294967291UL, 1610612741UL, 4294967291UL,
}; };
struct aaA struct aaA
{ {
aaA *next; aaA *next;
Key key; Key key;
Value value; Value value;
}; };
struct AA struct AA
{ {
aaA* *b; aaA* *b;
size_t b_length; size_t b_length;
size_t nodes; // total number of aaA nodes size_t nodes; // total number of aaA nodes
aaA* binit[4]; // initial value of b[] aaA* binit[4]; // initial value of b[]
}; };
static const AA bbinit = { NULL, }; static const AA bbinit = { NULL, };
/**************************************************** /****************************************************
* Determine number of entries in associative array. * Determine number of entries in associative array.
*/ */
size_t _aaLen(AA* aa) size_t _aaLen(AA* aa)
{ {
return aa ? aa->nodes : 0; return aa ? aa->nodes : 0;
} }
/************************************************* /*************************************************
* Get pointer to value in associative array indexed by key. * Get pointer to value in associative array indexed by key.
* Add entry for key if it is not already there. * Add entry for key if it is not already there.
*/ */
Value* _aaGet(AA** paa, Key key) Value* _aaGet(AA** paa, Key key)
{ {
//printf("paa = %p\n", paa); //printf("paa = %p\n", paa);
if (!*paa) if (!*paa)
{ AA *a = new AA(); { AA *a = new AA();
*a = bbinit; *a = bbinit;
a->b = a->binit; a->b = a->binit;
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]); a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
*paa = a; *paa = a;
assert((*paa)->b_length == 4); assert((*paa)->b_length == 4);
} }
//printf("paa = %p, *paa = %p\n", paa, *paa); //printf("paa = %p, *paa = %p\n", paa, *paa);
assert((*paa)->b_length); assert((*paa)->b_length);
size_t i = (size_t)key % (*paa)->b_length; size_t i = (size_t)key % (*paa)->b_length;
aaA** pe = &(*paa)->b[i]; aaA** pe = &(*paa)->b[i];
aaA *e; aaA *e;
while ((e = *pe) != NULL) while ((e = *pe) != NULL)
{ {
if (key == e->key) if (key == e->key)
return &e->value; return &e->value;
pe = &e->next; pe = &e->next;
} }
// Not found, create new elem // Not found, create new elem
//printf("create new one\n"); //printf("create new one\n");
e = new aaA(); e = new aaA();
e->next = NULL; e->next = NULL;
e->key = key; e->key = key;
e->value = NULL; e->value = NULL;
*pe = e; *pe = e;
size_t nodes = ++(*paa)->nodes; size_t nodes = ++(*paa)->nodes;
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes); //printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
if (nodes > (*paa)->b_length * 4) if (nodes > (*paa)->b_length * 4)
{ {
//printf("rehash\n"); //printf("rehash\n");
_aaRehash(paa); _aaRehash(paa);
} }
return &e->value; return &e->value;
} }
/************************************************* /*************************************************
* Get value in associative array indexed by key. * Get value in associative array indexed by key.
* Returns NULL if it is not already there. * Returns NULL if it is not already there.
*/ */
Value _aaGetRvalue(AA* aa, Key key) Value _aaGetRvalue(AA* aa, Key key)
{ {
//printf("_aaGetRvalue(key = %p)\n", key); //printf("_aaGetRvalue(key = %p)\n", key);
if (!aa) if (!aa)
return NULL; return NULL;
size_t len = aa->b_length; size_t len = aa->b_length;
if (len) if (len)
{ {
size_t i = (size_t)key % len; size_t i = (size_t)key % len;
aaA* e = aa->b[i]; aaA* e = aa->b[i];
while (e) while (e)
{ {
if (key == e->key) if (key == e->key)
return e->value; return e->value;
e = e->next; e = e->next;
} }
} }
return NULL; // not found return NULL; // not found
} }
/******************************************** /********************************************
* Rehash an array. * Rehash an array.
*/ */
void _aaRehash(AA** paa) void _aaRehash(AA** paa)
{ {
//printf("Rehash\n"); //printf("Rehash\n");
if (*paa) if (*paa)
{ {
AA newb = bbinit; AA newb = bbinit;
AA *aa = *paa; AA *aa = *paa;
size_t len = _aaLen(*paa); size_t len = _aaLen(*paa);
if (len) if (len)
{ size_t i; { size_t i;
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++) for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
{ {
if (len <= prime_list[i]) if (len <= prime_list[i])
break; break;
} }
len = prime_list[i]; len = prime_list[i];
newb.b = new aaA*[len]; newb.b = new aaA*[len];
memset(newb.b, 0, len * sizeof(aaA*)); memset(newb.b, 0, len * sizeof(aaA*));
newb.b_length = len; newb.b_length = len;
for (size_t k = 0; k < aa->b_length; k++) for (size_t k = 0; k < aa->b_length; k++)
{ aaA *e = aa->b[k]; { aaA *e = aa->b[k];
while (e) while (e)
{ aaA* enext = e->next; { aaA* enext = e->next;
size_t j = (size_t)e->key % len; size_t j = (size_t)e->key % len;
e->next = newb.b[j]; e->next = newb.b[j];
newb.b[j] = e; newb.b[j] = e;
e = enext; e = enext;
} }
} }
if (aa->b != aa->binit) if (aa->b != aa->binit)
delete[] aa->b; delete[] aa->b;
newb.nodes = aa->nodes; newb.nodes = aa->nodes;
} }
**paa = newb; **paa = newb;
} }
} }
#if UNITTEST #if UNITTEST
void unittest_aa() void unittest_aa()
{ {
AA* aa = NULL; AA* aa = NULL;
Value v = _aaGetRvalue(aa, NULL); Value v = _aaGetRvalue(aa, NULL);
assert(!v); assert(!v);
Value *pv = _aaGet(&aa, NULL); Value *pv = _aaGet(&aa, NULL);
assert(pv); assert(pv);
*pv = (void *)3; *pv = (void *)3;
v = _aaGetRvalue(aa, NULL); v = _aaGetRvalue(aa, NULL);
assert(v == (void *)3); assert(v == (void *)3);
} }
#endif #endif

View File

@@ -1,11 +1,11 @@
typedef void* Value; typedef void* Value;
typedef void* Key; typedef void* Key;
struct AA; struct AA;
size_t _aaLen(AA* aa); size_t _aaLen(AA* aa);
Value* _aaGet(AA** aa, Key key); Value* _aaGet(AA** aa, Key key);
Value _aaGetRvalue(AA* aa, Key key); Value _aaGetRvalue(AA* aa, Key key);
void _aaRehash(AA** paa); void _aaRehash(AA** paa);

View File

@@ -1,257 +1,257 @@
// Copyright (c) 1999-2010 by Digital Mars // Copyright (c) 1999-2010 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#if (defined (__SVR4) && defined (__sun)) #if (defined (__SVR4) && defined (__sun))
#include <alloca.h> #include <alloca.h>
#endif #endif
#if _MSC_VER || __MINGW32__ #if _MSC_VER || __MINGW32__
#include <malloc.h> #include <malloc.h>
#endif #endif
#if IN_GCC #if IN_GCC
#include "gdc_alloca.h" #include "gdc_alloca.h"
#endif #endif
#if _WIN32 #if _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <utime.h> #include <utime.h>
#endif #endif
#include "port.h" #include "port.h"
#include "root.h" #include "root.h"
#include "dchar.h" #include "dchar.h"
#include "rmem.h" #include "rmem.h"
/********************************* Array ****************************/ /********************************* Array ****************************/
Array::Array() Array::Array()
{ {
data = SMALLARRAYCAP ? &smallarray[0] : NULL; data = SMALLARRAYCAP ? &smallarray[0] : NULL;
dim = 0; dim = 0;
allocdim = SMALLARRAYCAP; allocdim = SMALLARRAYCAP;
} }
Array::~Array() Array::~Array()
{ {
if (data != &smallarray[0]) if (data != &smallarray[0])
mem.free(data); mem.free(data);
} }
void Array::mark() void Array::mark()
{ unsigned u; { unsigned u;
mem.mark(data); mem.mark(data);
for (u = 0; u < dim; u++) for (u = 0; u < dim; u++)
mem.mark(data[u]); // BUG: what if arrays of Object's? mem.mark(data[u]); // BUG: what if arrays of Object's?
} }
void Array::reserve(unsigned nentries) void Array::reserve(unsigned nentries)
{ {
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries); //printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
if (allocdim - dim < nentries) if (allocdim - dim < nentries)
{ {
if (allocdim == 0) if (allocdim == 0)
{ // Not properly initialized, someone memset it to zero { // Not properly initialized, someone memset it to zero
if (nentries <= SMALLARRAYCAP) if (nentries <= SMALLARRAYCAP)
{ allocdim = SMALLARRAYCAP; { allocdim = SMALLARRAYCAP;
data = SMALLARRAYCAP ? &smallarray[0] : NULL; data = SMALLARRAYCAP ? &smallarray[0] : NULL;
} }
else else
{ allocdim = nentries; { allocdim = nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data)); data = (void **)mem.malloc(allocdim * sizeof(*data));
} }
} }
else if (allocdim == SMALLARRAYCAP) else if (allocdim == SMALLARRAYCAP)
{ {
allocdim = dim + nentries; allocdim = dim + nentries;
data = (void **)mem.malloc(allocdim * sizeof(*data)); data = (void **)mem.malloc(allocdim * sizeof(*data));
memcpy(data, &smallarray[0], dim * sizeof(*data)); memcpy(data, &smallarray[0], dim * sizeof(*data));
} }
else else
{ allocdim = dim + nentries; { allocdim = dim + nentries;
data = (void **)mem.realloc(data, allocdim * sizeof(*data)); data = (void **)mem.realloc(data, allocdim * sizeof(*data));
} }
} }
} }
void Array::setDim(unsigned newdim) void Array::setDim(unsigned newdim)
{ {
if (dim < newdim) if (dim < newdim)
{ {
reserve(newdim - dim); reserve(newdim - dim);
} }
dim = newdim; dim = newdim;
} }
void Array::fixDim() void Array::fixDim()
{ {
if (dim != allocdim) if (dim != allocdim)
{ {
if (allocdim >= SMALLARRAYCAP) if (allocdim >= SMALLARRAYCAP)
{ {
if (dim <= SMALLARRAYCAP) if (dim <= SMALLARRAYCAP)
{ {
memcpy(&smallarray[0], data, dim * sizeof(*data)); memcpy(&smallarray[0], data, dim * sizeof(*data));
mem.free(data); mem.free(data);
} }
else else
data = (void **)mem.realloc(data, dim * sizeof(*data)); data = (void **)mem.realloc(data, dim * sizeof(*data));
} }
allocdim = dim; allocdim = dim;
} }
} }
void Array::push(void *ptr) void Array::push(void *ptr)
{ {
reserve(1); reserve(1);
data[dim++] = ptr; data[dim++] = ptr;
} }
void *Array::pop() void *Array::pop()
{ {
return data[--dim]; return data[--dim];
} }
void Array::shift(void *ptr) void Array::shift(void *ptr)
{ {
reserve(1); reserve(1);
memmove(data + 1, data, dim * sizeof(*data)); memmove(data + 1, data, dim * sizeof(*data));
data[0] = ptr; data[0] = ptr;
dim++; dim++;
} }
void Array::insert(unsigned index, void *ptr) void Array::insert(unsigned index, void *ptr)
{ {
reserve(1); reserve(1);
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
data[index] = ptr; data[index] = ptr;
dim++; dim++;
} }
void Array::insert(unsigned index, Array *a) void Array::insert(unsigned index, Array *a)
{ {
if (a) if (a)
{ unsigned d; { unsigned d;
d = a->dim; d = a->dim;
reserve(d); reserve(d);
if (dim != index) if (dim != index)
memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
memcpy(data + index, a->data, d * sizeof(*data)); memcpy(data + index, a->data, d * sizeof(*data));
dim += d; dim += d;
} }
} }
/*********************************** /***********************************
* Append array a to this array. * Append array a to this array.
*/ */
void Array::append(Array *a) void Array::append(Array *a)
{ {
insert(dim, a); insert(dim, a);
} }
void Array::remove(unsigned i) void Array::remove(unsigned i)
{ {
if (dim - i - 1) if (dim - i - 1)
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0])); memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
dim--; dim--;
} }
char *Array::toChars() char *Array::toChars()
{ {
unsigned len; unsigned len;
unsigned u; unsigned u;
char **buf; char **buf;
char *str; char *str;
char *p; char *p;
buf = (char **)malloc(dim * sizeof(char *)); buf = (char **)malloc(dim * sizeof(char *));
assert(buf); assert(buf);
len = 2; len = 2;
for (u = 0; u < dim; u++) for (u = 0; u < dim; u++)
{ {
buf[u] = ((Object *)data[u])->toChars(); buf[u] = ((Object *)data[u])->toChars();
len += strlen(buf[u]) + 1; len += strlen(buf[u]) + 1;
} }
str = (char *)mem.malloc(len); str = (char *)mem.malloc(len);
str[0] = '['; str[0] = '[';
p = str + 1; p = str + 1;
for (u = 0; u < dim; u++) for (u = 0; u < dim; u++)
{ {
if (u) if (u)
*p++ = ','; *p++ = ',';
len = strlen(buf[u]); len = strlen(buf[u]);
memcpy(p,buf[u],len); memcpy(p,buf[u],len);
p += len; p += len;
} }
*p++ = ']'; *p++ = ']';
*p = 0; *p = 0;
free(buf); free(buf);
return str; return str;
} }
void Array::zero() void Array::zero()
{ {
memset(data,0,dim * sizeof(data[0])); memset(data,0,dim * sizeof(data[0]));
} }
void *Array::tos() void *Array::tos()
{ {
return dim ? data[dim - 1] : NULL; return dim ? data[dim - 1] : NULL;
} }
int int
#if _WIN32 #if _WIN32
__cdecl __cdecl
#endif #endif
Array_sort_compare(const void *x, const void *y) Array_sort_compare(const void *x, const void *y)
{ {
Object *ox = *(Object **)x; Object *ox = *(Object **)x;
Object *oy = *(Object **)y; Object *oy = *(Object **)y;
return ox->compare(oy); return ox->compare(oy);
} }
void Array::sort() void Array::sort()
{ {
if (dim) if (dim)
{ {
qsort(data, dim, sizeof(Object *), Array_sort_compare); qsort(data, dim, sizeof(Object *), Array_sort_compare);
} }
} }
Array *Array::copy() Array *Array::copy()
{ {
Array *a = new Array(); Array *a = new Array();
a->setDim(dim); a->setDim(dim);
memcpy(a->data, data, dim * sizeof(void *)); memcpy(a->data, data, dim * sizeof(void *));
return a; return a;
} }

View File

@@ -1,325 +1,325 @@
#define _MT 1 #define _MT 1
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#if _WIN32 #if _WIN32
#include <windows.h> #include <windows.h>
#include <errno.h> #include <errno.h>
#include <process.h> #include <process.h>
#include "root.h" #include "root.h"
static unsigned __stdcall startthread(void *p); static unsigned __stdcall startthread(void *p);
struct FileData struct FileData
{ {
File *file; File *file;
int result; int result;
HANDLE event; HANDLE event;
}; };
struct AsyncRead struct AsyncRead
{ {
static AsyncRead *create(size_t nfiles); static AsyncRead *create(size_t nfiles);
void addFile(File *file); void addFile(File *file);
void start(); void start();
int read(size_t i); int read(size_t i);
static void dispose(AsyncRead *); static void dispose(AsyncRead *);
HANDLE hThread; HANDLE hThread;
size_t filesdim; size_t filesdim;
size_t filesmax; size_t filesmax;
FileData files[1]; FileData files[1];
}; };
AsyncRead *AsyncRead::create(size_t nfiles) AsyncRead *AsyncRead::create(size_t nfiles)
{ {
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData)); (nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles; aw->filesmax = nfiles;
return aw; return aw;
} }
void AsyncRead::addFile(File *file) void AsyncRead::addFile(File *file)
{ {
//printf("addFile(file = %p)\n", file); //printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax); assert(filesdim < filesmax);
files[filesdim].file = file; files[filesdim].file = file;
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
ResetEvent(files[filesdim].event); ResetEvent(files[filesdim].event);
filesdim++; filesdim++;
} }
void AsyncRead::start() void AsyncRead::start()
{ {
//printf("aw->filesdim = %p %d\n", this, filesdim); //printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim) if (filesdim)
{ {
unsigned threadaddr; unsigned threadaddr;
hThread = (HANDLE) _beginthreadex(NULL, hThread = (HANDLE) _beginthreadex(NULL,
0, 0,
&startthread, &startthread,
this, this,
0, 0,
(unsigned *)&threadaddr); (unsigned *)&threadaddr);
if (hThread) if (hThread)
{ {
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
} }
else else
{ {
assert(0); assert(0);
} }
} }
} }
int AsyncRead::read(size_t i) int AsyncRead::read(size_t i)
{ {
FileData *f = &files[i]; FileData *f = &files[i];
WaitForSingleObject(f->event, INFINITE); WaitForSingleObject(f->event, INFINITE);
Sleep(0); // give up time slice Sleep(0); // give up time slice
return f->result; return f->result;
} }
void AsyncRead::dispose(AsyncRead *aw) void AsyncRead::dispose(AsyncRead *aw)
{ {
free(aw); free(aw);
} }
unsigned __stdcall startthread(void *p) unsigned __stdcall startthread(void *p)
{ {
AsyncRead *aw = (AsyncRead *)p; AsyncRead *aw = (AsyncRead *)p;
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim); //printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
for (size_t i = 0; i < aw->filesdim; i++) for (size_t i = 0; i < aw->filesdim; i++)
{ FileData *f = &aw->files[i]; { FileData *f = &aw->files[i];
f->result = f->file->read(); f->result = f->file->read();
SetEvent(f->event); SetEvent(f->event);
} }
_endthreadex(EXIT_SUCCESS); _endthreadex(EXIT_SUCCESS);
return EXIT_SUCCESS; // if skidding return EXIT_SUCCESS; // if skidding
} }
#elif linux // Posix #elif linux // Posix
#include <errno.h> #include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <time.h> #include <time.h>
#include "root.h" #include "root.h"
void *startthread(void *arg); void *startthread(void *arg);
void err_abort(int status, const char *msg) void err_abort(int status, const char *msg)
{ {
fprintf(stderr, "fatal error = %d, %s\n", status, msg); fprintf(stderr, "fatal error = %d, %s\n", status, msg);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct FileData struct FileData
{ {
File *file; File *file;
int result; int result;
pthread_mutex_t mutex; pthread_mutex_t mutex;
pthread_cond_t cond; pthread_cond_t cond;
int value; int value;
}; };
struct AsyncRead struct AsyncRead
{ {
static AsyncRead *create(size_t nfiles); static AsyncRead *create(size_t nfiles);
void addFile(File *file); void addFile(File *file);
void start(); void start();
int read(size_t i); int read(size_t i);
static void dispose(AsyncRead *); static void dispose(AsyncRead *);
size_t filesdim; size_t filesdim;
size_t filesmax; size_t filesmax;
FileData files[1]; FileData files[1];
}; };
AsyncRead *AsyncRead::create(size_t nfiles) AsyncRead *AsyncRead::create(size_t nfiles)
{ {
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData)); (nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles; aw->filesmax = nfiles;
return aw; return aw;
} }
void AsyncRead::addFile(File *file) void AsyncRead::addFile(File *file)
{ {
//printf("addFile(file = %p)\n", file); //printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax); assert(filesdim < filesmax);
FileData *f = &files[filesdim]; FileData *f = &files[filesdim];
f->file = file; f->file = file;
int status = pthread_mutex_init(&f->mutex, NULL); int status = pthread_mutex_init(&f->mutex, NULL);
if (status != 0) if (status != 0)
err_abort(status, "init mutex"); err_abort(status, "init mutex");
status = pthread_cond_init(&f->cond, NULL); status = pthread_cond_init(&f->cond, NULL);
if (status != 0) if (status != 0)
err_abort(status, "init cond"); err_abort(status, "init cond");
filesdim++; filesdim++;
} }
void AsyncRead::start() void AsyncRead::start()
{ {
//printf("aw->filesdim = %p %d\n", this, filesdim); //printf("aw->filesdim = %p %d\n", this, filesdim);
if (filesdim) if (filesdim)
{ {
pthread_t thread_id; pthread_t thread_id;
int status = pthread_create(&thread_id, int status = pthread_create(&thread_id,
NULL, NULL,
&startthread, &startthread,
this); this);
if (status != 0) if (status != 0)
err_abort(status, "create thread"); err_abort(status, "create thread");
} }
} }
int AsyncRead::read(size_t i) int AsyncRead::read(size_t i)
{ {
FileData *f = &files[i]; FileData *f = &files[i];
// Wait for the event // Wait for the event
int status = pthread_mutex_lock(&f->mutex); int status = pthread_mutex_lock(&f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "lock mutex"); err_abort(status, "lock mutex");
while (f->value == 0) while (f->value == 0)
{ {
status = pthread_cond_wait(&f->cond, &f->mutex); status = pthread_cond_wait(&f->cond, &f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "wait on condition"); err_abort(status, "wait on condition");
} }
status = pthread_mutex_unlock(&f->mutex); status = pthread_mutex_unlock(&f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "unlock mutex"); err_abort(status, "unlock mutex");
return f->result; return f->result;
} }
void AsyncRead::dispose(AsyncRead *aw) void AsyncRead::dispose(AsyncRead *aw)
{ {
//printf("AsyncRead::dispose()\n"); //printf("AsyncRead::dispose()\n");
for (int i = 0; i < aw->filesdim; i++) for (int i = 0; i < aw->filesdim; i++)
{ {
FileData *f = &aw->files[i]; FileData *f = &aw->files[i];
int status = pthread_cond_destroy(&f->cond); int status = pthread_cond_destroy(&f->cond);
if (status != 0) if (status != 0)
err_abort(status, "cond destroy"); err_abort(status, "cond destroy");
status = pthread_mutex_destroy(&f->mutex); status = pthread_mutex_destroy(&f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "mutex destroy"); err_abort(status, "mutex destroy");
} }
free(aw); free(aw);
} }
void *startthread(void *p) void *startthread(void *p)
{ {
AsyncRead *aw = (AsyncRead *)p; AsyncRead *aw = (AsyncRead *)p;
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim); //printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
size_t dim = aw->filesdim; size_t dim = aw->filesdim;
for (size_t i = 0; i < dim; i++) for (size_t i = 0; i < dim; i++)
{ FileData *f = &aw->files[i]; { FileData *f = &aw->files[i];
f->result = f->file->read(); f->result = f->file->read();
// Set event // Set event
int status = pthread_mutex_lock(&f->mutex); int status = pthread_mutex_lock(&f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "lock mutex"); err_abort(status, "lock mutex");
f->value = 1; f->value = 1;
status = pthread_cond_signal(&f->cond); status = pthread_cond_signal(&f->cond);
if (status != 0) if (status != 0)
err_abort(status, "signal condition"); err_abort(status, "signal condition");
status = pthread_mutex_unlock(&f->mutex); status = pthread_mutex_unlock(&f->mutex);
if (status != 0) if (status != 0)
err_abort(status, "unlock mutex"); err_abort(status, "unlock mutex");
} }
return NULL; // end thread return NULL; // end thread
} }
#else #else
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include "root.h" #include "root.h"
struct FileData struct FileData
{ {
File *file; File *file;
int result; int result;
//HANDLE event; //HANDLE event;
}; };
struct AsyncRead struct AsyncRead
{ {
static AsyncRead *create(size_t nfiles); static AsyncRead *create(size_t nfiles);
void addFile(File *file); void addFile(File *file);
void start(); void start();
int read(size_t i); int read(size_t i);
static void dispose(AsyncRead *); static void dispose(AsyncRead *);
//HANDLE hThread; //HANDLE hThread;
size_t filesdim; size_t filesdim;
size_t filesmax; size_t filesmax;
FileData files[1]; FileData files[1];
}; };
AsyncRead *AsyncRead::create(size_t nfiles) AsyncRead *AsyncRead::create(size_t nfiles)
{ {
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) + AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData)); (nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles; aw->filesmax = nfiles;
return aw; return aw;
} }
void AsyncRead::addFile(File *file) void AsyncRead::addFile(File *file)
{ {
//printf("addFile(file = %p)\n", file); //printf("addFile(file = %p)\n", file);
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax); //printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
assert(filesdim < filesmax); assert(filesdim < filesmax);
files[filesdim].file = file; files[filesdim].file = file;
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL); //files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
//ResetEvent(files[filesdim].event); //ResetEvent(files[filesdim].event);
filesdim++; filesdim++;
} }
void AsyncRead::start() void AsyncRead::start()
{ {
} }
int AsyncRead::read(size_t i) int AsyncRead::read(size_t i)
{ {
FileData *f = &files[i]; FileData *f = &files[i];
f->result = f->file->read(); f->result = f->file->read();
return f->result; return f->result;
} }
void AsyncRead::dispose(AsyncRead *aw) void AsyncRead::dispose(AsyncRead *aw)
{ {
free(aw); free(aw);
} }
#endif #endif

View File

@@ -1,33 +1,33 @@
// Copyright (c) 2009-2009 by Digital Mars // Copyright (c) 2009-2009 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef ASYNC_H #ifndef ASYNC_H
#define ASYNC_H #define ASYNC_H
#if __DMC__ #if __DMC__
#pragma once #pragma once
#endif #endif
/******************* /*******************
* Simple interface to read files asynchronously in another * Simple interface to read files asynchronously in another
* thread. * thread.
*/ */
struct AsyncRead struct AsyncRead
{ {
static AsyncRead *create(size_t nfiles); static AsyncRead *create(size_t nfiles);
void addFile(File *file); void addFile(File *file);
void start(); void start();
int read(size_t i); int read(size_t i);
static void dispose(AsyncRead *); static void dispose(AsyncRead *);
}; };
#endif #endif

View File

@@ -1,482 +1,482 @@
// Copyright (c) 1999-2006 by Digital Mars // Copyright (c) 1999-2006 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// www.digitalmars.com // www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
#include "dchar.h" #include "dchar.h"
#include "rmem.h" #include "rmem.h"
#if M_UNICODE #if M_UNICODE
// Converts a char string to Unicode // Converts a char string to Unicode
dchar *Dchar::dup(char *p) dchar *Dchar::dup(char *p)
{ {
dchar *s; dchar *s;
size_t len; size_t len;
if (!p) if (!p)
return NULL; return NULL;
len = strlen(p); len = strlen(p);
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
for (unsigned i = 0; i < len; i++) for (unsigned i = 0; i < len; i++)
{ {
s[i] = (dchar)(p[i] & 0xFF); s[i] = (dchar)(p[i] & 0xFF);
} }
s[len] = 0; s[len] = 0;
return s; return s;
} }
dchar *Dchar::memchr(dchar *p, int c, int count) dchar *Dchar::memchr(dchar *p, int c, int count)
{ {
int u; int u;
for (u = 0; u < count; u++) for (u = 0; u < count; u++)
{ {
if (p[u] == c) if (p[u] == c)
return p + u; return p + u;
} }
return NULL; return NULL;
} }
#if _WIN32 && __DMC__ #if _WIN32 && __DMC__
__declspec(naked) __declspec(naked)
unsigned Dchar::calcHash(const dchar *str, unsigned len) unsigned Dchar::calcHash(const dchar *str, unsigned len)
{ {
__asm __asm
{ {
mov ECX,4[ESP] mov ECX,4[ESP]
mov EDX,8[ESP] mov EDX,8[ESP]
xor EAX,EAX xor EAX,EAX
test EDX,EDX test EDX,EDX
je L92 je L92
LC8: cmp EDX,1 LC8: cmp EDX,1
je L98 je L98
cmp EDX,2 cmp EDX,2
je LAE je LAE
add EAX,[ECX] add EAX,[ECX]
// imul EAX,EAX,025h // imul EAX,EAX,025h
lea EAX,[EAX][EAX*8] lea EAX,[EAX][EAX*8]
add ECX,4 add ECX,4
sub EDX,2 sub EDX,2
jmp LC8 jmp LC8
L98: mov DX,[ECX] L98: mov DX,[ECX]
and EDX,0FFFFh and EDX,0FFFFh
add EAX,EDX add EAX,EDX
ret ret
LAE: add EAX,[ECX] LAE: add EAX,[ECX]
L92: ret L92: ret
} }
} }
#else #else
hash_t Dchar::calcHash(const dchar *str, size_t len) hash_t Dchar::calcHash(const dchar *str, size_t len)
{ {
unsigned hash = 0; unsigned hash = 0;
for (;;) for (;;)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash += *(const uint16_t *)str; hash += *(const uint16_t *)str;
return hash; return hash;
case 2: case 2:
hash += *(const uint32_t *)str; hash += *(const uint32_t *)str;
return hash; return hash;
default: default:
hash += *(const uint32_t *)str; hash += *(const uint32_t *)str;
hash *= 37; hash *= 37;
str += 2; str += 2;
len -= 2; len -= 2;
break; break;
} }
} }
} }
#endif #endif
hash_t Dchar::icalcHash(const dchar *str, size_t len) hash_t Dchar::icalcHash(const dchar *str, size_t len)
{ {
hash_t hash = 0; hash_t hash = 0;
for (;;) for (;;)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash += *(const uint16_t *)str | 0x20; hash += *(const uint16_t *)str | 0x20;
return hash; return hash;
case 2: case 2:
hash += *(const uint32_t *)str | 0x200020; hash += *(const uint32_t *)str | 0x200020;
return hash; return hash;
default: default:
hash += *(const uint32_t *)str | 0x200020; hash += *(const uint32_t *)str | 0x200020;
hash *= 37; hash *= 37;
str += 2; str += 2;
len -= 2; len -= 2;
break; break;
} }
} }
} }
#elif MCBS #elif MCBS
hash_t Dchar::calcHash(const dchar *str, size_t len) hash_t Dchar::calcHash(const dchar *str, size_t len)
{ {
hash_t hash = 0; hash_t hash = 0;
while (1) while (1)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash *= 37; hash *= 37;
hash += *(const uint8_t *)str; hash += *(const uint8_t *)str;
return hash; return hash;
case 2: case 2:
hash *= 37; hash *= 37;
hash += *(const uint16_t *)str; hash += *(const uint16_t *)str;
return hash; return hash;
case 3: case 3:
hash *= 37; hash *= 37;
hash += (*(const uint16_t *)str << 8) + hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]; ((const uint8_t *)str)[2];
return hash; return hash;
default: default:
hash *= 37; hash *= 37;
hash += *(const uint32_t *)str; hash += *(const uint32_t *)str;
str += 4; str += 4;
len -= 4; len -= 4;
break; break;
} }
} }
} }
#elif UTF8 #elif UTF8
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 // Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
char Dchar::mblen[256] = 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,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,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,
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, 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, 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
}; };
dchar *Dchar::dec(dchar *pstart, dchar *p) dchar *Dchar::dec(dchar *pstart, dchar *p)
{ {
while ((p[-1] & 0xC0) == 0x80) while ((p[-1] & 0xC0) == 0x80)
p--; p--;
return p; return p;
} }
int Dchar::get(dchar *p) int Dchar::get(dchar *p)
{ {
unsigned c; unsigned c;
unsigned char *q = (unsigned char *)p; unsigned char *q = (unsigned char *)p;
c = q[0]; c = q[0];
switch (mblen[c]) switch (mblen[c])
{ {
case 2: case 2:
c = ((c - 0xC0) << 6) | c = ((c - 0xC0) << 6) |
(q[1] - 0x80); (q[1] - 0x80);
break; break;
case 3: case 3:
c = ((c - 0xE0) << 12) | c = ((c - 0xE0) << 12) |
((q[1] - 0x80) << 6) | ((q[1] - 0x80) << 6) |
(q[2] - 0x80); (q[2] - 0x80);
break; break;
case 4: case 4:
c = ((c - 0xF0) << 18) | c = ((c - 0xF0) << 18) |
((q[1] - 0x80) << 12) | ((q[1] - 0x80) << 12) |
((q[2] - 0x80) << 6) | ((q[2] - 0x80) << 6) |
(q[3] - 0x80); (q[3] - 0x80);
break; break;
case 5: case 5:
c = ((c - 0xF8) << 24) | c = ((c - 0xF8) << 24) |
((q[1] - 0x80) << 18) | ((q[1] - 0x80) << 18) |
((q[2] - 0x80) << 12) | ((q[2] - 0x80) << 12) |
((q[3] - 0x80) << 6) | ((q[3] - 0x80) << 6) |
(q[4] - 0x80); (q[4] - 0x80);
break; break;
case 6: case 6:
c = ((c - 0xFC) << 30) | c = ((c - 0xFC) << 30) |
((q[1] - 0x80) << 24) | ((q[1] - 0x80) << 24) |
((q[2] - 0x80) << 18) | ((q[2] - 0x80) << 18) |
((q[3] - 0x80) << 12) | ((q[3] - 0x80) << 12) |
((q[4] - 0x80) << 6) | ((q[4] - 0x80) << 6) |
(q[5] - 0x80); (q[5] - 0x80);
break; break;
} }
return c; return c;
} }
dchar *Dchar::put(dchar *p, unsigned c) dchar *Dchar::put(dchar *p, unsigned c)
{ {
if (c <= 0x7F) if (c <= 0x7F)
{ {
*p++ = c; *p++ = c;
} }
else if (c <= 0x7FF) else if (c <= 0x7FF)
{ {
p[0] = 0xC0 + (c >> 6); p[0] = 0xC0 + (c >> 6);
p[1] = 0x80 + (c & 0x3F); p[1] = 0x80 + (c & 0x3F);
p += 2; p += 2;
} }
else if (c <= 0xFFFF) else if (c <= 0xFFFF)
{ {
p[0] = 0xE0 + (c >> 12); p[0] = 0xE0 + (c >> 12);
p[1] = 0x80 + ((c >> 6) & 0x3F); p[1] = 0x80 + ((c >> 6) & 0x3F);
p[2] = 0x80 + (c & 0x3F); p[2] = 0x80 + (c & 0x3F);
p += 3; p += 3;
} }
else if (c <= 0x1FFFFF) else if (c <= 0x1FFFFF)
{ {
p[0] = 0xF0 + (c >> 18); p[0] = 0xF0 + (c >> 18);
p[1] = 0x80 + ((c >> 12) & 0x3F); p[1] = 0x80 + ((c >> 12) & 0x3F);
p[2] = 0x80 + ((c >> 6) & 0x3F); p[2] = 0x80 + ((c >> 6) & 0x3F);
p[3] = 0x80 + (c & 0x3F); p[3] = 0x80 + (c & 0x3F);
p += 4; p += 4;
} }
else if (c <= 0x3FFFFFF) else if (c <= 0x3FFFFFF)
{ {
p[0] = 0xF8 + (c >> 24); p[0] = 0xF8 + (c >> 24);
p[1] = 0x80 + ((c >> 18) & 0x3F); p[1] = 0x80 + ((c >> 18) & 0x3F);
p[2] = 0x80 + ((c >> 12) & 0x3F); p[2] = 0x80 + ((c >> 12) & 0x3F);
p[3] = 0x80 + ((c >> 6) & 0x3F); p[3] = 0x80 + ((c >> 6) & 0x3F);
p[4] = 0x80 + (c & 0x3F); p[4] = 0x80 + (c & 0x3F);
p += 5; p += 5;
} }
else if (c <= 0x7FFFFFFF) else if (c <= 0x7FFFFFFF)
{ {
p[0] = 0xFC + (c >> 30); p[0] = 0xFC + (c >> 30);
p[1] = 0x80 + ((c >> 24) & 0x3F); p[1] = 0x80 + ((c >> 24) & 0x3F);
p[2] = 0x80 + ((c >> 18) & 0x3F); p[2] = 0x80 + ((c >> 18) & 0x3F);
p[3] = 0x80 + ((c >> 12) & 0x3F); p[3] = 0x80 + ((c >> 12) & 0x3F);
p[4] = 0x80 + ((c >> 6) & 0x3F); p[4] = 0x80 + ((c >> 6) & 0x3F);
p[5] = 0x80 + (c & 0x3F); p[5] = 0x80 + (c & 0x3F);
p += 6; p += 6;
} }
else else
assert(0); // not a UCS-4 character assert(0); // not a UCS-4 character
return p; return p;
} }
hash_t Dchar::calcHash(const dchar *str, size_t len) hash_t Dchar::calcHash(const dchar *str, size_t len)
{ {
hash_t hash = 0; hash_t hash = 0;
while (1) while (1)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash *= 37; hash *= 37;
hash += *(const uint8_t *)str; hash += *(const uint8_t *)str;
return hash; return hash;
case 2: case 2:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += *(const uint16_t *)str; hash += *(const uint16_t *)str;
#else #else
hash += str[0] * 256 + str[1]; hash += str[0] * 256 + str[1];
#endif #endif
return hash; return hash;
case 3: case 3:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) + hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]; ((const uint8_t *)str)[2];
#else #else
hash += (str[0] * 256 + str[1]) * 256 + str[2]; hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif #endif
return hash; return hash;
default: default:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += *(const uint32_t *)str; hash += *(const uint32_t *)str;
#else #else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif #endif
str += 4; str += 4;
len -= 4; len -= 4;
break; break;
} }
} }
} }
#else // ascii #else // ascii
hash_t Dchar::calcHash(const dchar *str, size_t len) hash_t Dchar::calcHash(const dchar *str, size_t len)
{ {
hash_t hash = 0; hash_t hash = 0;
while (1) while (1)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash *= 37; hash *= 37;
hash += *(const uint8_t *)str; hash += *(const uint8_t *)str;
return hash; return hash;
case 2: case 2:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += *(const uint16_t *)str; hash += *(const uint16_t *)str;
#else #else
hash += str[0] * 256 + str[1]; hash += str[0] * 256 + str[1];
#endif #endif
return hash; return hash;
case 3: case 3:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += (*(const uint16_t *)str << 8) + hash += (*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]; ((const uint8_t *)str)[2];
#else #else
hash += (str[0] * 256 + str[1]) * 256 + str[2]; hash += (str[0] * 256 + str[1]) * 256 + str[2];
#endif #endif
return hash; return hash;
default: default:
hash *= 37; hash *= 37;
#if LITTLE_ENDIAN #if LITTLE_ENDIAN
hash += *(const uint32_t *)str; hash += *(const uint32_t *)str;
#else #else
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
#endif #endif
str += 4; str += 4;
len -= 4; len -= 4;
break; break;
} }
} }
} }
hash_t Dchar::icalcHash(const dchar *str, size_t len) hash_t Dchar::icalcHash(const dchar *str, size_t len)
{ {
hash_t hash = 0; hash_t hash = 0;
while (1) while (1)
{ {
switch (len) switch (len)
{ {
case 0: case 0:
return hash; return hash;
case 1: case 1:
hash *= 37; hash *= 37;
hash += *(const uint8_t *)str | 0x20; hash += *(const uint8_t *)str | 0x20;
return hash; return hash;
case 2: case 2:
hash *= 37; hash *= 37;
hash += *(const uint16_t *)str | 0x2020; hash += *(const uint16_t *)str | 0x2020;
return hash; return hash;
case 3: case 3:
hash *= 37; hash *= 37;
hash += ((*(const uint16_t *)str << 8) + hash += ((*(const uint16_t *)str << 8) +
((const uint8_t *)str)[2]) | 0x202020; ((const uint8_t *)str)[2]) | 0x202020;
return hash; return hash;
default: default:
hash *= 37; hash *= 37;
hash += *(const uint32_t *)str | 0x20202020; hash += *(const uint32_t *)str | 0x20202020;
str += 4; str += 4;
len -= 4; len -= 4;
break; break;
} }
} }
} }
#endif #endif
#if 0 #if 0
#include <stdio.h> #include <stdio.h>
void main() void main()
{ {
// Print out values to hardcode into Dchar::mblen[] // Print out values to hardcode into Dchar::mblen[]
int c; int c;
int s; int s;
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
{ {
s = 1; s = 1;
if (c >= 0xC0 && c <= 0xDF) if (c >= 0xC0 && c <= 0xDF)
s = 2; s = 2;
if (c >= 0xE0 && c <= 0xEF) if (c >= 0xE0 && c <= 0xEF)
s = 3; s = 3;
if (c >= 0xF0 && c <= 0xF7) if (c >= 0xF0 && c <= 0xF7)
s = 4; s = 4;
if (c >= 0xF8 && c <= 0xFB) if (c >= 0xF8 && c <= 0xFB)
s = 5; s = 5;
if (c >= 0xFC && c <= 0xFD) if (c >= 0xFC && c <= 0xFD)
s = 6; s = 6;
printf("%d", s); printf("%d", s);
if ((c & 15) == 15) if ((c & 15) == 15)
printf(",\n"); printf(",\n");
else else
printf(","); printf(",");
} }
} }
#endif #endif

View File

@@ -1,194 +1,194 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// www.digitalmars.com // www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef DCHAR_H #ifndef DCHAR_H
#define DCHAR_H #define DCHAR_H
#if __GNUC__ && !_WIN32 #if __GNUC__ && !_WIN32
#include "gnuc.h" #include "gnuc.h"
#endif #endif
#if _MSC_VER #if _MSC_VER
// Disable useless warnings about unreferenced functions // Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514) #pragma warning (disable : 4514)
#endif #endif
//#include "root.h" //#include "root.h"
typedef size_t hash_t; typedef size_t hash_t;
#undef TEXT #undef TEXT
// NOTE: All functions accepting pointer arguments must not be NULL // NOTE: All functions accepting pointer arguments must not be NULL
#if M_UNICODE #if M_UNICODE
#include <string.h> #include <string.h>
#include <wchar.h> #include <wchar.h>
typedef wchar_t dchar; typedef wchar_t dchar;
#define TEXT(x) L##x #define TEXT(x) L##x
#define Dchar_mbmax 1 #define Dchar_mbmax 1
struct Dchar struct Dchar
{ {
static dchar *inc(dchar *p) { return p + 1; } static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; 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 int len(const dchar *p) { return wcslen(p); }
static dchar get(dchar *p) { return *p; } static dchar get(dchar *p) { return *p; }
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } 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 dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) static int cmp(dchar *s1, dchar *s2)
{ {
#if __DMC__ #if __DMC__
if (!*s1 && !*s2) // wcscmp is broken if (!*s1 && !*s2) // wcscmp is broken
return 0; return 0;
#endif #endif
return wcscmp(s1, s2); return wcscmp(s1, s2);
#if 0 #if 0
return (*s1 == *s2) return (*s1 == *s2)
? wcscmp(s1, s2) ? wcscmp(s1, s2)
: ((int)*s1 - (int)*s2); : ((int)*s1 - (int)*s2);
#endif #endif
} }
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } 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 isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return iswalpha(c); } static int isAlpha(dchar c) { return iswalpha(c); }
static int isUpper(dchar c) { return iswupper(c); } static int isUpper(dchar c) { return iswupper(c); }
static int isLower(dchar c) { return iswlower(c); } static int isLower(dchar c) { return iswlower(c); }
static int isLocaleUpper(dchar c) { return isUpper(c); } static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); } static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); } static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } 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(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
static dchar *dup(char *p); static dchar *dup(char *p);
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } 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 *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
static dchar *memchr(dchar *p, int c, int count); static dchar *memchr(dchar *p, int c, int count);
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len); static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions // Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } 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 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); static hash_t icalcHash(const dchar *str, size_t len);
}; };
#elif MCBS #elif MCBS
#include <limits.h> #include <limits.h>
#include <mbstring.h> #include <mbstring.h>
typedef char dchar; typedef char dchar;
#define TEXT(x) x #define TEXT(x) x
#define Dchar_mbmax MB_LEN_MAX #define Dchar_mbmax MB_LEN_MAX
#elif UTF8 #elif UTF8
typedef char dchar; typedef char dchar;
#define TEXT(x) x #define TEXT(x) x
#define Dchar_mbmax 6 #define Dchar_mbmax 6
struct Dchar struct Dchar
{ {
static char mblen[256]; static char mblen[256];
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
static dchar *dec(dchar *pstart, dchar *p); static dchar *dec(dchar *pstart, dchar *p);
static int len(const dchar *p) { return strlen(p); } static int len(const dchar *p) { return strlen(p); }
static int get(dchar *p); static int get(dchar *p);
static int getprev(dchar *pstart, dchar *p) static int getprev(dchar *pstart, dchar *p)
{ return *dec(pstart, p) & 0xFF; } { return *dec(pstart, p) & 0xFF; }
static dchar *put(dchar *p, unsigned c); static dchar *put(dchar *p, unsigned c);
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } 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 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 isDigit(dchar c) { return '0' <= c && c <= '9'; }
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
static int isUpper(dchar c) { return c <= 0x7F ? isupper(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 isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
static int isLocaleUpper(dchar c) { return isUpper(c); } static int isLocaleUpper(dchar c) { return isUpper(c); }
static int isLocaleLower(dchar c) { return isLower(c); } static int isLocaleLower(dchar c) { return isLower(c); }
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); } static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } 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 *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
static dchar *chr(dchar *p, int c) { return strchr(p, c); } static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count) static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); } { return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len); static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions // Case insensitive versions
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } 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); } static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
}; };
#else #else
#include <string.h> #include <string.h>
#ifndef GCC_SAFE_DMD #ifndef GCC_SAFE_DMD
#include <ctype.h> #include <ctype.h>
#endif #endif
typedef char dchar; typedef char dchar;
#define TEXT(x) x #define TEXT(x) x
#define Dchar_mbmax 1 #define Dchar_mbmax 1
struct Dchar struct Dchar
{ {
static dchar *inc(dchar *p) { return p + 1; } static dchar *inc(dchar *p) { return p + 1; }
static dchar *dec(dchar *pstart, 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 len(const dchar *p) { return strlen(p); }
static int get(dchar *p) { return *p & 0xFF; } static int get(dchar *p) { return *p & 0xFF; }
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 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 dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } 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 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 isDigit(dchar c) { return '0' <= c && c <= '9'; }
#ifndef GCC_SAFE_DMD #ifndef GCC_SAFE_DMD
static int isAlpha(dchar c) { return isalpha((unsigned char)c); } static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
static int isUpper(dchar c) { return isupper((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 isLower(dchar c) { return islower((unsigned char)c); }
static int isLocaleUpper(dchar c) { return isupper((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 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 c) { return isupper((unsigned char)c) ? tolower(c) : c; }
static int toLower(dchar *p) { return toLower(*p); } static int toLower(dchar *p) { return toLower(*p); }
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; } 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? static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
#endif #endif
static dchar *chr(dchar *p, int c) { return strchr(p, c); } static dchar *chr(dchar *p, int c) { return strchr(p, c); }
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
static dchar *memchr(dchar *p, int c, int count) static dchar *memchr(dchar *p, int c, int count)
{ return (dchar *)::memchr(p, c, count); } { return (dchar *)::memchr(p, c, count); }
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
static hash_t calcHash(const dchar *str, size_t len); static hash_t calcHash(const dchar *str, size_t len);
// Case insensitive versions // Case insensitive versions
#ifdef __GNUC__ #ifdef __GNUC__
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
#else #else
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
#endif #endif
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } 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); static hash_t icalcHash(const dchar *str, size_t len);
}; };
#endif #endif
#endif #endif

636
dmd/root/longdouble.c Normal file
View File

@@ -0,0 +1,636 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Rainer Schuetze
// 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.
// 80 bit floating point value implementation for Microsoft compiler
#if _MSC_VER
#include "longdouble.h"
#include "assert.h"
#include <float.h>
#include <stdio.h>
#include <string.h>
extern "C"
{
// implemented in ldfpu.asm for _WIN64
int ld_initfpu(int bits, int mask);
void ld_expl(longdouble* ld, int exp);
longdouble ld_add(longdouble ld1, longdouble ld2);
longdouble ld_sub(longdouble ld1, longdouble ld2);
longdouble ld_mul(longdouble ld1, longdouble ld2);
longdouble ld_div(longdouble ld1, longdouble ld2);
longdouble ld_mod(longdouble ld1, longdouble ld2);
bool ld_cmpb(longdouble ld1, longdouble ld2);
bool ld_cmpbe(longdouble ld1, longdouble ld2);
bool ld_cmpa(longdouble ld1, longdouble ld2);
bool ld_cmpae(longdouble ld1, longdouble ld2);
bool ld_cmpe(longdouble ld1, longdouble ld2);
bool ld_cmpne(longdouble ld1, longdouble ld2);
longdouble ld_sqrt(longdouble ld1);
longdouble ld_sin(longdouble ld1);
longdouble ld_cos(longdouble ld1);
longdouble ld_tan(longdouble ld1);
}
bool initFPU()
{
#ifdef _WIN64
// int old_cw = ld_initfpu(_RC_NEAR);
int old_cw = ld_initfpu(0x300 /*_PC_64 | _RC_NEAR*/, // #defines NOT identical to CPU FPU control word!
0xF00 /*_MCW_PC | _MCW_RC*/);
#else
int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR,
_MCW_EM | _MCW_PC | _MCW_RC);
#endif
return true;
}
static bool doInitFPU = initFPU();
#ifndef _WIN64
extern "C"
{
double ld_read(const longdouble* pthis)
{
double res;
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fstp res
}
return res;
}
long long ld_readll(const longdouble* pthis)
{
#if 1
return ld_readull(pthis);
#elif defined _WIN64
return ld_readll(this);
#else
longdouble* pthis = this;
long long res;
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fistp qword ptr res
}
return res;
#endif
}
unsigned long long ld_readull(const longdouble* pthis)
{
#if 1
// somehow the FPU does not respect the CHOP mode of the rounding control
// in 64-bit mode
// so we roll our own conversion (it also allows the usual C wrap-around
// instead of the "invalid value" created by the FPU)
int expo = pthis->exponent - 0x3fff;
unsigned long long u;
if(expo < 0 || expo > 127)
return 0;
if(expo < 64)
u = pthis->mantissa >> (63 - expo);
else
u = pthis->mantissa << (expo - 63);
if(pthis->sign)
u = ~u + 1;
return u;
#else
longdouble* pthis = this;
long long res; // cannot use unsigned, VC will not generate "fistp qword"
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
__asm
{
mov eax, pthis
fld tbyte ptr [eax]
fld tbyte ptr twoPow63
fsubp ST(1),ST(0) // move it into signed range
lea eax, res
fistp qword ptr [eax]
}
res ^= (1LL << 63);
return res;
#endif
}
void ld_set(longdouble* pthis, double d)
{
__asm
{
mov eax, pthis
fld d
fstp tbyte ptr [eax]
}
}
void ld_setll(longdouble* pthis, long long d)
{
__asm
{
fild qword ptr d
mov eax, pthis
fstp tbyte ptr [eax]
}
}
void ld_setull(longdouble* pthis, unsigned long long d)
{
d ^= (1LL << 63);
longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 };
__asm
{
fild qword ptr d
fld tbyte ptr twoPow63
faddp ST(1),ST(0)
mov eax, pthis
fstp tbyte ptr [eax]
}
}
} // extern "C"
#endif // !_WIN64
longdouble ldexpl(longdouble ld, int exp)
{
#ifdef _WIN64
ld_expl(&ld, exp);
#else
__asm
{
fild dword ptr exp
fld tbyte ptr ld
fscale // ST(0) = ST(0) * (2**ST(1))
fstp ST(1)
fstp tbyte ptr ld
}
#endif
return ld;
}
///////////////////////////////////////////////////////////////////////
longdouble operator+(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_add(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fadd
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator-(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_sub(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fsub
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator*(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_mul(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fmul
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble operator/(longdouble ld1, longdouble ld2)
{
#ifdef _WIN64
return ld_div(ld1, ld2);
#else
longdouble res;
__asm
{
fld tbyte ptr ld1
fld tbyte ptr ld2
fdiv
fstp tbyte ptr res;
}
return res;
#endif
}
bool operator< (longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpb(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setb AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator<=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpbe(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setbe AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator> (longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpa(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
seta AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator>=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpae(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setae AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator==(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpe(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
sete AL
setnp AH
and AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
bool operator!=(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_cmpne(x, y);
#else
short sw;
bool res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
fucomip ST(0),ST(1)
setne AL
setp AH
or AL,AH
mov res,AL
fstp ST(0)
}
return res;
#endif
}
int _isnan(longdouble ld)
{
return (ld.exponent == 0x7fff && ld.mantissa != 0);
}
longdouble fabsl(longdouble ld)
{
ld.sign = 0;
return ld;
}
longdouble sqrtl(longdouble ld)
{
#ifdef _WIN64
return ld_sqrt(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fsqrt;
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble sinl (longdouble ld)
{
#ifdef _WIN64
return ld_sin(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fsin; // exact for |x|<=PI/4
fstp tbyte ptr res
}
return res;
#endif
}
longdouble cosl (longdouble ld)
{
#ifdef _WIN64
return ld_cos(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fcos; // exact for |x|<=PI/4
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble tanl (longdouble ld)
{
#ifdef _WIN64
return ld_tan(ld);
#else
longdouble res;
__asm
{
fld tbyte ptr ld;
fptan;
fstp ST(0); // always 1
fstp tbyte ptr res;
}
return res;
#endif
}
longdouble fmodl(longdouble x, longdouble y)
{
#ifdef _WIN64
return ld_mod(x, y);
#else
short sw;
longdouble res;
__asm
{
fld tbyte ptr y
fld tbyte ptr x // ST = x, ST1 = y
FM1: // We don't use fprem1 because for some inexplicable
// reason we get -5 when we do _modulo(15, 10)
fprem // ST = ST % ST1
fstsw word ptr sw
fwait
mov AH,byte ptr sw+1 // get msb of status word in AH
sahf // transfer to flags
jp FM1 // continue till ST < ST1
fstp ST(1) // leave remainder on stack
fstp tbyte ptr res;
}
return res;
#endif
}
//////////////////////////////////////////////////////////////
longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 };
longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 };
longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 };
longdouble ld_zero = { 0, 0, 0 };
longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 };
longdouble ld_pi = { 0xc90fdaa22168c235ULL, 0x4000, 0 };
longdouble ld_log2t = { 0xd49a784bcd1b8afeULL, 0x4000, 0 };
longdouble ld_log2e = { 0xb8aa3b295c17f0bcULL, 0x3fff, 0 };
longdouble ld_log2 = { 0x9a209a84fbcff799ULL, 0x3ffd, 0 };
longdouble ld_ln2 = { 0xb17217f7d1cf79acULL, 0x3ffe, 0 };
longdouble ld_pi2 = ld_pi*2;
longdouble ld_piOver2 = ld_pi*0.5;
longdouble ld_piOver4 = ld_pi*0.25;
//////////////////////////////////////////////////////////////
#define LD_TYPE_OTHER 0
#define LD_TYPE_ZERO 1
#define LD_TYPE_INFINITE 2
#define LD_TYPE_SNAN 3
#define LD_TYPE_QNAN 4
int ld_type(longdouble x)
{
if(x.exponent == 0)
return x.mantissa == 0 ? LD_TYPE_ZERO : LD_TYPE_OTHER; // dnormal if not zero
if(x.exponent != 0x7fff)
return LD_TYPE_OTHER;
if(x.mantissa == 0)
return LD_TYPE_INFINITE;
if(x.mantissa & (1LL << 63))
return LD_TYPE_QNAN;
return LD_TYPE_SNAN;
}
int ld_sprint(char* str, int fmt, longdouble x)
{
// fmt is 'a','A','f' or 'g'
if(fmt != 'a' && fmt != 'A')
{
char format[] = { '%', fmt, 0 };
return sprintf(str, format, ld_read(&x));
}
unsigned short exp = x.exponent;
unsigned long long mantissa = x.mantissa;
switch(ld_type(x))
{
case LD_TYPE_ZERO:
return sprintf(str, "0x0.0L");
case LD_TYPE_QNAN:
case LD_TYPE_SNAN:
return sprintf(str, "NAN");
case LD_TYPE_INFINITE:
return sprintf(str, x.sign ? "-INF" : "INF");
}
int len = 0;
if(x.sign)
str[len++] = '-';
len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0.");
mantissa = mantissa << 1;
while(mantissa)
{
int dig = (mantissa >> 60) & 0xf;
dig += dig < 10 ? '0' : fmt - 10;
str[len++] = dig;
mantissa = mantissa << 4;
}
str[len++] = 'p';
if(exp < 0x3fff)
{
str[len++] = '-';
exp = 0x3fff - exp;
}
else
{
str[len++] = '+';
exp = exp - 0x3fff;
}
int exppos = len;
for(int i = 12; i >= 0; i -= 4)
{
int dig = (exp >> i) & 0xf;
if(dig != 0 || len > exppos || i == 0)
str[len++] = dig + (dig < 10 ? '0' : fmt - 10);
}
str[len] = 0;
return len;
}
//////////////////////////////////////////////////////////////
#if UNITTEST
static bool unittest()
{
char buffer[32];
ld_sprint(buffer, 'a', ld_pi);
assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0);
longdouble ldb = ldouble(0.4);
long long b = ldb;
assert(b == 0);
b = ldouble(0.9);
assert(b == 0);
long long x = 0x12345678abcdef78LL;
longdouble ldx = ldouble(x);
assert(ldx > 0);
long long y = ldx;
assert(x == y);
x = -0x12345678abcdef78LL;
ldx = ldouble(x);
assert(ldx < 0);
y = ldx;
assert(x == y);
unsigned long long u = 0x12345678abcdef78LL;
longdouble ldu = ldouble(u);
assert(ldu > 0);
unsigned long long v = ldu;
assert(u == v);
u = 0xf234567812345678ULL;
ldu = ldouble(u);
assert(ldu > 0);
v = ldu;
assert(u == v);
u = 0xf2345678;
ldu = ldouble(u);
ldu = ldu * ldu;
ldu = sqrt(ldu);
v = ldu;
assert(u == v);
u = 0x123456789A;
ldu = ldouble(u);
ldu = ldu * (1LL << 23);
v = ldu;
u = u * (1LL << 23);
assert(u == v);
return true;
}
static bool runUnittest = unittest();
#endif // UNITTEST
#endif // _MSC_VER

254
dmd/root/longdouble.h Normal file
View File

@@ -0,0 +1,254 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Rainer Schuetze
// 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.
// 80 bit floating point value implementation for Microsoft compiler
#ifndef __LONG_DOUBLE_H__
#define __LONG_DOUBLE_H__
#if IN_GCC
#include "d-gcc-real.h"
typedef real_t longdouble;
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
inline int ld_sprint(char* str, int fmt, longdouble x)
{
if(fmt == 'a' || fmt == 'A')
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
return x.format(buffer, 46);
}
#elif !_MSC_VER // has native 10 byte doubles
#include <stdio.h>
typedef long double longdouble;
typedef volatile long double volatile_longdouble;
// also used from within C code, so use a #define rather than a template
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
#define ldouble(x) ((longdouble)(x))
inline int ld_sprint(char* str, int fmt, longdouble x)
{
char sfmt[4] = "%Lg";
sfmt[2] = fmt;
return sprintf(str, sfmt, x);
}
#else
#include <float.h>
#include <limits>
struct longdouble;
extern "C"
{
// implemented in ldfpu.asm for _WIN64
double ld_read(const longdouble* ld);
long long ld_readll(const longdouble* ld);
unsigned long long ld_readull(const longdouble* ld);
void ld_set(longdouble* ld, double d);
void ld_setll(longdouble* ld, long long d);
void ld_setull(longdouble* ld, unsigned long long d);
}
struct longdouble
{
unsigned long long mantissa;
unsigned short exponent:15; // bias 0x3fff
unsigned short sign:1;
unsigned short fill:16; // for 12 byte alignment
// no constructor to be able to use this class in a union
// use ldouble() to explicitely create a longdouble value
template<typename T> longdouble& operator=(T x) { set(x); return *this; }
void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; }
// we need to list all basic types to avoid ambiguities
void set(float d) { ld_set(this, d); }
void set(double d) { ld_set(this, d); }
void set(long double d) { ld_set(this, d); }
void set(signed char d) { ld_set(this, d); }
void set(short d) { ld_set(this, d); }
void set(int d) { ld_set(this, d); }
void set(long d) { ld_set(this, d); }
void set(long long d) { ld_setll(this, d); }
void set(unsigned char d) { ld_set(this, d); }
void set(unsigned short d) { ld_set(this, d); }
void set(unsigned int d) { ld_set(this, d); }
void set(unsigned long d) { ld_set(this, d); }
void set(unsigned long long d) { ld_setull(this, d); }
void set(bool d) { ld_set(this, d); }
operator float () { return ld_read(this); }
operator double () { return ld_read(this); }
operator signed char () { return ld_read(this); }
operator short () { return ld_read(this); }
operator int () { return ld_read(this); }
operator long () { return ld_read(this); }
operator long long () { return ld_readll(this); }
operator unsigned char () { return ld_read(this); }
operator unsigned short () { return ld_read(this); }
operator unsigned int () { return ld_read(this); }
operator unsigned long () { return ld_read(this); }
operator unsigned long long() { return ld_readull(this); }
operator bool () { return mantissa != 0 || exponent != 0; } // correct?
};
// some optimizations are avoided by adding volatile to the longdouble
// type, but this introduces bad ambiguities when using the class implementation above
// as we are going through asm these optimizations won't kick in anyway, so "volatile"
// is not required.
typedef longdouble volatile_longdouble;
inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
{
longdouble d;
d.mantissa = mantissa;
d.exponent = exp;
d.sign = sign;
return d;
}
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
longdouble operator+(longdouble ld1, longdouble ld2);
longdouble operator-(longdouble ld1, longdouble ld2);
longdouble operator*(longdouble ld1, longdouble ld2);
longdouble operator/(longdouble ld1, longdouble ld2);
bool operator< (longdouble ld1, longdouble ld2);
bool operator<=(longdouble ld1, longdouble ld2);
bool operator> (longdouble ld1, longdouble ld2);
bool operator>=(longdouble ld1, longdouble ld2);
bool operator==(longdouble ld1, longdouble ld2);
bool operator!=(longdouble ld1, longdouble ld2);
inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; }
inline longdouble operator+(longdouble ld1) { return ld1; }
template<typename T> inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); }
template<typename T> inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); }
template<typename T> inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); }
template<typename T> inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); }
template<typename T> inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; }
template<typename T> inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; }
template<typename T> inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; }
template<typename T> inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; }
template<typename T> inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; }
template<typename T> inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; }
template<typename T> inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; }
template<typename T> inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; }
template<typename T> inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); }
template<typename T> inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); }
template<typename T> inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); }
template<typename T> inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); }
template<typename T> inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); }
template<typename T> inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); }
template<typename T> inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; }
template<typename T> inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; }
template<typename T> inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; }
template<typename T> inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; }
template<typename T> inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; }
template<typename T> inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; }
int _isnan(longdouble ld);
longdouble fabsl(longdouble ld);
longdouble sqrtl(longdouble ld);
longdouble sinl (longdouble ld);
longdouble cosl (longdouble ld);
longdouble tanl (longdouble ld);
longdouble fmodl(longdouble x, longdouble y);
longdouble ldexpl(longdouble ldval, int exp); // see strtold
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
#undef LDBL_DIG
#undef LDBL_MAX
#undef LDBL_MIN
#undef LDBL_EPSILON
#undef LDBL_MANT_DIG
#undef LDBL_MAX_EXP
#undef LDBL_MIN_EXP
#undef LDBL_MAX_10_EXP
#undef LDBL_MIN_10_EXP
#define LDBL_DIG 18
#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe)
#define LDBL_MIN ldouble(0x8000000000000000ULL, 1)
#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal?
#define LDBL_MANT_DIG 64
#define LDBL_MAX_EXP 16384
#define LDBL_MIN_EXP (-16381)
#define LDBL_MAX_10_EXP 4932
#define LDBL_MIN_10_EXP (-4932)
extern longdouble ld_zero;
extern longdouble ld_one;
extern longdouble ld_pi;
extern longdouble ld_log2t;
extern longdouble ld_log2e;
extern longdouble ld_log2;
extern longdouble ld_ln2;
extern longdouble ld_inf;
extern longdouble ld_qnan;
extern longdouble ld_snan;
///////////////////////////////////////////////////////////////////////
// CLASS numeric_limits<longdouble>
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
: public _Num_float_base
{ // limits for type long double
public:
typedef longdouble _Ty;
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
_STCONS(int, digits, LDBL_MANT_DIG);
_STCONS(int, digits10, LDBL_DIG);
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
};
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
int ld_sprint(char* str, int fmt, longdouble x);
#endif // !_MSC_VER
#endif // __LONG_DOUBLE_H__

View File

@@ -1,63 +1,63 @@
// lstring.c // lstring.c
// Copyright (c) 1999-2002 by Digital Mars // Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// www.digitalmars.com // www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#include <stdlib.h> #include <stdlib.h>
#include "dchar.h" #include "dchar.h"
#include "rmem.h" #include "rmem.h"
#include "lstring.h" #include "lstring.h"
#ifdef _MSC_VER // prevent compiler internal crash #ifdef _MSC_VER // prevent compiler internal crash
Lstring Lstring::zero; Lstring Lstring::zero;
#else #else
Lstring Lstring::zero = LSTRING_EMPTY(); Lstring Lstring::zero = LSTRING_EMPTY();
#endif #endif
Lstring *Lstring::ctor(const dchar *p, unsigned length) Lstring *Lstring::ctor(const dchar *p, unsigned length)
{ {
Lstring *s; Lstring *s;
s = alloc(length); s = alloc(length);
memcpy(s->string, p, length * sizeof(dchar)); memcpy(s->string, p, length * sizeof(dchar));
return s; return s;
} }
Lstring *Lstring::alloc(unsigned length) Lstring *Lstring::alloc(unsigned length)
{ {
Lstring *s; Lstring *s;
s = (Lstring *)mem.malloc(size(length)); s = (Lstring *)mem.malloc(size(length));
s->length = length; s->length = length;
s->string[length] = 0; s->string[length] = 0;
return s; return s;
} }
Lstring *Lstring::append(const Lstring *s) Lstring *Lstring::append(const Lstring *s)
{ {
Lstring *t; Lstring *t;
if (!s->length) if (!s->length)
return this; return this;
t = alloc(length + s->length); t = alloc(length + s->length);
memcpy(t->string, string, length * sizeof(dchar)); memcpy(t->string, string, length * sizeof(dchar));
memcpy(t->string + length, s->string, s->length * sizeof(dchar)); memcpy(t->string + length, s->string, s->length * sizeof(dchar));
return t; return t;
} }
Lstring *Lstring::substring(int start, int end) Lstring *Lstring::substring(int start, int end)
{ {
Lstring *t; Lstring *t;
if (start == end) if (start == end)
return &zero; return &zero;
t = alloc(end - start); t = alloc(end - start);
memcpy(t->string, string + start, (end - start) * sizeof(dchar)); memcpy(t->string, string + start, (end - start) * sizeof(dchar));
return t; return t;
} }

View File

@@ -1,72 +1,74 @@
// lstring.h // lstring.h
// length-prefixed strings // length-prefixed strings
// Copyright (c) 1999-2002 by Digital Mars // Copyright (c) 1999-2002 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// www.digitalmars.com // www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef LSTRING_H #ifndef LSTRING_H
#define LSTRING_H 1 #define LSTRING_H 1
#include "dchar.h" #include "dchar.h"
struct Lstring struct Lstring
{ {
unsigned length; unsigned length;
// Disable warning about nonstandard extension #ifndef IN_GCC
#pragma warning (disable : 4200) // Disable warning about nonstandard extension
dchar string[]; #pragma warning (disable : 4200)
#endif
static Lstring zero; // 0 length string dchar string[];
// No constructors because we want to be able to statically static Lstring zero; // 0 length string
// initialize Lstring's, and Lstrings are of variable size.
// No constructors because we want to be able to statically
#if M_UNICODE // initialize Lstring's, and Lstrings are of variable size.
#define LSTRING(p,length) { length, L##p }
#else #if M_UNICODE
#define LSTRING(p,length) { length, p } #define LSTRING(p,length) { length, L##p }
#endif #else
#define LSTRING(p,length) { length, p }
#if __GNUC__ #endif
#define LSTRING_EMPTY() { 0 }
#else #if __GNUC__
#define LSTRING_EMPTY() LSTRING("", 0) #define LSTRING_EMPTY() { 0 }
#endif #else
#define LSTRING_EMPTY() LSTRING("", 0)
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } #endif
static Lstring *ctor(const dchar *p, unsigned length);
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
static Lstring *alloc(unsigned length); static Lstring *ctor(const dchar *p, unsigned length);
Lstring *clone(); static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
static Lstring *alloc(unsigned length);
unsigned len() { return length; } Lstring *clone();
dchar *toDchars() { return string; } unsigned len() { return length; }
hash_t hash() { return Dchar::calcHash(string, length); } dchar *toDchars() { return string; }
hash_t ihash() { return Dchar::icalcHash(string, length); }
hash_t hash() { return Dchar::calcHash(string, length); }
static int cmp(const Lstring *s1, const Lstring *s2) hash_t ihash() { return Dchar::icalcHash(string, length); }
{
int c = s2->length - s1->length; static int cmp(const Lstring *s1, const Lstring *s2)
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); {
} 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; static int icmp(const Lstring *s1, const Lstring *s2)
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); {
} 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);
}; Lstring *append(const Lstring *s);
Lstring *substring(int start, int end);
#endif };
#endif

View File

@@ -1,100 +1,100 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 2008-2009 by Digital Mars // Copyright (c) 2008-2009 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#if _WIN32 #if _WIN32
#include <windows.h> #include <windows.h>
#pragma comment(lib,"shell32.lib") #pragma comment(lib,"shell32.lib")
void browse(const char *url) void browse(const char *url)
{ {
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
} }
#endif #endif
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 #if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
void browse(const char *url) void browse(const char *url)
{ {
pid_t childpid; pid_t childpid;
const char *args[3]; const char *args[3];
const char *browser = getenv("BROWSER"); const char *browser = getenv("BROWSER");
if (browser) if (browser)
browser = strdup(browser); browser = strdup(browser);
else else
browser = "x-www-browser"; browser = "x-www-browser";
args[0] = browser; args[0] = browser;
args[1] = url; args[1] = url;
args[2] = NULL; args[2] = NULL;
childpid = fork(); childpid = fork();
if (childpid == 0) if (childpid == 0)
{ {
execvp(args[0], (char**)args); execvp(args[0], (char**)args);
perror(args[0]); // failed to execute perror(args[0]); // failed to execute
return; return;
} }
} }
#endif #endif
#if __APPLE__ #if __APPLE__
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
void browse(const char *url) void browse(const char *url)
{ {
pid_t childpid; pid_t childpid;
const char *args[5]; const char *args[5];
char *browser = getenv("BROWSER"); char *browser = getenv("BROWSER");
if (browser) if (browser)
{ browser = strdup(browser); { browser = strdup(browser);
args[0] = browser; args[0] = browser;
args[1] = url; args[1] = url;
args[2] = NULL; args[2] = NULL;
} }
else else
{ {
//browser = "/Applications/Safari.app/Contents/MacOS/Safari"; //browser = "/Applications/Safari.app/Contents/MacOS/Safari";
args[0] = "open"; args[0] = "open";
args[1] = "-a"; args[1] = "-a";
args[2] = "/Applications/Safari.app"; args[2] = "/Applications/Safari.app";
args[3] = url; args[3] = url;
args[4] = NULL; args[4] = NULL;
} }
childpid = fork(); childpid = fork();
if (childpid == 0) if (childpid == 0)
{ {
execvp(args[0], (char**)args); execvp(args[0], (char**)args);
perror(args[0]); // failed to execute perror(args[0]); // failed to execute
return; return;
} }
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,81 +1,83 @@
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
#ifndef PORT_H #ifndef PORT_H
#define PORT_H #define PORT_H
// Portable wrapper around compiler/system specific things. // Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code. // The idea is to minimize #ifdef's in the app code.
#ifndef TYPEDEFS #include "longdouble.h"
#define TYPEDEFS
#ifndef TYPEDEFS
#include <wchar.h> #define TYPEDEFS
#if _MSC_VER #include <wchar.h>
typedef __int64 longlong;
typedef unsigned __int64 ulonglong; #if _MSC_VER
typedef __int64 longlong;
// According to VC 8.0 docs, long double is the same as double typedef unsigned __int64 ulonglong;
#define strtold strtod
#define strtof strtod // According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
#else #define strtof strtod
typedef long long longlong;
typedef unsigned long long ulonglong; #else
#endif typedef long long longlong;
typedef unsigned long long ulonglong;
#endif #endif
typedef double d_time; #endif
struct Port typedef double d_time;
{
static double nan; struct Port
static double infinity; {
static double dbl_max; static double nan;
static double dbl_min; static double infinity;
static long double ldbl_max; static double dbl_max;
static double dbl_min;
#if __OpenBSD__ static longdouble ldbl_max;
#elif __GNUC__ && !defined __HAIKU__
// These conflict with macros in math.h, should rename them #if __OpenBSD__
#undef isnan #elif __GNUC__ && !defined __HAIKU__
#undef isfinite // These conflict with macros in math.h, should rename them
#undef isinfinity #undef isnan
#undef signbit #undef isfinite
#endif #undef isinfinity
static int isNan(double); #undef signbit
static int isNan(long double); #endif
static int isNan(double);
static int isSignallingNan(double); static int isNan(longdouble);
static int isSignallingNan(long double);
static int isSignallingNan(double);
static int isFinite(double); static int isSignallingNan(longdouble);
static int isInfinity(double);
static int Signbit(double); static int isFinite(double);
static int isInfinity(double);
static double floor(double); static int Signbit(double);
static double pow(double x, double y);
static double floor(double);
static long double fmodl(long double x, long double y); static double pow(double x, double y);
static ulonglong strtoull(const char *p, char **pend, int base); static longdouble fmodl(longdouble x, longdouble y);
static char *ull_to_string(char *buffer, ulonglong ull); static ulonglong strtoull(const char *p, char **pend, int base);
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
static char *ull_to_string(char *buffer, ulonglong ull);
// Convert ulonglong to double static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
static double ull_to_double(ulonglong ull);
// Convert ulonglong to double
// Get locale-dependent list separator static double ull_to_double(ulonglong ull);
static const char *list_separator();
static const wchar_t *wlist_separator(); // Get locale-dependent list separator
static const char *list_separator();
static char *strupr(char *); static const wchar_t *wlist_separator();
};
static char *strupr(char *);
#endif };
#endif

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -8,7 +8,7 @@
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef POSIX #ifndef POSIX
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) #define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
#endif #endif
#include <stdio.h> #include <stdio.h>
@@ -35,7 +35,7 @@
#endif #endif
#ifdef __HAIKU__ #ifdef __HAIKU__
#include <iostream> #include <iostream>
#endif #endif
#if POSIX #if POSIX
@@ -364,21 +364,21 @@ FileName::FileName(char *path, char *name)
} }
// Split a path into an Array of paths // Split a path into an Array of paths
Strings *FileName::splitPath(const char *path) Strings *FileName::splitPath(const char *path)
{ {
char c = 0; // unnecessary initializer is for VC /W4 char c = 0; // unnecessary initializer is for VC /W4
const char *p; const char *p;
OutBuffer buf; OutBuffer buf;
Strings *array; Strings *array;
array = new Strings(); array = new Strings();
if (path) if (path)
{ {
p = path; p = path;
do do
{ char instring = 0; { char instring = 0;
while (isspace((unsigned char)*p)) // skip leading whitespace while (isspace((unsigned char)*p)) // skip leading whitespace
p++; p++;
buf.reserve(strlen(p) + 1); // guess size of path buf.reserve(strlen(p) + 1); // guess size of path
// LDC remember first character // LDC remember first character
@@ -799,7 +799,7 @@ void FileName::CopyTo(FileName *to)
* cwd if !=0, search current directory before searching path * cwd if !=0, search current directory before searching path
*/ */
char *FileName::searchPath(Strings *path, const char *name, int cwd) char *FileName::searchPath(Strings *path, const char *name, int cwd)
{ {
if (absolute(name)) if (absolute(name))
{ {
@@ -815,7 +815,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
for (i = 0; i < path->dim; i++) for (i = 0; i < path->dim; i++)
{ {
char *p = path->tdata()[i]; char *p = path->tdata()[i];
char *n = combine(p, name); char *n = combine(p, name);
if (exists(n)) if (exists(n))
@@ -839,7 +839,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
* !=NULL mem.malloc'd file name * !=NULL mem.malloc'd file name
*/ */
char *FileName::safeSearchPath(Strings *path, const char *name) char *FileName::safeSearchPath(Strings *path, const char *name)
{ {
#if _WIN32 #if _WIN32
/* Disallow % / \ : and .. in name characters /* Disallow % / \ : and .. in name characters
@@ -876,7 +876,7 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
for (i = 0; i < path->dim; i++) for (i = 0; i < path->dim; i++)
{ {
char *cname = NULL; char *cname = NULL;
char *cpath = canonicalName(path->tdata()[i]); char *cpath = canonicalName(path->tdata()[i]);
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
// name, (char *)path->data[i], cpath); // name, (char *)path->data[i], cpath);
if (cpath == NULL) if (cpath == NULL)
@@ -966,7 +966,7 @@ void FileName::ensurePathExists(const char *path)
{ {
//printf("mkdir(%s)\n", path); //printf("mkdir(%s)\n", path);
#if _WIN32 #if _WIN32
if (_mkdir(path)) if (_mkdir(path))
#endif #endif
#if POSIX #if POSIX
if (mkdir(path, 0777)) if (mkdir(path, 0777))
@@ -1088,13 +1088,13 @@ int File::read()
//printf("File::read('%s')\n",name); //printf("File::read('%s')\n",name);
fd = open(name, O_RDONLY); fd = open(name, O_RDONLY);
if (fd == -1) if (fd == -1)
{ {
//printf("\topen error, errno = %d\n",errno); //printf("\topen error, errno = %d\n",errno);
goto err1; goto err1;
} }
if (!ref) if (!ref)
::free(buffer); ::free(buffer);
ref = 0; // we own the buffer now ref = 0; // we own the buffer now
//printf("\tfile opened\n"); //printf("\tfile opened\n");
@@ -1104,7 +1104,7 @@ int File::read()
goto err2; goto err2;
} }
size = buf.st_size; size = buf.st_size;
buffer = (unsigned char *) ::malloc(size + 2); buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer) if (!buffer)
{ {
printf("\tmalloc error, errno = %d\n",errno); printf("\tmalloc error, errno = %d\n",errno);
@@ -1137,7 +1137,7 @@ int File::read()
err2: err2:
close(fd); close(fd);
err: err:
::free(buffer); ::free(buffer);
buffer = NULL; buffer = NULL;
len = 0; len = 0;
@@ -1158,11 +1158,11 @@ err1:
goto err1; goto err1;
if (!ref) if (!ref)
::free(buffer); ::free(buffer);
ref = 0; ref = 0;
size = GetFileSize(h,NULL); size = GetFileSize(h,NULL);
buffer = (unsigned char *) ::malloc(size + 2); buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer) if (!buffer)
goto err2; goto err2;
@@ -1191,7 +1191,7 @@ err1:
err2: err2:
CloseHandle(h); CloseHandle(h);
err: err:
::free(buffer); ::free(buffer);
buffer = NULL; buffer = NULL;
len = 0; len = 0;
@@ -1454,23 +1454,23 @@ void File::remove()
#endif #endif
} }
Files *File::match(char *n) Files *File::match(char *n)
{ {
return match(new FileName(n, 0)); return match(new FileName(n, 0));
} }
Files *File::match(FileName *n) Files *File::match(FileName *n)
{ {
#if POSIX #if POSIX
return NULL; return NULL;
#elif _WIN32 #elif _WIN32
HANDLE h; HANDLE h;
WIN32_FIND_DATAA fileinfo; WIN32_FIND_DATAA fileinfo;
Files *a; Files *a;
char *c; char *c;
char *name; char *name;
a = new Files(); a = new Files();
c = n->toChars(); c = n->toChars();
name = n->name(); name = n->name();
h = FindFirstFileA(c,&fileinfo); h = FindFirstFileA(c,&fileinfo);
@@ -1540,7 +1540,7 @@ void File::stat()
void File::checkoffset(size_t offset, size_t nbytes) void File::checkoffset(size_t offset, size_t nbytes)
{ {
if (offset > len || offset + nbytes > len) if (offset > len || offset + nbytes > len)
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset);
} }
char *File::toChars() char *File::toChars()
@@ -1563,11 +1563,11 @@ OutBuffer::~OutBuffer()
mem.free(data); mem.free(data);
} }
char *OutBuffer::extractData() char *OutBuffer::extractData()
{ {
char *p; char *p;
p = (char *)data; p = (char *)data;
data = NULL; data = NULL;
offset = 0; offset = 0;
size = 0; size = 0;
@@ -1813,7 +1813,7 @@ void OutBuffer::align(unsigned size)
// The compiler shipped with Visual Studio 2005 (and possible // The compiler shipped with Visual Studio 2005 (and possible
// other versions) does not support C99 printf format specfiers // other versions) does not support C99 printf format specfiers
// such as %z and %j // such as %z and %j
#if _MSC_VER || __MINGW32__ #if 0 && _MSC_VER
using std::string; using std::string;
using std::wstring; using std::wstring;
@@ -1832,7 +1832,7 @@ search_and_replace(S& str, const S& what, const S& replacement)
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
S tmp = f; \ S tmp = f; \
search_and_replace(fmt, S("%z"), S("%l")); \ search_and_replace(fmt, S("%z"), S("%l")); \
search_and_replace(fmt, S("%j"), S("%i")); \ search_and_replace(fmt, S("%j"), S("%l")); \
f = tmp.c_str(); f = tmp.c_str();
#else #else
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)

View File

@@ -1,425 +1,428 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef ROOT_H #ifndef ROOT_H
#define ROOT_H #define ROOT_H
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#ifdef DEBUG #ifdef DEBUG
#include <assert.h> #include <assert.h>
#endif #endif
#if __DMC__ #if __DMC__
#pragma once #pragma once
#endif #endif
#ifndef IS_PRINTF #ifndef IS_PRINTF
# ifdef __GNUC__ # ifdef __GNUC__
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) )) # define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
# else # else
# define IS_PRINTF(FMTARG) # define IS_PRINTF(FMTARG)
# endif # endif
#endif #endif
typedef size_t hash_t; typedef size_t hash_t;
#include "dchar.h" #include "longdouble.h"
#include "dchar.h"
char *wchar2ascii(wchar_t *);
int wcharIsAscii(wchar_t *); char *wchar2ascii(wchar_t *);
char *wchar2ascii(wchar_t *, unsigned len); int wcharIsAscii(wchar_t *);
int wcharIsAscii(wchar_t *, unsigned len); char *wchar2ascii(wchar_t *, unsigned len);
int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b); int bstrcmp(unsigned char *s1, unsigned char *s2);
void error(const char *format, ...) IS_PRINTF(1); char *bstr2str(unsigned char *b);
void error(const wchar_t *format, ...); void error(const char *format, ...) IS_PRINTF(1);
void warning(const char *format, ...) IS_PRINTF(1); #if M_UNICODE
void error(const dchar *format, ...);
#ifndef TYPEDEFS #endif
#define TYPEDEFS void warning(const char *format, ...) IS_PRINTF(1);
#if _MSC_VER #ifndef TYPEDEFS
#include <float.h> // for _isnan #define TYPEDEFS
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double #if _MSC_VER
#define strtold strtod #include <float.h> // for _isnan
#define strtof strtod #include <malloc.h> // for alloca
#define isnan _isnan // According to VC 8.0 docs, long double is the same as double
longdouble strtold(const char *p,char **endp);
typedef __int64 longlong; #define strtof strtod
typedef unsigned __int64 ulonglong; #define isnan _isnan
#else
typedef long long longlong; typedef __int64 longlong;
typedef unsigned long long ulonglong; typedef unsigned __int64 ulonglong;
#endif #else
typedef long long longlong;
#endif typedef unsigned long long ulonglong;
#endif
longlong randomx();
#endif
/*
* Root of our class library. longlong randomx();
*/
/*
struct OutBuffer; * Root of our class library.
*/
// Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase; struct OutBuffer;
typedef ArrayBase<struct File> Files;
typedef ArrayBase<char> Strings; // Can't include arraytypes.h here, need to declare these directly.
template <typename TYPE> struct ArrayBase;
typedef ArrayBase<struct File> Files;
struct Object typedef ArrayBase<char> Strings;
{
Object() { }
virtual ~Object() { } struct Object
{
virtual int equals(Object *o); Object() { }
virtual ~Object() { }
/**
* Returns a hash code, useful for things like building hash tables of Objects. virtual int equals(Object *o);
*/
virtual hash_t hashCode(); /**
* Returns a hash code, useful for things like building hash tables of Objects.
/** */
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. virtual hash_t hashCode();
* Useful for sorting Objects.
*/ /**
virtual int compare(Object *obj); * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
* Useful for sorting Objects.
/** */
* Pretty-print an Object. Useful for debugging the old-fashioned way. virtual int compare(Object *obj);
*/
virtual void print(); /**
* Pretty-print an Object. Useful for debugging the old-fashioned way.
virtual char *toChars(); */
virtual dchar *toDchars(); virtual void print();
virtual void toBuffer(OutBuffer *buf);
virtual char *toChars();
/** virtual dchar *toDchars();
* Used as a replacement for dynamic_cast. Returns a unique number virtual void toBuffer(OutBuffer *buf);
* defined by the library user. For Object, the return value is 0.
*/ /**
virtual int dyncast(); * Used as a replacement for dynamic_cast. Returns a unique number
* defined by the library user. For Object, the return value is 0.
/** */
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. virtual int dyncast();
*/
/*virtual*/ // not used, disable for now /**
void mark(); * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
}; */
/*virtual*/ // not used, disable for now
struct String : Object void mark();
{ };
int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself struct String : Object
{
String(char *str, int ref = 1); int ref; // != 0 if this is a reference to someone else's string
char *str; // the string itself
~String();
String(char *str, int ref = 1);
static hash_t calcHash(const char *str, size_t len);
static hash_t calcHash(const char *str); ~String();
hash_t hashCode();
unsigned len(); static hash_t calcHash(const char *str, size_t len);
int equals(Object *obj); static hash_t calcHash(const char *str);
int compare(Object *obj); hash_t hashCode();
char *toChars(); unsigned len();
void print(); int equals(Object *obj);
void mark(); int compare(Object *obj);
}; char *toChars();
void print();
struct FileName : String void mark();
{ };
FileName(char *str, int ref);
FileName(char *path, char *name); struct FileName : String
hash_t hashCode(); {
int equals(Object *obj); FileName(char *str, int ref);
static int equals(const char *name1, const char *name2); FileName(char *path, char *name);
int compare(Object *obj); hash_t hashCode();
static int compare(const char *name1, const char *name2); int equals(Object *obj);
static int absolute(const char *name); static int equals(const char *name1, const char *name2);
static char *ext(const char *); int compare(Object *obj);
char *ext(); static int compare(const char *name1, const char *name2);
static char *removeExt(const char *str); static int absolute(const char *name);
static char *name(const char *); static char *ext(const char *);
char *name(); char *ext();
static char *path(const char *); static char *removeExt(const char *str);
static const char *replaceName(const char *path, const char *name); static char *name(const char *);
char *name();
static char *combine(const char *path, const char *name); static char *path(const char *);
static Strings *splitPath(const char *path); static const char *replaceName(const char *path, const char *name);
static FileName *defaultExt(const char *name, const char *ext);
static FileName *forceExt(const char *name, const char *ext); static char *combine(const char *path, const char *name);
int equalsExt(const char *ext); static Strings *splitPath(const char *path);
static FileName *defaultExt(const char *name, const char *ext);
void CopyTo(FileName *to); static FileName *forceExt(const char *name, const char *ext);
static char *searchPath(Strings *path, const char *name, int cwd); int equalsExt(const char *ext);
static char *safeSearchPath(Strings *path, const char *name);
static int exists(const char *name); void CopyTo(FileName *to);
static void ensurePathExists(const char *path); static char *searchPath(Strings *path, const char *name, int cwd);
static char *canonicalName(const char *name); static char *safeSearchPath(Strings *path, const char *name);
}; static int exists(const char *name);
static void ensurePathExists(const char *path);
struct File : Object static char *canonicalName(const char *name);
{ };
int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file struct File : Object
unsigned len; // amount of data in buffer[] {
void *touchtime; // system time to use for file int ref; // != 0 if this is a reference to someone else's buffer
unsigned char *buffer; // data for our file
FileName *name; // name of our file unsigned len; // amount of data in buffer[]
void *touchtime; // system time to use for file
File(char *);
File(FileName *); FileName *name; // name of our file
~File();
File(char *);
void mark(); File(FileName *);
~File();
char *toChars();
void mark();
/* Read file, return !=0 if error
*/ char *toChars();
int read(); /* Read file, return !=0 if error
*/
/* Write file, either succeed or fail
* with error message & exit. int read();
*/
/* Write file, either succeed or fail
void readv(); * with error message & exit.
*/
/* Read file, return !=0 if error
*/ void readv();
int mmread(); /* Read file, return !=0 if error
*/
/* Write file, either succeed or fail
* with error message & exit. int mmread();
*/
/* Write file, either succeed or fail
void mmreadv(); * with error message & exit.
*/
/* Write file, return !=0 if error
*/ void mmreadv();
int write(); /* Write file, return !=0 if error
*/
/* Write file, either succeed or fail
* with error message & exit. int write();
*/
/* Write file, either succeed or fail
void writev(); * with error message & exit.
*/
/* Return !=0 if file exists.
* 0: file doesn't exist void writev();
* 1: normal file
* 2: directory /* Return !=0 if file exists.
*/ * 0: file doesn't exist
* 1: normal file
/* Append to file, return !=0 if error * 2: directory
*/ */
int append(); /* Append to file, return !=0 if error
*/
/* Append to file, either succeed or fail
* with error message & exit. int append();
*/
/* Append to file, either succeed or fail
void appendv(); * with error message & exit.
*/
/* Return !=0 if file exists.
* 0: file doesn't exist void appendv();
* 1: normal file
* 2: directory /* Return !=0 if file exists.
*/ * 0: file doesn't exist
* 1: normal file
int exists(); * 2: directory
*/
/* Given wildcard filespec, return an array of
* matching File's. int exists();
*/
/* Given wildcard filespec, return an array of
static Files *match(char *); * matching File's.
static Files *match(FileName *); */
// Compare file times. static Files *match(char *);
// Return <0 this < f static Files *match(FileName *);
// =0 this == f
// >0 this > f // Compare file times.
int compareTime(File *f); // Return <0 this < f
// =0 this == f
// Read system file statistics // >0 this > f
void stat(); int compareTime(File *f);
/* Set buffer // Read system file statistics
*/ void stat();
void setbuffer(void *buffer, unsigned len) /* Set buffer
{ */
this->buffer = (unsigned char *)buffer;
this->len = len; void setbuffer(void *buffer, unsigned len)
} {
this->buffer = (unsigned char *)buffer;
void checkoffset(size_t offset, size_t nbytes); this->len = len;
}
void remove(); // delete file
}; void checkoffset(size_t offset, size_t nbytes);
struct OutBuffer : Object void remove(); // delete file
{ };
unsigned char *data;
unsigned offset; struct OutBuffer : Object
unsigned size; {
unsigned char *data;
OutBuffer(); unsigned offset;
~OutBuffer(); unsigned size;
char *extractData();
void mark(); OutBuffer();
~OutBuffer();
void reserve(unsigned nbytes); char *extractData();
void setsize(unsigned size); void mark();
void reset();
void write(const void *data, unsigned nbytes); void reserve(unsigned nbytes);
void writebstring(unsigned char *string); void setsize(unsigned size);
void writestring(const char *string); void reset();
void writedstring(const char *string); void write(const void *data, unsigned nbytes);
void writedstring(const wchar_t *string); void writebstring(unsigned char *string);
void prependstring(const char *string); void writestring(const char *string);
void writenl(); // write newline void writedstring(const char *string);
void writeByte(unsigned b); void writedstring(const wchar_t *string);
void writebyte(unsigned b) { writeByte(b); } void prependstring(const char *string);
void writeUTF8(unsigned b); void writenl(); // write newline
void writedchar(unsigned b); void writeByte(unsigned b);
void prependbyte(unsigned b); void writebyte(unsigned b) { writeByte(b); }
void writeword(unsigned w); void writeUTF8(unsigned b);
void writeUTF16(unsigned w); void writedchar(unsigned b);
void write4(unsigned w); void prependbyte(unsigned b);
void write(OutBuffer *buf); void writeword(unsigned w);
void write(Object *obj); void writeUTF16(unsigned w);
void fill0(unsigned nbytes); void write4(unsigned w);
void align(unsigned size); void write(OutBuffer *buf);
void vprintf(const char *format, va_list args); void write(Object *obj);
void printf(const char *format, ...) IS_PRINTF(2); void fill0(unsigned nbytes);
#if M_UNICODE void align(unsigned size);
void vprintf(const unsigned short *format, va_list args); void vprintf(const char *format, va_list args);
void printf(const unsigned short *format, ...); void printf(const char *format, ...) IS_PRINTF(2);
#endif #if M_UNICODE
void bracket(char left, char right); void vprintf(const unsigned short *format, va_list args);
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right); void printf(const unsigned short *format, ...);
void spread(unsigned offset, unsigned nbytes); #endif
unsigned insert(unsigned offset, const void *data, unsigned nbytes); void bracket(char left, char right);
void remove(unsigned offset, unsigned nbytes); unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
char *toChars(); void spread(unsigned offset, unsigned nbytes);
char *extractString(); unsigned insert(unsigned offset, const void *data, unsigned nbytes);
}; void remove(unsigned offset, unsigned nbytes);
char *toChars();
struct Array : Object char *extractString();
{ };
unsigned dim;
void **data; struct Array : Object
{
private: unsigned dim;
unsigned allocdim; void **data;
#define SMALLARRAYCAP 1
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays private:
unsigned allocdim;
public: #define SMALLARRAYCAP 1
Array(); void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
~Array();
//Array(const Array&); public:
void mark(); Array();
char *toChars(); ~Array();
//Array(const Array&);
void reserve(unsigned nentries); void mark();
void setDim(unsigned newdim); char *toChars();
void fixDim();
void push(void *ptr); void reserve(unsigned nentries);
void *pop(); void setDim(unsigned newdim);
void shift(void *ptr); void fixDim();
void insert(unsigned index, void *ptr); void push(void *ptr);
void insert(unsigned index, Array *a); void *pop();
void append(Array *a); void shift(void *ptr);
void remove(unsigned i); void insert(unsigned index, void *ptr);
void zero(); void insert(unsigned index, Array *a);
void *tos(); void append(Array *a);
void sort(); void remove(unsigned i);
Array *copy(); void zero();
}; void *tos();
void sort();
template <typename TYPE> Array *copy();
struct ArrayBase : Array };
{
TYPE **tdata() template <typename TYPE>
{ struct ArrayBase : Array
return (TYPE **)data; {
} TYPE **tdata()
{
TYPE*& operator[] (size_t index) return (TYPE **)data;
{ }
#ifdef DEBUG
assert(index < dim); TYPE*& operator[] (size_t index)
#endif {
return ((TYPE **)data)[index]; #ifdef DEBUG
} assert(index < dim);
#endif
void insert(size_t index, TYPE *v) return ((TYPE **)data)[index];
{ }
Array::insert(index, (void *)v);
} void insert(size_t index, TYPE *v)
{
void insert(size_t index, ArrayBase *a) Array::insert(index, (void *)v);
{ }
Array::insert(index, (Array *)a);
} void insert(size_t index, ArrayBase *a)
{
void append(ArrayBase *a) Array::insert(index, (Array *)a);
{ }
Array::append((Array *)a);
} void append(ArrayBase *a)
{
void push(TYPE *a) Array::append((Array *)a);
{ }
Array::push((void *)a);
} void push(TYPE *a)
{
ArrayBase *copy() Array::push((void *)a);
{ }
return (ArrayBase *)Array::copy();
} ArrayBase *copy()
}; {
return (ArrayBase *)Array::copy();
struct Bits : Object }
{ };
unsigned bitdim;
unsigned allocdim; struct Bits : Object
unsigned *data; {
unsigned bitdim;
Bits(); unsigned allocdim;
~Bits(); unsigned *data;
void mark();
Bits();
void resize(unsigned bitdim); ~Bits();
void mark();
void set(unsigned bitnum);
void clear(unsigned bitnum); void resize(unsigned bitdim);
int test(unsigned bitnum);
void set(unsigned bitnum);
void set(); void clear(unsigned bitnum);
void clear(); int test(unsigned bitnum);
void copy(Bits *from);
Bits *clone(); void set();
void clear();
void sub(Bits *b); void copy(Bits *from);
}; Bits *clone();
#endif void sub(Bits *b);
};
#endif

View File

@@ -1,139 +1,139 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "root.h" #include "root.h"
#include "rmem.h" #include "rmem.h"
#include "dchar.h" #include "dchar.h"
#include "lstring.h" #include "lstring.h"
#include "stringtable.h" #include "stringtable.h"
void StringTable::init(unsigned size) void StringTable::init(unsigned size)
{ {
table = (void **)mem.calloc(size, sizeof(void *)); table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size; tabledim = size;
count = 0; count = 0;
} }
StringTable::~StringTable() StringTable::~StringTable()
{ {
unsigned i; unsigned i;
// Zero out dangling pointers to help garbage collector. // Zero out dangling pointers to help garbage collector.
// Should zero out StringEntry's too. // Should zero out StringEntry's too.
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
table[i] = NULL; table[i] = NULL;
mem.free(table); mem.free(table);
table = NULL; table = NULL;
} }
struct StringEntry struct StringEntry
{ {
StringEntry *left; StringEntry *left;
StringEntry *right; StringEntry *right;
hash_t hash; hash_t hash;
StringValue value; StringValue value;
static StringEntry *alloc(const dchar *s, unsigned len); static StringEntry *alloc(const dchar *s, unsigned len);
}; };
StringEntry *StringEntry::alloc(const dchar *s, unsigned len) StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
{ {
StringEntry *se; StringEntry *se;
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
se->value.lstring.length = len; se->value.lstring.length = len;
se->hash = Dchar::calcHash(s,len); se->hash = Dchar::calcHash(s,len);
memcpy(se->value.lstring.string, s, len * sizeof(dchar)); memcpy(se->value.lstring.string, s, len * sizeof(dchar));
return se; return se;
} }
void **StringTable::search(const dchar *s, unsigned len) void **StringTable::search(const dchar *s, unsigned len)
{ {
hash_t hash; hash_t hash;
unsigned u; unsigned u;
int cmp; int cmp;
StringEntry **se; StringEntry **se;
//printf("StringTable::search(%p,%d)\n",s,len); //printf("StringTable::search(%p,%d)\n",s,len);
hash = Dchar::calcHash(s,len); hash = Dchar::calcHash(s,len);
u = hash % tabledim; u = hash % tabledim;
se = (StringEntry **)&table[u]; se = (StringEntry **)&table[u];
//printf("\thash = %d, u = %d\n",hash,u); //printf("\thash = %d, u = %d\n",hash,u);
while (*se) while (*se)
{ {
cmp = (*se)->hash - hash; cmp = (*se)->hash - hash;
if (cmp == 0) if (cmp == 0)
{ {
cmp = (*se)->value.lstring.len() - len; cmp = (*se)->value.lstring.len() - len;
if (cmp == 0) if (cmp == 0)
{ {
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
if (cmp == 0) if (cmp == 0)
break; break;
} }
} }
if (cmp < 0) if (cmp < 0)
se = &(*se)->left; se = &(*se)->left;
else else
se = &(*se)->right; se = &(*se)->right;
} }
//printf("\treturn %p, %p\n",se, (*se)); //printf("\treturn %p, %p\n",se, (*se));
return (void **)se; return (void **)se;
} }
StringValue *StringTable::lookup(const dchar *s, unsigned len) StringValue *StringTable::lookup(const dchar *s, unsigned len)
{ StringEntry *se; { StringEntry *se;
se = *(StringEntry **)search(s,len); se = *(StringEntry **)search(s,len);
if (se) if (se)
return &se->value; return &se->value;
else else
return NULL; return NULL;
} }
StringValue *StringTable::update(const dchar *s, unsigned len) StringValue *StringTable::update(const dchar *s, unsigned len)
{ StringEntry **pse; { StringEntry **pse;
StringEntry *se; StringEntry *se;
pse = (StringEntry **)search(s,len); pse = (StringEntry **)search(s,len);
se = *pse; se = *pse;
if (!se) // not in table: so create new entry if (!se) // not in table: so create new entry
{ {
se = StringEntry::alloc(s, len); se = StringEntry::alloc(s, len);
*pse = se; *pse = se;
} }
return &se->value; return &se->value;
} }
StringValue *StringTable::insert(const dchar *s, unsigned len) StringValue *StringTable::insert(const dchar *s, unsigned len)
{ StringEntry **pse; { StringEntry **pse;
StringEntry *se; StringEntry *se;
pse = (StringEntry **)search(s,len); pse = (StringEntry **)search(s,len);
se = *pse; se = *pse;
if (se) if (se)
return NULL; // error: already in table return NULL; // error: already in table
else else
{ {
se = StringEntry::alloc(s, len); se = StringEntry::alloc(s, len);
*pse = se; *pse = se;
} }
return &se->value; return &se->value;
} }

View File

@@ -1,48 +1,48 @@
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
// License for redistribution is by either the Artistic License // License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt. // in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details. // See the included readme.txt for details.
#ifndef STRINGTABLE_H #ifndef STRINGTABLE_H
#define STRINGTABLE_H #define STRINGTABLE_H
#if __SC__ #if __SC__
#pragma once #pragma once
#endif #endif
#include "root.h" #include "root.h"
#include "dchar.h" #include "dchar.h"
#include "lstring.h" #include "lstring.h"
struct StringValue struct StringValue
{ {
union union
{ int intvalue; { int intvalue;
void *ptrvalue; void *ptrvalue;
dchar *string; dchar *string;
}; };
Lstring lstring; Lstring lstring;
}; };
struct StringTable struct StringTable
{ {
void **table; void **table;
unsigned count; unsigned count;
unsigned tabledim; unsigned tabledim;
void init(unsigned size = 37); void init(unsigned size = 37);
~StringTable(); ~StringTable();
StringValue *lookup(const dchar *s, unsigned len); StringValue *lookup(const dchar *s, unsigned len);
StringValue *insert(const dchar *s, unsigned len); StringValue *insert(const dchar *s, unsigned len);
StringValue *update(const dchar *s, unsigned len); StringValue *update(const dchar *s, unsigned len);
private: private:
void **search(const dchar *s, unsigned len); void **search(const dchar *s, unsigned len);
}; };
#endif #endif

View File

@@ -78,7 +78,6 @@ Scope::Scope()
this->parameterSpecialization = 0; this->parameterSpecialization = 0;
this->callSuper = 0; this->callSuper = 0;
this->flags = 0; this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL; this->lastdc = NULL;
this->lastoffset = 0; this->lastoffset = 0;
this->docbuf = NULL; this->docbuf = NULL;
@@ -127,7 +126,6 @@ Scope::Scope(Scope *enclosing)
this->parameterSpecialization = enclosing->parameterSpecialization; this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper; this->callSuper = enclosing->callSuper;
this->flags = 0; this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL; this->lastdc = NULL;
this->lastoffset = 0; this->lastoffset = 0;
this->docbuf = enclosing->docbuf; this->docbuf = enclosing->docbuf;

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -64,6 +64,10 @@ struct Scope
Statement *scontinue; // enclosing statement that supports "continue" Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate unsigned offset; // next offset to use in aggregate
// This really shouldn't be a part of Scope, because it requires
// semantic() to be done in the lexical field order. It should be
// set in a pass after semantic() on all fields so they can be
// semantic'd in any order.
int inunion; // we're processing members of a union int inunion; // we're processing members of a union
int incontract; // we're inside contract code int incontract; // we're inside contract code
int nofree; // set if shouldn't free it int nofree; // set if shouldn't free it
@@ -95,7 +99,6 @@ struct Scope
#define SCOPEstaticif 2 // inside static if #define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list #define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec unsigned lastoffset; // offset in docbuf of where to insert next dec

View File

@@ -4,9 +4,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#if __sun&&__SVR4 #if __sun&&__SVR4 || _MSC_VER
#include <alloca.h> #include <alloca.h>
#endif #endif
#if _MSC_VER
#include <malloc.h>
#endif
#include "speller.h" #include "speller.h"

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -1441,7 +1441,13 @@ Statement *ForeachStatement::semantic(Scope *sc)
s =((ScopeExp *)e)->sds; s =((ScopeExp *)e)->sds;
if (s) if (s)
{
var = new AliasDeclaration(loc, arg->ident, s); var = new AliasDeclaration(loc, arg->ident, s);
}
else if (e->op == TOKtype)
{
var = new AliasDeclaration(loc, arg->ident, e->type);
}
else else
{ {
arg->type = e->type; arg->type = e->type;
@@ -3783,6 +3789,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
{ {
exp = exp->semantic(sc); exp = exp->semantic(sc);
exp = resolveProperties(sc, exp); exp = resolveProperties(sc, exp);
if (exp->op == TOKerror)
goto Lbody;
ClassDeclaration *cd = exp->type->isClassHandle(); ClassDeclaration *cd = exp->type->isClassHandle();
if (!cd) if (!cd)
error("can only synchronize on class objects, not '%s'", exp->type->toChars()); error("can only synchronize on class objects, not '%s'", exp->type->toChars());
@@ -3797,6 +3805,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
exp = exp->semantic(sc); exp = exp->semantic(sc);
} }
#if 1
/* Rewrite as: /* Rewrite as:
* auto tmp = exp; * auto tmp = exp;
* _d_monitorenter(tmp); * _d_monitorenter(tmp);
@@ -3827,7 +3836,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
s = new CompoundStatement(loc, cs); s = new CompoundStatement(loc, cs);
return s->semantic(sc); return s->semantic(sc);
#endif
} }
#if 1
else else
{ /* Generate our own critical section, then rewrite as: { /* Generate our own critical section, then rewrite as:
* __gshared byte[CriticalSection.sizeof] critsec; * __gshared byte[CriticalSection.sizeof] critsec;
@@ -3869,6 +3880,11 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
s = new CompoundStatement(loc, cs); s = new CompoundStatement(loc, cs);
return s->semantic(sc); return s->semantic(sc);
} }
#endif
Lbody:
if (body)
body = body->semantic(sc);
return this;
} }
int SynchronizedStatement::hasBreak() int SynchronizedStatement::hasBreak()
@@ -4141,7 +4157,9 @@ Catch *Catch::syntaxCopy()
} }
void Catch::semantic(Scope *sc) void Catch::semantic(Scope *sc)
{ ScopeDsymbol *sym; {
if (type && type->deco)
return;
//printf("Catch::semantic(%s)\n", ident->toChars()); //printf("Catch::semantic(%s)\n", ident->toChars());
@@ -4158,7 +4176,7 @@ void Catch::semantic(Scope *sc)
} }
#endif #endif
sym = new ScopeDsymbol(); ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc->scopesym; sym->parent = sc->scopesym;
sc = sc->push(sym); sc = sc->push(sym);

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -36,7 +36,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
alignsize = 0; // size of struct for alignment purposes alignsize = 0; // size of struct for alignment purposes
structalign = 0; // struct member alignment in effect structalign = 0; // struct member alignment in effect
hasUnions = 0; hasUnions = 0;
sizeok = 0; // size not determined yet sizeok = SIZEOKnone; // size not determined yet
isdeprecated = 0; isdeprecated = 0;
inv = NULL; inv = NULL;
aggNew = NULL; aggNew = NULL;
@@ -123,9 +123,9 @@ unsigned AggregateDeclaration::size(Loc loc)
//printf("AggregateDeclaration::size() = %d\n", structsize); //printf("AggregateDeclaration::size() = %d\n", structsize);
if (!members) if (!members)
error(loc, "unknown size"); error(loc, "unknown size");
if (sizeok != 1 && scope) if (sizeok != SIZEOKdone && scope)
semantic(NULL); semantic(NULL);
if (sizeok != 1) if (sizeok != SIZEOKdone)
{ error(loc, "no size yet for forward reference"); { error(loc, "no size yet for forward reference");
//*(char*)0=0; //*(char*)0=0;
} }
@@ -169,73 +169,41 @@ void AggregateDeclaration::alignmember(
//printf("result = %d\n", *poffset); //printf("result = %d\n", *poffset);
} }
/****************************************
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) * Place a member (mem) into an aggregate (agg), which can be a struct, union or class
* Returns:
* offset to place field at
*/
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
unsigned *paggsize, // size of aggregate (updated)
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
bool isunion // the aggregate is a union
)
{ {
unsigned memsize; // size of member unsigned ofs = *nextoffset;
unsigned memalignsize; // size of member for alignment purposes alignmember(memalign, memalignsize, &ofs);
unsigned xalign; // alignment boundaries unsigned memoffset = ofs;
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
// Check for forward referenced types which will fail the size() call
Type *t = v->type->toBasetype();
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
{ TypeStruct *ts = (TypeStruct *)t;
#if DMDV2
if (ts->sym == this)
{
error("cannot have field %s with same struct type", v->toChars());
}
#endif
if (ts->sym->sizeok != 1 && ts->sym->scope)
ts->sym->semantic(NULL);
if (ts->sym->sizeok != 1)
{
sizeok = 2; // cannot finish; flag as forward referenced
return;
}
}
if (t->ty == Tident)
{
sizeok = 2; // cannot finish; flag as forward referenced
return;
}
memsize = v->type->size(loc);
memalignsize = v->type->alignsize();
xalign = v->type->memalign(sc->structalign);
#if 0
alignmember(xalign, memalignsize, &sc->offset);
v->offset = sc->offset;
sc->offset += memsize;
if (sc->offset > structsize)
structsize = sc->offset;
#else
unsigned ofs = sc->offset;
alignmember(xalign, memalignsize, &ofs);
v->offset = ofs;
ofs += memsize; ofs += memsize;
if (ofs > structsize) if (ofs > *paggsize)
structsize = ofs; *paggsize = ofs;
if (!isUnionDeclaration()) if (!isunion)
sc->offset = ofs; *nextoffset = ofs;
#endif if (global.params.is64bit && memalign == 8 && memalignsize == 16)
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16)
/* Not sure how to handle this */ /* Not sure how to handle this */
; ;
else if (sc->structalign < memalignsize) else if (memalign < memalignsize)
memalignsize = sc->structalign; memalignsize = memalign;
if (alignsize < memalignsize) if (*paggalignsize < memalignsize)
alignsize = memalignsize; *paggalignsize = memalignsize;
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
v->storage_class |= STCfield; return memoffset;
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
fields.push(v);
} }
/**************************************** /****************************************
* If field[indx] is not part of a union, return indx. * If field[indx] is not part of a union, return indx.
* Otherwise, return the lowest field index of the union. * Otherwise, return the lowest field index of the union.
@@ -330,7 +298,7 @@ void StructDeclaration::semantic(Scope *sc)
return; return;
if (symtab) if (symtab)
{ if (sizeok == 1 || !scope) { if (sizeok == SIZEOKdone || !scope)
{ //printf("already completed\n"); { //printf("already completed\n");
scope = NULL; scope = NULL;
return; // semantic() already completed return; // semantic() already completed
@@ -369,7 +337,7 @@ void StructDeclaration::semantic(Scope *sc)
type = type->constOf(); type = type->constOf();
#endif #endif
if (sizeok == 0) // if not already done the addMember step if (sizeok == SIZEOKnone) // if not already done the addMember step
{ {
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
@@ -379,7 +347,7 @@ void StructDeclaration::semantic(Scope *sc)
} }
} }
sizeok = 0; sizeok = SIZEOKnone;
sc2 = sc->push(this); sc2 = sc->push(this);
sc2->stc = 0; sc2->stc = 0;
sc2->parent = this; sc2->parent = this;
@@ -394,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
* resolve individual members like enums. * resolve individual members like enums.
*/ */
for (size_t i = 0; i < members_dim; i++) for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = members->tdata()[i]; { Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because /* There are problems doing this in the general case because
* Scope keeps track of things like 'offset' * Scope keeps track of things like 'offset'
*/ */
@@ -407,8 +375,13 @@ void StructDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < members_dim; i++) for (size_t i = 0; i < members_dim; i++)
{ {
Dsymbol *s = members->tdata()[i]; Dsymbol *s = (*members)[i];
// Ungag errors when not speculative
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !isSpeculative())
global.gag = 0;
s->semantic(sc2); s->semantic(sc2);
global.gag = oldgag;
#if 0 #if 0
if (sizeok == 2) if (sizeok == 2)
{ //printf("forward reference\n"); { //printf("forward reference\n");
@@ -416,6 +389,7 @@ void StructDeclaration::semantic(Scope *sc)
} }
#endif #endif
} }
finalizeSize(sc2);
#if DMDV1 #if DMDV1
/* This doesn't work for DMDV2 because (ref S) and (S) parameter /* This doesn't work for DMDV2 because (ref S) and (S) parameter
@@ -480,44 +454,14 @@ void StructDeclaration::semantic(Scope *sc)
} }
#endif #endif
#if DMDV2 #if DMDV2
/* Try to find the opEquals function. Build it if necessary.
*/
TypeFunction *tfeqptr;
{ // bool opEquals(const T*) const;
Parameters *parameters = new Parameters;
#if STRUCTTHISREF
// bool opEquals(ref const T) const;
Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL);
#else
// bool opEquals(const T*) const;
Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL);
#endif
parameters->push(param);
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tfeqptr->mod = MODconst;
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2);
Dsymbol *s = search_function(this, Id::eq);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
eq = fdx->overloadExactMatch(tfeqptr);
if (!eq)
fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars());
}
TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL;
// BUG: should also check that td is a function template, not just a template
if (!eq && !td)
eq = buildOpEquals(sc2);
}
dtor = buildDtor(sc2); dtor = buildDtor(sc2);
postblit = buildPostBlit(sc2); postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2); cpctor = buildCpCtor(sc2);
buildOpAssign(sc2); buildOpAssign(sc2);
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
xeq = buildXopEquals(sc2);
#endif #endif
sc2->pop(); sc2->pop();
@@ -525,6 +469,12 @@ void StructDeclaration::semantic(Scope *sc)
if (sizeok == 2) if (sizeok == 2)
{ // semantic() failed because of forward references. { // semantic() failed because of forward references.
// Unwind what we did, and defer it for later // Unwind what we did, and defer it for later
for (size_t i = 0; i < fields.dim; i++)
{ Dsymbol *s = fields[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd)
vd->offset = 0;
}
fields.setDim(0); fields.setDim(0);
structsize = 0; structsize = 0;
alignsize = 0; alignsize = 0;
@@ -551,7 +501,7 @@ void StructDeclaration::semantic(Scope *sc)
// aligned properly. // aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1); structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1; sizeok = SIZEOKdone;
Module::dprogress++; Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
@@ -613,6 +563,36 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
return ScopeDsymbol::search(loc, ident, flags); return ScopeDsymbol::search(loc, ident, flags);
} }
void StructDeclaration::finalizeSize(Scope *sc)
{
if (sizeok != SIZEOKnone)
return;
// Set the offsets of the fields and determine the size of the struct
unsigned offset = 0;
bool isunion = isUnionDeclaration() != NULL;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setFieldOffset(this, &offset, isunion);
}
if (sizeok == SIZEOKfwd)
return;
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// 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);
sizeok = SIZEOKdone;
}
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{ {
buf->printf("%s ", kind()); buf->printf("%s ", kind());

View File

@@ -202,7 +202,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
{ {
if (sc1->scopesym == ti1) if (sc1->scopesym == ti1)
{ {
error("recursive template expansion for template argument %s", t1->toChars()); tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
return 1; // fake a match return 1; // fake a match
} }
} }
@@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->members = decldefs; this->members = decldefs;
this->overnext = NULL; this->overnext = NULL;
this->overroot = NULL; this->overroot = NULL;
this->semanticRun = 0; this->semanticRun = PASSinit;
this->onemember = NULL; this->onemember = NULL;
// Compute in advance for Ddoc's use // Compute in advance for Ddoc's use
@@ -438,7 +438,7 @@ void TemplateDeclaration::semantic(Scope *sc)
#endif #endif
if (semanticRun) if (semanticRun)
return; // semantic() already run return; // semantic() already run
semanticRun = 1; semanticRun = PASSsemantic;
if (sc->func) if (sc->func)
{ {
@@ -994,12 +994,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
* now form the tuple argument. * now form the tuple argument.
*/ */
Tuple *t = new Tuple(); Tuple *t = new Tuple();
dedargs->data[parameters->dim - 1] = (void *)t; dedargs->tdata()[parameters->dim - 1] = t;
tuple_dim = nfargs - (nfparams - 1); tuple_dim = nfargs - (nfparams - 1);
t->objects.setDim(tuple_dim); t->objects.setDim(tuple_dim);
for (size_t i = 0; i < tuple_dim; i++) for (size_t i = 0; i < tuple_dim; i++)
{ Expression *farg = (Expression *)fargs->data[fptupindex + i]; { Expression *farg = fargs->tdata()[fptupindex + i];
// Check invalid arguments to detect errors early.
if (farg->op == TOKerror || farg->type->ty == Terror)
goto Lnomatch;
t->objects.data[i] = (void *)farg->type; t->objects.data[i] = (void *)farg->type;
} }
declareParameter(paramscope, tp, t); declareParameter(paramscope, tp, t);
@@ -1025,7 +1030,7 @@ L2:
{ {
// Match 'ethis' to any TemplateThisParameter's // Match 'ethis' to any TemplateThisParameter's
for (size_t i = 0; i < parameters->dim; i++) for (size_t i = 0; i < parameters->dim; i++)
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; { TemplateParameter *tp = parameters->tdata()[i];
TemplateThisParameter *ttp = tp->isTemplateThisParameter(); TemplateThisParameter *ttp = tp->isTemplateThisParameter();
if (ttp) if (ttp)
{ MATCH m; { MATCH m;
@@ -1101,7 +1106,13 @@ L2:
} }
} }
else else
{ Expression *farg = (Expression *)fargs->data[i]; {
Expression *farg = fargs->tdata()[i];
// Check invalid arguments to detect errors early.
if (farg->op == TOKerror || farg->type->ty == Terror)
goto Lnomatch;
#if 0 #if 0
printf("\tfarg->type = %s\n", farg->type->toChars()); printf("\tfarg->type = %s\n", farg->type->toChars());
printf("\tfparam->type = %s\n", fparam->type->toChars()); printf("\tfparam->type = %s\n", fparam->type->toChars());
@@ -1121,10 +1132,34 @@ L2:
argtype = argtype->invariantOf(); argtype = argtype->invariantOf();
} }
} }
/* Allow implicit function literals to delegate conversion
*/
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = fparam->type;
Expression *e = fe->inferType(tp, 1, parameters);
if (!e)
goto Lvarargs;
farg = e;
argtype = farg->type;
}
if (!(fparam->storageClass & STClazy) && argtype->ty == Tvoid)
goto Lnomatch;
/* Remove top const for dynamic array types and pointer types
*/
if ((argtype->ty == Tarray || argtype->ty == Tpointer) &&
!argtype->isMutable() &&
(!(fparam->storageClass & STCref) ||
(fparam->storageClass & STCauto) && !farg->isLvalue()))
{
argtype = argtype->mutableOf();
}
#endif #endif
MATCH m; MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
//printf("\tdeduceType m = %d\n", m); //printf("\tdeduceType m = %d\n", m);
/* If no match, see if there's a conversion to a delegate /* If no match, see if there's a conversion to a delegate
@@ -1428,7 +1463,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
} }
printf(" fargs:\n"); printf(" fargs:\n");
for (size_t i = 0; i < fargs->dim; i++) for (size_t i = 0; i < fargs->dim; i++)
{ Expression *arg = (Expression *)fargs->data[i]; { Expression *arg = fargs->tdata()[i];
printf("\t%s %s\n", arg->type->toChars(), arg->toChars()); printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
//printf("\tty = %d\n", arg->type->ty); //printf("\tty = %d\n", arg->type->ty);
} }
@@ -1499,8 +1534,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
} }
if (td_ambig) if (td_ambig)
{ {
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(), kind(), parent->toPrettyChars(), ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
} }
@@ -1514,6 +1549,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
fd = ti->toAlias()->isFuncDeclaration(); fd = ti->toAlias()->isFuncDeclaration();
if (!fd) if (!fd)
goto Lerror; goto Lerror;
/* As Bugzilla 3682 shows, a template instance can be matched while instantiating
* that same template. Thus, the function type can be incomplete. Complete it.
*/
{ TypeFunction *tf = (TypeFunction *)fd->type;
assert(tf->ty == Tfunction);
if (tf->next)
fd->type = tf->semantic(loc, sc);
}
return fd; return fd;
Lerror: Lerror:
@@ -1530,14 +1575,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
{ {
if (i) if (i)
bufa.writeByte(','); bufa.writeByte(',');
Object *oarg = (Object *)args->data[i]; Object *oarg = args->tdata()[i];
ObjectToCBuffer(&bufa, &hgs, oarg); ObjectToCBuffer(&bufa, &hgs, oarg);
} }
} }
OutBuffer buf; OutBuffer buf;
argExpTypesToCBuffer(&buf, fargs, &hgs); argExpTypesToCBuffer(&buf, fargs, &hgs);
error(loc, "cannot deduce template function from argument types !(%s)(%s)", if (this->overnext)
::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
kind(), parent->toPrettyChars(), ident->toChars(),
bufa.toChars(), buf.toChars());
else
error("cannot deduce template function from argument types !(%s)(%s)",
bufa.toChars(), buf.toChars()); bufa.toChars(), buf.toChars());
} }
return NULL; return NULL;
@@ -1633,7 +1683,7 @@ char *TemplateDeclaration::toChars()
int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters) int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
{ {
for (size_t i = 0; i < parameters->dim; i++) for (size_t i = 0; i < parameters->dim; i++)
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; { TemplateParameter *tp = parameters->tdata()[i];
if (tp->ident->equals(id)) if (tp->ident->equals(id))
return i; return i;
@@ -1662,7 +1712,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
* Foo!(int*) // template instantiation * Foo!(int*) // template instantiation
* Input: * Input:
* this = int* * this = int*
* tparam = T * tparam = T*
* parameters = [ T:T* ] // Array of TemplateParameter's * parameters = [ T:T* ] // Array of TemplateParameter's
* Output: * Output:
* dedtypes = [ int ] // Array of Expression/Type's * dedtypes = [ int ] // Array of Expression/Type's
@@ -1696,7 +1746,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Loc loc; Loc loc;
if (parameters->dim) if (parameters->dim)
{ {
TemplateParameter *tp = (TemplateParameter *)parameters->data[0]; TemplateParameter *tp = parameters->tdata()[0];
loc = tp->loc; loc = tp->loc;
} }
@@ -1708,7 +1758,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
return deduceType(sc, tparam, parameters, dedtypes); return deduceType(sc, tparam, parameters, dedtypes);
} }
TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; TemplateParameter *tp = parameters->tdata()[i];
// Found the corresponding parameter tp // Found the corresponding parameter tp
if (!tp->isTemplateTypeParameter()) if (!tp->isTemplateTypeParameter())
@@ -2840,14 +2890,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
//printf("TemplateAliasParameter::matchArg()\n"); //printf("TemplateAliasParameter::matchArg()\n");
if (i < tiargs->dim) if (i < tiargs->dim)
oarg = (Object *)tiargs->data[i]; oarg = tiargs->tdata()[i];
else else
{ // Get default argument instead { // Get default argument instead
oarg = defaultArg(loc, sc); oarg = defaultArg(loc, sc);
if (!oarg) if (!oarg)
{ assert(i < dedtypes->dim); { assert(i < dedtypes->dim);
// It might have already been deduced // It might have already been deduced
oarg = (Object *)dedtypes->data[i]; oarg = dedtypes->tdata()[i];
if (!oarg) if (!oarg)
goto Lnomatch; goto Lnomatch;
} }
@@ -2937,7 +2987,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
{ {
s = defaultAlias->toDsymbol(sc); s = defaultAlias->toDsymbol(sc);
if (!s) if (!s)
error("%s is not a symbol", defaultAlias->toChars()); error(Loc(0), "%s is not a symbol", defaultAlias->toChars());
} }
return s; return s;
} }
@@ -2986,7 +3036,13 @@ void TemplateValueParameter::declareParameter(Scope *sc)
void TemplateValueParameter::semantic(Scope *sc) void TemplateValueParameter::semantic(Scope *sc)
{ {
bool wasSame = (sparam->type == valType);
sparam->semantic(sc); sparam->semantic(sc);
if (sparam->type == Type::terror && wasSame)
{ // If sparam has a type error, avoid duplicate errors
valType = Type::terror;
return;
}
valType = valType->semantic(loc, sc); valType = valType->semantic(loc, sc);
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
valType->ty != Tident) valType->ty != Tident)
@@ -3344,13 +3400,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->tinst = NULL; this->tinst = NULL;
this->argsym = NULL; this->argsym = NULL;
this->aliasdecl = NULL; this->aliasdecl = NULL;
this->semanticRun = 0; this->semanticRun = PASSinit;
this->semantictiargsdone = 0; this->semantictiargsdone = 0;
this->withsym = NULL; this->withsym = NULL;
this->nest = 0; this->nest = 0;
this->havetempdecl = 0; this->havetempdecl = 0;
this->isnested = NULL; this->isnested = NULL;
this->errors = 0;
this->speculative = 0; this->speculative = 0;
#if IN_LLVM #if IN_LLVM
@@ -3379,13 +3434,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->tinst = NULL; this->tinst = NULL;
this->argsym = NULL; this->argsym = NULL;
this->aliasdecl = NULL; this->aliasdecl = NULL;
this->semanticRun = 0; this->semanticRun = PASSinit;
this->semantictiargsdone = 1; this->semantictiargsdone = 1;
this->withsym = NULL; this->withsym = NULL;
this->nest = 0; this->nest = 0;
this->havetempdecl = 1; this->havetempdecl = 1;
this->isnested = NULL; this->isnested = NULL;
this->errors = 0;
this->speculative = 0; this->speculative = 0;
#if IN_LLVM #if IN_LLVM
@@ -3463,7 +3517,7 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst // get the enclosing template instance from the scope tinst
tinst = sc->tinst; tinst = sc->tinst;
if (semanticRun != 0) if (semanticRun != PASSinit)
{ {
#if LOG #if LOG
printf("Recursive template expansion\n"); printf("Recursive template expansion\n");
@@ -3472,7 +3526,7 @@ void TemplateInstance::semantic(Scope *sc)
// inst = this; // inst = this;
return; return;
} }
semanticRun = 1; semanticRun = PASSsemantic;
// get the enclosing template instance from the scope tinst // get the enclosing template instance from the scope tinst
tinst = sc->tinst; tinst = sc->tinst;
@@ -3579,7 +3633,7 @@ void TemplateInstance::semantic(Scope *sc)
} }
#if LOG #if LOG
printf("\tit's a match with instance %p\n", inst); printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun);
#endif #endif
return; return;
@@ -3866,7 +3920,7 @@ void TemplateInstance::semantic(Scope *sc)
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
target_symbol_list->remove(target_symbol_list_idx); target_symbol_list->remove(target_symbol_list_idx);
} }
semanticRun = 0; semanticRun = PASSinit;
inst = NULL; inst = NULL;
} }
} }
@@ -4208,13 +4262,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
// Only one template, so we can give better error message // Only one template, so we can give better error message
error("%s does not match template declaration %s", toChars(), tempdecl->toChars()); error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
else else
error("%s does not match any template declaration", toChars()); ::error(loc, "%s %s.%s does not match any template declaration",
tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars());
return NULL; return NULL;
} }
if (td_ambig) if (td_ambig)
{ {
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(), td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
} }
@@ -4275,7 +4330,12 @@ int TemplateInstance::hasNestedArgs(Objects *args)
sa = ((VarExp *)ea)->var; sa = ((VarExp *)ea)->var;
goto Lsa; goto Lsa;
} }
if (ea->op == TOKfunction) if (ea->op == TOKthis)
{
sa = ((ThisExp *)ea)->var;
goto Lsa;
}
if (ea->op == TOKfunction)
{ {
sa = ((FuncExp *)ea)->fd; sa = ((FuncExp *)ea)->fd;
goto Lsa; goto Lsa;
@@ -4472,16 +4532,15 @@ void TemplateInstance::declareParameters(Scope *sc)
//printf("TemplateInstance::declareParameters()\n"); //printf("TemplateInstance::declareParameters()\n");
for (size_t i = 0; i < tdtypes.dim; i++) for (size_t i = 0; i < tdtypes.dim; i++)
{ {
TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i]; TemplateParameter *tp = tempdecl->parameters->tdata()[i];
//Object *o = (Object *)tiargs->data[i]; //Object *o = tiargs->tdata()[i];
Object *o = (Object *)tdtypes.data[i]; // initializer for tp Object *o = tdtypes.tdata()[i]; // initializer for tp
//printf("\ttdtypes[%d] = %p\n", i, o); //printf("\ttdtypes[%d] = %p\n", i, o);
tempdecl->declareParameter(sc, tp, o); tempdecl->declareParameter(sc, tp, o);
} }
} }
/***************************************************** /*****************************************************
* Determine if template instance is really a template function, * Determine if template instance is really a template function,
* and that template function needs to infer types from the function * and that template function needs to infer types from the function
@@ -4493,6 +4552,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
//printf("TemplateInstance::needsTypeInference() %s\n", toChars()); //printf("TemplateInstance::needsTypeInference() %s\n", toChars());
if (!tempdecl) if (!tempdecl)
tempdecl = findTemplateDeclaration(sc); tempdecl = findTemplateDeclaration(sc);
int multipleMatches = FALSE;
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{ {
/* If any of the overloaded template declarations need inference, /* If any of the overloaded template declarations need inference,
@@ -4518,23 +4578,44 @@ int TemplateInstance::needsTypeInference(Scope *sc)
/* Determine if the instance arguments, tiargs, are all that is necessary /* Determine if the instance arguments, tiargs, are all that is necessary
* to instantiate the template. * to instantiate the template.
*/ */
TemplateTupleParameter *tp = td->isVariadic();
//printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
TypeFunction *fdtype = (TypeFunction *)fd->type; TypeFunction *fdtype = (TypeFunction *)fd->type;
if (Parameter::dim(fdtype->parameters) && if (Parameter::dim(fdtype->parameters))
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim)) {
return TRUE; TemplateParameter *tp = td->isVariadic();
if (tp && td->parameters->dim > 1)
return TRUE;
if (tiargs->dim < td->parameters->dim)
{ // Can remain tiargs be filled by default arguments?
for (size_t i = tiargs->dim; i < td->parameters->dim; i++)
{ tp = (*td->parameters)[i];
if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter())
{ if (!ttp->defaultType)
return TRUE;
}
else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter())
{ if (!tap->defaultAlias)
return TRUE;
}
else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter())
{ if (!tvp->defaultValue)
return TRUE;
}
}
}
}
} }
//printf("false\n"); //printf("false\n");
return FALSE; return multipleMatches;
} }
void TemplateInstance::semantic2(Scope *sc) void TemplateInstance::semantic2(Scope *sc)
{ int i; { int i;
if (semanticRun >= 2) if (semanticRun >= PASSsemantic2)
return; return;
semanticRun = 2; semanticRun = PASSsemantic2;
#if LOG #if LOG
printf("+TemplateInstance::semantic2('%s')\n", toChars()); printf("+TemplateInstance::semantic2('%s')\n", toChars());
#endif #endif
@@ -4567,9 +4648,9 @@ void TemplateInstance::semantic3(Scope *sc)
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun); printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
#endif #endif
//if (toChars()[0] == 'D') *(char*)0=0; //if (toChars()[0] == 'D') *(char*)0=0;
if (semanticRun >= 3) if (semanticRun >= PASSsemantic3)
return; return;
semanticRun = 3; semanticRun = PASSsemantic3;
if (!errors && members) if (!errors && members)
{ {
sc = tempdecl->scope; sc = tempdecl->scope;
@@ -4752,9 +4833,24 @@ Dsymbol *TemplateInstance::toAlias()
printf("TemplateInstance::toAlias()\n"); printf("TemplateInstance::toAlias()\n");
#endif #endif
if (!inst) if (!inst)
{ error("cannot resolve forward reference"); {
errors = 1; // Maybe we can resolve it
return this; if (scope)
{
/* Anything that affects scope->offset must be
* done in lexical order. Fwd ref error if it is affected, otherwise allow.
*/
unsigned offset = scope->offset;
Scope *sc = scope;
semantic(scope);
// if (offset != sc->offset)
// inst = NULL; // trigger fwd ref error
}
if (!inst)
{ error("cannot resolve forward reference");
errors = 1;
return this;
}
} }
if (inst != this) if (inst != this)
@@ -4865,7 +4961,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
ti = (TemplateInstance *)ti->syntaxCopy(NULL); ti = (TemplateInstance *)ti->syntaxCopy(NULL);
id = (Identifier *)ti; id = (Identifier *)ti;
} }
ids->data[i] = id; ids->tdata()[i] = id;
} }
tm = new TemplateMixin(loc, ident, tm = new TemplateMixin(loc, ident,
@@ -4886,7 +4982,7 @@ void TemplateMixin::semantic(Scope *sc)
// This for when a class/struct contains mixin members, and // This for when a class/struct contains mixin members, and
// is done over because of forward references // is done over because of forward references
if (parent && toParent()->isAggregateDeclaration()) if (parent && toParent()->isAggregateDeclaration())
semanticRun = 1; // do over semanticRun = PASSsemantic; // do over
else else
{ {
#if LOG #if LOG
@@ -4896,7 +4992,7 @@ void TemplateMixin::semantic(Scope *sc)
} }
} }
if (!semanticRun) if (!semanticRun)
semanticRun = 1; semanticRun = PASSsemantic;
#if LOG #if LOG
printf("\tdo semantic\n"); printf("\tdo semantic\n");
#endif #endif
@@ -4979,10 +5075,10 @@ void TemplateMixin::semantic(Scope *sc)
* runDeferred will re-run mixin's semantic outside of the struct's * runDeferred will re-run mixin's semantic outside of the struct's
* semantic. * semantic.
*/ */
semanticRun = 0; semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad) if (ad)
ad->sizeok = 2; ad->sizeok = SIZEOKfwd;
else else
{ {
// Forward reference // Forward reference
@@ -5027,11 +5123,11 @@ void TemplateMixin::semantic(Scope *sc)
continue; continue;
for (size_t i = 0; i < tiargs->dim; i++) for (size_t i = 0; i < tiargs->dim; i++)
{ Object *o = (Object *)tiargs->data[i]; { Object *o = (*tiargs)[i];
Type *ta = isType(o); Type *ta = isType(o);
Expression *ea = isExpression(o); Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o); Dsymbol *sa = isDsymbol(o);
Object *tmo = (Object *)tm->tiargs->data[i]; Object *tmo = (*tm->tiargs)[i];
if (ta) if (ta)
{ {
Type *tmta = isType(tmo); Type *tmta = isType(tmo);
@@ -5095,10 +5191,8 @@ void TemplateMixin::semantic(Scope *sc)
declareParameters(argscope); declareParameters(argscope);
// Add members to enclosing scope, as well as this scope // Add members to enclosing scope, as well as this scope
for (unsigned i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s; { Dsymbol *s = (*members)[i];
s = (Dsymbol *)members->data[i];
s->addMember(argscope, this, i); s->addMember(argscope, this, i);
//sc->insert(s); //sc->insert(s);
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
@@ -5124,7 +5218,7 @@ void TemplateMixin::semantic(Scope *sc)
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = (*members)[i];
s->semantic(sc2); s->semantic(sc2);
} }
@@ -5166,9 +5260,9 @@ void TemplateMixin::semantic(Scope *sc)
void TemplateMixin::semantic2(Scope *sc) void TemplateMixin::semantic2(Scope *sc)
{ {
if (semanticRun >= 2) if (semanticRun >= PASSsemantic2)
return; return;
semanticRun = 2; semanticRun = PASSsemantic2;
#if LOG #if LOG
printf("+TemplateMixin::semantic2('%s')\n", toChars()); printf("+TemplateMixin::semantic2('%s')\n", toChars());
#endif #endif
@@ -5179,7 +5273,7 @@ void TemplateMixin::semantic2(Scope *sc)
sc = sc->push(this); sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = (*members)[i];
#if LOG #if LOG
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
#endif #endif
@@ -5195,9 +5289,9 @@ void TemplateMixin::semantic2(Scope *sc)
void TemplateMixin::semantic3(Scope *sc) void TemplateMixin::semantic3(Scope *sc)
{ {
if (semanticRun >= 3) if (semanticRun >= PASSsemantic3)
return; return;
semanticRun = 3; semanticRun = PASSsemantic3;
#if LOG #if LOG
printf("TemplateMixin::semantic3('%s')\n", toChars()); printf("TemplateMixin::semantic3('%s')\n", toChars());
#endif #endif
@@ -5207,7 +5301,7 @@ void TemplateMixin::semantic3(Scope *sc)
sc = sc->push(this); sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{ {
Dsymbol *s = (Dsymbol *)members->data[i]; Dsymbol *s = members->tdata()[i];
s->semantic3(sc); s->semantic3(sc);
} }
sc = sc->pop(); sc = sc->pop();
@@ -5230,21 +5324,48 @@ int TemplateMixin::oneMember(Dsymbol **ps)
return Dsymbol::oneMember(ps); return Dsymbol::oneMember(ps);
} }
int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param)
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
if (s)
{
if (s->apply(fp, param))
return 1;
}
}
}
return 0;
}
int TemplateMixin::hasPointers() int TemplateMixin::hasPointers()
{ {
//printf("TemplateMixin::hasPointers() %s\n", toChars()); //printf("TemplateMixin::hasPointers() %s\n", toChars());
if (members) if (members)
for (size_t i = 0; i < members->dim; i++) for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf(" s = %s %s\n", s->kind(), s->toChars());
if (s->hasPointers())
{ {
return 1; Dsymbol *s = (*members)[i];
//printf(" s = %s %s\n", s->kind(), s->toChars());
if (s->hasPointers())
{
return 1;
}
}
return 0;
}
void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setFieldOffset(ad, poffset, isunion);
} }
} }
return 0;
} }
char *TemplateMixin::toChars() char *TemplateMixin::toChars()
@@ -5264,7 +5385,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("mixin "); buf->writestring("mixin ");
for (size_t i = 0; i < idents->dim; i++) for (size_t i = 0; i < idents->dim; i++)
{ Identifier *id = (Identifier *)idents->data[i]; { Identifier *id = idents->tdata()[i];
if (i) if (i)
buf->writeByte('.'); buf->writeByte('.');

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language // Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars // Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved // All Rights Reserved
// written by Walter Bright // written by Walter Bright
// http://www.digitalmars.com // http://www.digitalmars.com
@@ -40,6 +40,7 @@ struct AliasDeclaration;
struct FuncDeclaration; struct FuncDeclaration;
struct HdrGenState; struct HdrGenState;
enum MATCH; enum MATCH;
enum PASS;
struct Tuple : Object struct Tuple : Object
{ {
@@ -60,7 +61,7 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list TemplateDeclaration *overroot; // first in overnext list
int semanticRun; // 1 semantic() run enum PASS semanticRun; // 1 semantic() run
Dsymbol *onemember; // if !=NULL then one member of this template Dsymbol *onemember; // if !=NULL then one member of this template
@@ -287,12 +288,11 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member // sole member
WithScopeSymbol *withsym; // if a member of a with statement WithScopeSymbol *withsym; // if a member of a with statement
int semanticRun; // has semantic() been done? enum PASS semanticRun; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done? int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context Dsymbol *isnested; // if referencing local symbols, this is the context
int errors; // 1 if compiled with errors
int speculative; // 1 if only instantiated with errors gagged int speculative; // 1 if only instantiated with errors gagged
#ifdef IN_GCC #ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol /* On some targets, it is necessary to know whether a symbol
@@ -356,7 +356,9 @@ struct TemplateMixin : TemplateInstance
void inlineScan(); void inlineScan();
const char *kind(); const char *kind();
int oneMember(Dsymbol **ps); int oneMember(Dsymbol **ps);
int apply(Dsymbol_apply_ft_t fp, void *param);
int hasPointers(); int hasPointers();
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
char *toChars(); char *toChars();
char *mangle(); char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);