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
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -51,6 +51,13 @@ namespace llvm
}
#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
{
Type *type;
@@ -62,10 +69,7 @@ struct AggregateDeclaration : ScopeDsymbol
unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
VarDeclarations fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
enum Sizeok sizeok; // set when structsize contains valid data
int isdeprecated; // !=0 if deprecated
#if DMDV2
@@ -89,7 +93,8 @@ struct AggregateDeclaration : ScopeDsymbol
FuncDeclaration *dtor; // aggregate destructor
#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
AggregateDeclaration(Loc loc, Identifier *id);
@@ -98,8 +103,10 @@ struct AggregateDeclaration : ScopeDsymbol
void inlineScan();
unsigned size(Loc loc);
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();
void addField(Scope *sc, VarDeclaration *v);
int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
int isDeprecated(); // is aggregate deprecated?
@@ -163,14 +170,19 @@ struct StructDeclaration : AggregateDeclaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
void finalizeSize(Scope *sc);
#if DMDV1
Expression *cloneMembers();
#endif
#if DMDV2
int needOpAssign();
int needOpEquals();
FuncDeclaration *buildOpAssign(Scope *sc);
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
#endif
void toDocBuffer(OutBuffer *buf);
@@ -222,7 +234,8 @@ struct BaseClass
};
#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
#define CLASSINFO_SIZE (0x3C+12+4) // 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
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
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 m = 0;
@@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
m |= s->addMember(sc, sd, m | memnum);
}
@@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i];
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->setScope(newsc); // yes, the only difference from semanticNewSc()
}
@@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i];
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->semantic(newsc);
}
@@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc)
{
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
s->semantic(sc);
}
@@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc)
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
{ Dsymbol *s = (*d)[i];
s->semantic2(sc);
}
}
@@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc)
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
{ Dsymbol *s = (*d)[i];
s->semantic3(sc);
}
}
@@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan()
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::inlineScan %s\n", s->toChars());
s->inlineScan();
}
@@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::addComment %s\n", s->toChars());
s->addComment(comment);
}
@@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::emitComment %s\n", s->toChars());
s->emitComment(sc);
}
@@ -246,32 +264,27 @@ void AttribDeclaration::toObjFile(int multiobj)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
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);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
n = s->cvMember(p);
if (p)
p += n;
nwritten += n;
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->setFieldOffset(ad, poffset, isunion);
}
}
return nwritten;
}
#endif
int AttribDeclaration::hasPointers()
{
@@ -281,7 +294,7 @@ int AttribDeclaration::hasPointers()
{
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
if (s->hasPointers())
return 1;
}
@@ -323,8 +336,8 @@ void AttribDeclaration::checkCtorConstInit()
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->checkCtorConstInit();
}
}
@@ -339,8 +352,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->addLocalClass(aclasses);
}
}
@@ -354,15 +367,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (decl->dim == 0)
buf->writestring("{}");
else if (decl->dim == 1)
(decl->tdata()[0])->toCBuffer(buf, hgs);
((*decl)[0])->toCBuffer(buf, hgs);
else
{
buf->writenl();
buf->writeByte('{');
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(" ");
s->toCBuffer(buf, hgs);
@@ -467,6 +480,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCout, TOKout },
{ STCin, TOKin },
#if DMDV2
{ STCmanifest, TOKenum },
{ STCimmutable, TOKimmutable },
{ STCshared, TOKshared },
{ STCnothrow, TOKnothrow },
@@ -474,10 +488,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
{ STCref, TOKref },
{ STCtls, TOKtls },
{ STCgshared, TOKgshared },
{ STCproperty, TOKat },
{ STCsafe, TOKat },
{ STCtrusted, TOKat },
{ STCdisable, TOKat },
{ STCproperty, TOKat, Id::property },
{ STCsafe, TOKat, Id::safe },
{ STCtrusted, TOKat, Id::trusted },
{ STCsystem, TOKat, Id::system },
{ STCdisable, TOKat, Id::disable },
#endif
};
@@ -488,20 +503,9 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
enum TOK tok = table[i].tok;
#if DMDV2
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->writestring(id->toChars());
buf->writestring(table[i].id->toChars());
}
else
#endif
@@ -560,9 +564,9 @@ void LinkDeclaration::semantic3(Scope *sc)
{ enum LINK linkage_save = sc->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);
}
@@ -738,6 +742,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
: AttribDeclaration(decl)
{
this->loc = loc;
this->alignment = 0;
this->isunion = isunion;
this->sem = 0;
}
@@ -755,21 +760,6 @@ void AnonDeclaration::semantic(Scope *sc)
{
//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);
Dsymbol *parent = sc->parent->pastMixin();
@@ -781,106 +771,85 @@ void AnonDeclaration::semantic(Scope *sc)
return;
}
alignment = sc->structalign;
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->anonAgg = &aad;
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
sc->inunion = isunion;
sc->offset = 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);
if (isunion)
sc->offset = 0;
if (aad.sizeok == 2)
{
break;
}
}
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;
//printf("\tsetting ad->sizeok %p to 2\n", ad);
if (!sc->anonAgg)
{
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
Module::dprogress = dprogress_save;
//printf("\tforward reference %p\n", this);
return;
Dsymbol *s = (*decl)[i];
s->setFieldOffset(ad, &offset, this->isunion);
if (this->isunion)
offset = 0;
}
if (sem == 0)
{ Module::dprogress++;
sem = 1;
//printf("\tcompleted %p\n", this);
}
else
;//printf("\talready completed %p\n", this);
unsigned anonstructsize = ad->structsize;
unsigned anonalignsize = ad->alignsize;
ad->structsize = savestructsize;
ad->alignsize = savealignsize;
// 0 sized structs are set to 1 byte
if (aad.structsize == 0)
if (anonstructsize == 0)
{
aad.structsize = 1;
aad.alignsize = 1;
anonstructsize = 1;
anonalignsize = 1;
}
// Align size of anonymous aggregate
//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
//ad->structsize = sc->offset;
//printf("sc->offset = %d\n", sc->offset);
/* Given the anon 'member's size and alignment,
* go ahead and place it.
*/
unsigned anonoffset = AggregateDeclaration::placeField(
poffset,
anonstructsize, anonalignsize, alignment,
&ad->structsize, &ad->alignsize,
isunion);
// Add members of aad to ad
//printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars());
for (unsigned i = 0; i < aad.fields.dim; i++)
// Add to the anon fields the base offset of this anonymous aggregate
//printf("anon fields, anonoffset = %d\n", anonoffset);
for (size_t i = fieldstart; i < ad->fields.dim; i++)
{
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
v->offset += sc->offset;
ad->fields.push(v);
VarDeclaration *v = ad->fields[i];
//printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
v->offset += anonoffset;
}
// 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");
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(" ");
s->toCBuffer(buf, hgs);
@@ -953,10 +922,10 @@ void PragmaDeclaration::setScope(Scope *sc)
}
else
{
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e;
(*args)[0] = e;
StringExp* se = e->toString();
if (!se)
{
@@ -991,7 +960,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
for (size_t i = 0; i < args->dim; i++)
{
Expression *e = args->tdata()[i];
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
@@ -1013,11 +982,11 @@ void PragmaDeclaration::semantic(Scope *sc)
error("string expected for library name");
else
{
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e;
(*args)[0] = e;
if (e->op == TOKerror)
goto Lnodecl;
StringExp *se = e->toString();
@@ -1045,7 +1014,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Declaration *d = NULL;
StringExp *s = NULL;
e = (Expression *)args->data[0];
e = (*args)[0];
e = e->semantic(sc);
if (e->op == TOKvar)
{
@@ -1056,14 +1025,14 @@ void PragmaDeclaration::semantic(Scope *sc)
if (!d)
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->optimize(WANTvalue);
e = e->toString();
if (e && ((StringExp *)e)->sz == 1)
s = ((StringExp *)e);
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)
d->c_ident = Lexer::idPool((char*) s->string);
@@ -1078,10 +1047,10 @@ void PragmaDeclaration::semantic(Scope *sc)
error("function name expected for start address");
else
{
Expression *e = (Expression *)args->data[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->data[0] = (void *)e;
(*args)[0] = e;
Dsymbol *sa = getDsymbol(e);
if (!sa || !sa->isFuncDeclaration())
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++)
{
#if IN_LLVM
// ignore errors in ignored pragmas.
global.gag++;
unsigned errors_save = global.errors;
#endif
Expression *e = (Expression *)args->data[i];
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (i == 0)
@@ -1124,9 +1095,11 @@ void PragmaDeclaration::semantic(Scope *sc)
printf(",");
printf("%s", e->toChars());
#if IN_LLVM
// restore error state.
global.gag--;
global.errors = errors_save;
#endif
}
if (args->dim)
printf(")");
@@ -1141,9 +1114,9 @@ void PragmaDeclaration::semantic(Scope *sc)
Ldecl:
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);
@@ -1180,7 +1153,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
{
assert(args && args->dim == 1);
Expression *e = (Expression *)args->data[0];
Expression *e = (*args)[0];
assert(e->op == TOKstring);
@@ -1208,7 +1181,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
else if (ident == Id::startaddress)
{
assert(args && args->dim == 1);
Expression *e = (Expression *)args->data[0];
Expression *e = (*args)[0];
Dsymbol *sa = getDsymbol(e);
FuncDeclaration *f = sa->isFuncDeclaration();
assert(f);
@@ -1285,8 +1258,8 @@ void ConditionalDeclaration::emitComment(Scope *sc)
* a template, then include(NULL, NULL) will fail.
*/
Dsymbols *d = decl ? decl : elsedecl;
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->emitComment(sc);
}
}
@@ -1308,9 +1281,9 @@ void ConditionalDeclaration::setScope(Scope *sc)
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), 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);
}
@@ -1324,9 +1297,9 @@ void ConditionalDeclaration::importAll(Scope *sc)
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), 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);
}
@@ -1349,10 +1322,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment)
{
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s;
s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
s->addComment(comment);
}
@@ -1372,9 +1343,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
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(" ");
s->toCBuffer(buf, hgs);
@@ -1388,9 +1359,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
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(" ");
s->toCBuffer(buf, hgs);
@@ -1474,9 +1445,9 @@ void StaticIfDeclaration::semantic(Scope *sc)
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);
}

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -225,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
: Condition(loc)
{
this->exp = exp;
this->nest = 0;
}
Condition *StaticIfCondition::syntaxCopy()
@@ -235,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy()
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
{
#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)
{
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
@@ -243,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
#endif
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)
{
error(loc, "static if conditional cannot be at global scope");
@@ -250,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
return 0;
}
++nest;
sc = sc->push(sc->scopesym);
sc->sd = s; // s gets any addMember()
sc->flags |= SCOPEstaticif;
Expression *e = exp->semantic(sc);
sc->pop();
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;
else if (e->isBool(FALSE))
inc = 2;

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -530,7 +530,8 @@ void AliasDeclaration::semantic(Scope *sc)
goto L2;
}
else
{ error("cannot alias an expression %s", e->toChars());
{ if (e->op != TOKerror)
error("cannot alias an expression %s", e->toChars());
t = e->type;
}
}
@@ -543,7 +544,7 @@ void AliasDeclaration::semantic(Scope *sc)
ScopeDsymbol::multiplyDefined(0, this, overnext);
this->inSemantic = 0;
if (errors != global.errors)
if (global.gag && errors != global.errors)
type = savedtype;
return;
@@ -580,7 +581,7 @@ void AliasDeclaration::semantic(Scope *sc)
assert(global.errors);
s = NULL;
}
if (errors != global.errors)
if (global.gag && errors != global.errors)
{
type = savedtype;
overnext = savedovernext;
@@ -728,6 +729,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
#if DMDV1
nestedref = 0;
#endif
alignment = 0;
ctorinit = 0;
aliassym = NULL;
onstack = 0;
@@ -767,6 +769,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
sv->storage_class = storage_class;
}
// Syntax copy for header file
if (!htype) // Don't overwrite original
{ if (type) // Make copy for both old and new instances
@@ -955,9 +958,7 @@ void VarDeclaration::semantic(Scope *sc)
}
else
{
AggregateDeclaration *aad = sc->anonAgg;
if (!aad)
aad = parent->isAggregateDeclaration();
AggregateDeclaration *aad = parent->isAggregateDeclaration();
if (aad)
{
#if DMDV2
@@ -970,7 +971,15 @@ void VarDeclaration::semantic(Scope *sc)
}
else
#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();
@@ -1305,6 +1314,31 @@ ExpInitializer *VarDeclaration::getExpInitializer()
void VarDeclaration::semantic2(Scope *sc)
{
//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())
{ inuse++;
#if 0
@@ -1330,6 +1364,82 @@ void VarDeclaration::semantic3(Scope *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()
{
return "variable";

View File

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

View File

@@ -261,6 +261,9 @@ void Module::gendocfile()
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();
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
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -50,6 +50,7 @@ Dsymbol::Dsymbol()
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
this->errors = false;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->irsym = NULL;
@@ -69,6 +70,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
this->errors = false;
#if IN_LLVM
this->llvmInternal = LLVMnone;
this->irsym = NULL;
@@ -169,6 +171,10 @@ bool Dsymbol::hasStaticCtorOrDtor()
return FALSE;
}
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
}
char *Dsymbol::toChars()
{
return ident ? ident->toChars() : (char *)"__anonymous";
@@ -283,6 +289,23 @@ TemplateInstance *Dsymbol::inTemplateInstance()
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()
{
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)
{
/* 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;
Identifier id(seed, 0);
Module::clearCache();
s = s->search(0, &id, 4|2);
return s;
return s->search(0, id, 4|2);
}
Dsymbol *Dsymbol::search_correct(Identifier *ident)
@@ -409,7 +442,13 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
id = ti->name;
sm = s->search(loc, id, 0);
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());
return NULL;
}
@@ -495,6 +534,11 @@ int Dsymbol::isOverloadable()
}
#endif
int Dsymbol::hasOverloads()
{
return 0;
}
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
{
return NULL;
@@ -518,6 +562,11 @@ int Dsymbol::needThis()
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)
{
//printf("Dsymbol::addMember('%s')\n", toChars());
@@ -634,19 +683,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
Module *Dsymbol::getModule()
{
Module *m;
Dsymbol *s;
//printf("Dsymbol::getModule()\n");
TemplateDeclaration *td = getFuncTemplateDecl(this);
if (td)
return td->getModule();
s = this;
Dsymbol *s = this;
while (s)
{
//printf("\ts = '%s'\n", s->toChars());
m = s->isModule();
//printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
Module *m = s->isModule();
if (m)
return m;
s = s->parent;

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -345,10 +345,10 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
*/
Type *t0 = NULL;
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i];
{ Expression *e = (*exps)[i];
if (!e->type)
{ error("%s has no value", e->toChars());
{ error(e->loc, "%s has no value", e->toChars());
e = new ErrorExp();
}
e = resolveProperties(sc, e);
@@ -357,7 +357,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
t0 = e->type;
else
e = e->implicitCastTo(sc, t0);
exps->data[i] = (void *)e;
(*exps)[i] = e;
}
if (!t0)
@@ -384,11 +384,11 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
Expression *e0;
int j0;
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i];
{ Expression *e = (*exps)[i];
e = resolveProperties(sc, e);
if (!e->type)
{ error("%s has no value", e->toChars());
{ e->error("%s has no value", e->toChars());
e = new ErrorExp();
}
@@ -401,8 +401,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
condexp.type = NULL;
condexp.e1 = e0;
condexp.e2 = e;
condexp.loc = e->loc;
condexp.semantic(sc);
exps->data[j0] = (void *)condexp.e1;
(*exps)[j0] = condexp.e1;
e = condexp.e2;
j0 = i;
e0 = e;
@@ -414,15 +415,15 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
e0 = e;
t0 = e->type;
}
exps->data[i] = (void *)e;
(*exps)[i] = e;
}
if (t0)
{
for (size_t i = 0; i < exps->dim; i++)
{ Expression *e = (Expression *)exps->data[i];
{ Expression *e = (*exps)[i];
e = e->implicitCastTo(sc, t0);
exps->data[i] = (void *)e;
(*exps)[i] = e;
}
}
else
@@ -525,23 +526,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
}
#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,
* 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 (!tf->next && fd->inferRetType)
{
TemplateInstance *spec = isSpeculativeFunction(fd);
TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors;
fd->semantic3(fd->scope);
// Update the template instantiation with the number
@@ -583,10 +567,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
Expression *arg;
if (i < nargs)
arg = (Expression *)arguments->data[i];
arg = (*arguments)[i];
else
arg = NULL;
Type *tb;
if (i < nparams)
{
@@ -613,12 +596,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
if (tf->varargs == 2 && i + 1 == nparams)
{
//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;
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;
}
goto L1;
@@ -661,9 +645,6 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
Expression *e = new VarExp(loc, v);
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
AssignExp *ae = new AssignExp(loc, e, a);
#if DMDV2
ae->op = TOKconstruct;
#endif
if (c)
c = new CommaExp(loc, c, ae);
else
@@ -723,7 +704,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
// LDC we don't want this!
#if !IN_LLVM
// Convert static arrays to pointers
tb = arg->type->toBasetype();
Type *tb = arg->type->toBasetype();
if (tb->ty == Tsarray)
{
arg = arg->checkToPointer();
@@ -732,7 +713,19 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
#if DMDV2
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
@@ -801,7 +794,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
}
// 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)
{ TypeSArray *ts = (TypeSArray *)tb;
Type *ta = ts->next->arrayOf();
@@ -2222,6 +2216,7 @@ Lagain:
if (em)
{
e = em->value->copy();
e->loc = loc;
e = e->semantic(sc);
return e;
}
@@ -2234,8 +2229,8 @@ Lagain:
v->semantic(v->scope);
type = v->type;
if (!v->type)
{ error("forward reference of %s", v->toChars());
type = Type::terror;
{ error("forward reference of %s %s", v->kind(), v->toChars());
return new ErrorExp();
}
}
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray)
@@ -2245,8 +2240,7 @@ Lagain:
if (v->inuse)
{
error("circular reference to '%s'", v->toChars());
type = Type::tint32;
return this;
return new ErrorExp();
}
ExpInitializer *ei = v->init->isExpInitializer();
if (ei)
@@ -2282,13 +2276,19 @@ Lagain:
{ //printf("'%s' is a function\n", f->toChars());
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);
global.gag = oldgag;
}
#if DMDV2
// if inferring return type, sematic3 needs to be run
if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
{
TemplateInstance *spec = isSpeculativeFunction(f);
TemplateInstance *spec = f->isSpeculative();
int olderrs = global.errors;
f->semantic3(f->scope);
// Update the template instantiation with the number
@@ -2362,10 +2362,10 @@ Lagain:
}
TemplateInstance *ti = s->isTemplateInstance();
if (ti && !global.errors)
if (ti)
{ if (!ti->semanticRun)
ti->semantic(sc);
s = ti->inst->toAlias();
s = ti->toAlias();
if (!s->isTemplateInstance())
goto Lagain;
e = new ScopeExp(loc, ti);
@@ -3224,6 +3224,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
#endif
if (type)
return this;
// Run semantic() on each element
arrayExpressionSemantic(keys, sc);
arrayExpressionSemantic(values, sc);
@@ -3232,8 +3235,7 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
if (keys->dim != values->dim)
{
error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
keys->setDim(0);
values->setDim(0);
return new ErrorExp();
}
Type *tkey = NULL;
@@ -3241,6 +3243,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
keys = arrayExpressionToCommonType(sc, keys, &tkey);
values = arrayExpressionToCommonType(sc, values, &tvalue);
if (tkey == Type::terror || tvalue == Type::terror)
return new ErrorExp;
type = new TypeAArray(tvalue, tkey);
type = type->semantic(loc, sc);
return this;
@@ -3629,8 +3634,9 @@ Expression *ScopeExp::semantic(Scope *sc)
#endif
Lagain:
ti = sds->isTemplateInstance();
if (ti && !global.errors)
if (ti && !ti->errors)
{
unsigned olderrs = global.errors;
if (!ti->semanticRun)
ti->semantic(sc);
if (ti->inst)
@@ -3660,7 +3666,7 @@ Lagain:
}
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
}
if (global.errors)
if (olderrs != global.errors)
return new ErrorExp();
}
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)
: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
{
@@ -5921,7 +5953,9 @@ Expression *DotIdExp::semantic(Scope *sc)
if (tup)
{
if (eleft)
error("cannot have e.tuple");
{ error("cannot have e.tuple");
return new ErrorExp();
}
e = new TupleExp(loc, tup);
e = e->semantic(sc);
return e;
@@ -5959,7 +5993,12 @@ Expression *DotIdExp::semantic(Scope *sc)
e = e->semantic(sc);
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();
}
else if (e1->type->ty == Tpointer &&
@@ -6239,8 +6278,8 @@ L1:
return e;
if (e->op == TOKdottd)
{
if (global.errors)
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
if (ti->errors)
return new ErrorExp();
DotTemplateExp *dte = (DotTemplateExp *)e;
TemplateDeclaration *td = dte->td;
eleft = dte->e1;
@@ -6248,8 +6287,8 @@ L1:
#if DMDV2
if (ti->needsTypeInference(sc))
{
e = new CallExp(loc, this);
return e->semantic(sc);
e1 = eleft; // save result of semantic()
return this;
}
else
#endif
@@ -6451,6 +6490,7 @@ DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f)
: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
{
this->func = f;
this->hasOverloads = 0;
m = NULL;
}
@@ -6828,6 +6868,17 @@ Lagain:
arrayExpressionSemantic(arguments, sc);
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 ||
e1->op == TOKdottd)
{
@@ -7336,11 +7387,24 @@ Expression *AddrExp::semantic(Scope *sc)
return this;
}
if (f && f->isNested())
if (f)
{
Expression *e = new DelegateExp(loc, e1, f);
e = e->semantic(sc);
return e;
if (f->isNested())
{
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)
@@ -8554,10 +8618,11 @@ Expression *AssignExp::semantic(Scope *sc)
if (e1->op == TOKarray)
{
ArrayExp *ae = (ArrayExp *)e1;
AggregateDeclaration *ad;
AggregateDeclaration *ad = NULL;
Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc);
ae->e1 = resolveProperties(sc, ae->e1);
Type *t1 = ae->e1->type->toBasetype();
if (t1->ty == Tstruct)
{
@@ -8585,7 +8650,9 @@ Expression *AssignExp::semantic(Scope *sc)
{ Expression *e = new DotIdExp(loc, ae->e1, id);
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 = e->semantic(sc);
@@ -8601,7 +8668,7 @@ Expression *AssignExp::semantic(Scope *sc)
if (e1->op == TOKslice)
{ Type *t1;
SliceExp *ae = (SliceExp *)e1;
AggregateDeclaration *ad;
AggregateDeclaration *ad = NULL;
Identifier *id = Id::index;
ae->e1 = ae->e1->semantic(sc);
@@ -8697,8 +8764,9 @@ Expression *AssignExp::semantic(Scope *sc)
* check for operator overloading.
*/
if (t1->ty == Tclass || t1->ty == Tstruct)
{
if (!e2->type->implicitConvTo(e1->type))
{ // Disallow assignment operator overloads for same 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);
if (e)
@@ -8725,8 +8793,16 @@ Expression *AssignExp::semantic(Scope *sc)
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 &&
t1->nextOf() &&
t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) &&
e2->implicitConvTo(t1->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)
: 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)
: 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)
: 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);
if (e1->op == TOKerror)
return e1;
Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();
@@ -9039,13 +9117,15 @@ Expression *CatAssignExp::semantic(Scope *sc)
/************************************************************/
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 *e;
if (type)
return this;
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
@@ -9117,13 +9197,15 @@ Expression *MulAssignExp::semantic(Scope *sc)
/************************************************************/
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 *e;
if (type)
return this;
BinExp::semantic(sc);
e2 = resolveProperties(sc, e2);
@@ -9198,12 +9280,14 @@ Expression *DivAssignExp::semantic(Scope *sc)
/************************************************************/
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)
{
if (type)
return this;
BinExp::semantic(sc);
checkComplexMulAssign();
return commonSemanticAssign(sc);
@@ -9212,104 +9296,28 @@ Expression *ModAssignExp::semantic(Scope *sc)
/************************************************************/
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)
: 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)
: 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)
: 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)
: 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)
: 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
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -932,8 +932,12 @@ struct BinExp : Expression
struct BinAssignExp : BinExp
{
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
int checkSideEffect(int flag);
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
: BinExp(loc, op, size, e1, e2)
{
}
Expression *semantic(Scope *sc);
};
/****************************************************************/
@@ -1031,6 +1035,7 @@ struct DelegateExp : UnaExp
{
FuncDeclaration *func;
Module* m; // starting point for overload resolution
int hasOverloads;
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
Expression *semantic(Scope *sc);
@@ -1446,10 +1451,10 @@ struct ConstructExp : AssignExp
#endif
#define ASSIGNEXP(op) \
struct op##AssignExp : BinExp \
struct op##AssignExp : BinAssignExp \
{ \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
Expression *semantic(Scope *sc); \
S(Expression *semantic(Scope *sc);) \
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
X(Expression *buildArrayLoop(Parameters *fparams);) \
@@ -1460,6 +1465,7 @@ struct op##AssignExp : BinExp \
};
#define X(a) a
#define S(a) a
ASSIGNEXP(Add)
ASSIGNEXP(Min)
ASSIGNEXP(Mul)
@@ -1468,15 +1474,28 @@ ASSIGNEXP(Mod)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#undef S
#if DMDV2
#define S(a) a
ASSIGNEXP(Pow)
#undef S
#endif
#undef X
#define X(a)
#define S(a)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
#undef S
#define S(a) a
ASSIGNEXP(Cat)
#undef S
#undef X
#undef ASSIGNEXP
#undef ASSIGNEXP_TOELEM

View File

@@ -1,5 +1,5 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -306,7 +306,7 @@ void FuncDeclaration::semantic(Scope *sc)
(pd = toParent2()) != 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();
@@ -362,6 +362,9 @@ void FuncDeclaration::semantic(Scope *sc)
//printf("\tnot virtual\n");
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
* (the index will be the same as in cd's current vtbl[])
@@ -407,7 +410,7 @@ void FuncDeclaration::semantic(Scope *sc)
break;
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;
return;
@@ -488,18 +491,26 @@ void FuncDeclaration::semantic(Scope *sc)
break;
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;
return;
default:
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
Type *ti = NULL;
/* Remember which functions this overrides
*/
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)
ti = fdv->tintro;
else if (!type->equals(fdv->type))
@@ -513,7 +524,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (global.endGagging(errors))
{
// 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;
return;
}
@@ -524,10 +535,15 @@ void FuncDeclaration::semantic(Scope *sc)
}
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());
}
}
tintro = ti;
}
goto L2;
@@ -601,7 +617,7 @@ void FuncDeclaration::semantic(Scope *sc)
if (f->varargs)
{
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
}
int FuncDeclaration::hasOverloads()
{
return overnext != NULL;
}
// Determine if function needs
// a static frame pointer to its lexically enclosing function
@@ -3175,7 +3195,7 @@ int StaticCtorDeclaration::addPostInvariant()
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen)
if (hgs->hdrgen && !hgs->tpltMember)
{ buf->writestring("static this();");
buf->writenl();
return;

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -79,7 +79,16 @@ void Import::load(Scope *sc)
// See if existing module
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);
if (s)
{
@@ -89,7 +98,8 @@ void Import::load(Scope *sc)
if (s->isModule())
mod = (Module *)s;
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
}
@@ -97,11 +107,14 @@ void Import::load(Scope *sc)
{
// Load module
mod = Module::load(loc, packages, id);
if (mod)
{
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
}
if (!pkg)
pkg = mod;
@@ -151,7 +164,8 @@ void Import::semantic(Scope *sc)
// Load if not already done so
if (!mod)
{ load(sc);
mod->importAll(0);
if (mod)
mod->importAll(0);
}
if (mod)
@@ -200,7 +214,9 @@ void Import::semantic(Scope *sc)
}
//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:
* ImportDeclaration

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
a = new Initializers();
a->setDim(ai->dim);
for (size_t i = 0; i < a->dim; i++)
{ Initializer *e = (Initializer *)ai->data[i];
{ Initializer *e = (*ai)[i];
e = e->syntaxCopy();
a->data[i] = e;
(*a)[i] = e;
}
}
return a;
@@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy()
ai->value.setDim(value.dim);
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();
ai->value.data[i] = init;
ai->value[i] = init;
}
return ai;
}
@@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
s = ad->search(loc, id, 0);
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;
continue;
}
@@ -212,8 +217,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
if (s && (v = s->isVarDeclaration()) != NULL)
{
val = val->semantic(sc, v->type, needInterpret);
value.data[i] = (void *)val;
vars.data[i] = (void *)v;
value[i] = val;
vars[i] = v;
}
else
{ 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);
for (size_t i = 0; i < elements->dim; i++)
{
elements->data[i] = NULL;
(*elements)[i] = NULL;
}
unsigned fieldi = 0;
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());
goto Lno;
}
Initializer *iz = (Initializer *)value.data[i];
Initializer *iz = value[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
goto Lno;
if (elements->data[fieldi])
if ((*elements)[fieldi])
{ error(loc, "duplicate initializer for field '%s'",
((Dsymbol *)ad->fields.data[fieldi])->toChars());
ad->fields[fieldi]->toChars());
goto Lno;
}
elements->data[fieldi] = ex;
(*elements)[fieldi] = ex;
++fieldi;
}
// Now, fill in any missing elements with default initializers.
// We also need to validate any anonymous unions
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);
if (unionSize == 1)
{ // Not a union -- default initialize if missing
if (!elements->data[i])
elements->data[i] = vd->type->defaultInit();
if (!(*elements)[i])
(*elements)[i] = vd->type->defaultInit();
}
else
{ // anonymous union -- check for errors
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;
if (found >= 0)
{
@@ -375,13 +380,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (i > 0)
buf->writebyte(',');
Identifier *id = (Identifier *)field.data[i];
Identifier *id = field[i];
if (id)
{
buf->writestring(id->toChars());
buf->writebyte(':');
}
Initializer *iz = (Initializer *)value.data[i];
Initializer *iz = value[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
@@ -408,14 +413,14 @@ Initializer *ArrayInitializer::syntaxCopy()
ai->index.setDim(index.dim);
ai->value.setDim(value.dim);
for (size_t i = 0; i < ai->value.dim; i++)
{ Expression *e = (Expression *)index.data[i];
{ Expression *e = index[i];
if (e)
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();
ai->value.data[i] = init;
ai->value[i] = init;
}
return ai;
}
@@ -532,7 +537,7 @@ Expression *ArrayInitializer::toExpression()
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index[i])
j = (index[i])->toInteger();
j = index[i]->toInteger();
if (j >= edim)
edim = j + 1;
}
@@ -584,6 +589,7 @@ Lno:
return new ErrorExp();
}
/********************************
* 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++)
{
e = index.tdata()[i];
e = index[i];
if (!e)
goto Lno;
keys->tdata()[i] = e;
(*keys)[i] = e;
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (!iz)
goto Lno;
e = iz->toExpression();
if (!e)
goto Lno;
values->tdata()[i] = e;
(*values)[i] = e;
}
e = new AssocArrayLiteralExp(loc, keys, values);
return new ExpInitializer(loc, e);
@@ -668,13 +674,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (i > 0)
buf->writebyte(',');
Expression *ex = index.tdata()[i];
Expression *ex = index[i];
if (ex)
{
ex->toCBuffer(buf, hgs);
buf->writebyte(':');
}
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
@@ -707,7 +713,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
return this; // Failed, suppress duplicate error messages
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();
/* 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
if (exp->op == TOKdelegate)
{ DelegateExp *se = (DelegateExp *)exp;
if (
if (se->hasOverloads &&
se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique())
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
// written by Walter Bright
// http://www.digitalmars.com
@@ -196,6 +196,8 @@ int lambdaInlineCost(Expression *e, void *param)
int expressionInlineCost(Expression *e, InlineCostState *ics)
{
//printf("expressionInlineCost()\n");
//e->dump(0);
ICS2 ics2;
ics2.cost = 0;
ics2.ics = ics;
@@ -340,6 +342,7 @@ struct InlineDoState
Dsymbols from; // old Dsymbols
Dsymbols to; // parallel array of new Dsymbols
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 (
!fbody ||
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 &&
(
#if 0
@@ -1600,6 +1606,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
memset(&ids, 0, sizeof(ids));
ids.parent = iss->fd;
ids.fd = this;
if (ps)
as = new Statements();
@@ -1786,6 +1793,18 @@ Expression *Expression::inlineCopy(Scope *sc)
*/
return copy();
#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;
memset(&ics, 0, sizeof(ics));
@@ -1802,3 +1821,4 @@ Expression *Expression::inlineCopy(Scope *sc)
return e;
#endif
}

View File

@@ -27,7 +27,6 @@
#include "attrib.h" // for AttribDeclaration
#include "template.h"
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd);
#define LOG 0
@@ -45,6 +44,10 @@ private:
together with the VarDeclaration, and the previous
stack address of that variable, so that we can restore it
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
them as 'void *' because ArrayBase can only do pointers.
*/
@@ -143,7 +146,11 @@ public:
}
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;
globalValues.push(e);
}
@@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval);
bool needToCopyLiteral(Expression *expr);
Expression *copyLiteral(Expression *e);
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,
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
Expression *scrubReturnValue(Loc loc, Expression *e);
@@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression
{
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
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
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
@@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0)
* arguments function arguments
* 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)
@@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
*/
int olderrors = global.errors;
int oldgag = global.gag;
TemplateInstance *spec = isSpeculativeFunction(this);
TemplateInstance *spec = isSpeculative();
if (global.gag && !spec)
global.gag = 0;
semantic3(scope);
@@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
--evaluatingArgs;
if (earg == EXP_CANT_INTERPRET)
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)
{
@@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
// If fell off the end of a void function, return void
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
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 (exceptionOrCantInterpret(e))
{
@@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
((ThrownExceptionExp *)e)->generateUncaughtError();
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)
{
e = scrubReturnValue(loc, e);
@@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e)
}
// 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)
e1 = resolveSlice(e1);
if (e2->op == TOKslice)
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)
@@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *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
* 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());
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)
{
e = resolveSlice(e);
@@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
{
StructLiteralExp *se = (StructLiteralExp *)e;
se->ownedByCtfe = false;
scrubArray(loc, se->elements);
if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
}
if (e->op == TOKstring)
{
@@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
if (e->op == TOKarrayliteral)
{
((ArrayLiteralExp *)e)->ownedByCtfe = false;
scrubArray(loc, ((ArrayLiteralExp *)e)->elements);
if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
return EXP_CANT_INTERPRET;
}
if (e->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
aae->ownedByCtfe = false;
scrubArray(loc, aae->keys);
scrubArray(loc, aae->values);
if (!scrubArray(loc, aae->keys))
return EXP_CANT_INTERPRET;
if (!scrubArray(loc, aae->values))
return EXP_CANT_INTERPRET;
}
return e;
}
// Scrub all members of an array
void scrubArray(Loc loc, Expressions *elems)
// Scrub all members of an array. Return false if error
bool scrubArray(Loc loc, Expressions *elems, bool structlit)
{
for (size_t i = 0; i < elems->dim; i++)
{
Expression *m = elems->tdata()[i];
if (!m)
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;
}
return true;
}
@@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate)
Expression * caseExp = cs->exp->interpret(istate);
if (exceptionOrCantInterpret(caseExp))
return caseExp;
e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp);
e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp);
if (exceptionOrCantInterpret(e))
return e;
if (e->isBool(TRUE))
@@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate)
ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
Type *extype = ex->thrown->originalClass()->type;
// 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
Catch *ca = (Catch *)catches->data[i];
Catch *ca = (Catch *)catches->data[i];
#else
Catch *ca = catches->tdata()[i];
Catch *ca = catches->tdata()[i];
#endif
Type *catype = ca->type;
Type *catype = ca->type;
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler
if (ca->var)
{
ctfeStack.push(ca->var);
ca->var->setValue(ex->thrown);
}
return ca->handler->interpret(istate);
}
return ca->handler ? ca->handler->interpret(istate) : NULL;
}
}
return e;
}
@@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
}
Type *pointee = ((TypePointer *)type)->next;
Expression *val = getVarExp(loc, istate, var, goal);
if (val == EXP_CANT_INTERPRET)
return val;
if (val->type->ty == Tarray || val->type->ty == Tsarray)
{
// 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)
{
e = copyLiteral(e);
if (v->isDataseg())
ctfeStack.saveGlobalConstant(v, e);
else
v->setValueWithoutChecking(e);
ctfeStack.saveGlobalConstant(v, e);
}
}
else if (v->isCTFE() && !v->hasValue())
@@ -1919,11 +1993,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
{
if (v->init->isVoidInitializer())
{
error(loc, "variable %s is used before initialization", v->toChars());
return EXP_CANT_INTERPRET;
// var should have been initialized when it was created
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
e = v->type->defaultInitLiteral(loc);
@@ -1939,7 +2018,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
e = EXP_CANT_INTERPRET;
}
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))
return e;
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->type->toBasetype()->ty == Tpointer)
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
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)
{
#endif
e = s->dsym->type->defaultInitLiteral();
e = s->dsym->type->defaultInitLiteral(loc);
e = e->semantic(NULL);
if (e->op == TOKerror)
e = EXP_CANT_INTERPRET;
else // Convert NULL to VoidExp
e = e->interpret(istate, goal);
#if !IN_LLVM
}
else
@@ -2045,7 +2137,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
if (ie)
e = ie->exp->interpret(istate);
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
{
error("Declaration %s is not yet implemented in CTFE", toChars());
@@ -2274,7 +2371,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
ekey = resolveSlice(ekey);
for (size_t j = i; j < keysx->dim; 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)
goto Lerr;
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
|| elemType->ty == Tdchar)
return createBlockDuplicatedStringLiteral(loc, newtype,
(unsigned)(elemType->defaultInitLiteral()->toInteger()),
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
len, elemType->size());
return createBlockDuplicatedArrayLiteral(loc, newtype,
elemType->defaultInitLiteral(),
elemType->defaultInitLiteral(loc),
len);
}
@@ -2465,7 +2562,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
if (newtype->toBasetype()->ty == Tstruct)
{
Expression *se = newtype->defaultInitLiteral();
Expression *se = newtype->defaultInitLiteral(loc);
#if DMDV2
if (member)
{
@@ -2502,7 +2599,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
Dsymbol *s = c->fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
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))
return 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)
{
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;
}
@@ -2974,7 +3071,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi
for (size_t j = valuesx->dim; j; )
{ 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))
return ex;
if (ex->isBool(TRUE))
@@ -3144,7 +3241,7 @@ Expression *copyLiteral(Expression *e)
assert(v);
// If it is a void assignment, use the default initializer
if (!m)
m = v->type->defaultInitLiteral(e->loc);
m = v->type->voidInitLiteral(v);
if (m->op == TOKslice)
m = resolveSlice(m);
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 == TOKvar
|| e->op == TOKint64 || e->op == TOKfloat64
|| e->op == TOKchar || e->op == TOKcomplex80)
|| e->op == TOKchar || e->op == TOKcomplex80
|| e->op == TOKvoid)
{ // Simple value types
Expression *r = e->syntaxCopy();
r->type = e->type;
@@ -3341,7 +3439,7 @@ void assignInPlace(Expression *dest, Expression *src)
assert(o->op == e->op);
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);
}
@@ -3636,7 +3734,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
Type *elemType= NULL;
elemType = ((TypeArray *)t)->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral();
Expression *defaultElem = elemType->defaultInitLiteral(loc);
Expressions *elements = new Expressions();
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
// that the parent variable exists.
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral()));
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc)));
// ---------------------------------------
// Deal with reference assignment
@@ -3822,7 +3920,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
indx = resolveSlice(indx);
// 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))
return newAA;
if (!newAA)
@@ -3968,14 +4066,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
? (StructLiteralExp *)exx
: ((ClassReferenceExp *)exx)->value;
int fieldi = exx->op == TOKstructliteral
? se->getFieldIndex(member->type, member->offset)
: ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset);
? findFieldIndexByName(se->sd, member)
: ((ClassReferenceExp *)exx)->findFieldIndexByName(member);
if (fieldi == -1)
{
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
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)
assignInPlace(se->elements->tdata()[fieldi], newval);
else
@@ -4050,6 +4163,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
}
aggregate = getAggregateFromPointer(aggregate, &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);
}
if (indexToModify >= destarraylen)
@@ -4075,7 +4203,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{
IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate)
{
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))
{ // Slicing a pointer
oldval = oldval->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(oldval))
return oldval;
dinteger_t ofs;
oldval = getAggregateFromPointer(oldval, &ofs);
assignmentToSlicedPointer = true;
@@ -4186,7 +4316,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
&& 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;
}
uinteger_t dollar = resolveArrayLength(oldval);
@@ -4249,7 +4385,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{
IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate)
{
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();
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,
sexpold->upr->toInteger() - sexpold->lwr->toInteger());
return EXP_CANT_INTERPRET;
@@ -4285,11 +4421,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
dinteger_t 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;
firstIndex = lowerbound + ofs;
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);
return EXP_CANT_INTERPRET;
}
@@ -4430,9 +4571,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
else
{
error("%s cannot be evaluated at compile time", toChars());
#ifdef DEBUG
dump(0);
#endif
}
return returnValue;
}
@@ -4812,6 +4950,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
if (!global.gag)
showCtfeBackTrace(istate, this, fd);
}
else if (eresult == EXP_VOID_INTERPRET)
;
else
eresult->loc = loc;
return eresult;
}
@@ -4830,7 +4972,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
InterState istateComma;
if (!istate && firstComma->e1->op == TOKdeclaration)
{
assert(ctfeStack.stackPointer() == 0);
ctfeStack.startFrame();
istate = &istateComma;
}
@@ -4848,7 +4989,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
ctfeStack.push(v);
if (!v->init && !v->getValue())
{
v->setValue(copyLiteral(v->type->defaultInitLiteral()));
v->setValue(copyLiteral(v->type->defaultInitLiteral(loc)));
}
if (!v->getValue()) {
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 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
*/
@@ -4952,13 +5093,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
{
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)
{
error("cannot evaluate %s==%s at compile time",
ekey->toChars(), e2->toChars());
return ex;
}
if (ex->isBool(TRUE))
{
return ae->values->tdata()[i];
@@ -5013,23 +5150,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
if (exceptionOrCantInterpret(e2))
return e2;
dinteger_t indx = e2->toInteger();
dinteger_t ofs;
Expression *agg = getAggregateFromPointer(e1, &ofs);
if (agg->op == TOKnull)
{
error("cannot index null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET;
}
assert(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)
if ( agg->op == TOKarrayliteral || agg->op == TOKstring)
{
error("pointer index [%jd] exceeds allocated memory block [0..%jd]",
indx+ofs, len);
return EXP_CANT_INTERPRET;
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 [%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;
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
@@ -5070,7 +5221,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
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;
}
indx += ilo;
@@ -5091,7 +5242,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
{
if (e2->op == TOKslice)
e2 = resolveSlice(e2);
e = findKeyInAA((AssocArrayLiteralExp *)e1, e2);
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2);
if (!e)
{
error("key %s not found in associative array %s",
@@ -5112,6 +5263,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
return e;
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
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);
return e;
}
@@ -5166,12 +5323,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
error("cannot slice null pointer %s", this->e1->toChars());
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);
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
Type *pointee = ((TypePointer *)agg->type)->next;
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);
return EXP_CANT_INTERPRET;
}
@@ -5235,7 +5398,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{
if (ilwr== 0 && iupr == 0)
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;
}
if (e1->op == TOKslice)
@@ -5247,7 +5410,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
uinteger_t up1 = se->upr->toInteger();
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);
return EXP_CANT_INTERPRET;
}
@@ -5264,7 +5427,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{
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);
return EXP_CANT_INTERPRET;
}
@@ -5295,7 +5458,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
}
if (e1->op == TOKslice)
e1 = resolveSlice(e1);
e = findKeyInAA((AssocArrayLiteralExp *)e2, e1);
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1);
if (exceptionOrCantInterpret(e))
return e;
if (!e)
@@ -5354,8 +5517,12 @@ bool isAssocArray(Type *t)
if (t->ty != Tstruct)
return false;
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;
}
#endif
return false;
}
@@ -5510,9 +5677,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
e->type = type;
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());
return EXP_CANT_INTERPRET;
return EXP_CANT_INTERPRET;
}
}
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
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);
return EXP_CANT_INTERPRET;
}
@@ -5705,7 +5878,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
}
else if (e->op == TOKaddress)
e = ((AddrExp*)e)->e1; // *(&x) ==> x
if (e->op == TOKnull)
else if (e->op == TOKnull)
{
error("dereference of null pointer '%s'", e1->toChars());
return EXP_CANT_INTERPRET;
@@ -5794,6 +5967,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
e->op == TOKassocarrayliteral || e->op == TOKstring)
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) )
{
return paintTypeOntoLiteral(type, e);
@@ -5838,7 +6018,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal)
size_t removed = 0;
for (size_t j = 0; j < valuesx->dim; ++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))
return ex;
if (ex->isBool(TRUE))
@@ -6017,7 +6197,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
else if (str->op == TOKarrayliteral)
ale = (ArrayLiteralExp *)str;
else
{ error("CTFE internal error: cannot foreach %s", str->toChars());
{ str->error("CTFE internal error: cannot foreach %s", str->toChars());
return EXP_CANT_INTERPRET;
}
Expressions args;
@@ -6472,6 +6652,10 @@ bool isCtfeValueValid(Expression *newval)
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
return true;
}
if (newval->op == TOKvoid)
{
return true;
}
newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
return false;
}
@@ -6504,3 +6688,29 @@ void VarDeclaration::setValue(Expression *newval)
assert(isCtfeValueValid(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_start(ap, format);
verror(loc, format, ap);
verror(tokenLoc(), format, ap);
va_end(ap);
}
@@ -2870,6 +2870,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
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.
*/

View File

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

View File

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

View File

@@ -347,6 +347,12 @@ struct Global
unsigned gag; // !=0 means gag reporting of errors & warnings
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
unsigned startGagging();

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -1451,7 +1451,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Timaginary64: t = tfloat64; goto L2;
case Timaginary80: t = tfloat80; goto L2;
L2:
e = new RealExp(0, 0.0, t);
e = new RealExp(e->loc, 0.0, t);
break;
default:
@@ -1481,7 +1481,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Tfloat32:
case Tfloat64:
case Tfloat80:
e = new RealExp(0, 0.0, this);
e = new RealExp(e->loc, 0.0, this);
break;
default:
@@ -2645,6 +2645,22 @@ int TypeAArray::checkBoolean()
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()
{
return TRUE;
@@ -3184,13 +3200,25 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
error(loc, "cannot have parameter of type %s", fparam->type->toChars());
if (fparam->defaultArg)
{
fparam->defaultArg = fparam->defaultArg->semantic(argsc);
fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg);
fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type);
{ Expression *e = fparam->defaultArg;
e = e->semantic(argsc);
e = resolveProperties(argsc, e);
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.
*/
if (t->ty == Ttuple)
@@ -3650,7 +3678,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
else
{
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();
}
return;
@@ -4131,14 +4171,19 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
else
#endif
{
sc->intypeof++;
exp = exp->semantic(sc);
Scope *sc2 = sc->push();
sc2->intypeof++;
unsigned oldspecgag = global.speculativeGag;
if (global.gag)
global.speculativeGag = global.gag;
exp = exp->semantic(sc2);
global.speculativeGag = oldspecgag;
#if DMDV2
if (exp->type && exp->type->ty == Tfunction &&
((TypeFunction *)exp->type)->isproperty)
exp = resolveProperties(sc, exp);
exp = resolveProperties(sc2, exp);
#endif
sc->intypeof--;
sc2->pop();
if (exp->op == TOKtype)
{
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();
}
else
e = vd->type->defaultInitLiteral();
structelems->tdata()[j] = e;
e = vd->type->defaultInitLiteral(loc);
(*structelems)[j] = e;
}
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
// Why doesn't the StructLiteralExp constructor do this, when

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -78,7 +78,6 @@ Scope::Scope()
this->parameterSpecialization = 0;
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
@@ -127,7 +126,6 @@ Scope::Scope(Scope *enclosing)
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
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
// written by Walter Bright
// http://www.digitalmars.com
@@ -64,6 +64,10 @@ struct Scope
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
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 incontract; // we're inside contract code
int nofree; // set if shouldn't free it
@@ -95,7 +99,6 @@ struct Scope
#define SCOPEstaticif 2 // inside static if
#define SCOPEfree 4 // is on free list
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -36,7 +36,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
alignsize = 0; // size of struct for alignment purposes
structalign = 0; // struct member alignment in effect
hasUnions = 0;
sizeok = 0; // size not determined yet
sizeok = SIZEOKnone; // size not determined yet
isdeprecated = 0;
inv = NULL;
aggNew = NULL;
@@ -123,9 +123,9 @@ unsigned AggregateDeclaration::size(Loc loc)
//printf("AggregateDeclaration::size() = %d\n", structsize);
if (!members)
error(loc, "unknown size");
if (sizeok != 1 && scope)
if (sizeok != SIZEOKdone && scope)
semantic(NULL);
if (sizeok != 1)
if (sizeok != SIZEOKdone)
{ error(loc, "no size yet for forward reference");
//*(char*)0=0;
}
@@ -169,73 +169,41 @@ void AggregateDeclaration::alignmember(
//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 memalignsize; // size of member for alignment purposes
unsigned xalign; // alignment boundaries
//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;
unsigned ofs = *nextoffset;
alignmember(memalign, memalignsize, &ofs);
unsigned memoffset = ofs;
ofs += memsize;
if (ofs > structsize)
structsize = ofs;
if (!isUnionDeclaration())
sc->offset = ofs;
#endif
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16)
if (ofs > *paggsize)
*paggsize = ofs;
if (!isunion)
*nextoffset = ofs;
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
/* Not sure how to handle this */
;
else if (sc->structalign < memalignsize)
memalignsize = sc->structalign;
if (alignsize < memalignsize)
alignsize = memalignsize;
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
else if (memalign < memalignsize)
memalignsize = memalign;
if (*paggalignsize < memalignsize)
*paggalignsize = memalignsize;
v->storage_class |= STCfield;
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
fields.push(v);
return memoffset;
}
/****************************************
* If field[indx] is not part of a union, return indx.
* Otherwise, return the lowest field index of the union.
@@ -330,7 +298,7 @@ void StructDeclaration::semantic(Scope *sc)
return;
if (symtab)
{ if (sizeok == 1 || !scope)
{ if (sizeok == SIZEOKdone || !scope)
{ //printf("already completed\n");
scope = NULL;
return; // semantic() already completed
@@ -369,7 +337,7 @@ void StructDeclaration::semantic(Scope *sc)
type = type->constOf();
#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++)
{
@@ -379,7 +347,7 @@ void StructDeclaration::semantic(Scope *sc)
}
}
sizeok = 0;
sizeok = SIZEOKnone;
sc2 = sc->push(this);
sc2->stc = 0;
sc2->parent = this;
@@ -394,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
* resolve individual members like enums.
*/
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
* 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++)
{
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);
global.gag = oldgag;
#if 0
if (sizeok == 2)
{ //printf("forward reference\n");
@@ -416,6 +389,7 @@ void StructDeclaration::semantic(Scope *sc)
}
#endif
}
finalizeSize(sc2);
#if DMDV1
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
@@ -480,44 +454,14 @@ void StructDeclaration::semantic(Scope *sc)
}
#endif
#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);
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
buildOpAssign(sc2);
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
xeq = buildXopEquals(sc2);
#endif
sc2->pop();
@@ -525,6 +469,12 @@ void StructDeclaration::semantic(Scope *sc)
if (sizeok == 2)
{ // semantic() failed because of forward references.
// 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);
structsize = 0;
alignsize = 0;
@@ -551,7 +501,7 @@ void StructDeclaration::semantic(Scope *sc)
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
sizeok = SIZEOKdone;
Module::dprogress++;
//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);
}
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)
{
buf->printf("%s ", kind());

View File

@@ -202,7 +202,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
{
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
}
}
@@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->members = decldefs;
this->overnext = NULL;
this->overroot = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->onemember = NULL;
// Compute in advance for Ddoc's use
@@ -438,7 +438,7 @@ void TemplateDeclaration::semantic(Scope *sc)
#endif
if (semanticRun)
return; // semantic() already run
semanticRun = 1;
semanticRun = PASSsemantic;
if (sc->func)
{
@@ -994,12 +994,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
* now form the tuple argument.
*/
Tuple *t = new Tuple();
dedargs->data[parameters->dim - 1] = (void *)t;
dedargs->tdata()[parameters->dim - 1] = t;
tuple_dim = nfargs - (nfparams - 1);
t->objects.setDim(tuple_dim);
for (size_t i = 0; i < tuple_dim; i++)
{ Expression *farg = (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;
}
declareParameter(paramscope, tp, t);
@@ -1025,7 +1030,7 @@ L2:
{
// Match 'ethis' to any TemplateThisParameter's
for (size_t i = 0; i < parameters->dim; i++)
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
{ TemplateParameter *tp = parameters->tdata()[i];
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
if (ttp)
{ MATCH m;
@@ -1101,7 +1106,13 @@ L2:
}
}
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
printf("\tfarg->type = %s\n", farg->type->toChars());
printf("\tfparam->type = %s\n", fparam->type->toChars());
@@ -1121,10 +1132,34 @@ L2:
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
MATCH m;
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
//printf("\tdeduceType m = %d\n", m);
/* 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");
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("\tty = %d\n", arg->type->ty);
}
@@ -1499,8 +1534,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
}
if (td_ambig)
{
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
kind(), parent->toPrettyChars(), ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->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();
if (!fd)
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;
Lerror:
@@ -1530,14 +1575,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
{
if (i)
bufa.writeByte(',');
Object *oarg = (Object *)args->data[i];
Object *oarg = args->tdata()[i];
ObjectToCBuffer(&bufa, &hgs, oarg);
}
}
OutBuffer buf;
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());
}
return NULL;
@@ -1633,7 +1683,7 @@ char *TemplateDeclaration::toChars()
int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
{
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))
return i;
@@ -1662,7 +1712,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
* Foo!(int*) // template instantiation
* Input:
* this = int*
* tparam = T
* tparam = T*
* parameters = [ T:T* ] // Array of TemplateParameter's
* Output:
* dedtypes = [ int ] // Array of Expression/Type's
@@ -1696,7 +1746,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Loc loc;
if (parameters->dim)
{
TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
TemplateParameter *tp = parameters->tdata()[0];
loc = tp->loc;
}
@@ -1708,7 +1758,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
return deduceType(sc, tparam, parameters, dedtypes);
}
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
TemplateParameter *tp = parameters->tdata()[i];
// Found the corresponding parameter tp
if (!tp->isTemplateTypeParameter())
@@ -2840,14 +2890,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
//printf("TemplateAliasParameter::matchArg()\n");
if (i < tiargs->dim)
oarg = (Object *)tiargs->data[i];
oarg = tiargs->tdata()[i];
else
{ // Get default argument instead
oarg = defaultArg(loc, sc);
if (!oarg)
{ assert(i < dedtypes->dim);
// It might have already been deduced
oarg = (Object *)dedtypes->data[i];
oarg = dedtypes->tdata()[i];
if (!oarg)
goto Lnomatch;
}
@@ -2937,7 +2987,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
{
s = defaultAlias->toDsymbol(sc);
if (!s)
error("%s is not a symbol", defaultAlias->toChars());
error(Loc(0), "%s is not a symbol", defaultAlias->toChars());
}
return s;
}
@@ -2986,7 +3036,13 @@ void TemplateValueParameter::declareParameter(Scope *sc)
void TemplateValueParameter::semantic(Scope *sc)
{
bool wasSame = (sparam->type == valType);
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);
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
valType->ty != Tident)
@@ -3344,13 +3400,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->semantictiargsdone = 0;
this->withsym = NULL;
this->nest = 0;
this->havetempdecl = 0;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
#if IN_LLVM
@@ -3379,13 +3434,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->semantictiargsdone = 1;
this->withsym = NULL;
this->nest = 0;
this->havetempdecl = 1;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
#if IN_LLVM
@@ -3463,7 +3517,7 @@ void TemplateInstance::semantic(Scope *sc)
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
if (semanticRun != 0)
if (semanticRun != PASSinit)
{
#if LOG
printf("Recursive template expansion\n");
@@ -3472,7 +3526,7 @@ void TemplateInstance::semantic(Scope *sc)
// inst = this;
return;
}
semanticRun = 1;
semanticRun = PASSsemantic;
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
@@ -3579,7 +3633,7 @@ void TemplateInstance::semantic(Scope *sc)
}
#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
return;
@@ -3866,7 +3920,7 @@ void TemplateInstance::semantic(Scope *sc)
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
target_symbol_list->remove(target_symbol_list_idx);
}
semanticRun = 0;
semanticRun = PASSinit;
inst = NULL;
}
}
@@ -4208,13 +4262,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
// Only one template, so we can give better error message
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
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;
}
if (td_ambig)
{
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->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;
goto Lsa;
}
if (ea->op == TOKfunction)
if (ea->op == TOKthis)
{
sa = ((ThisExp *)ea)->var;
goto Lsa;
}
if (ea->op == TOKfunction)
{
sa = ((FuncExp *)ea)->fd;
goto Lsa;
@@ -4472,16 +4532,15 @@ void TemplateInstance::declareParameters(Scope *sc)
//printf("TemplateInstance::declareParameters()\n");
for (size_t i = 0; i < tdtypes.dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
//Object *o = (Object *)tiargs->data[i];
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
TemplateParameter *tp = tempdecl->parameters->tdata()[i];
//Object *o = tiargs->tdata()[i];
Object *o = tdtypes.tdata()[i]; // initializer for tp
//printf("\ttdtypes[%d] = %p\n", i, o);
tempdecl->declareParameter(sc, tp, o);
}
}
/*****************************************************
* Determine if template instance is really a template 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());
if (!tempdecl)
tempdecl = findTemplateDeclaration(sc);
int multipleMatches = FALSE;
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
{
/* 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
* 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);
TypeFunction *fdtype = (TypeFunction *)fd->type;
if (Parameter::dim(fdtype->parameters) &&
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim))
return TRUE;
if (Parameter::dim(fdtype->parameters))
{
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");
return FALSE;
return multipleMatches;
}
void TemplateInstance::semantic2(Scope *sc)
{ int i;
if (semanticRun >= 2)
if (semanticRun >= PASSsemantic2)
return;
semanticRun = 2;
semanticRun = PASSsemantic2;
#if LOG
printf("+TemplateInstance::semantic2('%s')\n", toChars());
#endif
@@ -4567,9 +4648,9 @@ void TemplateInstance::semantic3(Scope *sc)
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
#endif
//if (toChars()[0] == 'D') *(char*)0=0;
if (semanticRun >= 3)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = 3;
semanticRun = PASSsemantic3;
if (!errors && members)
{
sc = tempdecl->scope;
@@ -4752,9 +4833,24 @@ Dsymbol *TemplateInstance::toAlias()
printf("TemplateInstance::toAlias()\n");
#endif
if (!inst)
{ error("cannot resolve forward reference");
errors = 1;
return this;
{
// Maybe we can resolve it
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)
@@ -4865,7 +4961,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
ti = (TemplateInstance *)ti->syntaxCopy(NULL);
id = (Identifier *)ti;
}
ids->data[i] = id;
ids->tdata()[i] = id;
}
tm = new TemplateMixin(loc, ident,
@@ -4886,7 +4982,7 @@ void TemplateMixin::semantic(Scope *sc)
// This for when a class/struct contains mixin members, and
// is done over because of forward references
if (parent && toParent()->isAggregateDeclaration())
semanticRun = 1; // do over
semanticRun = PASSsemantic; // do over
else
{
#if LOG
@@ -4896,7 +4992,7 @@ void TemplateMixin::semantic(Scope *sc)
}
}
if (!semanticRun)
semanticRun = 1;
semanticRun = PASSsemantic;
#if LOG
printf("\tdo semantic\n");
#endif
@@ -4979,10 +5075,10 @@ void TemplateMixin::semantic(Scope *sc)
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticRun = 0;
semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = 2;
ad->sizeok = SIZEOKfwd;
else
{
// Forward reference
@@ -5027,11 +5123,11 @@ void TemplateMixin::semantic(Scope *sc)
continue;
for (size_t i = 0; i < tiargs->dim; i++)
{ Object *o = (Object *)tiargs->data[i];
{ Object *o = (*tiargs)[i];
Type *ta = isType(o);
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
Object *tmo = (Object *)tm->tiargs->data[i];
Object *tmo = (*tm->tiargs)[i];
if (ta)
{
Type *tmta = isType(tmo);
@@ -5095,10 +5191,8 @@ void TemplateMixin::semantic(Scope *sc)
declareParameters(argscope);
// Add members to enclosing scope, as well as this scope
for (unsigned i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = (Dsymbol *)members->data[i];
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->addMember(argscope, this, i);
//sc->insert(s);
//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++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
Dsymbol *s = (*members)[i];
s->semantic(sc2);
}
@@ -5166,9 +5260,9 @@ void TemplateMixin::semantic(Scope *sc)
void TemplateMixin::semantic2(Scope *sc)
{
if (semanticRun >= 2)
if (semanticRun >= PASSsemantic2)
return;
semanticRun = 2;
semanticRun = PASSsemantic2;
#if LOG
printf("+TemplateMixin::semantic2('%s')\n", toChars());
#endif
@@ -5179,7 +5273,7 @@ void TemplateMixin::semantic2(Scope *sc)
sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
Dsymbol *s = (*members)[i];
#if LOG
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
#endif
@@ -5195,9 +5289,9 @@ void TemplateMixin::semantic2(Scope *sc)
void TemplateMixin::semantic3(Scope *sc)
{
if (semanticRun >= 3)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = 3;
semanticRun = PASSsemantic3;
#if LOG
printf("TemplateMixin::semantic3('%s')\n", toChars());
#endif
@@ -5207,7 +5301,7 @@ void TemplateMixin::semantic3(Scope *sc)
sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (Dsymbol *)members->data[i];
Dsymbol *s = members->tdata()[i];
s->semantic3(sc);
}
sc = sc->pop();
@@ -5230,21 +5324,48 @@ int TemplateMixin::oneMember(Dsymbol **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()
{
//printf("TemplateMixin::hasPointers() %s\n", toChars());
if (members)
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())
for (size_t i = 0; i < members->dim; i++)
{
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()
@@ -5264,7 +5385,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("mixin ");
for (size_t i = 0; i < idents->dim; i++)
{ Identifier *id = (Identifier *)idents->data[i];
{ Identifier *id = idents->tdata()[i];
if (i)
buf->writeByte('.');

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -40,6 +40,7 @@ struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
enum MATCH;
enum PASS;
struct Tuple : Object
{
@@ -60,7 +61,7 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
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
@@ -287,12 +288,11 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
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 nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
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
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
@@ -356,7 +356,9 @@ struct TemplateMixin : TemplateInstance
void inlineScan();
const char *kind();
int oneMember(Dsymbol **ps);
int apply(Dsymbol_apply_ft_t fp, void *param);
int hasPointers();
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);