mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-26 00:23:14 +01:00
Merge dmd-1.074 into ldc.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -51,6 +51,13 @@ namespace llvm
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum Sizeok
|
||||||
|
{
|
||||||
|
SIZEOKnone, // size of aggregate is not computed yet
|
||||||
|
SIZEOKdone, // size of aggregate is set correctly
|
||||||
|
SIZEOKfwd, // error in computing size of aggregate
|
||||||
|
};
|
||||||
|
|
||||||
struct AggregateDeclaration : ScopeDsymbol
|
struct AggregateDeclaration : ScopeDsymbol
|
||||||
{
|
{
|
||||||
Type *type;
|
Type *type;
|
||||||
@@ -62,10 +69,7 @@ struct AggregateDeclaration : ScopeDsymbol
|
|||||||
unsigned structalign; // struct member alignment in effect
|
unsigned structalign; // struct member alignment in effect
|
||||||
int hasUnions; // set if aggregate has overlapping fields
|
int hasUnions; // set if aggregate has overlapping fields
|
||||||
VarDeclarations fields; // VarDeclaration fields
|
VarDeclarations fields; // VarDeclaration fields
|
||||||
unsigned sizeok; // set when structsize contains valid data
|
enum Sizeok sizeok; // set when structsize contains valid data
|
||||||
// 0: no size
|
|
||||||
// 1: size is correct
|
|
||||||
// 2: cannot determine size; fwd referenced
|
|
||||||
int isdeprecated; // !=0 if deprecated
|
int isdeprecated; // !=0 if deprecated
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
@@ -89,7 +93,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
|||||||
FuncDeclaration *dtor; // aggregate destructor
|
FuncDeclaration *dtor; // aggregate destructor
|
||||||
|
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
Array methods; // flat list of all methods for debug information
|
Expressions *attributes; // GCC decl/type attributes
|
||||||
|
FuncDeclarations methods; // flat list of all methods for debug information
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AggregateDeclaration(Loc loc, Identifier *id);
|
AggregateDeclaration(Loc loc, Identifier *id);
|
||||||
@@ -98,8 +103,10 @@ struct AggregateDeclaration : ScopeDsymbol
|
|||||||
void inlineScan();
|
void inlineScan();
|
||||||
unsigned size(Loc loc);
|
unsigned size(Loc loc);
|
||||||
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
|
||||||
|
static unsigned placeField(unsigned *nextoffset,
|
||||||
|
unsigned memsize, unsigned memalignsize, unsigned memalign,
|
||||||
|
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
|
||||||
Type *getType();
|
Type *getType();
|
||||||
void addField(Scope *sc, VarDeclaration *v);
|
|
||||||
int firstFieldInUnion(int indx); // first field in union that includes indx
|
int firstFieldInUnion(int indx); // first field in union that includes indx
|
||||||
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
|
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
|
||||||
int isDeprecated(); // is aggregate deprecated?
|
int isDeprecated(); // is aggregate deprecated?
|
||||||
@@ -163,14 +170,19 @@ struct StructDeclaration : AggregateDeclaration
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
char *mangle();
|
char *mangle();
|
||||||
const char *kind();
|
const char *kind();
|
||||||
|
void finalizeSize(Scope *sc);
|
||||||
#if DMDV1
|
#if DMDV1
|
||||||
Expression *cloneMembers();
|
Expression *cloneMembers();
|
||||||
#endif
|
#endif
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
int needOpAssign();
|
int needOpAssign();
|
||||||
|
int needOpEquals();
|
||||||
FuncDeclaration *buildOpAssign(Scope *sc);
|
FuncDeclaration *buildOpAssign(Scope *sc);
|
||||||
|
FuncDeclaration *buildOpEquals(Scope *sc);
|
||||||
FuncDeclaration *buildPostBlit(Scope *sc);
|
FuncDeclaration *buildPostBlit(Scope *sc);
|
||||||
FuncDeclaration *buildCpCtor(Scope *sc);
|
FuncDeclaration *buildCpCtor(Scope *sc);
|
||||||
|
|
||||||
|
FuncDeclaration *buildXopEquals(Scope *sc);
|
||||||
#endif
|
#endif
|
||||||
void toDocBuffer(OutBuffer *buf);
|
void toDocBuffer(OutBuffer *buf);
|
||||||
|
|
||||||
@@ -222,7 +234,8 @@ struct BaseClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
#define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
|
#define CLASSINFO_SIZE_64 0x98 // value of ClassInfo.size
|
||||||
|
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
|
||||||
#else
|
#else
|
||||||
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
|
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
|
||||||
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
|
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
|
||||||
|
|||||||
333
dmd/attrib.c
333
dmd/attrib.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
|
|||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||||
|
{
|
||||||
|
Dsymbols *d = include(NULL, NULL);
|
||||||
|
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
|
{ Dsymbol *s = (*d)[i];
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
if (s->apply(fp, param))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||||
{
|
{
|
||||||
int m = 0;
|
int m = 0;
|
||||||
@@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
|
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
|
||||||
m |= s->addMember(sc, sd, m | memnum);
|
m |= s->addMember(sc, sd, m | memnum);
|
||||||
}
|
}
|
||||||
@@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
|
|||||||
newsc->explicitProtection = explicitProtection;
|
newsc->explicitProtection = explicitProtection;
|
||||||
newsc->structalign = structalign;
|
newsc->structalign = structalign;
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{ Dsymbol *s = decl->tdata()[i];
|
{ Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
s->setScope(newsc); // yes, the only difference from semanticNewSc()
|
s->setScope(newsc); // yes, the only difference from semanticNewSc()
|
||||||
}
|
}
|
||||||
@@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc,
|
|||||||
newsc->explicitProtection = explicitProtection;
|
newsc->explicitProtection = explicitProtection;
|
||||||
newsc->structalign = structalign;
|
newsc->structalign = structalign;
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{ Dsymbol *s = decl->tdata()[i];
|
{ Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
s->semantic(newsc);
|
s->semantic(newsc);
|
||||||
}
|
}
|
||||||
@@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = d->tdata()[i];
|
Dsymbol *s = (*d)[i];
|
||||||
|
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
}
|
}
|
||||||
@@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc)
|
|||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->semantic2(sc);
|
s->semantic2(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc)
|
|||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->semantic3(sc);
|
s->semantic3(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan()
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
//printf("AttribDeclaration::inlineScan %s\n", s->toChars());
|
//printf("AttribDeclaration::inlineScan %s\n", s->toChars());
|
||||||
s->inlineScan();
|
s->inlineScan();
|
||||||
}
|
}
|
||||||
@@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment)
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
//printf("AttribDeclaration::addComment %s\n", s->toChars());
|
//printf("AttribDeclaration::addComment %s\n", s->toChars());
|
||||||
s->addComment(comment);
|
s->addComment(comment);
|
||||||
}
|
}
|
||||||
@@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc)
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
//printf("AttribDeclaration::emitComment %s\n", s->toChars());
|
//printf("AttribDeclaration::emitComment %s\n", s->toChars());
|
||||||
s->emitComment(sc);
|
s->emitComment(sc);
|
||||||
}
|
}
|
||||||
@@ -246,32 +264,27 @@ void AttribDeclaration::toObjFile(int multiobj)
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->toObjFile(multiobj);
|
s->toObjFile(multiobj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AttribDeclaration::cvMember(unsigned char *p)
|
#endif
|
||||||
|
|
||||||
|
void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||||
{
|
{
|
||||||
int nwritten = 0;
|
|
||||||
int n;
|
|
||||||
Dsymbols *d = include(NULL, NULL);
|
Dsymbols *d = include(NULL, NULL);
|
||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
n = s->cvMember(p);
|
s->setFieldOffset(ad, poffset, isunion);
|
||||||
if (p)
|
|
||||||
p += n;
|
|
||||||
nwritten += n;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nwritten;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int AttribDeclaration::hasPointers()
|
int AttribDeclaration::hasPointers()
|
||||||
{
|
{
|
||||||
@@ -281,7 +294,7 @@ int AttribDeclaration::hasPointers()
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = d->tdata()[i];
|
Dsymbol *s = (*d)[i];
|
||||||
if (s->hasPointers())
|
if (s->hasPointers())
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -323,8 +336,8 @@ void AttribDeclaration::checkCtorConstInit()
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->checkCtorConstInit();
|
s->checkCtorConstInit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,8 +352,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
|
|||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->addLocalClass(aclasses);
|
s->addLocalClass(aclasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,15 +367,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
if (decl->dim == 0)
|
if (decl->dim == 0)
|
||||||
buf->writestring("{}");
|
buf->writestring("{}");
|
||||||
else if (decl->dim == 1)
|
else if (decl->dim == 1)
|
||||||
(decl->tdata()[0])->toCBuffer(buf, hgs);
|
((*decl)[0])->toCBuffer(buf, hgs);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
buf->writeByte('{');
|
buf->writeByte('{');
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
buf->writestring(" ");
|
buf->writestring(" ");
|
||||||
s->toCBuffer(buf, hgs);
|
s->toCBuffer(buf, hgs);
|
||||||
@@ -467,6 +480,7 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
|||||||
{ STCout, TOKout },
|
{ STCout, TOKout },
|
||||||
{ STCin, TOKin },
|
{ STCin, TOKin },
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
|
{ STCmanifest, TOKenum },
|
||||||
{ STCimmutable, TOKimmutable },
|
{ STCimmutable, TOKimmutable },
|
||||||
{ STCshared, TOKshared },
|
{ STCshared, TOKshared },
|
||||||
{ STCnothrow, TOKnothrow },
|
{ STCnothrow, TOKnothrow },
|
||||||
@@ -474,10 +488,11 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
|||||||
{ STCref, TOKref },
|
{ STCref, TOKref },
|
||||||
{ STCtls, TOKtls },
|
{ STCtls, TOKtls },
|
||||||
{ STCgshared, TOKgshared },
|
{ STCgshared, TOKgshared },
|
||||||
{ STCproperty, TOKat },
|
{ STCproperty, TOKat, Id::property },
|
||||||
{ STCsafe, TOKat },
|
{ STCsafe, TOKat, Id::safe },
|
||||||
{ STCtrusted, TOKat },
|
{ STCtrusted, TOKat, Id::trusted },
|
||||||
{ STCdisable, TOKat },
|
{ STCsystem, TOKat, Id::system },
|
||||||
|
{ STCdisable, TOKat, Id::disable },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -488,20 +503,9 @@ void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
|
|||||||
enum TOK tok = table[i].tok;
|
enum TOK tok = table[i].tok;
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
if (tok == TOKat)
|
if (tok == TOKat)
|
||||||
{ Identifier *id;
|
{
|
||||||
|
|
||||||
if (stc & STCproperty)
|
|
||||||
id = Id::property;
|
|
||||||
else if (stc & STCsafe)
|
|
||||||
id = Id::safe;
|
|
||||||
else if (stc & STCtrusted)
|
|
||||||
id = Id::trusted;
|
|
||||||
else if (stc & STCdisable)
|
|
||||||
id = Id::disable;
|
|
||||||
else
|
|
||||||
assert(0);
|
|
||||||
buf->writeByte('@');
|
buf->writeByte('@');
|
||||||
buf->writestring(id->toChars());
|
buf->writestring(table[i].id->toChars());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -560,9 +564,9 @@ void LinkDeclaration::semantic3(Scope *sc)
|
|||||||
{ enum LINK linkage_save = sc->linkage;
|
{ enum LINK linkage_save = sc->linkage;
|
||||||
|
|
||||||
sc->linkage = linkage;
|
sc->linkage = linkage;
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
s->semantic3(sc);
|
s->semantic3(sc);
|
||||||
}
|
}
|
||||||
@@ -738,6 +742,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
|
|||||||
: AttribDeclaration(decl)
|
: AttribDeclaration(decl)
|
||||||
{
|
{
|
||||||
this->loc = loc;
|
this->loc = loc;
|
||||||
|
this->alignment = 0;
|
||||||
this->isunion = isunion;
|
this->isunion = isunion;
|
||||||
this->sem = 0;
|
this->sem = 0;
|
||||||
}
|
}
|
||||||
@@ -755,21 +760,6 @@ void AnonDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
|
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
|
||||||
|
|
||||||
if (sem == 1)
|
|
||||||
{ //printf("already completed\n");
|
|
||||||
scope = NULL;
|
|
||||||
return; // semantic() already completed
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope *scx = NULL;
|
|
||||||
if (scope)
|
|
||||||
{ sc = scope;
|
|
||||||
scx = scope;
|
|
||||||
scope = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned dprogress_save = Module::dprogress;
|
|
||||||
|
|
||||||
assert(sc->parent);
|
assert(sc->parent);
|
||||||
|
|
||||||
Dsymbol *parent = sc->parent->pastMixin();
|
Dsymbol *parent = sc->parent->pastMixin();
|
||||||
@@ -781,106 +771,85 @@ void AnonDeclaration::semantic(Scope *sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alignment = sc->structalign;
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
AnonymousAggregateDeclaration aad;
|
|
||||||
int adisunion;
|
|
||||||
|
|
||||||
if (sc->anonAgg)
|
|
||||||
{ ad = sc->anonAgg;
|
|
||||||
adisunion = sc->inunion;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
adisunion = ad->isUnionDeclaration() != NULL;
|
|
||||||
|
|
||||||
// printf("\tsc->anonAgg = %p\n", sc->anonAgg);
|
|
||||||
// printf("\tad = %p\n", ad);
|
|
||||||
// printf("\taad = %p\n", &aad);
|
|
||||||
|
|
||||||
sc = sc->push();
|
sc = sc->push();
|
||||||
sc->anonAgg = &aad;
|
|
||||||
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
|
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
|
||||||
sc->inunion = isunion;
|
sc->inunion = isunion;
|
||||||
sc->offset = 0;
|
sc->offset = 0;
|
||||||
sc->flags = 0;
|
sc->flags = 0;
|
||||||
aad.structalign = sc->structalign;
|
|
||||||
aad.parent = ad;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
if (isunion)
|
|
||||||
sc->offset = 0;
|
|
||||||
if (aad.sizeok == 2)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sc = sc->pop();
|
sc = sc->pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If failed due to forward references, unwind and try again later
|
|
||||||
if (aad.sizeok == 2)
|
void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||||
|
{
|
||||||
|
//printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
|
||||||
|
|
||||||
|
if (decl)
|
||||||
|
{
|
||||||
|
/* This works by treating an AnonDeclaration as an aggregate 'member',
|
||||||
|
* so in order to place that member we need to compute the member's
|
||||||
|
* size and alignment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
size_t fieldstart = ad->fields.dim;
|
||||||
|
|
||||||
|
/* Hackishly hijack ad's structsize and alignsize fields
|
||||||
|
* for use in our fake anon aggregate member.
|
||||||
|
*/
|
||||||
|
unsigned savestructsize = ad->structsize;
|
||||||
|
unsigned savealignsize = ad->alignsize;
|
||||||
|
ad->structsize = 0;
|
||||||
|
ad->alignsize = 0;
|
||||||
|
|
||||||
|
unsigned offset = 0;
|
||||||
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
ad->sizeok = 2;
|
Dsymbol *s = (*decl)[i];
|
||||||
//printf("\tsetting ad->sizeok %p to 2\n", ad);
|
|
||||||
if (!sc->anonAgg)
|
s->setFieldOffset(ad, &offset, this->isunion);
|
||||||
{
|
if (this->isunion)
|
||||||
scope = scx ? scx : new Scope(*sc);
|
offset = 0;
|
||||||
scope->setNoFree();
|
|
||||||
scope->module->addDeferredSemantic(this);
|
|
||||||
}
|
|
||||||
Module::dprogress = dprogress_save;
|
|
||||||
//printf("\tforward reference %p\n", this);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (sem == 0)
|
|
||||||
{ Module::dprogress++;
|
unsigned anonstructsize = ad->structsize;
|
||||||
sem = 1;
|
unsigned anonalignsize = ad->alignsize;
|
||||||
//printf("\tcompleted %p\n", this);
|
ad->structsize = savestructsize;
|
||||||
}
|
ad->alignsize = savealignsize;
|
||||||
else
|
|
||||||
;//printf("\talready completed %p\n", this);
|
|
||||||
|
|
||||||
// 0 sized structs are set to 1 byte
|
// 0 sized structs are set to 1 byte
|
||||||
if (aad.structsize == 0)
|
if (anonstructsize == 0)
|
||||||
{
|
{
|
||||||
aad.structsize = 1;
|
anonstructsize = 1;
|
||||||
aad.alignsize = 1;
|
anonalignsize = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align size of anonymous aggregate
|
/* Given the anon 'member's size and alignment,
|
||||||
//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
|
* go ahead and place it.
|
||||||
ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
|
*/
|
||||||
//ad->structsize = sc->offset;
|
unsigned anonoffset = AggregateDeclaration::placeField(
|
||||||
//printf("sc->offset = %d\n", sc->offset);
|
poffset,
|
||||||
|
anonstructsize, anonalignsize, alignment,
|
||||||
|
&ad->structsize, &ad->alignsize,
|
||||||
|
isunion);
|
||||||
|
|
||||||
// Add members of aad to ad
|
// Add to the anon fields the base offset of this anonymous aggregate
|
||||||
//printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars());
|
//printf("anon fields, anonoffset = %d\n", anonoffset);
|
||||||
for (unsigned i = 0; i < aad.fields.dim; i++)
|
for (size_t i = fieldstart; i < ad->fields.dim; i++)
|
||||||
{
|
{
|
||||||
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
|
VarDeclaration *v = ad->fields[i];
|
||||||
|
//printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
|
||||||
v->offset += sc->offset;
|
v->offset += anonoffset;
|
||||||
ad->fields.push(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add size of aad to ad
|
|
||||||
if (adisunion)
|
|
||||||
{
|
|
||||||
if (aad.structsize > ad->structsize)
|
|
||||||
ad->structsize = aad.structsize;
|
|
||||||
sc->offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ad->structsize = sc->offset + aad.structsize;
|
|
||||||
sc->offset = ad->structsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ad->alignsize < aad.alignsize)
|
|
||||||
ad->alignsize = aad.alignsize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,9 +860,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring("\n{\n");
|
buf->writestring("\n{\n");
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
//buf->writestring(" ");
|
//buf->writestring(" ");
|
||||||
s->toCBuffer(buf, hgs);
|
s->toCBuffer(buf, hgs);
|
||||||
@@ -953,10 +922,10 @@ void PragmaDeclaration::setScope(Scope *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Expression *e = args->tdata()[0];
|
Expression *e = (*args)[0];
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
args->tdata()[0] = e;
|
(*args)[0] = e;
|
||||||
StringExp* se = e->toString();
|
StringExp* se = e->toString();
|
||||||
if (!se)
|
if (!se)
|
||||||
{
|
{
|
||||||
@@ -991,7 +960,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < args->dim; i++)
|
for (size_t i = 0; i < args->dim; i++)
|
||||||
{
|
{
|
||||||
Expression *e = args->tdata()[i];
|
Expression *e = (*args)[i];
|
||||||
|
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
@@ -1013,11 +982,11 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
error("string expected for library name");
|
error("string expected for library name");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Expression *e = args->tdata()[0];
|
Expression *e = (*args)[0];
|
||||||
|
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
args->tdata()[0] = e;
|
(*args)[0] = e;
|
||||||
if (e->op == TOKerror)
|
if (e->op == TOKerror)
|
||||||
goto Lnodecl;
|
goto Lnodecl;
|
||||||
StringExp *se = e->toString();
|
StringExp *se = e->toString();
|
||||||
@@ -1045,7 +1014,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
Declaration *d = NULL;
|
Declaration *d = NULL;
|
||||||
StringExp *s = NULL;
|
StringExp *s = NULL;
|
||||||
|
|
||||||
e = (Expression *)args->data[0];
|
e = (*args)[0];
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
if (e->op == TOKvar)
|
if (e->op == TOKvar)
|
||||||
{
|
{
|
||||||
@@ -1056,14 +1025,14 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
if (!d)
|
if (!d)
|
||||||
error("first argument of GNU_asm must be a function or variable declaration");
|
error("first argument of GNU_asm must be a function or variable declaration");
|
||||||
|
|
||||||
e = args->tdata()[1];
|
e = (*args)[1];
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue);
|
e = e->optimize(WANTvalue);
|
||||||
e = e->toString();
|
e = e->toString();
|
||||||
if (e && ((StringExp *)e)->sz == 1)
|
if (e && ((StringExp *)e)->sz == 1)
|
||||||
s = ((StringExp *)e);
|
s = ((StringExp *)e);
|
||||||
else
|
else
|
||||||
error("second argument of GNU_asm must be a char string");
|
error("second argument of GNU_asm must be a character string");
|
||||||
|
|
||||||
if (d && s)
|
if (d && s)
|
||||||
d->c_ident = Lexer::idPool((char*) s->string);
|
d->c_ident = Lexer::idPool((char*) s->string);
|
||||||
@@ -1078,10 +1047,10 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
error("function name expected for start address");
|
error("function name expected for start address");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Expression *e = (Expression *)args->data[0];
|
Expression *e = (*args)[0];
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
args->data[0] = (void *)e;
|
(*args)[0] = e;
|
||||||
Dsymbol *sa = getDsymbol(e);
|
Dsymbol *sa = getDsymbol(e);
|
||||||
if (!sa || !sa->isFuncDeclaration())
|
if (!sa || !sa->isFuncDeclaration())
|
||||||
error("function name expected for start address, not '%s'", e->toChars());
|
error("function name expected for start address, not '%s'", e->toChars());
|
||||||
@@ -1111,11 +1080,13 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < args->dim; i++)
|
for (size_t i = 0; i < args->dim; i++)
|
||||||
{
|
{
|
||||||
|
#if IN_LLVM
|
||||||
// ignore errors in ignored pragmas.
|
// ignore errors in ignored pragmas.
|
||||||
global.gag++;
|
global.gag++;
|
||||||
unsigned errors_save = global.errors;
|
unsigned errors_save = global.errors;
|
||||||
|
#endif
|
||||||
|
|
||||||
Expression *e = (Expression *)args->data[i];
|
Expression *e = (*args)[i];
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@@ -1124,9 +1095,11 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
printf(",");
|
printf(",");
|
||||||
printf("%s", e->toChars());
|
printf("%s", e->toChars());
|
||||||
|
|
||||||
|
#if IN_LLVM
|
||||||
// restore error state.
|
// restore error state.
|
||||||
global.gag--;
|
global.gag--;
|
||||||
global.errors = errors_save;
|
global.errors = errors_save;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (args->dim)
|
if (args->dim)
|
||||||
printf(")");
|
printf(")");
|
||||||
@@ -1141,9 +1114,9 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||||||
Ldecl:
|
Ldecl:
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
|
|
||||||
@@ -1180,7 +1153,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
|
|||||||
{
|
{
|
||||||
assert(args && args->dim == 1);
|
assert(args && args->dim == 1);
|
||||||
|
|
||||||
Expression *e = (Expression *)args->data[0];
|
Expression *e = (*args)[0];
|
||||||
|
|
||||||
assert(e->op == TOKstring);
|
assert(e->op == TOKstring);
|
||||||
|
|
||||||
@@ -1208,7 +1181,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
|
|||||||
else if (ident == Id::startaddress)
|
else if (ident == Id::startaddress)
|
||||||
{
|
{
|
||||||
assert(args && args->dim == 1);
|
assert(args && args->dim == 1);
|
||||||
Expression *e = (Expression *)args->data[0];
|
Expression *e = (*args)[0];
|
||||||
Dsymbol *sa = getDsymbol(e);
|
Dsymbol *sa = getDsymbol(e);
|
||||||
FuncDeclaration *f = sa->isFuncDeclaration();
|
FuncDeclaration *f = sa->isFuncDeclaration();
|
||||||
assert(f);
|
assert(f);
|
||||||
@@ -1285,8 +1258,8 @@ void ConditionalDeclaration::emitComment(Scope *sc)
|
|||||||
* a template, then include(NULL, NULL) will fail.
|
* a template, then include(NULL, NULL) will fail.
|
||||||
*/
|
*/
|
||||||
Dsymbols *d = decl ? decl : elsedecl;
|
Dsymbols *d = decl ? decl : elsedecl;
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s = d->tdata()[i];
|
{ Dsymbol *s = (*d)[i];
|
||||||
s->emitComment(sc);
|
s->emitComment(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1308,9 +1281,9 @@ void ConditionalDeclaration::setScope(Scope *sc)
|
|||||||
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
|
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = d->tdata()[i];
|
Dsymbol *s = (*d)[i];
|
||||||
|
|
||||||
s->setScope(sc);
|
s->setScope(sc);
|
||||||
}
|
}
|
||||||
@@ -1324,9 +1297,9 @@ void ConditionalDeclaration::importAll(Scope *sc)
|
|||||||
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
|
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = d->tdata()[i];
|
Dsymbol *s = (*d)[i];
|
||||||
|
|
||||||
s->importAll(sc);
|
s->importAll(sc);
|
||||||
}
|
}
|
||||||
@@ -1349,10 +1322,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment)
|
|||||||
{
|
{
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{ Dsymbol *s;
|
{ Dsymbol *s = (*d)[i];
|
||||||
|
|
||||||
s = d->tdata()[i];
|
|
||||||
//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
|
//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
|
||||||
s->addComment(comment);
|
s->addComment(comment);
|
||||||
}
|
}
|
||||||
@@ -1372,9 +1343,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writenl();
|
buf->writenl();
|
||||||
if (decl)
|
if (decl)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < decl->dim; i++)
|
for (size_t i = 0; i < decl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = decl->tdata()[i];
|
Dsymbol *s = (*decl)[i];
|
||||||
|
|
||||||
buf->writestring(" ");
|
buf->writestring(" ");
|
||||||
s->toCBuffer(buf, hgs);
|
s->toCBuffer(buf, hgs);
|
||||||
@@ -1388,9 +1359,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writenl();
|
buf->writenl();
|
||||||
buf->writeByte('{');
|
buf->writeByte('{');
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
for (unsigned i = 0; i < elsedecl->dim; i++)
|
for (size_t i = 0; i < elsedecl->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = elsedecl->tdata()[i];
|
Dsymbol *s = (*elsedecl)[i];
|
||||||
|
|
||||||
buf->writestring(" ");
|
buf->writestring(" ");
|
||||||
s->toCBuffer(buf, hgs);
|
s->toCBuffer(buf, hgs);
|
||||||
@@ -1474,9 +1445,9 @@ void StaticIfDeclaration::semantic(Scope *sc)
|
|||||||
addisdone = 1;
|
addisdone = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i < d->dim; i++)
|
for (size_t i = 0; i < d->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = d->tdata()[i];
|
Dsymbol *s = (*d)[i];
|
||||||
|
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol
|
|||||||
|
|
||||||
AttribDeclaration(Dsymbols *decl);
|
AttribDeclaration(Dsymbols *decl);
|
||||||
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
|
||||||
|
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||||
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||||
void setScopeNewSc(Scope *sc,
|
void setScopeNewSc(Scope *sc,
|
||||||
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
|
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
|
||||||
@@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol
|
|||||||
void emitComment(Scope *sc);
|
void emitComment(Scope *sc);
|
||||||
const char *kind();
|
const char *kind();
|
||||||
int oneMember(Dsymbol **ps);
|
int oneMember(Dsymbol **ps);
|
||||||
|
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||||
int hasPointers();
|
int hasPointers();
|
||||||
bool hasStaticCtorOrDtor();
|
bool hasStaticCtorOrDtor();
|
||||||
void checkCtorConstInit();
|
void checkCtorConstInit();
|
||||||
@@ -58,7 +60,6 @@ struct AttribDeclaration : Dsymbol
|
|||||||
|
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
void toObjFile(int multiobj); // compile to .obj file
|
void toObjFile(int multiobj); // compile to .obj file
|
||||||
int cvMember(unsigned char *p);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -119,12 +120,14 @@ struct AlignDeclaration : AttribDeclaration
|
|||||||
|
|
||||||
struct AnonDeclaration : AttribDeclaration
|
struct AnonDeclaration : AttribDeclaration
|
||||||
{
|
{
|
||||||
int isunion;
|
bool isunion;
|
||||||
|
unsigned alignment;
|
||||||
int sem; // 1 if successful semantic()
|
int sem; // 1 if successful semantic()
|
||||||
|
|
||||||
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
|
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
|
||||||
Dsymbol *syntaxCopy(Dsymbol *s);
|
Dsymbol *syntaxCopy(Dsymbol *s);
|
||||||
void semantic(Scope *sc);
|
void semantic(Scope *sc);
|
||||||
|
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
const char *kind();
|
const char *kind();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1166,17 +1166,16 @@ Expression *SymOffExp::castTo(Scope *sc, Type *t)
|
|||||||
|
|
||||||
Expression *DelegateExp::castTo(Scope *sc, Type *t)
|
Expression *DelegateExp::castTo(Scope *sc, Type *t)
|
||||||
{
|
{
|
||||||
Type *tb;
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
|
printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n",
|
||||||
toChars(), type->toChars(), t->toChars());
|
toChars(), type->toChars(), t->toChars());
|
||||||
#endif
|
#endif
|
||||||
Expression *e = this;
|
|
||||||
static char msg[] = "cannot form delegate due to covariant return type";
|
static char msg[] = "cannot form delegate due to covariant return type";
|
||||||
|
|
||||||
tb = t->toBasetype();
|
Expression *e = this;
|
||||||
|
Type *tb = t->toBasetype();
|
||||||
type = type->toBasetype();
|
type = type->toBasetype();
|
||||||
if (tb != type)
|
if (tb != type || hasOverloads)
|
||||||
{
|
{
|
||||||
// Look for delegates to functions where the functions are overloaded.
|
// Look for delegates to functions where the functions are overloaded.
|
||||||
FuncDeclaration *f;
|
FuncDeclaration *f;
|
||||||
|
|||||||
112
dmd/class.c
112
dmd/class.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -228,9 +228,9 @@ Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
cd->baseclasses->setDim(this->baseclasses->dim);
|
cd->baseclasses->setDim(this->baseclasses->dim);
|
||||||
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
||||||
{
|
{
|
||||||
BaseClass *b = (BaseClass *)this->baseclasses->data[i];
|
BaseClass *b = this->baseclasses->tdata()[i];
|
||||||
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
|
BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
|
||||||
cd->baseclasses->data[i] = b2;
|
cd->baseclasses->tdata()[i] = b2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopeDsymbol::syntaxCopy(cd);
|
ScopeDsymbol::syntaxCopy(cd);
|
||||||
@@ -264,7 +264,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (symtab)
|
if (symtab)
|
||||||
{ if (sizeok == 1 || !scope)
|
{ if (sizeok == SIZEOKdone || !scope)
|
||||||
{ //printf("\tsemantic for '%s' is already completed\n", toChars());
|
{ //printf("\tsemantic for '%s' is already completed\n", toChars());
|
||||||
return; // semantic() already completed
|
return; // semantic() already completed
|
||||||
}
|
}
|
||||||
@@ -290,7 +290,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
// Expand any tuples in baseclasses[]
|
// Expand any tuples in baseclasses[]
|
||||||
for (size_t i = 0; i < baseclasses->dim; )
|
for (size_t i = 0; i < baseclasses->dim; )
|
||||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
{ BaseClass *b = baseclasses->tdata()[i];
|
||||||
b->type = b->type->semantic(loc, sc);
|
b->type = b->type->semantic(loc, sc);
|
||||||
Type *tb = b->type->toBasetype();
|
Type *tb = b->type->toBasetype();
|
||||||
|
|
||||||
@@ -315,11 +315,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
BaseClass *b;
|
BaseClass *b;
|
||||||
Type *tb;
|
Type *tb;
|
||||||
|
|
||||||
b = (BaseClass *)baseclasses->data[0];
|
b = baseclasses->tdata()[0];
|
||||||
//b->type = b->type->semantic(loc, sc);
|
//b->type = b->type->semantic(loc, sc);
|
||||||
tb = b->type->toBasetype();
|
tb = b->type->toBasetype();
|
||||||
if (tb->ty != Tclass)
|
if (tb->ty != Tclass)
|
||||||
{ error("base type must be class or interface, not %s", b->type->toChars());
|
{ if (b->type != Type::terror)
|
||||||
|
error("base type must be class or interface, not %s", b->type->toChars());
|
||||||
baseclasses->remove(0);
|
baseclasses->remove(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -331,7 +332,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
if (!isDeprecated())
|
if (!isDeprecated())
|
||||||
{
|
{
|
||||||
// Deriving from deprecated class makes this one deprecated too
|
// Deriving from deprecated class makes this one deprecated too
|
||||||
isdeprecated = 1;
|
isdeprecated = true;
|
||||||
|
|
||||||
tc->checkDeprecated(loc, sc);
|
tc->checkDeprecated(loc, sc);
|
||||||
}
|
}
|
||||||
@@ -350,12 +351,12 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
goto L7;
|
goto L7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tc->sym->symtab || tc->sym->sizeok == 0)
|
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
|
||||||
{ // Try to resolve forward reference
|
{ // Try to resolve forward reference
|
||||||
if (/*sc->mustsemantic &&*/ tc->sym->scope)
|
if (/*sc->mustsemantic &&*/ tc->sym->scope)
|
||||||
tc->sym->semantic(NULL);
|
tc->sym->semantic(NULL);
|
||||||
}
|
}
|
||||||
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
|
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
|
||||||
{
|
{
|
||||||
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
|
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
|
||||||
//error("forward reference of base class %s", baseClass->toChars());
|
//error("forward reference of base class %s", baseClass->toChars());
|
||||||
@@ -384,7 +385,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
BaseClass *b;
|
BaseClass *b;
|
||||||
Type *tb;
|
Type *tb;
|
||||||
|
|
||||||
b = (BaseClass *)baseclasses->data[i];
|
b = baseclasses->tdata()[i];
|
||||||
b->type = b->type->semantic(loc, sc);
|
b->type = b->type->semantic(loc, sc);
|
||||||
tb = b->type->toBasetype();
|
tb = b->type->toBasetype();
|
||||||
if (tb->ty == Tclass)
|
if (tb->ty == Tclass)
|
||||||
@@ -392,7 +393,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
else
|
else
|
||||||
tc = NULL;
|
tc = NULL;
|
||||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||||
{
|
{ if (b->type != Type::terror)
|
||||||
error("base type must be interface, not %s", b->type->toChars());
|
error("base type must be interface, not %s", b->type->toChars());
|
||||||
baseclasses->remove(i);
|
baseclasses->remove(i);
|
||||||
continue;
|
continue;
|
||||||
@@ -404,7 +405,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
if (!isDeprecated())
|
if (!isDeprecated())
|
||||||
{
|
{
|
||||||
// Deriving from deprecated class makes this one deprecated too
|
// Deriving from deprecated class makes this one deprecated too
|
||||||
isdeprecated = 1;
|
isdeprecated = true;
|
||||||
|
|
||||||
tc->checkDeprecated(loc, sc);
|
tc->checkDeprecated(loc, sc);
|
||||||
}
|
}
|
||||||
@@ -413,7 +414,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
// Check for duplicate interfaces
|
// Check for duplicate interfaces
|
||||||
for (size_t j = (baseClass ? 1 : 0); j < i; j++)
|
for (size_t j = (baseClass ? 1 : 0); j < i; j++)
|
||||||
{
|
{
|
||||||
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
|
BaseClass *b2 = baseclasses->tdata()[j];
|
||||||
if (b2->base == tc->sym)
|
if (b2->base == tc->sym)
|
||||||
error("inherits from duplicate interface %s", b2->base->toChars());
|
error("inherits from duplicate interface %s", b2->base->toChars());
|
||||||
}
|
}
|
||||||
@@ -467,7 +468,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
interfaces_dim = baseclasses->dim;
|
interfaces_dim = baseclasses->dim;
|
||||||
interfaces = (BaseClass **)baseclasses->data;
|
interfaces = baseclasses->tdata();
|
||||||
|
|
||||||
|
|
||||||
if (baseClass)
|
if (baseClass)
|
||||||
@@ -480,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
// Copy vtbl[] from base class
|
// Copy vtbl[] from base class
|
||||||
vtbl.setDim(baseClass->vtbl.dim);
|
vtbl.setDim(baseClass->vtbl.dim);
|
||||||
memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
|
memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
|
||||||
|
|
||||||
// Inherit properties from base class
|
// Inherit properties from base class
|
||||||
com = baseClass->isCOMclass();
|
com = baseClass->isCOMclass();
|
||||||
@@ -503,7 +504,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
Dsymbol *s = (*members)[i];
|
||||||
s->addMember(sc, this, 1);
|
s->addMember(sc, this, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,17 +607,20 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
structsize = sc->offset;
|
structsize = sc->offset;
|
||||||
Scope scsave = *sc;
|
Scope scsave = *sc;
|
||||||
size_t members_dim = members->dim;
|
size_t members_dim = members->dim;
|
||||||
sizeok = 0;
|
sizeok = SIZEOKnone;
|
||||||
|
|
||||||
/* Set scope so if there are forward references, we still might be able to
|
/* Set scope so if there are forward references, we still might be able to
|
||||||
* resolve individual members like enums.
|
* resolve individual members like enums.
|
||||||
*/
|
*/
|
||||||
for (size_t i = 0; i < members_dim; i++)
|
for (size_t i = 0; i < members_dim; i++)
|
||||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
{ Dsymbol *s = (*members)[i];
|
||||||
/* There are problems doing this in the general case because
|
/* There are problems doing this in the general case because
|
||||||
* Scope keeps track of things like 'offset'
|
* Scope keeps track of things like 'offset'
|
||||||
*/
|
*/
|
||||||
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
|
if (s->isEnumDeclaration() ||
|
||||||
|
(s->isAggregateDeclaration() && s->ident) ||
|
||||||
|
s->isTemplateMixin() ||
|
||||||
|
s->isAliasDeclaration())
|
||||||
{
|
{
|
||||||
//printf("setScope %s %s\n", s->kind(), s->toChars());
|
//printf("setScope %s %s\n", s->kind(), s->toChars());
|
||||||
s->setScope(sc);
|
s->setScope(sc);
|
||||||
@@ -624,13 +628,35 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < members_dim; i++)
|
for (size_t i = 0; i < members_dim; i++)
|
||||||
{ Dsymbol *s = (Dsymbol *)members->data[i];
|
{ Dsymbol *s = (*members)[i];
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeok == 2)
|
// Set the offsets of the fields and determine the size of the class
|
||||||
{ // semantic() failed because of forward references.
|
|
||||||
|
unsigned offset = structsize;
|
||||||
|
bool isunion = isUnionDeclaration() != NULL;
|
||||||
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
|
{ Dsymbol *s = (*members)[i];
|
||||||
|
s->setFieldOffset(this, &offset, false);
|
||||||
|
}
|
||||||
|
sc->offset = structsize;
|
||||||
|
|
||||||
|
if (global.gag && global.gaggedErrors != errors)
|
||||||
|
{ // The type is no good, yet the error messages were gagged.
|
||||||
|
type = Type::terror;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeok == 2) // failed due to forward references
|
||||||
|
{ // semantic() failed due to forward references
|
||||||
// Unwind what we did, and defer it for later
|
// Unwind what we did, and defer it for later
|
||||||
|
|
||||||
|
for (size_t i = 0; i < fields.dim; i++)
|
||||||
|
{ Dsymbol *s = fields[i];
|
||||||
|
VarDeclaration *vd = s->isVarDeclaration();
|
||||||
|
if (vd)
|
||||||
|
vd->offset = 0;
|
||||||
|
}
|
||||||
fields.setDim(0);
|
fields.setDim(0);
|
||||||
structsize = 0;
|
structsize = 0;
|
||||||
alignsize = 0;
|
alignsize = 0;
|
||||||
@@ -650,7 +676,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
//printf("\tsemantic('%s') successful\n", toChars());
|
//printf("\tsemantic('%s') successful\n", toChars());
|
||||||
|
|
||||||
structsize = sc->offset;
|
|
||||||
//members->print();
|
//members->print();
|
||||||
|
|
||||||
/* Look for special member functions.
|
/* Look for special member functions.
|
||||||
@@ -683,7 +708,6 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
members->push(ctor);
|
members->push(ctor);
|
||||||
ctor->addMember(sc, this, 1);
|
ctor->addMember(sc, this, 1);
|
||||||
*sc = scsave; // why? What about sc->nofree?
|
*sc = scsave; // why? What about sc->nofree?
|
||||||
sc->offset = structsize;
|
|
||||||
ctor->semantic(sc);
|
ctor->semantic(sc);
|
||||||
this->ctor = ctor;
|
this->ctor = ctor;
|
||||||
defaultCtor = ctor;
|
defaultCtor = ctor;
|
||||||
@@ -699,9 +723,10 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Allocate instance of each new interface
|
// Allocate instance of each new interface
|
||||||
|
sc->offset = structsize;
|
||||||
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
for (size_t i = 0; i < vtblInterfaces->dim; i++)
|
||||||
{
|
{
|
||||||
BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
|
BaseClass *b = (*vtblInterfaces)[i];
|
||||||
unsigned thissize = PTRSIZE;
|
unsigned thissize = PTRSIZE;
|
||||||
|
|
||||||
alignmember(structalign, thissize, &sc->offset);
|
alignmember(structalign, thissize, &sc->offset);
|
||||||
@@ -720,7 +745,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
alignsize = thissize;
|
alignsize = thissize;
|
||||||
}
|
}
|
||||||
structsize = sc->offset;
|
structsize = sc->offset;
|
||||||
sizeok = 1;
|
sizeok = SIZEOKdone;
|
||||||
Module::dprogress++;
|
Module::dprogress++;
|
||||||
|
|
||||||
dtor = buildDtor(sc);
|
dtor = buildDtor(sc);
|
||||||
@@ -731,7 +756,7 @@ void ClassDeclaration::semantic(Scope *sc)
|
|||||||
// Fill in base class vtbl[]s
|
// Fill in base class vtbl[]s
|
||||||
for (i = 0; i < vtblInterfaces->dim; i++)
|
for (i = 0; i < vtblInterfaces->dim; i++)
|
||||||
{
|
{
|
||||||
BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
|
BaseClass *b = vtblInterfaces->tdata()[i];
|
||||||
|
|
||||||
//b->fillVtbl(this, &b->vtbl, 1);
|
//b->fillVtbl(this, &b->vtbl, 1);
|
||||||
}
|
}
|
||||||
@@ -750,7 +775,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
}
|
}
|
||||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||||
{
|
{
|
||||||
BaseClass *b = (BaseClass *)baseclasses->data[i];
|
BaseClass *b = baseclasses->tdata()[i];
|
||||||
|
|
||||||
if (i)
|
if (i)
|
||||||
buf->writeByte(',');
|
buf->writeByte(',');
|
||||||
@@ -764,7 +789,7 @@ void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writenl();
|
buf->writenl();
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
Dsymbol *s = members->tdata()[i];
|
||||||
|
|
||||||
buf->writestring(" ");
|
buf->writestring(" ");
|
||||||
s->toCBuffer(buf, hgs);
|
s->toCBuffer(buf, hgs);
|
||||||
@@ -799,7 +824,7 @@ int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
|
|||||||
return 0;
|
return 0;
|
||||||
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
|
//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
|
||||||
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
for (size_t i = 0; i < cd->baseclasses->dim; i++)
|
||||||
{ BaseClass *b = (BaseClass *)cd->baseclasses->data[i];
|
{ BaseClass *b = cd->baseclasses->tdata()[i];
|
||||||
|
|
||||||
if (b->base == this || isBaseOf2(b->base))
|
if (b->base == this || isBaseOf2(b->base))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -845,7 +870,7 @@ int ClassDeclaration::isBaseInfoComplete()
|
|||||||
if (!baseClass)
|
if (!baseClass)
|
||||||
return ident == Id::Object;
|
return ident == Id::Object;
|
||||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
{ BaseClass *b = baseclasses->tdata()[i];
|
||||||
if (!b->base || !b->base->isBaseInfoComplete())
|
if (!b->base || !b->base->isBaseInfoComplete())
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -860,7 +885,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
|||||||
if (scope && !symtab)
|
if (scope && !symtab)
|
||||||
{ Scope *sc = scope;
|
{ Scope *sc = scope;
|
||||||
sc->mustsemantic++;
|
sc->mustsemantic++;
|
||||||
|
// If speculatively gagged, ungag now.
|
||||||
|
unsigned oldgag = global.gag;
|
||||||
|
if (global.isSpeculativeGagging())
|
||||||
|
global.gag = 0;
|
||||||
semantic(sc);
|
semantic(sc);
|
||||||
|
global.gag = oldgag;
|
||||||
sc->mustsemantic--;
|
sc->mustsemantic--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,7 +908,7 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
|
|||||||
|
|
||||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||||
{
|
{
|
||||||
BaseClass *b = (BaseClass *)baseclasses->data[i];
|
BaseClass *b = baseclasses->tdata()[i];
|
||||||
|
|
||||||
if (b->base)
|
if (b->base)
|
||||||
{
|
{
|
||||||
@@ -1178,12 +1208,12 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
if (sc->stc & STCdeprecated)
|
if (sc->stc & STCdeprecated)
|
||||||
{
|
{
|
||||||
isdeprecated = 1;
|
isdeprecated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand any tuples in baseclasses[]
|
// Expand any tuples in baseclasses[]
|
||||||
for (size_t i = 0; i < baseclasses->dim; )
|
for (size_t i = 0; i < baseclasses->dim; )
|
||||||
{ BaseClass *b = (BaseClass *)baseclasses->data[0];
|
{ BaseClass *b = (*baseclasses)[0];
|
||||||
b->type = b->type->semantic(loc, sc);
|
b->type = b->type->semantic(loc, sc);
|
||||||
Type *tb = b->type->toBasetype();
|
Type *tb = b->type->toBasetype();
|
||||||
|
|
||||||
@@ -1208,7 +1238,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
BaseClass *b;
|
BaseClass *b;
|
||||||
Type *tb;
|
Type *tb;
|
||||||
|
|
||||||
b = (BaseClass *)baseclasses->data[i];
|
b = baseclasses->tdata()[i];
|
||||||
b->type = b->type->semantic(loc, sc);
|
b->type = b->type->semantic(loc, sc);
|
||||||
tb = b->type->toBasetype();
|
tb = b->type->toBasetype();
|
||||||
if (tb->ty == Tclass)
|
if (tb->ty == Tclass)
|
||||||
@@ -1216,7 +1246,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
else
|
else
|
||||||
tc = NULL;
|
tc = NULL;
|
||||||
if (!tc || !tc->sym->isInterfaceDeclaration())
|
if (!tc || !tc->sym->isInterfaceDeclaration())
|
||||||
{
|
{ if (b->type != Type::terror)
|
||||||
error("base type must be interface, not %s", b->type->toChars());
|
error("base type must be interface, not %s", b->type->toChars());
|
||||||
baseclasses->remove(i);
|
baseclasses->remove(i);
|
||||||
continue;
|
continue;
|
||||||
@@ -1226,7 +1256,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
// Check for duplicate interfaces
|
// Check for duplicate interfaces
|
||||||
for (size_t j = 0; j < i; j++)
|
for (size_t j = 0; j < i; j++)
|
||||||
{
|
{
|
||||||
BaseClass *b2 = (BaseClass *)baseclasses->data[j];
|
BaseClass *b2 = baseclasses->tdata()[j];
|
||||||
if (b2->base == tc->sym)
|
if (b2->base == tc->sym)
|
||||||
error("inherits from duplicate interface %s", b2->base->toChars());
|
error("inherits from duplicate interface %s", b2->base->toChars());
|
||||||
}
|
}
|
||||||
@@ -1311,10 +1341,10 @@ void InterfaceDeclaration::semantic(Scope *sc)
|
|||||||
sc->explicitProtection = 0;
|
sc->explicitProtection = 0;
|
||||||
structalign = sc->structalign;
|
structalign = sc->structalign;
|
||||||
sc->offset = PTRSIZE * 2;
|
sc->offset = PTRSIZE * 2;
|
||||||
|
structsize = sc->offset;
|
||||||
inuse++;
|
inuse++;
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{ Dsymbol *s = (*members)[i];
|
||||||
Dsymbol *s = (*members)[i];
|
|
||||||
s->semantic(sc);
|
s->semantic(sc);
|
||||||
}
|
}
|
||||||
inuse--;
|
inuse--;
|
||||||
@@ -1408,7 +1438,7 @@ int InterfaceDeclaration::isBaseInfoComplete()
|
|||||||
{
|
{
|
||||||
assert(!baseClass);
|
assert(!baseClass);
|
||||||
for (size_t i = 0; i < baseclasses->dim; i++)
|
for (size_t i = 0; i < baseclasses->dim; i++)
|
||||||
{ BaseClass *b = (BaseClass *)baseclasses->data[i];
|
{ BaseClass *b = baseclasses->tdata()[i];
|
||||||
if (!b->base || !b->base->isBaseInfoComplete ())
|
if (!b->base || !b->base->isBaseInfoComplete ())
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
22
dmd/cond.c
22
dmd/cond.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -225,6 +225,7 @@ StaticIfCondition::StaticIfCondition(Loc loc, Expression *exp)
|
|||||||
: Condition(loc)
|
: Condition(loc)
|
||||||
{
|
{
|
||||||
this->exp = exp;
|
this->exp = exp;
|
||||||
|
this->nest = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Condition *StaticIfCondition::syntaxCopy()
|
Condition *StaticIfCondition::syntaxCopy()
|
||||||
@@ -235,7 +236,7 @@ Condition *StaticIfCondition::syntaxCopy()
|
|||||||
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
printf("StaticIfCondition::include(sc = %p, s = %p)\n", sc, s);
|
printf("StaticIfCondition::include(sc = %p, s = %p) this=%p inc = %d\n", sc, s, this, inc);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
printf("\ts = '%s', kind = %s\n", s->toChars(), s->kind());
|
||||||
@@ -243,6 +244,15 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
|||||||
#endif
|
#endif
|
||||||
if (inc == 0)
|
if (inc == 0)
|
||||||
{
|
{
|
||||||
|
if (exp->op == TOKerror || nest > 100)
|
||||||
|
{
|
||||||
|
error(loc, (nest > 1000) ? "unresolvable circular static if expression"
|
||||||
|
: "error evaluating static if expression");
|
||||||
|
if (!global.gag)
|
||||||
|
inc = 2; // so we don't see the error message again
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!sc)
|
if (!sc)
|
||||||
{
|
{
|
||||||
error(loc, "static if conditional cannot be at global scope");
|
error(loc, "static if conditional cannot be at global scope");
|
||||||
@@ -250,13 +260,19 @@ int StaticIfCondition::include(Scope *sc, ScopeDsymbol *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++nest;
|
||||||
sc = sc->push(sc->scopesym);
|
sc = sc->push(sc->scopesym);
|
||||||
sc->sd = s; // s gets any addMember()
|
sc->sd = s; // s gets any addMember()
|
||||||
sc->flags |= SCOPEstaticif;
|
sc->flags |= SCOPEstaticif;
|
||||||
Expression *e = exp->semantic(sc);
|
Expression *e = exp->semantic(sc);
|
||||||
sc->pop();
|
sc->pop();
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
if (e->isBool(TRUE))
|
--nest;
|
||||||
|
if (e->op == TOKerror)
|
||||||
|
{ exp = e;
|
||||||
|
inc = 0;
|
||||||
|
}
|
||||||
|
else if (e->isBool(TRUE))
|
||||||
inc = 1;
|
inc = 1;
|
||||||
else if (e->isBool(FALSE))
|
else if (e->isBool(FALSE))
|
||||||
inc = 2;
|
inc = 2;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -36,6 +36,7 @@ struct Condition
|
|||||||
virtual Condition *syntaxCopy() = 0;
|
virtual Condition *syntaxCopy() = 0;
|
||||||
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
|
virtual int include(Scope *sc, ScopeDsymbol *s) = 0;
|
||||||
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0;
|
||||||
|
virtual DebugCondition *isDebugCondition() { return NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DVCondition : Condition
|
struct DVCondition : Condition
|
||||||
@@ -59,6 +60,7 @@ struct DebugCondition : DVCondition
|
|||||||
|
|
||||||
int include(Scope *sc, ScopeDsymbol *s);
|
int include(Scope *sc, ScopeDsymbol *s);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
DebugCondition *isDebugCondition() { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VersionCondition : DVCondition
|
struct VersionCondition : DVCondition
|
||||||
@@ -77,6 +79,7 @@ struct VersionCondition : DVCondition
|
|||||||
struct StaticIfCondition : Condition
|
struct StaticIfCondition : Condition
|
||||||
{
|
{
|
||||||
Expression *exp;
|
Expression *exp;
|
||||||
|
int nest; // limit circular dependencies
|
||||||
|
|
||||||
StaticIfCondition(Loc loc, Expression *exp);
|
StaticIfCondition(Loc loc, Expression *exp);
|
||||||
Condition *syntaxCopy();
|
Condition *syntaxCopy();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -530,7 +530,8 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
goto L2;
|
goto L2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ error("cannot alias an expression %s", e->toChars());
|
{ if (e->op != TOKerror)
|
||||||
|
error("cannot alias an expression %s", e->toChars());
|
||||||
t = e->type;
|
t = e->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,7 +544,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
ScopeDsymbol::multiplyDefined(0, this, overnext);
|
ScopeDsymbol::multiplyDefined(0, this, overnext);
|
||||||
this->inSemantic = 0;
|
this->inSemantic = 0;
|
||||||
|
|
||||||
if (errors != global.errors)
|
if (global.gag && errors != global.errors)
|
||||||
type = savedtype;
|
type = savedtype;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -580,7 +581,7 @@ void AliasDeclaration::semantic(Scope *sc)
|
|||||||
assert(global.errors);
|
assert(global.errors);
|
||||||
s = NULL;
|
s = NULL;
|
||||||
}
|
}
|
||||||
if (errors != global.errors)
|
if (global.gag && errors != global.errors)
|
||||||
{
|
{
|
||||||
type = savedtype;
|
type = savedtype;
|
||||||
overnext = savedovernext;
|
overnext = savedovernext;
|
||||||
@@ -728,6 +729,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
|||||||
#if DMDV1
|
#if DMDV1
|
||||||
nestedref = 0;
|
nestedref = 0;
|
||||||
#endif
|
#endif
|
||||||
|
alignment = 0;
|
||||||
ctorinit = 0;
|
ctorinit = 0;
|
||||||
aliassym = NULL;
|
aliassym = NULL;
|
||||||
onstack = 0;
|
onstack = 0;
|
||||||
@@ -767,6 +769,7 @@ Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
|
|||||||
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
|
sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
|
||||||
sv->storage_class = storage_class;
|
sv->storage_class = storage_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Syntax copy for header file
|
// Syntax copy for header file
|
||||||
if (!htype) // Don't overwrite original
|
if (!htype) // Don't overwrite original
|
||||||
{ if (type) // Make copy for both old and new instances
|
{ if (type) // Make copy for both old and new instances
|
||||||
@@ -955,9 +958,7 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AggregateDeclaration *aad = sc->anonAgg;
|
AggregateDeclaration *aad = parent->isAggregateDeclaration();
|
||||||
if (!aad)
|
|
||||||
aad = parent->isAggregateDeclaration();
|
|
||||||
if (aad)
|
if (aad)
|
||||||
{
|
{
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
@@ -970,7 +971,15 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
aad->addField(sc, this);
|
{
|
||||||
|
storage_class |= STCfield;
|
||||||
|
alignment = sc->structalign;
|
||||||
|
#if DMDV2
|
||||||
|
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
|
||||||
|
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
|
||||||
|
aad->noDefaultCtor = TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InterfaceDeclaration *id = parent->isInterfaceDeclaration();
|
InterfaceDeclaration *id = parent->isInterfaceDeclaration();
|
||||||
@@ -1305,6 +1314,31 @@ ExpInitializer *VarDeclaration::getExpInitializer()
|
|||||||
void VarDeclaration::semantic2(Scope *sc)
|
void VarDeclaration::semantic2(Scope *sc)
|
||||||
{
|
{
|
||||||
//printf("VarDeclaration::semantic2('%s')\n", toChars());
|
//printf("VarDeclaration::semantic2('%s')\n", toChars());
|
||||||
|
// Inside unions, default to void initializers
|
||||||
|
if (!init && sc->inunion && !toParent()->isFuncDeclaration())
|
||||||
|
{
|
||||||
|
AggregateDeclaration *aad = parent->isAggregateDeclaration();
|
||||||
|
if (aad)
|
||||||
|
{
|
||||||
|
if (aad->fields[0] == this)
|
||||||
|
{
|
||||||
|
int hasinit = 0;
|
||||||
|
for (size_t i = 1; i < aad->fields.dim; i++)
|
||||||
|
{
|
||||||
|
if (aad->fields[i]->init &&
|
||||||
|
!aad->fields[i]->init->isVoidInitializer())
|
||||||
|
{
|
||||||
|
hasinit = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasinit)
|
||||||
|
init = new ExpInitializer(loc, type->defaultInitLiteral(loc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
init = new VoidInitializer(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (init && !toParent()->isFuncDeclaration())
|
if (init && !toParent()->isFuncDeclaration())
|
||||||
{ inuse++;
|
{ inuse++;
|
||||||
#if 0
|
#if 0
|
||||||
@@ -1330,6 +1364,82 @@ void VarDeclaration::semantic3(Scope *sc)
|
|||||||
Declaration::semantic3(sc);
|
Declaration::semantic3(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||||
|
{
|
||||||
|
//printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars());
|
||||||
|
|
||||||
|
if (aliassym)
|
||||||
|
{ // If this variable was really a tuple, set the offsets for the tuple fields
|
||||||
|
TupleDeclaration *v2 = aliassym->isTupleDeclaration();
|
||||||
|
assert(v2);
|
||||||
|
for (size_t i = 0; i < v2->objects->dim; i++)
|
||||||
|
{ Object *o = (*v2->objects)[i];
|
||||||
|
assert(o->dyncast() == DYNCAST_EXPRESSION);
|
||||||
|
Expression *e = (Expression *)o;
|
||||||
|
assert(e->op == TOKdsymbol);
|
||||||
|
DsymbolExp *se = (DsymbolExp *)e;
|
||||||
|
se->s->setFieldOffset(ad, poffset, isunion);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(storage_class & STCfield))
|
||||||
|
return;
|
||||||
|
assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
|
||||||
|
|
||||||
|
/* Fields that are tuples appear both as part of TupleDeclarations and
|
||||||
|
* as members. That means ignore them if they are already a field.
|
||||||
|
*/
|
||||||
|
if (offset)
|
||||||
|
return; // already a field
|
||||||
|
for (size_t i = 0; i < ad->fields.dim; i++)
|
||||||
|
{
|
||||||
|
if (ad->fields[i] == this)
|
||||||
|
return; // already a field
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for forward referenced types which will fail the size() call
|
||||||
|
Type *t = type->toBasetype();
|
||||||
|
if (storage_class & STCref)
|
||||||
|
{ // References are the size of a pointer
|
||||||
|
t = Type::tvoidptr;
|
||||||
|
}
|
||||||
|
if (t->ty == Tstruct)
|
||||||
|
{ TypeStruct *ts = (TypeStruct *)t;
|
||||||
|
#if DMDV2
|
||||||
|
if (ts->sym == ad)
|
||||||
|
{
|
||||||
|
ad->error("cannot have field %s with same struct type", toChars());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope)
|
||||||
|
ts->sym->semantic(NULL);
|
||||||
|
if (ts->sym->sizeok != SIZEOKdone)
|
||||||
|
{
|
||||||
|
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t->ty == Tident)
|
||||||
|
{
|
||||||
|
ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned memsize = t->size(loc); // size of member
|
||||||
|
unsigned memalignsize = t->alignsize(); // size of member for alignment purposes
|
||||||
|
unsigned memalign = t->memalign(alignment); // alignment boundaries
|
||||||
|
|
||||||
|
offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign,
|
||||||
|
&ad->structsize, &ad->alignsize, isunion);
|
||||||
|
|
||||||
|
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
||||||
|
|
||||||
|
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize);
|
||||||
|
ad->fields.push(this);
|
||||||
|
}
|
||||||
|
|
||||||
const char *VarDeclaration::kind()
|
const char *VarDeclaration::kind()
|
||||||
{
|
{
|
||||||
return "variable";
|
return "variable";
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ struct VarDeclaration : Declaration
|
|||||||
#else
|
#else
|
||||||
int nestedref; // referenced by a lexically nested function
|
int nestedref; // referenced by a lexically nested function
|
||||||
#endif
|
#endif
|
||||||
|
unsigned short alignment;
|
||||||
int ctorinit; // it has been initialized in a ctor
|
int ctorinit; // it has been initialized in a ctor
|
||||||
int onstack; // 1: it has been allocated on the stack
|
int onstack; // 1: it has been allocated on the stack
|
||||||
// 2: on stack, run destructor anyway
|
// 2: on stack, run destructor anyway
|
||||||
@@ -305,6 +306,7 @@ struct VarDeclaration : Declaration
|
|||||||
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
|
||||||
Dsymbol *syntaxCopy(Dsymbol *);
|
Dsymbol *syntaxCopy(Dsymbol *);
|
||||||
void semantic(Scope *sc);
|
void semantic(Scope *sc);
|
||||||
|
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||||
void semantic2(Scope *sc);
|
void semantic2(Scope *sc);
|
||||||
const char *kind();
|
const char *kind();
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
@@ -795,6 +797,7 @@ struct FuncDeclaration : Declaration
|
|||||||
int isAbstract();
|
int isAbstract();
|
||||||
int isCodeseg();
|
int isCodeseg();
|
||||||
int isOverloadable();
|
int isOverloadable();
|
||||||
|
int hasOverloads();
|
||||||
int isPure();
|
int isPure();
|
||||||
int isSafe();
|
int isSafe();
|
||||||
int isTrusted();
|
int isTrusted();
|
||||||
|
|||||||
@@ -261,6 +261,9 @@ void Module::gendocfile()
|
|||||||
Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
|
Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *srcfilename = srcfile->toChars();
|
||||||
|
Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
|
||||||
|
|
||||||
char *docfilename = docfile->toChars();
|
char *docfilename = docfile->toChars();
|
||||||
Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
|
Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -50,6 +50,7 @@ Dsymbol::Dsymbol()
|
|||||||
this->loc = 0;
|
this->loc = 0;
|
||||||
this->comment = NULL;
|
this->comment = NULL;
|
||||||
this->scope = NULL;
|
this->scope = NULL;
|
||||||
|
this->errors = false;
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
this->llvmInternal = LLVMnone;
|
this->llvmInternal = LLVMnone;
|
||||||
this->irsym = NULL;
|
this->irsym = NULL;
|
||||||
@@ -69,6 +70,7 @@ Dsymbol::Dsymbol(Identifier *ident)
|
|||||||
this->loc = 0;
|
this->loc = 0;
|
||||||
this->comment = NULL;
|
this->comment = NULL;
|
||||||
this->scope = NULL;
|
this->scope = NULL;
|
||||||
|
this->errors = false;
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
this->llvmInternal = LLVMnone;
|
this->llvmInternal = LLVMnone;
|
||||||
this->irsym = NULL;
|
this->irsym = NULL;
|
||||||
@@ -169,6 +171,10 @@ bool Dsymbol::hasStaticCtorOrDtor()
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
char *Dsymbol::toChars()
|
char *Dsymbol::toChars()
|
||||||
{
|
{
|
||||||
return ident ? ident->toChars() : (char *)"__anonymous";
|
return ident ? ident->toChars() : (char *)"__anonymous";
|
||||||
@@ -283,6 +289,23 @@ TemplateInstance *Dsymbol::inTemplateInstance()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if this function is a member of a template which has only been
|
||||||
|
// instantiated speculatively, eg from inside is(typeof()).
|
||||||
|
// Return the speculative template instance it is part of,
|
||||||
|
// or NULL if not speculative.
|
||||||
|
TemplateInstance *Dsymbol::isSpeculative()
|
||||||
|
{
|
||||||
|
Dsymbol * par = parent;
|
||||||
|
while (par)
|
||||||
|
{
|
||||||
|
TemplateInstance *ti = par->isTemplateInstance();
|
||||||
|
if (ti && ti->speculative)
|
||||||
|
return ti;
|
||||||
|
par = par->toParent();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int Dsymbol::isAnonymous()
|
int Dsymbol::isAnonymous()
|
||||||
{
|
{
|
||||||
return ident ? 0 : 1;
|
return ident ? 0 : 1;
|
||||||
@@ -367,11 +390,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
|
|||||||
|
|
||||||
void *symbol_search_fp(void *arg, const char *seed)
|
void *symbol_search_fp(void *arg, const char *seed)
|
||||||
{
|
{
|
||||||
|
/* If not in the lexer's string table, it certainly isn't in the symbol table.
|
||||||
|
* Doing this first is a lot faster.
|
||||||
|
*/
|
||||||
|
size_t len = strlen(seed);
|
||||||
|
if (!len)
|
||||||
|
return NULL;
|
||||||
|
StringValue *sv = Lexer::stringtable.lookup(seed, len);
|
||||||
|
if (!sv)
|
||||||
|
return NULL;
|
||||||
|
Identifier *id = (Identifier *)sv->ptrvalue;
|
||||||
|
assert(id);
|
||||||
|
|
||||||
Dsymbol *s = (Dsymbol *)arg;
|
Dsymbol *s = (Dsymbol *)arg;
|
||||||
Identifier id(seed, 0);
|
|
||||||
Module::clearCache();
|
Module::clearCache();
|
||||||
s = s->search(0, &id, 4|2);
|
return s->search(0, id, 4|2);
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
Dsymbol *Dsymbol::search_correct(Identifier *ident)
|
||||||
@@ -409,7 +442,13 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
|
|||||||
id = ti->name;
|
id = ti->name;
|
||||||
sm = s->search(loc, id, 0);
|
sm = s->search(loc, id, 0);
|
||||||
if (!sm)
|
if (!sm)
|
||||||
{ error("template identifier %s is not a member of %s %s",
|
{
|
||||||
|
sm = s->search_correct(id);
|
||||||
|
if (sm)
|
||||||
|
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
|
||||||
|
id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
|
||||||
|
else
|
||||||
|
error("template identifier '%s' is not a member of '%s %s'",
|
||||||
id->toChars(), s->kind(), s->toChars());
|
id->toChars(), s->kind(), s->toChars());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -495,6 +534,11 @@ int Dsymbol::isOverloadable()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int Dsymbol::hasOverloads()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
|
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -518,6 +562,11 @@ int Dsymbol::needThis()
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||||
|
{
|
||||||
|
return (*fp)(this, param);
|
||||||
|
}
|
||||||
|
|
||||||
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
|
||||||
{
|
{
|
||||||
//printf("Dsymbol::addMember('%s')\n", toChars());
|
//printf("Dsymbol::addMember('%s')\n", toChars());
|
||||||
@@ -634,19 +683,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
|
|||||||
|
|
||||||
Module *Dsymbol::getModule()
|
Module *Dsymbol::getModule()
|
||||||
{
|
{
|
||||||
Module *m;
|
|
||||||
Dsymbol *s;
|
|
||||||
|
|
||||||
//printf("Dsymbol::getModule()\n");
|
//printf("Dsymbol::getModule()\n");
|
||||||
TemplateDeclaration *td = getFuncTemplateDecl(this);
|
TemplateDeclaration *td = getFuncTemplateDecl(this);
|
||||||
if (td)
|
if (td)
|
||||||
return td->getModule();
|
return td->getModule();
|
||||||
|
|
||||||
s = this;
|
Dsymbol *s = this;
|
||||||
while (s)
|
while (s)
|
||||||
{
|
{
|
||||||
//printf("\ts = '%s'\n", s->toChars());
|
//printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
|
||||||
m = s->isModule();
|
Module *m = s->isModule();
|
||||||
if (m)
|
if (m)
|
||||||
return m;
|
return m;
|
||||||
s = s->parent;
|
s = s->parent;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -128,6 +128,8 @@ enum PASS
|
|||||||
PASSobj, // toObjFile() run
|
PASSobj, // toObjFile() run
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
|
||||||
|
|
||||||
struct Dsymbol : Object
|
struct Dsymbol : Object
|
||||||
{
|
{
|
||||||
Identifier *ident;
|
Identifier *ident;
|
||||||
@@ -140,6 +142,7 @@ struct Dsymbol : Object
|
|||||||
unsigned char *comment; // documentation comment for this Dsymbol
|
unsigned char *comment; // documentation comment for this Dsymbol
|
||||||
Loc loc; // where defined
|
Loc loc; // where defined
|
||||||
Scope *scope; // !=NULL means context to use for semantic()
|
Scope *scope; // !=NULL means context to use for semantic()
|
||||||
|
bool errors; // this symbol failed to pass semantic()
|
||||||
|
|
||||||
Dsymbol();
|
Dsymbol();
|
||||||
Dsymbol(Identifier *);
|
Dsymbol(Identifier *);
|
||||||
@@ -157,6 +160,7 @@ struct Dsymbol : Object
|
|||||||
Dsymbol *toParent();
|
Dsymbol *toParent();
|
||||||
Dsymbol *toParent2();
|
Dsymbol *toParent2();
|
||||||
TemplateInstance *inTemplateInstance();
|
TemplateInstance *inTemplateInstance();
|
||||||
|
TemplateInstance *isSpeculative();
|
||||||
|
|
||||||
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
|
||||||
|
|
||||||
@@ -165,6 +169,7 @@ struct Dsymbol : Object
|
|||||||
virtual const char *toPrettyChars();
|
virtual const char *toPrettyChars();
|
||||||
virtual const char *kind();
|
virtual const char *kind();
|
||||||
virtual Dsymbol *toAlias(); // resolve real symbol
|
virtual Dsymbol *toAlias(); // resolve real symbol
|
||||||
|
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||||
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
|
||||||
virtual void setScope(Scope *sc);
|
virtual void setScope(Scope *sc);
|
||||||
virtual void importAll(Scope *sc);
|
virtual void importAll(Scope *sc);
|
||||||
@@ -193,6 +198,7 @@ struct Dsymbol : Object
|
|||||||
#if DMDV2
|
#if DMDV2
|
||||||
virtual int isOverloadable();
|
virtual int isOverloadable();
|
||||||
#endif
|
#endif
|
||||||
|
virtual int hasOverloads();
|
||||||
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
|
||||||
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
|
||||||
virtual Type *getType(); // is this a type?
|
virtual Type *getType(); // is this a type?
|
||||||
@@ -202,6 +208,7 @@ struct Dsymbol : Object
|
|||||||
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
|
||||||
virtual int oneMember(Dsymbol **ps);
|
virtual int oneMember(Dsymbol **ps);
|
||||||
static int oneMembers(Dsymbols *members, Dsymbol **ps);
|
static int oneMembers(Dsymbols *members, Dsymbol **ps);
|
||||||
|
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||||
virtual int hasPointers();
|
virtual int hasPointers();
|
||||||
virtual bool hasStaticCtorOrDtor();
|
virtual bool hasStaticCtorOrDtor();
|
||||||
virtual void addLocalClass(ClassDeclarations *) { }
|
virtual void addLocalClass(ClassDeclarations *) { }
|
||||||
|
|||||||
316
dmd/expression.c
316
dmd/expression.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -345,10 +345,10 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
|||||||
*/
|
*/
|
||||||
Type *t0 = NULL;
|
Type *t0 = NULL;
|
||||||
for (size_t i = 0; i < exps->dim; i++)
|
for (size_t i = 0; i < exps->dim; i++)
|
||||||
{ Expression *e = (Expression *)exps->data[i];
|
{ Expression *e = (*exps)[i];
|
||||||
|
|
||||||
if (!e->type)
|
if (!e->type)
|
||||||
{ error("%s has no value", e->toChars());
|
{ error(e->loc, "%s has no value", e->toChars());
|
||||||
e = new ErrorExp();
|
e = new ErrorExp();
|
||||||
}
|
}
|
||||||
e = resolveProperties(sc, e);
|
e = resolveProperties(sc, e);
|
||||||
@@ -357,7 +357,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
|||||||
t0 = e->type;
|
t0 = e->type;
|
||||||
else
|
else
|
||||||
e = e->implicitCastTo(sc, t0);
|
e = e->implicitCastTo(sc, t0);
|
||||||
exps->data[i] = (void *)e;
|
(*exps)[i] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t0)
|
if (!t0)
|
||||||
@@ -384,11 +384,11 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
|||||||
Expression *e0;
|
Expression *e0;
|
||||||
int j0;
|
int j0;
|
||||||
for (size_t i = 0; i < exps->dim; i++)
|
for (size_t i = 0; i < exps->dim; i++)
|
||||||
{ Expression *e = (Expression *)exps->data[i];
|
{ Expression *e = (*exps)[i];
|
||||||
|
|
||||||
e = resolveProperties(sc, e);
|
e = resolveProperties(sc, e);
|
||||||
if (!e->type)
|
if (!e->type)
|
||||||
{ error("%s has no value", e->toChars());
|
{ e->error("%s has no value", e->toChars());
|
||||||
e = new ErrorExp();
|
e = new ErrorExp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,8 +401,9 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
|||||||
condexp.type = NULL;
|
condexp.type = NULL;
|
||||||
condexp.e1 = e0;
|
condexp.e1 = e0;
|
||||||
condexp.e2 = e;
|
condexp.e2 = e;
|
||||||
|
condexp.loc = e->loc;
|
||||||
condexp.semantic(sc);
|
condexp.semantic(sc);
|
||||||
exps->data[j0] = (void *)condexp.e1;
|
(*exps)[j0] = condexp.e1;
|
||||||
e = condexp.e2;
|
e = condexp.e2;
|
||||||
j0 = i;
|
j0 = i;
|
||||||
e0 = e;
|
e0 = e;
|
||||||
@@ -414,15 +415,15 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt
|
|||||||
e0 = e;
|
e0 = e;
|
||||||
t0 = e->type;
|
t0 = e->type;
|
||||||
}
|
}
|
||||||
exps->data[i] = (void *)e;
|
(*exps)[i] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t0)
|
if (t0)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < exps->dim; i++)
|
for (size_t i = 0; i < exps->dim; i++)
|
||||||
{ Expression *e = (Expression *)exps->data[i];
|
{ Expression *e = (*exps)[i];
|
||||||
e = e->implicitCastTo(sc, t0);
|
e = e->implicitCastTo(sc, t0);
|
||||||
exps->data[i] = (void *)e;
|
(*exps)[i] = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -525,23 +526,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if this function is a member of a template which has only been
|
|
||||||
// instantiated speculatively, eg from inside is(typeof()).
|
|
||||||
// Return the speculative template instance it is part of,
|
|
||||||
// or NULL if not speculative.
|
|
||||||
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd)
|
|
||||||
{
|
|
||||||
Dsymbol * par = fd->parent;
|
|
||||||
while (par)
|
|
||||||
{
|
|
||||||
TemplateInstance *ti = par->isTemplateInstance();
|
|
||||||
if (ti && ti->speculative)
|
|
||||||
return ti;
|
|
||||||
par = par->toParent();
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
* Now that we know the exact type of the function we're calling,
|
* Now that we know the exact type of the function we're calling,
|
||||||
* the arguments[] need to be adjusted:
|
* the arguments[] need to be adjusted:
|
||||||
@@ -565,7 +549,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
// If inferring return type, and semantic3() needs to be run if not already run
|
// If inferring return type, and semantic3() needs to be run if not already run
|
||||||
if (!tf->next && fd->inferRetType)
|
if (!tf->next && fd->inferRetType)
|
||||||
{
|
{
|
||||||
TemplateInstance *spec = isSpeculativeFunction(fd);
|
TemplateInstance *spec = fd->isSpeculative();
|
||||||
int olderrs = global.errors;
|
int olderrs = global.errors;
|
||||||
fd->semantic3(fd->scope);
|
fd->semantic3(fd->scope);
|
||||||
// Update the template instantiation with the number
|
// Update the template instantiation with the number
|
||||||
@@ -583,10 +567,9 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
Expression *arg;
|
Expression *arg;
|
||||||
|
|
||||||
if (i < nargs)
|
if (i < nargs)
|
||||||
arg = (Expression *)arguments->data[i];
|
arg = (*arguments)[i];
|
||||||
else
|
else
|
||||||
arg = NULL;
|
arg = NULL;
|
||||||
Type *tb;
|
|
||||||
|
|
||||||
if (i < nparams)
|
if (i < nparams)
|
||||||
{
|
{
|
||||||
@@ -613,12 +596,13 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
if (tf->varargs == 2 && i + 1 == nparams)
|
if (tf->varargs == 2 && i + 1 == nparams)
|
||||||
{
|
{
|
||||||
//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
|
//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
|
||||||
if (arg->implicitConvTo(p->type))
|
MATCH m;
|
||||||
|
if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch)
|
||||||
{
|
{
|
||||||
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()))
|
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
|
||||||
goto L2;
|
goto L2;
|
||||||
else if (nargs != nparams)
|
else if (nargs != nparams)
|
||||||
{ error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
|
{ error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
goto L1;
|
goto L1;
|
||||||
@@ -661,9 +645,6 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
Expression *e = new VarExp(loc, v);
|
Expression *e = new VarExp(loc, v);
|
||||||
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
|
e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
|
||||||
AssignExp *ae = new AssignExp(loc, e, a);
|
AssignExp *ae = new AssignExp(loc, e, a);
|
||||||
#if DMDV2
|
|
||||||
ae->op = TOKconstruct;
|
|
||||||
#endif
|
|
||||||
if (c)
|
if (c)
|
||||||
c = new CommaExp(loc, c, ae);
|
c = new CommaExp(loc, c, ae);
|
||||||
else
|
else
|
||||||
@@ -723,7 +704,7 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
// LDC we don't want this!
|
// LDC we don't want this!
|
||||||
#if !IN_LLVM
|
#if !IN_LLVM
|
||||||
// Convert static arrays to pointers
|
// Convert static arrays to pointers
|
||||||
tb = arg->type->toBasetype();
|
Type *tb = arg->type->toBasetype();
|
||||||
if (tb->ty == Tsarray)
|
if (tb->ty == Tsarray)
|
||||||
{
|
{
|
||||||
arg = arg->checkToPointer();
|
arg = arg->checkToPointer();
|
||||||
@@ -732,7 +713,19 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
#if DMDV2
|
#if DMDV2
|
||||||
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
|
||||||
{
|
{
|
||||||
arg = callCpCtor(loc, sc, arg);
|
if (arg->op == TOKcall)
|
||||||
|
{
|
||||||
|
/* The struct value returned from the function is transferred
|
||||||
|
* to the function, so the callee should not call the destructor
|
||||||
|
* on it.
|
||||||
|
*/
|
||||||
|
valueNoDtor(arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* Not transferring it, so call the copy constructor
|
||||||
|
*/
|
||||||
|
arg = callCpCtor(loc, sc, arg, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -801,7 +794,8 @@ void functionParameters(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argum
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert static arrays to dynamic arrays
|
// Convert static arrays to dynamic arrays
|
||||||
tb = arg->type->toBasetype();
|
// BUG: I don't think this is right for D2
|
||||||
|
Type *tb = arg->type->toBasetype();
|
||||||
if (tb->ty == Tsarray)
|
if (tb->ty == Tsarray)
|
||||||
{ TypeSArray *ts = (TypeSArray *)tb;
|
{ TypeSArray *ts = (TypeSArray *)tb;
|
||||||
Type *ta = ts->next->arrayOf();
|
Type *ta = ts->next->arrayOf();
|
||||||
@@ -2222,6 +2216,7 @@ Lagain:
|
|||||||
if (em)
|
if (em)
|
||||||
{
|
{
|
||||||
e = em->value->copy();
|
e = em->value->copy();
|
||||||
|
e->loc = loc;
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -2234,8 +2229,8 @@ Lagain:
|
|||||||
v->semantic(v->scope);
|
v->semantic(v->scope);
|
||||||
type = v->type;
|
type = v->type;
|
||||||
if (!v->type)
|
if (!v->type)
|
||||||
{ error("forward reference of %s", v->toChars());
|
{ error("forward reference of %s %s", v->kind(), v->toChars());
|
||||||
type = Type::terror;
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray)
|
if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray)
|
||||||
@@ -2245,8 +2240,7 @@ Lagain:
|
|||||||
if (v->inuse)
|
if (v->inuse)
|
||||||
{
|
{
|
||||||
error("circular reference to '%s'", v->toChars());
|
error("circular reference to '%s'", v->toChars());
|
||||||
type = Type::tint32;
|
return new ErrorExp();
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
ExpInitializer *ei = v->init->isExpInitializer();
|
ExpInitializer *ei = v->init->isExpInitializer();
|
||||||
if (ei)
|
if (ei)
|
||||||
@@ -2282,13 +2276,19 @@ Lagain:
|
|||||||
{ //printf("'%s' is a function\n", f->toChars());
|
{ //printf("'%s' is a function\n", f->toChars());
|
||||||
|
|
||||||
if (!f->originalType && f->scope) // semantic not yet run
|
if (!f->originalType && f->scope) // semantic not yet run
|
||||||
|
{
|
||||||
|
unsigned oldgag = global.gag;
|
||||||
|
if (global.isSpeculativeGagging() && !f->isSpeculative())
|
||||||
|
global.gag = 0;
|
||||||
f->semantic(f->scope);
|
f->semantic(f->scope);
|
||||||
|
global.gag = oldgag;
|
||||||
|
}
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
// if inferring return type, sematic3 needs to be run
|
// if inferring return type, sematic3 needs to be run
|
||||||
if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
|
if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
|
||||||
{
|
{
|
||||||
TemplateInstance *spec = isSpeculativeFunction(f);
|
TemplateInstance *spec = f->isSpeculative();
|
||||||
int olderrs = global.errors;
|
int olderrs = global.errors;
|
||||||
f->semantic3(f->scope);
|
f->semantic3(f->scope);
|
||||||
// Update the template instantiation with the number
|
// Update the template instantiation with the number
|
||||||
@@ -2362,10 +2362,10 @@ Lagain:
|
|||||||
}
|
}
|
||||||
|
|
||||||
TemplateInstance *ti = s->isTemplateInstance();
|
TemplateInstance *ti = s->isTemplateInstance();
|
||||||
if (ti && !global.errors)
|
if (ti)
|
||||||
{ if (!ti->semanticRun)
|
{ if (!ti->semanticRun)
|
||||||
ti->semantic(sc);
|
ti->semantic(sc);
|
||||||
s = ti->inst->toAlias();
|
s = ti->toAlias();
|
||||||
if (!s->isTemplateInstance())
|
if (!s->isTemplateInstance())
|
||||||
goto Lagain;
|
goto Lagain;
|
||||||
e = new ScopeExp(loc, ti);
|
e = new ScopeExp(loc, ti);
|
||||||
@@ -3224,6 +3224,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
|||||||
printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
|
printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
return this;
|
||||||
|
|
||||||
// Run semantic() on each element
|
// Run semantic() on each element
|
||||||
arrayExpressionSemantic(keys, sc);
|
arrayExpressionSemantic(keys, sc);
|
||||||
arrayExpressionSemantic(values, sc);
|
arrayExpressionSemantic(values, sc);
|
||||||
@@ -3232,8 +3235,7 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
|||||||
if (keys->dim != values->dim)
|
if (keys->dim != values->dim)
|
||||||
{
|
{
|
||||||
error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
|
error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
|
||||||
keys->setDim(0);
|
return new ErrorExp();
|
||||||
values->setDim(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *tkey = NULL;
|
Type *tkey = NULL;
|
||||||
@@ -3241,6 +3243,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc)
|
|||||||
keys = arrayExpressionToCommonType(sc, keys, &tkey);
|
keys = arrayExpressionToCommonType(sc, keys, &tkey);
|
||||||
values = arrayExpressionToCommonType(sc, values, &tvalue);
|
values = arrayExpressionToCommonType(sc, values, &tvalue);
|
||||||
|
|
||||||
|
if (tkey == Type::terror || tvalue == Type::terror)
|
||||||
|
return new ErrorExp;
|
||||||
|
|
||||||
type = new TypeAArray(tvalue, tkey);
|
type = new TypeAArray(tvalue, tkey);
|
||||||
type = type->semantic(loc, sc);
|
type = type->semantic(loc, sc);
|
||||||
return this;
|
return this;
|
||||||
@@ -3629,8 +3634,9 @@ Expression *ScopeExp::semantic(Scope *sc)
|
|||||||
#endif
|
#endif
|
||||||
Lagain:
|
Lagain:
|
||||||
ti = sds->isTemplateInstance();
|
ti = sds->isTemplateInstance();
|
||||||
if (ti && !global.errors)
|
if (ti && !ti->errors)
|
||||||
{
|
{
|
||||||
|
unsigned olderrs = global.errors;
|
||||||
if (!ti->semanticRun)
|
if (!ti->semanticRun)
|
||||||
ti->semantic(sc);
|
ti->semantic(sc);
|
||||||
if (ti->inst)
|
if (ti->inst)
|
||||||
@@ -3660,7 +3666,7 @@ Lagain:
|
|||||||
}
|
}
|
||||||
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
|
//printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
|
||||||
}
|
}
|
||||||
if (global.errors)
|
if (olderrs != global.errors)
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -5471,6 +5477,32 @@ void BinExp::incompatibleTypes()
|
|||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
|
Expression *BinAssignExp::semantic(Scope *sc)
|
||||||
|
{ Expression *e;
|
||||||
|
|
||||||
|
//printf("BinAssignExp::semantic()\n");
|
||||||
|
if (type)
|
||||||
|
return this;
|
||||||
|
BinExp::semantic(sc);
|
||||||
|
e2 = resolveProperties(sc, e2);
|
||||||
|
|
||||||
|
e = op_overload(sc);
|
||||||
|
if (e)
|
||||||
|
return e;
|
||||||
|
|
||||||
|
e1 = e1->modifiableLvalue(sc, e1);
|
||||||
|
e1->checkScalar();
|
||||||
|
e1->checkNoBool();
|
||||||
|
type = e1->type;
|
||||||
|
typeCombine(sc);
|
||||||
|
e1->checkIntegral();
|
||||||
|
e2 = e2->checkIntegral();
|
||||||
|
e2 = e2->castTo(sc, Type::tshiftcnt);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************/
|
||||||
|
|
||||||
CompileExp::CompileExp(Loc loc, Expression *e)
|
CompileExp::CompileExp(Loc loc, Expression *e)
|
||||||
: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
|
: UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
|
||||||
{
|
{
|
||||||
@@ -5921,7 +5953,9 @@ Expression *DotIdExp::semantic(Scope *sc)
|
|||||||
if (tup)
|
if (tup)
|
||||||
{
|
{
|
||||||
if (eleft)
|
if (eleft)
|
||||||
error("cannot have e.tuple");
|
{ error("cannot have e.tuple");
|
||||||
|
return new ErrorExp();
|
||||||
|
}
|
||||||
e = new TupleExp(loc, tup);
|
e = new TupleExp(loc, tup);
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
return e;
|
return e;
|
||||||
@@ -5959,7 +5993,12 @@ Expression *DotIdExp::semantic(Scope *sc)
|
|||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
error("undefined identifier %s", toChars());
|
s = ie->sds->search_correct(ident);
|
||||||
|
if (s)
|
||||||
|
error("undefined identifier '%s', did you mean '%s %s'?",
|
||||||
|
ident->toChars(), s->kind(), s->toChars());
|
||||||
|
else
|
||||||
|
error("undefined identifier '%s'", ident->toChars());
|
||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
else if (e1->type->ty == Tpointer &&
|
else if (e1->type->ty == Tpointer &&
|
||||||
@@ -6239,8 +6278,8 @@ L1:
|
|||||||
return e;
|
return e;
|
||||||
if (e->op == TOKdottd)
|
if (e->op == TOKdottd)
|
||||||
{
|
{
|
||||||
if (global.errors)
|
if (ti->errors)
|
||||||
return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
|
return new ErrorExp();
|
||||||
DotTemplateExp *dte = (DotTemplateExp *)e;
|
DotTemplateExp *dte = (DotTemplateExp *)e;
|
||||||
TemplateDeclaration *td = dte->td;
|
TemplateDeclaration *td = dte->td;
|
||||||
eleft = dte->e1;
|
eleft = dte->e1;
|
||||||
@@ -6248,8 +6287,8 @@ L1:
|
|||||||
#if DMDV2
|
#if DMDV2
|
||||||
if (ti->needsTypeInference(sc))
|
if (ti->needsTypeInference(sc))
|
||||||
{
|
{
|
||||||
e = new CallExp(loc, this);
|
e1 = eleft; // save result of semantic()
|
||||||
return e->semantic(sc);
|
return this;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@@ -6451,6 +6490,7 @@ DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f)
|
|||||||
: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
|
: UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
|
||||||
{
|
{
|
||||||
this->func = f;
|
this->func = f;
|
||||||
|
this->hasOverloads = 0;
|
||||||
m = NULL;
|
m = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6828,6 +6868,17 @@ Lagain:
|
|||||||
arrayExpressionSemantic(arguments, sc);
|
arrayExpressionSemantic(arguments, sc);
|
||||||
preFunctionParameters(loc, sc, arguments);
|
preFunctionParameters(loc, sc, arguments);
|
||||||
|
|
||||||
|
// If there was an error processing any template argument,
|
||||||
|
// return an error without trying to resolve the template.
|
||||||
|
if (targsi && targsi->dim)
|
||||||
|
{
|
||||||
|
for (size_t k = 0; k < targsi->dim; k++)
|
||||||
|
{ Object *o = targsi->tdata()[k];
|
||||||
|
if (isError(o))
|
||||||
|
return new ErrorExp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (e1->op == TOKdotvar && t1->ty == Tfunction ||
|
if (e1->op == TOKdotvar && t1->ty == Tfunction ||
|
||||||
e1->op == TOKdottd)
|
e1->op == TOKdottd)
|
||||||
{
|
{
|
||||||
@@ -7336,11 +7387,24 @@ Expression *AddrExp::semantic(Scope *sc)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f && f->isNested())
|
if (f)
|
||||||
{
|
{
|
||||||
Expression *e = new DelegateExp(loc, e1, f);
|
if (f->isNested())
|
||||||
e = e->semantic(sc);
|
{
|
||||||
return e;
|
if (f->isFuncLiteralDeclaration())
|
||||||
|
{
|
||||||
|
if (!f->FuncDeclaration::isNested())
|
||||||
|
{ /* Supply a 'null' for a this pointer if no this is available
|
||||||
|
*/
|
||||||
|
Expression *e = new DelegateExp(loc, new NullExp(loc, Type::tvoidptr), f);
|
||||||
|
e = e->semantic(sc);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expression *e = new DelegateExp(loc, e1, f);
|
||||||
|
e = e->semantic(sc);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (e1->op == TOKarray)
|
else if (e1->op == TOKarray)
|
||||||
@@ -8554,10 +8618,11 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||||||
if (e1->op == TOKarray)
|
if (e1->op == TOKarray)
|
||||||
{
|
{
|
||||||
ArrayExp *ae = (ArrayExp *)e1;
|
ArrayExp *ae = (ArrayExp *)e1;
|
||||||
AggregateDeclaration *ad;
|
AggregateDeclaration *ad = NULL;
|
||||||
Identifier *id = Id::index;
|
Identifier *id = Id::index;
|
||||||
|
|
||||||
ae->e1 = ae->e1->semantic(sc);
|
ae->e1 = ae->e1->semantic(sc);
|
||||||
|
ae->e1 = resolveProperties(sc, ae->e1);
|
||||||
Type *t1 = ae->e1->type->toBasetype();
|
Type *t1 = ae->e1->type->toBasetype();
|
||||||
if (t1->ty == Tstruct)
|
if (t1->ty == Tstruct)
|
||||||
{
|
{
|
||||||
@@ -8585,7 +8650,9 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||||||
{ Expression *e = new DotIdExp(loc, ae->e1, id);
|
{ Expression *e = new DotIdExp(loc, ae->e1, id);
|
||||||
|
|
||||||
if (1 || !global.params.useDeprecated)
|
if (1 || !global.params.useDeprecated)
|
||||||
error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
|
{ error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
|
||||||
|
return new ErrorExp();
|
||||||
|
}
|
||||||
|
|
||||||
e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
|
e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
|
||||||
e = e->semantic(sc);
|
e = e->semantic(sc);
|
||||||
@@ -8601,7 +8668,7 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||||||
if (e1->op == TOKslice)
|
if (e1->op == TOKslice)
|
||||||
{ Type *t1;
|
{ Type *t1;
|
||||||
SliceExp *ae = (SliceExp *)e1;
|
SliceExp *ae = (SliceExp *)e1;
|
||||||
AggregateDeclaration *ad;
|
AggregateDeclaration *ad = NULL;
|
||||||
Identifier *id = Id::index;
|
Identifier *id = Id::index;
|
||||||
|
|
||||||
ae->e1 = ae->e1->semantic(sc);
|
ae->e1 = ae->e1->semantic(sc);
|
||||||
@@ -8697,8 +8764,9 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||||||
* check for operator overloading.
|
* check for operator overloading.
|
||||||
*/
|
*/
|
||||||
if (t1->ty == Tclass || t1->ty == Tstruct)
|
if (t1->ty == Tclass || t1->ty == Tstruct)
|
||||||
{
|
{ // Disallow assignment operator overloads for same type
|
||||||
if (!e2->type->implicitConvTo(e1->type))
|
if (/*op == TOKassign &&*/ // construction shouldn't be allowed, but OK to avoid breaking existing code
|
||||||
|
!e2->implicitConvTo(e1->type))
|
||||||
{
|
{
|
||||||
Expression *e = op_overload(sc);
|
Expression *e = op_overload(sc);
|
||||||
if (e)
|
if (e)
|
||||||
@@ -8725,8 +8793,16 @@ Expression *AssignExp::semantic(Scope *sc)
|
|||||||
e1 = e1->modifiableLvalue(sc, e1old);
|
e1 = e1->modifiableLvalue(sc, e1old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it is a array, get the element type. Note that it may be
|
||||||
|
// multi-dimensional.
|
||||||
|
Type *telem = t1;
|
||||||
|
while (telem->ty == Tarray)
|
||||||
|
telem = telem->nextOf();
|
||||||
|
|
||||||
|
// Check for block assignment. If it is of type void[], void[][], etc,
|
||||||
|
// '= null' is the only allowable block assignment (Bug 7493)
|
||||||
if (e1->op == TOKslice &&
|
if (e1->op == TOKslice &&
|
||||||
t1->nextOf() &&
|
t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) &&
|
||||||
e2->implicitConvTo(t1->nextOf())
|
e2->implicitConvTo(t1->nextOf())
|
||||||
// !(t1->nextOf()->equals(e2->type->nextOf()))
|
// !(t1->nextOf()->equals(e2->type->nextOf()))
|
||||||
)
|
)
|
||||||
@@ -8792,7 +8868,7 @@ ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
|
AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8903,7 +8979,7 @@ Expression *AddAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
|
MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8957,7 +9033,7 @@ Expression *MinAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
|
CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8981,6 +9057,8 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
e1 = e1->modifiableLvalue(sc, e1);
|
e1 = e1->modifiableLvalue(sc, e1);
|
||||||
|
if (e1->op == TOKerror)
|
||||||
|
return e1;
|
||||||
|
|
||||||
Type *tb1 = e1->type->toBasetype();
|
Type *tb1 = e1->type->toBasetype();
|
||||||
Type *tb2 = e2->type->toBasetype();
|
Type *tb2 = e2->type->toBasetype();
|
||||||
@@ -9039,13 +9117,15 @@ Expression *CatAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
|
MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *MulAssignExp::semantic(Scope *sc)
|
Expression *MulAssignExp::semantic(Scope *sc)
|
||||||
{ Expression *e;
|
{ Expression *e;
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
return this;
|
||||||
BinExp::semantic(sc);
|
BinExp::semantic(sc);
|
||||||
e2 = resolveProperties(sc, e2);
|
e2 = resolveProperties(sc, e2);
|
||||||
|
|
||||||
@@ -9117,13 +9197,15 @@ Expression *MulAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
|
DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *DivAssignExp::semantic(Scope *sc)
|
Expression *DivAssignExp::semantic(Scope *sc)
|
||||||
{ Expression *e;
|
{ Expression *e;
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
return this;
|
||||||
BinExp::semantic(sc);
|
BinExp::semantic(sc);
|
||||||
e2 = resolveProperties(sc, e2);
|
e2 = resolveProperties(sc, e2);
|
||||||
|
|
||||||
@@ -9198,12 +9280,14 @@ Expression *DivAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
|
ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ModAssignExp::semantic(Scope *sc)
|
Expression *ModAssignExp::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
|
if (type)
|
||||||
|
return this;
|
||||||
BinExp::semantic(sc);
|
BinExp::semantic(sc);
|
||||||
checkComplexMulAssign();
|
checkComplexMulAssign();
|
||||||
return commonSemanticAssign(sc);
|
return commonSemanticAssign(sc);
|
||||||
@@ -9212,104 +9296,28 @@ Expression *ModAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
|
ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ShlAssignExp::semantic(Scope *sc)
|
|
||||||
{ Expression *e;
|
|
||||||
|
|
||||||
//printf("ShlAssignExp::semantic()\n");
|
|
||||||
BinExp::semantic(sc);
|
|
||||||
e2 = resolveProperties(sc, e2);
|
|
||||||
|
|
||||||
e = op_overload(sc);
|
|
||||||
if (e)
|
|
||||||
return e;
|
|
||||||
|
|
||||||
e1 = e1->modifiableLvalue(sc, e1);
|
|
||||||
e1->checkScalar();
|
|
||||||
e1->checkNoBool();
|
|
||||||
type = e1->type;
|
|
||||||
typeCombine(sc);
|
|
||||||
e1->checkIntegral();
|
|
||||||
e2 = e2->checkIntegral();
|
|
||||||
#if !IN_LLVM
|
|
||||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
|
||||||
#else
|
|
||||||
e2 = e2->castTo(sc, e1->type);
|
|
||||||
#endif
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ShrAssignExp::semantic(Scope *sc)
|
|
||||||
{ Expression *e;
|
|
||||||
|
|
||||||
BinExp::semantic(sc);
|
|
||||||
e2 = resolveProperties(sc, e2);
|
|
||||||
|
|
||||||
e = op_overload(sc);
|
|
||||||
if (e)
|
|
||||||
return e;
|
|
||||||
|
|
||||||
e1 = e1->modifiableLvalue(sc, e1);
|
|
||||||
e1->checkScalar();
|
|
||||||
e1->checkNoBool();
|
|
||||||
type = e1->type;
|
|
||||||
typeCombine(sc);
|
|
||||||
e1->checkIntegral();
|
|
||||||
e2 = e2->checkIntegral();
|
|
||||||
#if !IN_LLVM
|
|
||||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
|
||||||
#else
|
|
||||||
e2 = e2->castTo(sc, e1->type);
|
|
||||||
#endif
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *UshrAssignExp::semantic(Scope *sc)
|
|
||||||
{ Expression *e;
|
|
||||||
|
|
||||||
BinExp::semantic(sc);
|
|
||||||
e2 = resolveProperties(sc, e2);
|
|
||||||
|
|
||||||
e = op_overload(sc);
|
|
||||||
if (e)
|
|
||||||
return e;
|
|
||||||
|
|
||||||
e1 = e1->modifiableLvalue(sc, e1);
|
|
||||||
e1->checkScalar();
|
|
||||||
e1->checkNoBool();
|
|
||||||
type = e1->type;
|
|
||||||
typeCombine(sc);
|
|
||||||
e1->checkIntegral();
|
|
||||||
e2 = e2->checkIntegral();
|
|
||||||
#if !IN_LLVM
|
|
||||||
e2 = e2->castTo(sc, Type::tshiftcnt);
|
|
||||||
#else
|
|
||||||
e2 = e2->castTo(sc, e1->type);
|
|
||||||
#endif
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
|
AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9321,7 +9329,7 @@ Expression *AndAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9333,7 +9341,7 @@ Expression *OrAssignExp::semantic(Scope *sc)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
|
XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
|
||||||
: BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
|
: BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -932,8 +932,12 @@ struct BinExp : Expression
|
|||||||
|
|
||||||
struct BinAssignExp : BinExp
|
struct BinAssignExp : BinExp
|
||||||
{
|
{
|
||||||
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
|
BinAssignExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
|
||||||
int checkSideEffect(int flag);
|
: BinExp(loc, op, size, e1, e2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *semantic(Scope *sc);
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************/
|
/****************************************************************/
|
||||||
@@ -1031,6 +1035,7 @@ struct DelegateExp : UnaExp
|
|||||||
{
|
{
|
||||||
FuncDeclaration *func;
|
FuncDeclaration *func;
|
||||||
Module* m; // starting point for overload resolution
|
Module* m; // starting point for overload resolution
|
||||||
|
int hasOverloads;
|
||||||
|
|
||||||
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
|
DelegateExp(Loc loc, Expression *e, FuncDeclaration *func);
|
||||||
Expression *semantic(Scope *sc);
|
Expression *semantic(Scope *sc);
|
||||||
@@ -1446,10 +1451,10 @@ struct ConstructExp : AssignExp
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ASSIGNEXP(op) \
|
#define ASSIGNEXP(op) \
|
||||||
struct op##AssignExp : BinExp \
|
struct op##AssignExp : BinAssignExp \
|
||||||
{ \
|
{ \
|
||||||
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
|
||||||
Expression *semantic(Scope *sc); \
|
S(Expression *semantic(Scope *sc);) \
|
||||||
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
|
||||||
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
|
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
|
||||||
X(Expression *buildArrayLoop(Parameters *fparams);) \
|
X(Expression *buildArrayLoop(Parameters *fparams);) \
|
||||||
@@ -1460,6 +1465,7 @@ struct op##AssignExp : BinExp \
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define X(a) a
|
#define X(a) a
|
||||||
|
#define S(a) a
|
||||||
ASSIGNEXP(Add)
|
ASSIGNEXP(Add)
|
||||||
ASSIGNEXP(Min)
|
ASSIGNEXP(Min)
|
||||||
ASSIGNEXP(Mul)
|
ASSIGNEXP(Mul)
|
||||||
@@ -1468,15 +1474,28 @@ ASSIGNEXP(Mod)
|
|||||||
ASSIGNEXP(And)
|
ASSIGNEXP(And)
|
||||||
ASSIGNEXP(Or)
|
ASSIGNEXP(Or)
|
||||||
ASSIGNEXP(Xor)
|
ASSIGNEXP(Xor)
|
||||||
|
#undef S
|
||||||
|
|
||||||
|
#if DMDV2
|
||||||
|
#define S(a) a
|
||||||
|
ASSIGNEXP(Pow)
|
||||||
|
#undef S
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
#define X(a)
|
#define X(a)
|
||||||
|
#define S(a)
|
||||||
|
|
||||||
ASSIGNEXP(Shl)
|
ASSIGNEXP(Shl)
|
||||||
ASSIGNEXP(Shr)
|
ASSIGNEXP(Shr)
|
||||||
ASSIGNEXP(Ushr)
|
ASSIGNEXP(Ushr)
|
||||||
|
#undef S
|
||||||
|
|
||||||
|
#define S(a) a
|
||||||
ASSIGNEXP(Cat)
|
ASSIGNEXP(Cat)
|
||||||
|
|
||||||
|
#undef S
|
||||||
#undef X
|
#undef X
|
||||||
#undef ASSIGNEXP
|
#undef ASSIGNEXP
|
||||||
#undef ASSIGNEXP_TOELEM
|
#undef ASSIGNEXP_TOELEM
|
||||||
|
|||||||
38
dmd/func.c
38
dmd/func.c
@@ -1,5 +1,5 @@
|
|||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -306,7 +306,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
(pd = toParent2()) != NULL &&
|
(pd = toParent2()) != NULL &&
|
||||||
(id = pd->isInterfaceDeclaration()) != NULL)
|
(id = pd->isInterfaceDeclaration()) != NULL)
|
||||||
{
|
{
|
||||||
error("template member function not allowed in interface %s", id->toChars());
|
error("template member functions are not allowed in interface %s", id->toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
cd = parent->isClassDeclaration();
|
cd = parent->isClassDeclaration();
|
||||||
@@ -362,6 +362,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
//printf("\tnot virtual\n");
|
//printf("\tnot virtual\n");
|
||||||
goto Ldone;
|
goto Ldone;
|
||||||
}
|
}
|
||||||
|
// Suppress further errors if the return type is an error
|
||||||
|
if (type->nextOf() == Type::terror)
|
||||||
|
goto Ldone;
|
||||||
|
|
||||||
/* Find index of existing function in base class's vtbl[] to override
|
/* Find index of existing function in base class's vtbl[] to override
|
||||||
* (the index will be the same as in cd's current vtbl[])
|
* (the index will be the same as in cd's current vtbl[])
|
||||||
@@ -407,7 +410,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case -2: // can't determine because of fwd refs
|
case -2: // can't determine because of fwd refs
|
||||||
cd->sizeok = 2; // can't finish due to forward reference
|
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||||
Module::dprogress = dprogress_save;
|
Module::dprogress = dprogress_save;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -488,18 +491,26 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case -2:
|
case -2:
|
||||||
cd->sizeok = 2; // can't finish due to forward reference
|
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||||
Module::dprogress = dprogress_save;
|
Module::dprogress = dprogress_save;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.data[vi];
|
{ FuncDeclaration *fdv = (FuncDeclaration *)b->base->vtbl.tdata()[vi];
|
||||||
Type *ti = NULL;
|
Type *ti = NULL;
|
||||||
|
|
||||||
/* Remember which functions this overrides
|
/* Remember which functions this overrides
|
||||||
*/
|
*/
|
||||||
foverrides.push(fdv);
|
foverrides.push(fdv);
|
||||||
|
|
||||||
|
#if DMDV2
|
||||||
|
/* Should we really require 'override' when implementing
|
||||||
|
* an interface function?
|
||||||
|
*/
|
||||||
|
//if (!isOverride())
|
||||||
|
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (fdv->tintro)
|
if (fdv->tintro)
|
||||||
ti = fdv->tintro;
|
ti = fdv->tintro;
|
||||||
else if (!type->equals(fdv->type))
|
else if (!type->equals(fdv->type))
|
||||||
@@ -513,7 +524,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
if (global.endGagging(errors))
|
if (global.endGagging(errors))
|
||||||
{
|
{
|
||||||
// any error in isBaseOf() is a forward reference error, so we bail out
|
// any error in isBaseOf() is a forward reference error, so we bail out
|
||||||
cd->sizeok = 2; // can't finish due to forward reference
|
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
|
||||||
Module::dprogress = dprogress_save;
|
Module::dprogress = dprogress_save;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -524,10 +535,15 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
if (ti)
|
if (ti)
|
||||||
{
|
{
|
||||||
if (tintro && !tintro->equals(ti))
|
if (tintro)
|
||||||
|
{
|
||||||
|
if (!tintro->nextOf()->equals(ti->nextOf()) &&
|
||||||
|
!tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
|
||||||
|
!ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
|
||||||
{
|
{
|
||||||
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
|
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tintro = ti;
|
tintro = ti;
|
||||||
}
|
}
|
||||||
goto L2;
|
goto L2;
|
||||||
@@ -601,7 +617,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
if (f->varargs)
|
if (f->varargs)
|
||||||
{
|
{
|
||||||
Lmainerr:
|
Lmainerr:
|
||||||
error("parameters must be main() or main(char[][] args)");
|
error("parameters must be main() or main(string[] args)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2508,6 +2524,10 @@ int FuncDeclaration::isCodeseg()
|
|||||||
return TRUE; // functions are always in the code segment
|
return TRUE; // functions are always in the code segment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FuncDeclaration::hasOverloads()
|
||||||
|
{
|
||||||
|
return overnext != NULL;
|
||||||
|
}
|
||||||
// Determine if function needs
|
// Determine if function needs
|
||||||
// a static frame pointer to its lexically enclosing function
|
// a static frame pointer to its lexically enclosing function
|
||||||
|
|
||||||
@@ -3175,7 +3195,7 @@ int StaticCtorDeclaration::addPostInvariant()
|
|||||||
|
|
||||||
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||||
{
|
{
|
||||||
if (hgs->hdrgen)
|
if (hgs->hdrgen && !hgs->tpltMember)
|
||||||
{ buf->writestring("static this();");
|
{ buf->writestring("static this();");
|
||||||
buf->writenl();
|
buf->writenl();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -104,15 +104,15 @@ void Html::error(const char *format, ...)
|
|||||||
{
|
{
|
||||||
if (!global.gag)
|
if (!global.gag)
|
||||||
{
|
{
|
||||||
printf("%s(%d) : HTML Error: ", sourcename, linnum);
|
fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum);
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
vprintf(format, ap);
|
vfprintf(stderr, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
printf("\n");
|
fprintf(stderr, "\n");
|
||||||
fflush(stdout);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.errors++;
|
global.errors++;
|
||||||
|
|||||||
26
dmd/import.c
26
dmd/import.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2009 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -79,7 +79,16 @@ void Import::load(Scope *sc)
|
|||||||
|
|
||||||
// See if existing module
|
// See if existing module
|
||||||
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
|
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
|
||||||
|
#if TARGET_NET //dot net needs modules and packages with same name
|
||||||
|
#else
|
||||||
|
if (pkg && pkg->isModule())
|
||||||
|
{
|
||||||
|
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
|
||||||
|
pkg->toChars(), pkg->toPrettyChars(), id->toChars());
|
||||||
|
mod = pkg->isModule(); // Error recovery - treat as import of that module
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Dsymbol *s = dst->lookup(id);
|
Dsymbol *s = dst->lookup(id);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
@@ -89,7 +98,8 @@ void Import::load(Scope *sc)
|
|||||||
if (s->isModule())
|
if (s->isModule())
|
||||||
mod = (Module *)s;
|
mod = (Module *)s;
|
||||||
else
|
else
|
||||||
error("package and module have the same name");
|
::error(loc, "can only import from a module, not from package %s.%s",
|
||||||
|
pkg->toPrettyChars(), id->toChars());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,11 +107,14 @@ void Import::load(Scope *sc)
|
|||||||
{
|
{
|
||||||
// Load module
|
// Load module
|
||||||
mod = Module::load(loc, packages, id);
|
mod = Module::load(loc, packages, id);
|
||||||
|
if (mod)
|
||||||
|
{
|
||||||
dst->insert(id, mod); // id may be different from mod->ident,
|
dst->insert(id, mod); // id may be different from mod->ident,
|
||||||
// if so then insert alias
|
// if so then insert alias
|
||||||
if (!mod->importedFrom)
|
if (!mod->importedFrom)
|
||||||
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!pkg)
|
if (!pkg)
|
||||||
pkg = mod;
|
pkg = mod;
|
||||||
|
|
||||||
@@ -151,7 +164,8 @@ void Import::semantic(Scope *sc)
|
|||||||
// Load if not already done so
|
// Load if not already done so
|
||||||
if (!mod)
|
if (!mod)
|
||||||
{ load(sc);
|
{ load(sc);
|
||||||
mod->importAll(0);
|
if (mod)
|
||||||
|
mod->importAll(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod)
|
if (mod)
|
||||||
@@ -200,7 +214,9 @@ void Import::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
//printf("-Import::semantic('%s'), pkg = %p\n", toChars(), pkg);
|
||||||
|
|
||||||
if (global.params.moduleDeps != NULL)
|
if (global.params.moduleDeps != NULL &&
|
||||||
|
// object self-imports itself, so skip that (Bugzilla 7547)
|
||||||
|
!(id == Id::object && sc->module->ident == Id::object))
|
||||||
{
|
{
|
||||||
/* The grammar of the file is:
|
/* The grammar of the file is:
|
||||||
* ImportDeclaration
|
* ImportDeclaration
|
||||||
|
|||||||
74
dmd/init.c
74
dmd/init.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
|
|||||||
a = new Initializers();
|
a = new Initializers();
|
||||||
a->setDim(ai->dim);
|
a->setDim(ai->dim);
|
||||||
for (size_t i = 0; i < a->dim; i++)
|
for (size_t i = 0; i < a->dim; i++)
|
||||||
{ Initializer *e = (Initializer *)ai->data[i];
|
{ Initializer *e = (*ai)[i];
|
||||||
|
|
||||||
e = e->syntaxCopy();
|
e = e->syntaxCopy();
|
||||||
a->data[i] = e;
|
(*a)[i] = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
@@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy()
|
|||||||
ai->value.setDim(value.dim);
|
ai->value.setDim(value.dim);
|
||||||
for (size_t i = 0; i < field.dim; i++)
|
for (size_t i = 0; i < field.dim; i++)
|
||||||
{
|
{
|
||||||
ai->field.data[i] = field.data[i];
|
ai->field[i] = field[i];
|
||||||
|
|
||||||
Initializer *init = (Initializer *)value.data[i];
|
Initializer *init = value[i];
|
||||||
init = init->syntaxCopy();
|
init = init->syntaxCopy();
|
||||||
ai->value.data[i] = init;
|
ai->value[i] = init;
|
||||||
}
|
}
|
||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
|||||||
s = ad->search(loc, id, 0);
|
s = ad->search(loc, id, 0);
|
||||||
if (!s)
|
if (!s)
|
||||||
{
|
{
|
||||||
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
s = ad->search_correct(id);
|
||||||
|
if (s)
|
||||||
|
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
|
||||||
|
id->toChars(), t->toChars(), s->kind(), s->toChars());
|
||||||
|
else
|
||||||
|
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
|
||||||
errors = 1;
|
errors = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -212,8 +217,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
|||||||
if (s && (v = s->isVarDeclaration()) != NULL)
|
if (s && (v = s->isVarDeclaration()) != NULL)
|
||||||
{
|
{
|
||||||
val = val->semantic(sc, v->type, needInterpret);
|
val = val->semantic(sc, v->type, needInterpret);
|
||||||
value.data[i] = (void *)val;
|
value[i] = val;
|
||||||
vars.data[i] = (void *)v;
|
vars[i] = v;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
|
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
|
||||||
@@ -273,7 +278,7 @@ Expression *StructInitializer::toExpression()
|
|||||||
elements->setDim(nfields);
|
elements->setDim(nfields);
|
||||||
for (size_t i = 0; i < elements->dim; i++)
|
for (size_t i = 0; i < elements->dim; i++)
|
||||||
{
|
{
|
||||||
elements->data[i] = NULL;
|
(*elements)[i] = NULL;
|
||||||
}
|
}
|
||||||
unsigned fieldi = 0;
|
unsigned fieldi = 0;
|
||||||
for (size_t i = 0; i < value.dim; i++)
|
for (size_t i = 0; i < value.dim; i++)
|
||||||
@@ -305,37 +310,37 @@ Expression *StructInitializer::toExpression()
|
|||||||
{ error(loc, "too many initializers for '%s'", ad->toChars());
|
{ error(loc, "too many initializers for '%s'", ad->toChars());
|
||||||
goto Lno;
|
goto Lno;
|
||||||
}
|
}
|
||||||
Initializer *iz = (Initializer *)value.data[i];
|
Initializer *iz = value[i];
|
||||||
if (!iz)
|
if (!iz)
|
||||||
goto Lno;
|
goto Lno;
|
||||||
Expression *ex = iz->toExpression();
|
Expression *ex = iz->toExpression();
|
||||||
if (!ex)
|
if (!ex)
|
||||||
goto Lno;
|
goto Lno;
|
||||||
if (elements->data[fieldi])
|
if ((*elements)[fieldi])
|
||||||
{ error(loc, "duplicate initializer for field '%s'",
|
{ error(loc, "duplicate initializer for field '%s'",
|
||||||
((Dsymbol *)ad->fields.data[fieldi])->toChars());
|
ad->fields[fieldi]->toChars());
|
||||||
goto Lno;
|
goto Lno;
|
||||||
}
|
}
|
||||||
elements->data[fieldi] = ex;
|
(*elements)[fieldi] = ex;
|
||||||
++fieldi;
|
++fieldi;
|
||||||
}
|
}
|
||||||
// Now, fill in any missing elements with default initializers.
|
// Now, fill in any missing elements with default initializers.
|
||||||
// We also need to validate any anonymous unions
|
// We also need to validate any anonymous unions
|
||||||
for (size_t i = 0; i < elements->dim; )
|
for (size_t i = 0; i < elements->dim; )
|
||||||
{
|
{
|
||||||
VarDeclaration * vd = ((Dsymbol *)ad->fields.data[i])->isVarDeclaration();
|
VarDeclaration * vd = ad->fields[i]->isVarDeclaration();
|
||||||
int unionSize = ad->numFieldsInUnion(i);
|
int unionSize = ad->numFieldsInUnion(i);
|
||||||
if (unionSize == 1)
|
if (unionSize == 1)
|
||||||
{ // Not a union -- default initialize if missing
|
{ // Not a union -- default initialize if missing
|
||||||
if (!elements->data[i])
|
if (!(*elements)[i])
|
||||||
elements->data[i] = vd->type->defaultInit();
|
(*elements)[i] = vd->type->defaultInit();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // anonymous union -- check for errors
|
{ // anonymous union -- check for errors
|
||||||
int found = -1; // index of the first field with an initializer
|
int found = -1; // index of the first field with an initializer
|
||||||
for (int j = i; j < i + unionSize; ++j)
|
for (size_t j = i; j < i + unionSize; ++j)
|
||||||
{
|
{
|
||||||
if (!elements->data[j])
|
if (!(*elements)[j])
|
||||||
continue;
|
continue;
|
||||||
if (found >= 0)
|
if (found >= 0)
|
||||||
{
|
{
|
||||||
@@ -375,13 +380,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
buf->writebyte(',');
|
buf->writebyte(',');
|
||||||
Identifier *id = (Identifier *)field.data[i];
|
Identifier *id = field[i];
|
||||||
if (id)
|
if (id)
|
||||||
{
|
{
|
||||||
buf->writestring(id->toChars());
|
buf->writestring(id->toChars());
|
||||||
buf->writebyte(':');
|
buf->writebyte(':');
|
||||||
}
|
}
|
||||||
Initializer *iz = (Initializer *)value.data[i];
|
Initializer *iz = value[i];
|
||||||
if (iz)
|
if (iz)
|
||||||
iz->toCBuffer(buf, hgs);
|
iz->toCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
@@ -408,14 +413,14 @@ Initializer *ArrayInitializer::syntaxCopy()
|
|||||||
ai->index.setDim(index.dim);
|
ai->index.setDim(index.dim);
|
||||||
ai->value.setDim(value.dim);
|
ai->value.setDim(value.dim);
|
||||||
for (size_t i = 0; i < ai->value.dim; i++)
|
for (size_t i = 0; i < ai->value.dim; i++)
|
||||||
{ Expression *e = (Expression *)index.data[i];
|
{ Expression *e = index[i];
|
||||||
if (e)
|
if (e)
|
||||||
e = e->syntaxCopy();
|
e = e->syntaxCopy();
|
||||||
ai->index.data[i] = e;
|
ai->index[i] = e;
|
||||||
|
|
||||||
Initializer *init = (Initializer *)value.data[i];
|
Initializer *init = value[i];
|
||||||
init = init->syntaxCopy();
|
init = init->syntaxCopy();
|
||||||
ai->value.data[i] = init;
|
ai->value[i] = init;
|
||||||
}
|
}
|
||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
@@ -532,7 +537,7 @@ Expression *ArrayInitializer::toExpression()
|
|||||||
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
|
||||||
{
|
{
|
||||||
if (index[i])
|
if (index[i])
|
||||||
j = (index[i])->toInteger();
|
j = index[i]->toInteger();
|
||||||
if (j >= edim)
|
if (j >= edim)
|
||||||
edim = j + 1;
|
edim = j + 1;
|
||||||
}
|
}
|
||||||
@@ -584,6 +589,7 @@ Lno:
|
|||||||
return new ErrorExp();
|
return new ErrorExp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
/********************************
|
||||||
* If possible, convert array initializer to associative array initializer.
|
* If possible, convert array initializer to associative array initializer.
|
||||||
*/
|
*/
|
||||||
@@ -601,18 +607,18 @@ Initializer *ArrayInitializer::toAssocArrayInitializer()
|
|||||||
|
|
||||||
for (size_t i = 0; i < value.dim; i++)
|
for (size_t i = 0; i < value.dim; i++)
|
||||||
{
|
{
|
||||||
e = index.tdata()[i];
|
e = index[i];
|
||||||
if (!e)
|
if (!e)
|
||||||
goto Lno;
|
goto Lno;
|
||||||
keys->tdata()[i] = e;
|
(*keys)[i] = e;
|
||||||
|
|
||||||
Initializer *iz = value.tdata()[i];
|
Initializer *iz = value[i];
|
||||||
if (!iz)
|
if (!iz)
|
||||||
goto Lno;
|
goto Lno;
|
||||||
e = iz->toExpression();
|
e = iz->toExpression();
|
||||||
if (!e)
|
if (!e)
|
||||||
goto Lno;
|
goto Lno;
|
||||||
values->tdata()[i] = e;
|
(*values)[i] = e;
|
||||||
}
|
}
|
||||||
e = new AssocArrayLiteralExp(loc, keys, values);
|
e = new AssocArrayLiteralExp(loc, keys, values);
|
||||||
return new ExpInitializer(loc, e);
|
return new ExpInitializer(loc, e);
|
||||||
@@ -668,13 +674,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
{
|
{
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
buf->writebyte(',');
|
buf->writebyte(',');
|
||||||
Expression *ex = index.tdata()[i];
|
Expression *ex = index[i];
|
||||||
if (ex)
|
if (ex)
|
||||||
{
|
{
|
||||||
ex->toCBuffer(buf, hgs);
|
ex->toCBuffer(buf, hgs);
|
||||||
buf->writebyte(':');
|
buf->writebyte(':');
|
||||||
}
|
}
|
||||||
Initializer *iz = value.tdata()[i];
|
Initializer *iz = value[i];
|
||||||
if (iz)
|
if (iz)
|
||||||
iz->toCBuffer(buf, hgs);
|
iz->toCBuffer(buf, hgs);
|
||||||
}
|
}
|
||||||
@@ -707,7 +713,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
|
|||||||
return this; // Failed, suppress duplicate error messages
|
return this; // Failed, suppress duplicate error messages
|
||||||
|
|
||||||
if (exp->op == TOKtype)
|
if (exp->op == TOKtype)
|
||||||
error("initializer must be an expression, not '%s'", exp->toChars());
|
exp->error("initializer must be an expression, not '%s'", exp->toChars());
|
||||||
Type *tb = t->toBasetype();
|
Type *tb = t->toBasetype();
|
||||||
|
|
||||||
/* Look for case of initializing a static array with a too-short
|
/* Look for case of initializing a static array with a too-short
|
||||||
@@ -767,7 +773,7 @@ Type *ExpInitializer::inferType(Scope *sc)
|
|||||||
// Give error for overloaded function addresses
|
// Give error for overloaded function addresses
|
||||||
if (exp->op == TOKdelegate)
|
if (exp->op == TOKdelegate)
|
||||||
{ DelegateExp *se = (DelegateExp *)exp;
|
{ DelegateExp *se = (DelegateExp *)exp;
|
||||||
if (
|
if (se->hasOverloads &&
|
||||||
se->func->isFuncDeclaration() &&
|
se->func->isFuncDeclaration() &&
|
||||||
!se->func->isFuncDeclaration()->isUnique())
|
!se->func->isFuncDeclaration()->isUnique())
|
||||||
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
|
||||||
|
|||||||
22
dmd/inline.c
22
dmd/inline.c
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -196,6 +196,8 @@ int lambdaInlineCost(Expression *e, void *param)
|
|||||||
|
|
||||||
int expressionInlineCost(Expression *e, InlineCostState *ics)
|
int expressionInlineCost(Expression *e, InlineCostState *ics)
|
||||||
{
|
{
|
||||||
|
//printf("expressionInlineCost()\n");
|
||||||
|
//e->dump(0);
|
||||||
ICS2 ics2;
|
ICS2 ics2;
|
||||||
ics2.cost = 0;
|
ics2.cost = 0;
|
||||||
ics2.ics = ics;
|
ics2.ics = ics;
|
||||||
@@ -340,6 +342,7 @@ struct InlineDoState
|
|||||||
Dsymbols from; // old Dsymbols
|
Dsymbols from; // old Dsymbols
|
||||||
Dsymbols to; // parallel array of new Dsymbols
|
Dsymbols to; // parallel array of new Dsymbols
|
||||||
Dsymbol *parent; // new parent
|
Dsymbol *parent; // new parent
|
||||||
|
FuncDeclaration *fd; // function being inlined (old parent)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
@@ -1486,6 +1489,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
|
|||||||
if (
|
if (
|
||||||
!fbody ||
|
!fbody ||
|
||||||
ident == Id::ensure || // ensure() has magic properties the inliner loses
|
ident == Id::ensure || // ensure() has magic properties the inliner loses
|
||||||
|
(ident == Id::require && // require() has magic properties too
|
||||||
|
toParent()->isFuncDeclaration() && // see bug 7699
|
||||||
|
toParent()->isFuncDeclaration()->needThis()) ||
|
||||||
!hdrscan &&
|
!hdrscan &&
|
||||||
(
|
(
|
||||||
#if 0
|
#if 0
|
||||||
@@ -1600,6 +1606,7 @@ Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethi
|
|||||||
|
|
||||||
memset(&ids, 0, sizeof(ids));
|
memset(&ids, 0, sizeof(ids));
|
||||||
ids.parent = iss->fd;
|
ids.parent = iss->fd;
|
||||||
|
ids.fd = this;
|
||||||
|
|
||||||
if (ps)
|
if (ps)
|
||||||
as = new Statements();
|
as = new Statements();
|
||||||
@@ -1786,6 +1793,18 @@ Expression *Expression::inlineCopy(Scope *sc)
|
|||||||
*/
|
*/
|
||||||
return copy();
|
return copy();
|
||||||
#else
|
#else
|
||||||
|
if (op == TOKdelegate)
|
||||||
|
{ DelegateExp *de = (DelegateExp *)this;
|
||||||
|
|
||||||
|
if (de->func->isNested())
|
||||||
|
{ /* See Bugzilla 4820
|
||||||
|
* Defer checking until later if we actually need the 'this' pointer
|
||||||
|
*/
|
||||||
|
Expression *e = de->copy();
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InlineCostState ics;
|
InlineCostState ics;
|
||||||
|
|
||||||
memset(&ics, 0, sizeof(ics));
|
memset(&ics, 0, sizeof(ics));
|
||||||
@@ -1802,3 +1821,4 @@ Expression *Expression::inlineCopy(Scope *sc)
|
|||||||
return e;
|
return e;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
390
dmd/interpret.c
390
dmd/interpret.c
@@ -27,7 +27,6 @@
|
|||||||
#include "attrib.h" // for AttribDeclaration
|
#include "attrib.h" // for AttribDeclaration
|
||||||
|
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd);
|
|
||||||
|
|
||||||
|
|
||||||
#define LOG 0
|
#define LOG 0
|
||||||
@@ -45,6 +44,10 @@ private:
|
|||||||
together with the VarDeclaration, and the previous
|
together with the VarDeclaration, and the previous
|
||||||
stack address of that variable, so that we can restore it
|
stack address of that variable, so that we can restore it
|
||||||
when we leave the stack frame.
|
when we leave the stack frame.
|
||||||
|
Note that when a function is forward referenced, the interpreter must
|
||||||
|
run semantic3, and that may start CTFE again with a NULL istate. Thus
|
||||||
|
the stack might not be empty when CTFE begins.
|
||||||
|
|
||||||
Ctfe Stack addresses are just 0-based integers, but we save
|
Ctfe Stack addresses are just 0-based integers, but we save
|
||||||
them as 'void *' because ArrayBase can only do pointers.
|
them as 'void *' because ArrayBase can only do pointers.
|
||||||
*/
|
*/
|
||||||
@@ -143,7 +146,11 @@ public:
|
|||||||
}
|
}
|
||||||
void saveGlobalConstant(VarDeclaration *v, Expression *e)
|
void saveGlobalConstant(VarDeclaration *v, Expression *e)
|
||||||
{
|
{
|
||||||
assert(v->isDataseg() && !v->isCTFE());
|
#if DMDV2
|
||||||
|
assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE());
|
||||||
|
#else
|
||||||
|
assert( v->init && v->isConst() && !v->isCTFE());
|
||||||
|
#endif
|
||||||
v->ctfeAdrOnStack = globalValues.dim;
|
v->ctfeAdrOnStack = globalValues.dim;
|
||||||
globalValues.push(e);
|
globalValues.push(e);
|
||||||
}
|
}
|
||||||
@@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval);
|
|||||||
bool needToCopyLiteral(Expression *expr);
|
bool needToCopyLiteral(Expression *expr);
|
||||||
Expression *copyLiteral(Expression *e);
|
Expression *copyLiteral(Expression *e);
|
||||||
Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
|
Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
|
||||||
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2);
|
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
|
||||||
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
|
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
|
||||||
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
|
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
|
||||||
Expression *scrubReturnValue(Loc loc, Expression *e);
|
Expression *scrubReturnValue(Loc loc, Expression *e);
|
||||||
@@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression
|
|||||||
{
|
{
|
||||||
return value->sd->isClassDeclaration();
|
return value->sd->isClassDeclaration();
|
||||||
}
|
}
|
||||||
|
VarDeclaration *getFieldAt(int index)
|
||||||
|
{
|
||||||
|
ClassDeclaration *cd = originalClass();
|
||||||
|
size_t fieldsSoFar = 0;
|
||||||
|
while (index - fieldsSoFar >= cd->fields.dim)
|
||||||
|
{ fieldsSoFar += cd->fields.dim;
|
||||||
|
cd = cd->baseClass;
|
||||||
|
}
|
||||||
|
return cd->fields.tdata()[index - fieldsSoFar];
|
||||||
|
}
|
||||||
// Return index of the field, or -1 if not found
|
// Return index of the field, or -1 if not found
|
||||||
int getFieldIndex(Type *fieldtype, size_t fieldoffset)
|
int getFieldIndex(Type *fieldtype, size_t fieldoffset)
|
||||||
{
|
{
|
||||||
@@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VoidInitExp : Expression
|
||||||
|
{
|
||||||
|
VarDeclaration *var;
|
||||||
|
|
||||||
|
VoidInitExp(VarDeclaration *var, Type *type)
|
||||||
|
: Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
|
||||||
|
{
|
||||||
|
this->var = var;
|
||||||
|
this->type = var->type;
|
||||||
|
}
|
||||||
|
char *toChars()
|
||||||
|
{
|
||||||
|
return (char *)"void";
|
||||||
|
}
|
||||||
|
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue)
|
||||||
|
{
|
||||||
|
error("CTFE internal error: trying to read uninitialized variable");
|
||||||
|
assert(0);
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Return index of the field, or -1 if not found
|
// Return index of the field, or -1 if not found
|
||||||
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
|
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
|
||||||
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
|
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
|
||||||
@@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0)
|
|||||||
* arguments function arguments
|
* arguments function arguments
|
||||||
* thisarg 'this', if a needThis() function, NULL if not.
|
* thisarg 'this', if a needThis() function, NULL if not.
|
||||||
*
|
*
|
||||||
* Return result expression if successful, EXP_CANT_INTERPRET if not.
|
* Return result expression if successful, EXP_CANT_INTERPRET if not,
|
||||||
|
* or EXP_VOID_INTERPRET if function returned void.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
|
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
|
||||||
@@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
*/
|
*/
|
||||||
int olderrors = global.errors;
|
int olderrors = global.errors;
|
||||||
int oldgag = global.gag;
|
int oldgag = global.gag;
|
||||||
TemplateInstance *spec = isSpeculativeFunction(this);
|
TemplateInstance *spec = isSpeculative();
|
||||||
if (global.gag && !spec)
|
if (global.gag && !spec)
|
||||||
global.gag = 0;
|
global.gag = 0;
|
||||||
semantic3(scope);
|
semantic3(scope);
|
||||||
@@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
--evaluatingArgs;
|
--evaluatingArgs;
|
||||||
if (earg == EXP_CANT_INTERPRET)
|
if (earg == EXP_CANT_INTERPRET)
|
||||||
return earg;
|
return earg;
|
||||||
|
/* Struct literals are passed by value, but we don't need to
|
||||||
|
* copy them if they are passed as const
|
||||||
|
*/
|
||||||
|
if (earg->op == TOKstructliteral
|
||||||
|
#if DMDV2
|
||||||
|
&& !(arg->storageClass & (STCconst | STCimmutable))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
earg = copyLiteral(earg);
|
||||||
}
|
}
|
||||||
if (earg->op == TOKthrownexception)
|
if (earg->op == TOKthrownexception)
|
||||||
{
|
{
|
||||||
@@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
// If fell off the end of a void function, return void
|
// If fell off the end of a void function, return void
|
||||||
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
|
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
|
||||||
return EXP_VOID_INTERPRET;
|
return EXP_VOID_INTERPRET;
|
||||||
|
|
||||||
|
// If result is void, return void
|
||||||
|
if (e == EXP_VOID_INTERPRET)
|
||||||
|
return e;
|
||||||
|
|
||||||
// If it generated an exception, return it
|
// If it generated an exception, return it
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
{
|
{
|
||||||
@@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
((ThrownExceptionExp *)e)->generateUncaughtError();
|
((ThrownExceptionExp *)e)->generateUncaughtError();
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're about to leave CTFE, make sure we don't crash the
|
||||||
|
// compiler by returning a CTFE-internal expression.
|
||||||
if (!istate && !evaluatingArgs)
|
if (!istate && !evaluatingArgs)
|
||||||
{
|
{
|
||||||
e = scrubReturnValue(loc, e);
|
e = scrubReturnValue(loc, e);
|
||||||
@@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// As Equal, but resolves slices before comparing
|
// As Equal, but resolves slices before comparing
|
||||||
Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2)
|
||||||
{
|
{
|
||||||
if (e1->op == TOKslice)
|
if (e1->op == TOKslice)
|
||||||
e1 = resolveSlice(e1);
|
e1 = resolveSlice(e1);
|
||||||
if (e2->op == TOKslice)
|
if (e2->op == TOKslice)
|
||||||
e2 = resolveSlice(e2);
|
e2 = resolveSlice(e2);
|
||||||
return Equal(op, type, e1, e2);
|
Expression *e = Equal(op, type, e1, e2);
|
||||||
|
if (e == EXP_CANT_INTERPRET)
|
||||||
|
error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars());
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
||||||
@@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
|
|||||||
return Cat(type, e1, e2);
|
return Cat(type, e1, e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrubArray(Loc loc, Expressions *elems);
|
bool scrubArray(Loc loc, Expressions *elems, bool structlit = false);
|
||||||
|
|
||||||
/* All results destined for use outside of CTFE need to have their CTFE-specific
|
/* All results destined for use outside of CTFE need to have their CTFE-specific
|
||||||
* features removed.
|
* features removed.
|
||||||
@@ -986,6 +1046,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
|||||||
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
|
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
|
if (e->op == TOKvoid)
|
||||||
|
{
|
||||||
|
error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
|
||||||
|
e = new ErrorExp();
|
||||||
|
}
|
||||||
if (e->op == TOKslice)
|
if (e->op == TOKslice)
|
||||||
{
|
{
|
||||||
e = resolveSlice(e);
|
e = resolveSlice(e);
|
||||||
@@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
|||||||
{
|
{
|
||||||
StructLiteralExp *se = (StructLiteralExp *)e;
|
StructLiteralExp *se = (StructLiteralExp *)e;
|
||||||
se->ownedByCtfe = false;
|
se->ownedByCtfe = false;
|
||||||
scrubArray(loc, se->elements);
|
if (!scrubArray(loc, se->elements, true))
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
if (e->op == TOKstring)
|
if (e->op == TOKstring)
|
||||||
{
|
{
|
||||||
@@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
|
|||||||
if (e->op == TOKarrayliteral)
|
if (e->op == TOKarrayliteral)
|
||||||
{
|
{
|
||||||
((ArrayLiteralExp *)e)->ownedByCtfe = false;
|
((ArrayLiteralExp *)e)->ownedByCtfe = false;
|
||||||
scrubArray(loc, ((ArrayLiteralExp *)e)->elements);
|
if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
if (e->op == TOKassocarrayliteral)
|
if (e->op == TOKassocarrayliteral)
|
||||||
{
|
{
|
||||||
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
|
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
|
||||||
aae->ownedByCtfe = false;
|
aae->ownedByCtfe = false;
|
||||||
scrubArray(loc, aae->keys);
|
if (!scrubArray(loc, aae->keys))
|
||||||
scrubArray(loc, aae->values);
|
return EXP_CANT_INTERPRET;
|
||||||
|
if (!scrubArray(loc, aae->values))
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scrub all members of an array
|
// Scrub all members of an array. Return false if error
|
||||||
void scrubArray(Loc loc, Expressions *elems)
|
bool scrubArray(Loc loc, Expressions *elems, bool structlit)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < elems->dim; i++)
|
for (size_t i = 0; i < elems->dim; i++)
|
||||||
{
|
{
|
||||||
Expression *m = elems->tdata()[i];
|
Expression *m = elems->tdata()[i];
|
||||||
if (!m)
|
if (!m)
|
||||||
continue;
|
continue;
|
||||||
m = scrubReturnValue(loc, m);
|
if (m && m->op == TOKvoid && structlit)
|
||||||
|
m = NULL;
|
||||||
|
if (m)
|
||||||
|
m = scrubReturnValue(loc, m);
|
||||||
|
if (m == EXP_CANT_INTERPRET)
|
||||||
|
return false;
|
||||||
elems->tdata()[i] = m;
|
elems->tdata()[i] = m;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate)
|
|||||||
Expression * caseExp = cs->exp->interpret(istate);
|
Expression * caseExp = cs->exp->interpret(istate);
|
||||||
if (exceptionOrCantInterpret(caseExp))
|
if (exceptionOrCantInterpret(caseExp))
|
||||||
return caseExp;
|
return caseExp;
|
||||||
e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp);
|
e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp);
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
return e;
|
return e;
|
||||||
if (e->isBool(TRUE))
|
if (e->isBool(TRUE))
|
||||||
@@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate)
|
|||||||
ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
|
ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
|
||||||
Type *extype = ex->thrown->originalClass()->type;
|
Type *extype = ex->thrown->originalClass()->type;
|
||||||
// Search for an appropriate catch clause.
|
// Search for an appropriate catch clause.
|
||||||
for (size_t i = 0; i < catches->dim; i++)
|
for (size_t i = 0; i < catches->dim; i++)
|
||||||
{
|
{
|
||||||
#if DMDV1
|
#if DMDV1
|
||||||
Catch *ca = (Catch *)catches->data[i];
|
Catch *ca = (Catch *)catches->data[i];
|
||||||
#else
|
#else
|
||||||
Catch *ca = catches->tdata()[i];
|
Catch *ca = catches->tdata()[i];
|
||||||
#endif
|
#endif
|
||||||
Type *catype = ca->type;
|
Type *catype = ca->type;
|
||||||
|
|
||||||
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
|
||||||
{ // Execute the handler
|
{ // Execute the handler
|
||||||
if (ca->var)
|
if (ca->var)
|
||||||
{
|
{
|
||||||
ctfeStack.push(ca->var);
|
ctfeStack.push(ca->var);
|
||||||
ca->var->setValue(ex->thrown);
|
ca->var->setValue(ex->thrown);
|
||||||
}
|
}
|
||||||
return ca->handler->interpret(istate);
|
return ca->handler ? ca->handler->interpret(istate) : NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
Type *pointee = ((TypePointer *)type)->next;
|
Type *pointee = ((TypePointer *)type)->next;
|
||||||
Expression *val = getVarExp(loc, istate, var, goal);
|
Expression *val = getVarExp(loc, istate, var, goal);
|
||||||
|
if (val == EXP_CANT_INTERPRET)
|
||||||
|
return val;
|
||||||
if (val->type->ty == Tarray || val->type->ty == Tsarray)
|
if (val->type->ty == Tarray || val->type->ty == Tsarray)
|
||||||
{
|
{
|
||||||
// Check for unsupported type painting operations
|
// Check for unsupported type painting operations
|
||||||
@@ -1907,10 +1984,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
|||||||
if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception)
|
if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception)
|
||||||
{
|
{
|
||||||
e = copyLiteral(e);
|
e = copyLiteral(e);
|
||||||
if (v->isDataseg())
|
ctfeStack.saveGlobalConstant(v, e);
|
||||||
ctfeStack.saveGlobalConstant(v, e);
|
|
||||||
else
|
|
||||||
v->setValueWithoutChecking(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (v->isCTFE() && !v->hasValue())
|
else if (v->isCTFE() && !v->hasValue())
|
||||||
@@ -1919,11 +1993,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
|||||||
{
|
{
|
||||||
if (v->init->isVoidInitializer())
|
if (v->init->isVoidInitializer())
|
||||||
{
|
{
|
||||||
error(loc, "variable %s is used before initialization", v->toChars());
|
// var should have been initialized when it was created
|
||||||
return EXP_CANT_INTERPRET;
|
error(loc, "CTFE internal error - trying to access uninitialized var");
|
||||||
|
assert(0);
|
||||||
|
e = EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e = v->init->toExpression();
|
||||||
|
e = e->interpret(istate);
|
||||||
}
|
}
|
||||||
e = v->init->toExpression();
|
|
||||||
e = e->interpret(istate);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
e = v->type->defaultInitLiteral(loc);
|
e = v->type->defaultInitLiteral(loc);
|
||||||
@@ -1939,7 +2018,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
|||||||
e = EXP_CANT_INTERPRET;
|
e = EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
else if (!e)
|
else if (!e)
|
||||||
error(loc, "variable %s is used before initialization", v->toChars());
|
{
|
||||||
|
assert(0);
|
||||||
|
assert(v->init && v->init->isVoidInitializer());
|
||||||
|
e = v->type->voidInitLiteral(v);
|
||||||
|
}
|
||||||
else if (exceptionOrCantInterpret(e))
|
else if (exceptionOrCantInterpret(e))
|
||||||
return e;
|
return e;
|
||||||
else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex)
|
else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex)
|
||||||
@@ -1958,6 +2041,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
|||||||
|| e->op == TOKassocarrayliteral || e->op == TOKslice
|
|| e->op == TOKassocarrayliteral || e->op == TOKslice
|
||||||
|| e->type->toBasetype()->ty == Tpointer)
|
|| e->type->toBasetype()->ty == Tpointer)
|
||||||
return e; // it's already an Lvalue
|
return e; // it's already an Lvalue
|
||||||
|
else if (e->op == TOKvoid)
|
||||||
|
{
|
||||||
|
VoidInitExp *ve = (VoidInitExp *)e;
|
||||||
|
error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars());
|
||||||
|
errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars());
|
||||||
|
e = EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
e = e->interpret(istate, goal);
|
e = e->interpret(istate, goal);
|
||||||
}
|
}
|
||||||
@@ -1971,10 +2061,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|
|||||||
if (s->dsym->toInitializer() == s->sym)
|
if (s->dsym->toInitializer() == s->sym)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
e = s->dsym->type->defaultInitLiteral();
|
e = s->dsym->type->defaultInitLiteral(loc);
|
||||||
e = e->semantic(NULL);
|
e = e->semantic(NULL);
|
||||||
if (e->op == TOKerror)
|
if (e->op == TOKerror)
|
||||||
e = EXP_CANT_INTERPRET;
|
e = EXP_CANT_INTERPRET;
|
||||||
|
else // Convert NULL to VoidExp
|
||||||
|
e = e->interpret(istate, goal);
|
||||||
#if !IN_LLVM
|
#if !IN_LLVM
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2045,7 +2137,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (ie)
|
if (ie)
|
||||||
e = ie->exp->interpret(istate);
|
e = ie->exp->interpret(istate);
|
||||||
else if (v->init->isVoidInitializer())
|
else if (v->init->isVoidInitializer())
|
||||||
e = NULL;
|
{
|
||||||
|
e = v->type->voidInitLiteral(v);
|
||||||
|
// There is no AssignExp for void initializers,
|
||||||
|
// so set it here.
|
||||||
|
v->setValue(e);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||||
@@ -2274,7 +2371,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
ekey = resolveSlice(ekey);
|
ekey = resolveSlice(ekey);
|
||||||
for (size_t j = i; j < keysx->dim; j++)
|
for (size_t j = i; j < keysx->dim; j++)
|
||||||
{ Expression *ekey2 = keysx->tdata()[j];
|
{ Expression *ekey2 = keysx->tdata()[j];
|
||||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2);
|
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2);
|
||||||
if (ex == EXP_CANT_INTERPRET)
|
if (ex == EXP_CANT_INTERPRET)
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
if (ex->isBool(TRUE)) // if a match
|
if (ex->isBool(TRUE)) // if a match
|
||||||
@@ -2448,10 +2545,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
|
|||||||
if (elemType->ty == Tchar || elemType->ty == Twchar
|
if (elemType->ty == Tchar || elemType->ty == Twchar
|
||||||
|| elemType->ty == Tdchar)
|
|| elemType->ty == Tdchar)
|
||||||
return createBlockDuplicatedStringLiteral(loc, newtype,
|
return createBlockDuplicatedStringLiteral(loc, newtype,
|
||||||
(unsigned)(elemType->defaultInitLiteral()->toInteger()),
|
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
|
||||||
len, elemType->size());
|
len, elemType->size());
|
||||||
return createBlockDuplicatedArrayLiteral(loc, newtype,
|
return createBlockDuplicatedArrayLiteral(loc, newtype,
|
||||||
elemType->defaultInitLiteral(),
|
elemType->defaultInitLiteral(loc),
|
||||||
len);
|
len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2465,7 +2562,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
|
|
||||||
if (newtype->toBasetype()->ty == Tstruct)
|
if (newtype->toBasetype()->ty == Tstruct)
|
||||||
{
|
{
|
||||||
Expression *se = newtype->defaultInitLiteral();
|
Expression *se = newtype->defaultInitLiteral(loc);
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
if (member)
|
if (member)
|
||||||
{
|
{
|
||||||
@@ -2502,7 +2599,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
Dsymbol *s = c->fields.tdata()[i];
|
Dsymbol *s = c->fields.tdata()[i];
|
||||||
VarDeclaration *v = s->isVarDeclaration();
|
VarDeclaration *v = s->isVarDeclaration();
|
||||||
assert(v);
|
assert(v);
|
||||||
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral();
|
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc);
|
||||||
if (exceptionOrCantInterpret(m))
|
if (exceptionOrCantInterpret(m))
|
||||||
return m;
|
return m;
|
||||||
elems->tdata()[fieldsSoFar+i] = copyLiteral(m);
|
elems->tdata()[fieldsSoFar+i] = copyLiteral(m);
|
||||||
@@ -2672,7 +2769,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
|
|||||||
}
|
}
|
||||||
if (indx < 0 || indx > len)
|
if (indx < 0 || indx > len)
|
||||||
{
|
{
|
||||||
error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len);
|
error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2974,7 +3071,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi
|
|||||||
for (size_t j = valuesx->dim; j; )
|
for (size_t j = valuesx->dim; j; )
|
||||||
{ j--;
|
{ j--;
|
||||||
Expression *ekey = aae->keys->tdata()[j];
|
Expression *ekey = aae->keys->tdata()[j];
|
||||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
|
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
|
||||||
if (exceptionOrCantInterpret(ex))
|
if (exceptionOrCantInterpret(ex))
|
||||||
return ex;
|
return ex;
|
||||||
if (ex->isBool(TRUE))
|
if (ex->isBool(TRUE))
|
||||||
@@ -3144,7 +3241,7 @@ Expression *copyLiteral(Expression *e)
|
|||||||
assert(v);
|
assert(v);
|
||||||
// If it is a void assignment, use the default initializer
|
// If it is a void assignment, use the default initializer
|
||||||
if (!m)
|
if (!m)
|
||||||
m = v->type->defaultInitLiteral(e->loc);
|
m = v->type->voidInitLiteral(v);
|
||||||
if (m->op == TOKslice)
|
if (m->op == TOKslice)
|
||||||
m = resolveSlice(m);
|
m = resolveSlice(m);
|
||||||
if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
|
if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
|
||||||
@@ -3171,7 +3268,8 @@ Expression *copyLiteral(Expression *e)
|
|||||||
|| e->op == TOKsymoff || e->op == TOKnull
|
|| e->op == TOKsymoff || e->op == TOKnull
|
||||||
|| e->op == TOKvar
|
|| e->op == TOKvar
|
||||||
|| e->op == TOKint64 || e->op == TOKfloat64
|
|| e->op == TOKint64 || e->op == TOKfloat64
|
||||||
|| e->op == TOKchar || e->op == TOKcomplex80)
|
|| e->op == TOKchar || e->op == TOKcomplex80
|
||||||
|
|| e->op == TOKvoid)
|
||||||
{ // Simple value types
|
{ // Simple value types
|
||||||
Expression *r = e->syntaxCopy();
|
Expression *r = e->syntaxCopy();
|
||||||
r->type = e->type;
|
r->type = e->type;
|
||||||
@@ -3341,7 +3439,7 @@ void assignInPlace(Expression *dest, Expression *src)
|
|||||||
assert(o->op == e->op);
|
assert(o->op == e->op);
|
||||||
assignInPlace(o, e);
|
assignInPlace(o, e);
|
||||||
}
|
}
|
||||||
else if (e->type->ty == Tsarray && o->type->ty == Tsarray)
|
else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid)
|
||||||
{
|
{
|
||||||
assignInPlace(o, e);
|
assignInPlace(o, e);
|
||||||
}
|
}
|
||||||
@@ -3636,7 +3734,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
Type *elemType= NULL;
|
Type *elemType= NULL;
|
||||||
elemType = ((TypeArray *)t)->next;
|
elemType = ((TypeArray *)t)->next;
|
||||||
assert(elemType);
|
assert(elemType);
|
||||||
Expression *defaultElem = elemType->defaultInitLiteral();
|
Expression *defaultElem = elemType->defaultInitLiteral(loc);
|
||||||
|
|
||||||
Expressions *elements = new Expressions();
|
Expressions *elements = new Expressions();
|
||||||
elements->setDim(newlen);
|
elements->setDim(newlen);
|
||||||
@@ -3744,7 +3842,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
// only modifying part of the variable. So we need to make sure
|
// only modifying part of the variable. So we need to make sure
|
||||||
// that the parent variable exists.
|
// that the parent variable exists.
|
||||||
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
|
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
|
||||||
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral()));
|
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc)));
|
||||||
|
|
||||||
// ---------------------------------------
|
// ---------------------------------------
|
||||||
// Deal with reference assignment
|
// Deal with reference assignment
|
||||||
@@ -3822,7 +3920,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
indx = resolveSlice(indx);
|
indx = resolveSlice(indx);
|
||||||
|
|
||||||
// Look up this index in it up in the existing AA, to get the next level of AA.
|
// Look up this index in it up in the existing AA, to get the next level of AA.
|
||||||
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx);
|
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx);
|
||||||
if (exceptionOrCantInterpret(newAA))
|
if (exceptionOrCantInterpret(newAA))
|
||||||
return newAA;
|
return newAA;
|
||||||
if (!newAA)
|
if (!newAA)
|
||||||
@@ -3968,14 +4066,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
? (StructLiteralExp *)exx
|
? (StructLiteralExp *)exx
|
||||||
: ((ClassReferenceExp *)exx)->value;
|
: ((ClassReferenceExp *)exx)->value;
|
||||||
int fieldi = exx->op == TOKstructliteral
|
int fieldi = exx->op == TOKstructliteral
|
||||||
? se->getFieldIndex(member->type, member->offset)
|
? findFieldIndexByName(se->sd, member)
|
||||||
: ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset);
|
: ((ClassReferenceExp *)exx)->findFieldIndexByName(member);
|
||||||
if (fieldi == -1)
|
if (fieldi == -1)
|
||||||
{
|
{
|
||||||
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
|
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
assert(fieldi>=0 && fieldi < se->elements->dim);
|
assert(fieldi >= 0 && fieldi < se->elements->dim);
|
||||||
|
// If it's a union, set all other members of this union to void
|
||||||
|
if (exx->op == TOKstructliteral)
|
||||||
|
{
|
||||||
|
assert(se->sd);
|
||||||
|
int unionStart = se->sd->firstFieldInUnion(fieldi);
|
||||||
|
int unionSize = se->sd->numFieldsInUnion(fieldi);
|
||||||
|
for(int i = unionStart; i < unionStart + unionSize; ++i)
|
||||||
|
{ if (i == fieldi)
|
||||||
|
continue;
|
||||||
|
Expression **el = &se->elements->tdata()[i];
|
||||||
|
if ((*el)->op != TOKvoid)
|
||||||
|
*el = (*el)->type->voidInitLiteral(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (newval->op == TOKstructliteral)
|
if (newval->op == TOKstructliteral)
|
||||||
assignInPlace(se->elements->tdata()[fieldi], newval);
|
assignInPlace(se->elements->tdata()[fieldi], newval);
|
||||||
else
|
else
|
||||||
@@ -4050,6 +4163,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
}
|
}
|
||||||
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
||||||
indexToModify += ofs;
|
indexToModify += ofs;
|
||||||
|
if (aggregate->op != TOKslice && aggregate->op != TOKstring &&
|
||||||
|
aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral)
|
||||||
|
{
|
||||||
|
if (indexToModify != 0)
|
||||||
|
{
|
||||||
|
error("pointer index [%lld] lies outside memory block [0..1]", indexToModify);
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
// It is equivalent to *aggregate = newval.
|
||||||
|
// Aggregate could be varexp, a dotvar, ...
|
||||||
|
// TODO: we could support this
|
||||||
|
error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead",
|
||||||
|
ie->e1->toChars(), e2->toChars());
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
destarraylen = resolveArrayLength(aggregate);
|
destarraylen = resolveArrayLength(aggregate);
|
||||||
}
|
}
|
||||||
if (indexToModify >= destarraylen)
|
if (indexToModify >= destarraylen)
|
||||||
@@ -4075,7 +4203,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
||||||
{
|
{
|
||||||
IndexExp *ix = (IndexExp *)aggregate;
|
IndexExp *ix = (IndexExp *)aggregate;
|
||||||
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
|
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||||
if (!aggregate)
|
if (!aggregate)
|
||||||
{
|
{
|
||||||
error("key %s not found in associative array %s",
|
error("key %s not found in associative array %s",
|
||||||
@@ -4177,6 +4305,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
if (isPointer(oldval->type))
|
if (isPointer(oldval->type))
|
||||||
{ // Slicing a pointer
|
{ // Slicing a pointer
|
||||||
oldval = oldval->interpret(istate, ctfeNeedLvalue);
|
oldval = oldval->interpret(istate, ctfeNeedLvalue);
|
||||||
|
if (exceptionOrCantInterpret(oldval))
|
||||||
|
return oldval;
|
||||||
dinteger_t ofs;
|
dinteger_t ofs;
|
||||||
oldval = getAggregateFromPointer(oldval, &ofs);
|
oldval = getAggregateFromPointer(oldval, &ofs);
|
||||||
assignmentToSlicedPointer = true;
|
assignmentToSlicedPointer = true;
|
||||||
@@ -4186,7 +4316,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
|
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
|
||||||
&& oldval->op != TOKslice && oldval->op != TOKnull)
|
&& oldval->op != TOKslice && oldval->op != TOKnull)
|
||||||
{
|
{
|
||||||
error("CTFE ICE: cannot resolve array length");
|
if (assignmentToSlicedPointer)
|
||||||
|
{
|
||||||
|
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
|
||||||
|
sexp->e1->toChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error("CTFE ICE: cannot resolve array length");
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
uinteger_t dollar = resolveArrayLength(oldval);
|
uinteger_t dollar = resolveArrayLength(oldval);
|
||||||
@@ -4249,7 +4385,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
|
||||||
{
|
{
|
||||||
IndexExp *ix = (IndexExp *)aggregate;
|
IndexExp *ix = (IndexExp *)aggregate;
|
||||||
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
|
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
|
||||||
if (!aggregate)
|
if (!aggregate)
|
||||||
{
|
{
|
||||||
error("key %s not found in associative array %s",
|
error("key %s not found in associative array %s",
|
||||||
@@ -4273,7 +4409,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
firstIndex = lowerbound + sexpold->lwr->toInteger();
|
firstIndex = lowerbound + sexpold->lwr->toInteger();
|
||||||
if (hi > sexpold->upr->toInteger())
|
if (hi > sexpold->upr->toInteger())
|
||||||
{
|
{
|
||||||
error("slice [%d..%d] exceeds array bounds [0..%jd]",
|
error("slice [%d..%d] exceeds array bounds [0..%lld]",
|
||||||
lowerbound, upperbound,
|
lowerbound, upperbound,
|
||||||
sexpold->upr->toInteger() - sexpold->lwr->toInteger());
|
sexpold->upr->toInteger() - sexpold->lwr->toInteger());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
@@ -4285,11 +4421,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
|
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
|
||||||
dinteger_t ofs;
|
dinteger_t ofs;
|
||||||
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
aggregate = getAggregateFromPointer(aggregate, &ofs);
|
||||||
|
if (aggregate->op == TOKnull)
|
||||||
|
{
|
||||||
|
error("cannot slice null pointer %s", sexp->e1->toChars());
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
dinteger_t hi = upperbound + ofs;
|
dinteger_t hi = upperbound + ofs;
|
||||||
firstIndex = lowerbound + ofs;
|
firstIndex = lowerbound + ofs;
|
||||||
if (firstIndex < 0 || hi > dim)
|
if (firstIndex < 0 || hi > dim)
|
||||||
{
|
{
|
||||||
error("slice [%d..%jd] exceeds memory block bounds [0..%jd]",
|
error("slice [lld..%lld] exceeds memory block bounds [0..%lld]",
|
||||||
firstIndex, hi, dim);
|
firstIndex, hi, dim);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -4430,9 +4571,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
error("%s cannot be evaluated at compile time", toChars());
|
error("%s cannot be evaluated at compile time", toChars());
|
||||||
#ifdef DEBUG
|
|
||||||
dump(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
@@ -4812,6 +4950,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (!global.gag)
|
if (!global.gag)
|
||||||
showCtfeBackTrace(istate, this, fd);
|
showCtfeBackTrace(istate, this, fd);
|
||||||
}
|
}
|
||||||
|
else if (eresult == EXP_VOID_INTERPRET)
|
||||||
|
;
|
||||||
|
else
|
||||||
|
eresult->loc = loc;
|
||||||
return eresult;
|
return eresult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4830,7 +4972,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
InterState istateComma;
|
InterState istateComma;
|
||||||
if (!istate && firstComma->e1->op == TOKdeclaration)
|
if (!istate && firstComma->e1->op == TOKdeclaration)
|
||||||
{
|
{
|
||||||
assert(ctfeStack.stackPointer() == 0);
|
|
||||||
ctfeStack.startFrame();
|
ctfeStack.startFrame();
|
||||||
istate = &istateComma;
|
istate = &istateComma;
|
||||||
}
|
}
|
||||||
@@ -4848,7 +4989,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
ctfeStack.push(v);
|
ctfeStack.push(v);
|
||||||
if (!v->init && !v->getValue())
|
if (!v->init && !v->getValue())
|
||||||
{
|
{
|
||||||
v->setValue(copyLiteral(v->type->defaultInitLiteral()));
|
v->setValue(copyLiteral(v->type->defaultInitLiteral(loc)));
|
||||||
}
|
}
|
||||||
if (!v->getValue()) {
|
if (!v->getValue()) {
|
||||||
Expression *newval = v->init->toExpression();
|
Expression *newval = v->init->toExpression();
|
||||||
@@ -4944,7 +5085,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
* Return ae[e2] if present, or NULL if not found.
|
* Return ae[e2] if present, or NULL if not found.
|
||||||
* Return EXP_CANT_INTERPRET on error.
|
* Return EXP_CANT_INTERPRET on error.
|
||||||
*/
|
*/
|
||||||
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
|
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
|
||||||
{
|
{
|
||||||
/* Search the keys backwards, in case there are duplicate keys
|
/* Search the keys backwards, in case there are duplicate keys
|
||||||
*/
|
*/
|
||||||
@@ -4952,13 +5093,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
|
|||||||
{
|
{
|
||||||
i--;
|
i--;
|
||||||
Expression *ekey = ae->keys->tdata()[i];
|
Expression *ekey = ae->keys->tdata()[i];
|
||||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2);
|
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2);
|
||||||
if (ex == EXP_CANT_INTERPRET)
|
if (ex == EXP_CANT_INTERPRET)
|
||||||
{
|
|
||||||
error("cannot evaluate %s==%s at compile time",
|
|
||||||
ekey->toChars(), e2->toChars());
|
|
||||||
return ex;
|
return ex;
|
||||||
}
|
|
||||||
if (ex->isBool(TRUE))
|
if (ex->isBool(TRUE))
|
||||||
{
|
{
|
||||||
return ae->values->tdata()[i];
|
return ae->values->tdata()[i];
|
||||||
@@ -5013,23 +5150,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (exceptionOrCantInterpret(e2))
|
if (exceptionOrCantInterpret(e2))
|
||||||
return e2;
|
return e2;
|
||||||
dinteger_t indx = e2->toInteger();
|
dinteger_t indx = e2->toInteger();
|
||||||
|
|
||||||
dinteger_t ofs;
|
dinteger_t ofs;
|
||||||
Expression *agg = getAggregateFromPointer(e1, &ofs);
|
Expression *agg = getAggregateFromPointer(e1, &ofs);
|
||||||
|
|
||||||
if (agg->op == TOKnull)
|
if (agg->op == TOKnull)
|
||||||
{
|
{
|
||||||
error("cannot index null pointer %s", this->e1->toChars());
|
error("cannot index null pointer %s", this->e1->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
|
if ( agg->op == TOKarrayliteral || agg->op == TOKstring)
|
||||||
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
|
||||||
Type *pointee = ((TypePointer *)agg->type)->next;
|
|
||||||
if ((indx + ofs) < 0 || (indx+ofs) > len)
|
|
||||||
{
|
{
|
||||||
error("pointer index [%jd] exceeds allocated memory block [0..%jd]",
|
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
||||||
indx+ofs, len);
|
Type *pointee = ((TypePointer *)agg->type)->next;
|
||||||
return EXP_CANT_INTERPRET;
|
if ((indx + ofs) < 0 || (indx+ofs) > len)
|
||||||
|
{
|
||||||
|
error("pointer index [%lld] exceeds allocated memory block [0..%lld]",
|
||||||
|
indx+ofs, len);
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
return ctfeIndex(loc, type, agg, indx+ofs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Pointer to a non-array variable
|
||||||
|
if ((indx + ofs) != 0)
|
||||||
|
{
|
||||||
|
error("pointer index [%lld] lies outside memory block [0..1]",
|
||||||
|
indx+ofs);
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
return agg->interpret(istate);
|
||||||
}
|
}
|
||||||
return ctfeIndex(loc, type, agg, indx+ofs);
|
|
||||||
}
|
}
|
||||||
e1 = this->e1;
|
e1 = this->e1;
|
||||||
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
|
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
|
||||||
@@ -5070,7 +5221,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
|
|
||||||
if (indx > iup - ilo)
|
if (indx > iup - ilo)
|
||||||
{
|
{
|
||||||
error("index %ju exceeds array length %ju", indx, iup - ilo);
|
error("index %llu exceeds array length %llu", indx, iup - ilo);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
indx += ilo;
|
indx += ilo;
|
||||||
@@ -5091,7 +5242,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
{
|
{
|
||||||
if (e2->op == TOKslice)
|
if (e2->op == TOKslice)
|
||||||
e2 = resolveSlice(e2);
|
e2 = resolveSlice(e2);
|
||||||
e = findKeyInAA((AssocArrayLiteralExp *)e1, e2);
|
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2);
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
error("key %s not found in associative array %s",
|
error("key %s not found in associative array %s",
|
||||||
@@ -5112,6 +5263,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
return e;
|
return e;
|
||||||
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
|
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
|
||||||
e = e->interpret(istate);
|
e = e->interpret(istate);
|
||||||
|
if (goal == ctfeNeedRvalue && e->op == TOKvoid)
|
||||||
|
{
|
||||||
|
error("%s is used before initialized", toChars());
|
||||||
|
errorSupplemental(e->loc, "originally uninitialized here");
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
e = paintTypeOntoLiteral(type, e);
|
e = paintTypeOntoLiteral(type, e);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -5166,12 +5323,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
error("cannot slice null pointer %s", this->e1->toChars());
|
error("cannot slice null pointer %s", this->e1->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
|
if (agg->op != TOKarrayliteral && agg->op != TOKstring)
|
||||||
|
{
|
||||||
|
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
|
||||||
|
this->e1->toChars());
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
|
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
|
||||||
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
|
||||||
Type *pointee = ((TypePointer *)agg->type)->next;
|
Type *pointee = ((TypePointer *)agg->type)->next;
|
||||||
if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
|
if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
|
||||||
{
|
{
|
||||||
error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]",
|
error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]",
|
||||||
ilwr+ofs, iupr+ofs, len);
|
ilwr+ofs, iupr+ofs, len);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -5235,7 +5398,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
{
|
{
|
||||||
if (ilwr== 0 && iupr == 0)
|
if (ilwr== 0 && iupr == 0)
|
||||||
return e1;
|
return e1;
|
||||||
e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr);
|
e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
if (e1->op == TOKslice)
|
if (e1->op == TOKslice)
|
||||||
@@ -5247,7 +5410,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
uinteger_t up1 = se->upr->toInteger();
|
uinteger_t up1 = se->upr->toInteger();
|
||||||
if (ilwr > iupr || iupr > up1 - lo1)
|
if (ilwr > iupr || iupr > up1 - lo1)
|
||||||
{
|
{
|
||||||
error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]",
|
error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]",
|
||||||
ilwr, iupr, lo1, up1);
|
ilwr, iupr, lo1, up1);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -5264,7 +5427,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
{
|
{
|
||||||
if (iupr < ilwr || ilwr < 0 || iupr > dollar)
|
if (iupr < ilwr || ilwr < 0 || iupr > dollar)
|
||||||
{
|
{
|
||||||
error("slice [%jd..%jd] exceeds array bounds [0..%jd]",
|
error("slice [%lld..%lld] exceeds array bounds [0..%lld]",
|
||||||
ilwr, iupr, dollar);
|
ilwr, iupr, dollar);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -5295,7 +5458,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
if (e1->op == TOKslice)
|
if (e1->op == TOKslice)
|
||||||
e1 = resolveSlice(e1);
|
e1 = resolveSlice(e1);
|
||||||
e = findKeyInAA((AssocArrayLiteralExp *)e2, e1);
|
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1);
|
||||||
if (exceptionOrCantInterpret(e))
|
if (exceptionOrCantInterpret(e))
|
||||||
return e;
|
return e;
|
||||||
if (!e)
|
if (!e)
|
||||||
@@ -5354,8 +5517,12 @@ bool isAssocArray(Type *t)
|
|||||||
if (t->ty != Tstruct)
|
if (t->ty != Tstruct)
|
||||||
return false;
|
return false;
|
||||||
StructDeclaration *sym = ((TypeStruct *)t)->sym;
|
StructDeclaration *sym = ((TypeStruct *)t)->sym;
|
||||||
if (sym->ident == Id::AssociativeArray)
|
if (sym->ident == Id::AssociativeArray && sym->parent &&
|
||||||
|
sym->parent->parent &&
|
||||||
|
sym->parent->parent->ident == Id::object)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5510,9 +5677,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
e->type = type;
|
e->type = type;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
error("pointer cast from %s to %s is not supported at compile time",
|
|
||||||
|
// Check if we have a null pointer (eg, inside a struct)
|
||||||
|
e1 = e1->interpret(istate);
|
||||||
|
if (e1->op != TOKnull)
|
||||||
|
{
|
||||||
|
error("pointer cast from %s to %s is not supported at compile time",
|
||||||
e1->type->toChars(), to->toChars());
|
e1->type->toChars(), to->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (to->ty == Tarray && e1->op == TOKslice)
|
if (to->ty == Tarray && e1->op == TOKslice)
|
||||||
{
|
{
|
||||||
@@ -5660,7 +5833,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
assert(indx >=0 && indx <= len); // invalid pointer
|
assert(indx >=0 && indx <= len); // invalid pointer
|
||||||
if (indx == len)
|
if (indx == len)
|
||||||
{
|
{
|
||||||
error("dereference of pointer %s one past end of memory block limits [0..%jd]",
|
error("dereference of pointer %s one past end of memory block limits [0..%lld]",
|
||||||
toChars(), len);
|
toChars(), len);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
@@ -5705,7 +5878,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
}
|
}
|
||||||
else if (e->op == TOKaddress)
|
else if (e->op == TOKaddress)
|
||||||
e = ((AddrExp*)e)->e1; // *(&x) ==> x
|
e = ((AddrExp*)e)->e1; // *(&x) ==> x
|
||||||
if (e->op == TOKnull)
|
else if (e->op == TOKnull)
|
||||||
{
|
{
|
||||||
error("dereference of null pointer '%s'", e1->toChars());
|
error("dereference of null pointer '%s'", e1->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
@@ -5794,6 +5967,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
|
if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
|
||||||
e->op == TOKassocarrayliteral || e->op == TOKstring)
|
e->op == TOKassocarrayliteral || e->op == TOKstring)
|
||||||
return e;
|
return e;
|
||||||
|
if (e->op == TOKvoid)
|
||||||
|
{
|
||||||
|
VoidInitExp *ve = (VoidInitExp *)e;
|
||||||
|
error("cannot read uninitialized variable %s in ctfe", toChars());
|
||||||
|
ve->var->error("was uninitialized and used before set");
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
if ( isPointer(type) )
|
if ( isPointer(type) )
|
||||||
{
|
{
|
||||||
return paintTypeOntoLiteral(type, e);
|
return paintTypeOntoLiteral(type, e);
|
||||||
@@ -5838,7 +6018,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal)
|
|||||||
size_t removed = 0;
|
size_t removed = 0;
|
||||||
for (size_t j = 0; j < valuesx->dim; ++j)
|
for (size_t j = 0; j < valuesx->dim; ++j)
|
||||||
{ Expression *ekey = keysx->tdata()[j];
|
{ Expression *ekey = keysx->tdata()[j];
|
||||||
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
|
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
|
||||||
if (exceptionOrCantInterpret(ex))
|
if (exceptionOrCantInterpret(ex))
|
||||||
return ex;
|
return ex;
|
||||||
if (ex->isBool(TRUE))
|
if (ex->isBool(TRUE))
|
||||||
@@ -6017,7 +6197,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
|
|||||||
else if (str->op == TOKarrayliteral)
|
else if (str->op == TOKarrayliteral)
|
||||||
ale = (ArrayLiteralExp *)str;
|
ale = (ArrayLiteralExp *)str;
|
||||||
else
|
else
|
||||||
{ error("CTFE internal error: cannot foreach %s", str->toChars());
|
{ str->error("CTFE internal error: cannot foreach %s", str->toChars());
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
Expressions args;
|
Expressions args;
|
||||||
@@ -6472,6 +6652,10 @@ bool isCtfeValueValid(Expression *newval)
|
|||||||
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
|
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (newval->op == TOKvoid)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
|
newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -6504,3 +6688,29 @@ void VarDeclaration::setValue(Expression *newval)
|
|||||||
assert(isCtfeValueValid(newval));
|
assert(isCtfeValueValid(newval));
|
||||||
ctfeStack.setValue(this, newval);
|
ctfeStack.setValue(this, newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expression *Type::voidInitLiteral(VarDeclaration *var)
|
||||||
|
{
|
||||||
|
return new VoidInitExp(var, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
|
||||||
|
{
|
||||||
|
return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger());
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression *TypeStruct::voidInitLiteral(VarDeclaration *var)
|
||||||
|
{
|
||||||
|
Expressions *exps = new Expressions();
|
||||||
|
exps->setDim(sym->fields.dim);
|
||||||
|
for (size_t i = 0; i < sym->fields.dim; i++)
|
||||||
|
{
|
||||||
|
//(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
|
||||||
|
(*exps)[i] = sym->fields[i]->type->voidInitLiteral(var);
|
||||||
|
}
|
||||||
|
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
|
||||||
|
se->type = this;
|
||||||
|
se->ownedByCtfe = true;
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|||||||
34
dmd/lexer.c
34
dmd/lexer.c
@@ -304,7 +304,7 @@ void Lexer::error(const char *format, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
verror(loc, format, ap);
|
verror(tokenLoc(), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2870,6 +2870,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
* Search actual location of current token
|
||||||
|
* even when infinite look-ahead was done.
|
||||||
|
*/
|
||||||
|
Loc Lexer::tokenLoc()
|
||||||
|
{
|
||||||
|
Loc result = this->loc;
|
||||||
|
Token* last = &token;
|
||||||
|
while (last->next)
|
||||||
|
last = last->next;
|
||||||
|
|
||||||
|
unsigned char* start = token.ptr;
|
||||||
|
unsigned char* stop = last->ptr;
|
||||||
|
|
||||||
|
for (unsigned char* p = start; p < stop; ++p)
|
||||||
|
{
|
||||||
|
switch (*p)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
result.linnum--;
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
if (p[1] != '\n')
|
||||||
|
result.linnum--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
* Create an identifier in the string table.
|
* Create an identifier in the string table.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -312,6 +312,8 @@ struct Lexer
|
|||||||
|
|
||||||
static int isValidIdentifier(char *p);
|
static int isValidIdentifier(char *p);
|
||||||
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
|
||||||
|
|
||||||
|
Loc tokenLoc();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DMD_LEXER_H */
|
#endif /* DMD_LEXER_H */
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ Global::Global()
|
|||||||
|
|
||||||
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
|
copyright = "Copyright (c) 1999-2012 by Digital Mars and Tomas Lindquist Olsen";
|
||||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||||
version = "v1.073";
|
version = "v1.074";
|
||||||
ldc_version = "LDC trunk";
|
ldc_version = "LDC trunk";
|
||||||
llvm_version = "LLVM 3.0";
|
llvm_version = "LLVM 3.0";
|
||||||
global.structalign = 8;
|
global.structalign = 8;
|
||||||
@@ -102,6 +102,11 @@ bool Global::endGagging(unsigned oldGagged)
|
|||||||
return anyErrs;
|
return anyErrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Global::isSpeculativeGagging()
|
||||||
|
{
|
||||||
|
return gag && gag == speculativeGag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *Loc::toChars() const
|
char *Loc::toChars() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -347,6 +347,12 @@ struct Global
|
|||||||
unsigned gag; // !=0 means gag reporting of errors & warnings
|
unsigned gag; // !=0 means gag reporting of errors & warnings
|
||||||
unsigned gaggedErrors; // number of errors reported while gagged
|
unsigned gaggedErrors; // number of errors reported while gagged
|
||||||
|
|
||||||
|
/* Gagging can either be speculative (is(typeof()), etc)
|
||||||
|
* or because of forward references
|
||||||
|
*/
|
||||||
|
unsigned speculativeGag; // == gag means gagging is for is(typeof);
|
||||||
|
bool isSpeculativeGagging();
|
||||||
|
|
||||||
// Start gagging. Return the current number of gagged errors
|
// Start gagging. Return the current number of gagged errors
|
||||||
unsigned startGagging();
|
unsigned startGagging();
|
||||||
|
|
||||||
|
|||||||
45
dmd/module.c
45
dmd/module.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -387,7 +387,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
|||||||
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
m->read(loc);
|
if (!m->read(loc))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
m->parse();
|
m->parse();
|
||||||
|
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
@@ -397,7 +399,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::read(Loc loc)
|
bool Module::read(Loc loc)
|
||||||
{
|
{
|
||||||
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
|
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
|
||||||
if (srcfile->read())
|
if (srcfile->read())
|
||||||
@@ -415,9 +417,11 @@ void Module::read(Loc loc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
|
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
|
||||||
|
fatal();
|
||||||
}
|
}
|
||||||
fatal();
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned readwordLE(unsigned short *p)
|
inline unsigned readwordLE(unsigned short *p)
|
||||||
@@ -684,7 +688,15 @@ void Module::parse()
|
|||||||
|
|
||||||
if (md)
|
if (md)
|
||||||
{ this->ident = md->id;
|
{ this->ident = md->id;
|
||||||
dst = Package::resolve(md->packages, &this->parent, NULL);
|
this->safe = md->safe;
|
||||||
|
Package *ppack = NULL;
|
||||||
|
dst = Package::resolve(md->packages, &this->parent, &ppack);
|
||||||
|
if (ppack && ppack->isModule())
|
||||||
|
{
|
||||||
|
error(loc, "package name '%s' in file %s conflicts with usage as a module name in file %s",
|
||||||
|
ppack->toChars(), srcname, ppack->isModule()->srcfile->toChars());
|
||||||
|
dst = modules;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -709,7 +721,7 @@ void Module::parse()
|
|||||||
{
|
{
|
||||||
Package *pkg = prev->isPackage();
|
Package *pkg = prev->isPackage();
|
||||||
assert(pkg);
|
assert(pkg);
|
||||||
error(loc, "from file %s conflicts with package name %s",
|
error(pkg->loc, "from file %s conflicts with package name %s",
|
||||||
srcname, pkg->toChars());
|
srcname, pkg->toChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1216,19 +1228,24 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(p->isPackage());
|
assert(p->isPackage());
|
||||||
#if TARGET_NET //dot net needs modules and packages with same name
|
// It might already be a module, not a package, but that needs
|
||||||
#else
|
// to be checked at a higher level, where a nice error message
|
||||||
if (p->isModule())
|
// can be generated.
|
||||||
{ p->error("module and package have the same name");
|
// dot net needs modules and packages with same name
|
||||||
fatal();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
parent = p;
|
parent = p;
|
||||||
dst = ((Package *)p)->symtab;
|
dst = ((Package *)p)->symtab;
|
||||||
if (ppkg && !*ppkg)
|
if (ppkg && !*ppkg)
|
||||||
*ppkg = (Package *)p;
|
*ppkg = (Package *)p;
|
||||||
|
#if TARGET_NET
|
||||||
|
#else
|
||||||
|
if (p->isModule())
|
||||||
|
{ // Return the module so that a nice error message can be generated
|
||||||
|
if (ppkg)
|
||||||
|
*ppkg = (Package *)p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (pparent)
|
if (pparent)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -134,10 +134,11 @@ struct Module : Package
|
|||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
void toJsonBuffer(OutBuffer *buf);
|
void toJsonBuffer(OutBuffer *buf);
|
||||||
const char *kind();
|
const char *kind();
|
||||||
void read(Loc loc); // read file
|
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
void parse(bool gen_docs = false); // syntactic parse
|
void parse(bool gen_docs = false); // syntactic parse
|
||||||
#elif IN_GCC
|
#elif IN_GCC
|
||||||
|
void setDocfile(); // set docfile member
|
||||||
void parse(bool dump_source = false); // syntactic parse
|
void parse(bool dump_source = false); // syntactic parse
|
||||||
#else
|
#else
|
||||||
void parse(); // syntactic parse
|
void parse(); // syntactic parse
|
||||||
|
|||||||
75
dmd/mtype.c
75
dmd/mtype.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -1451,7 +1451,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
|||||||
case Timaginary64: t = tfloat64; goto L2;
|
case Timaginary64: t = tfloat64; goto L2;
|
||||||
case Timaginary80: t = tfloat80; goto L2;
|
case Timaginary80: t = tfloat80; goto L2;
|
||||||
L2:
|
L2:
|
||||||
e = new RealExp(0, 0.0, t);
|
e = new RealExp(e->loc, 0.0, t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1481,7 +1481,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
|||||||
case Tfloat32:
|
case Tfloat32:
|
||||||
case Tfloat64:
|
case Tfloat64:
|
||||||
case Tfloat80:
|
case Tfloat80:
|
||||||
e = new RealExp(0, 0.0, this);
|
e = new RealExp(e->loc, 0.0, this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -2645,6 +2645,22 @@ int TypeAArray::checkBoolean()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expression *TypeAArray::toExpression()
|
||||||
|
{
|
||||||
|
Expression *e = next->toExpression();
|
||||||
|
if (e)
|
||||||
|
{
|
||||||
|
Expression *ei = index->toExpression();
|
||||||
|
if (ei)
|
||||||
|
{
|
||||||
|
Expressions *arguments = new Expressions();
|
||||||
|
arguments->push(ei);
|
||||||
|
return new ArrayExp(0, e, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int TypeAArray::hasPointers()
|
int TypeAArray::hasPointers()
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -3184,13 +3200,25 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
|
|||||||
error(loc, "cannot have parameter of type %s", fparam->type->toChars());
|
error(loc, "cannot have parameter of type %s", fparam->type->toChars());
|
||||||
|
|
||||||
if (fparam->defaultArg)
|
if (fparam->defaultArg)
|
||||||
{
|
{ Expression *e = fparam->defaultArg;
|
||||||
fparam->defaultArg = fparam->defaultArg->semantic(argsc);
|
e = e->semantic(argsc);
|
||||||
fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg);
|
e = resolveProperties(argsc, e);
|
||||||
fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type);
|
if (e->op == TOKfunction) // see Bugzilla 4820
|
||||||
|
{ FuncExp *fe = (FuncExp *)e;
|
||||||
|
if (fe->fd)
|
||||||
|
{ // Replace function literal with a function symbol,
|
||||||
|
// since default arg expression must be copied when used
|
||||||
|
// and copying the literal itself is wrong.
|
||||||
|
e = new VarExp(e->loc, fe->fd);
|
||||||
|
e = new AddrExp(e->loc, e);
|
||||||
|
e = e->semantic(argsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e = e->implicitCastTo(argsc, fparam->type);
|
||||||
|
fparam->defaultArg = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If arg turns out to be a tuple, the number of parameters may
|
/* If fparam after semantic() turns out to be a tuple, the number of parameters may
|
||||||
* change.
|
* change.
|
||||||
*/
|
*/
|
||||||
if (t->ty == Ttuple)
|
if (t->ty == Ttuple)
|
||||||
@@ -3650,7 +3678,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Lerror:
|
Lerror:
|
||||||
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
|
if (id->dyncast() == DYNCAST_DSYMBOL)
|
||||||
|
{ // searchX already handles errors for template instances
|
||||||
|
assert(global.errors);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sm = s->search_correct(id);
|
||||||
|
if (sm)
|
||||||
|
error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?",
|
||||||
|
id->toChars(), toChars(), sm->kind(), sm->toChars());
|
||||||
|
else
|
||||||
|
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
|
||||||
|
}
|
||||||
*pe = new ErrorExp();
|
*pe = new ErrorExp();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -4131,14 +4171,19 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
sc->intypeof++;
|
Scope *sc2 = sc->push();
|
||||||
exp = exp->semantic(sc);
|
sc2->intypeof++;
|
||||||
|
unsigned oldspecgag = global.speculativeGag;
|
||||||
|
if (global.gag)
|
||||||
|
global.speculativeGag = global.gag;
|
||||||
|
exp = exp->semantic(sc2);
|
||||||
|
global.speculativeGag = oldspecgag;
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
if (exp->type && exp->type->ty == Tfunction &&
|
if (exp->type && exp->type->ty == Tfunction &&
|
||||||
((TypeFunction *)exp->type)->isproperty)
|
((TypeFunction *)exp->type)->isproperty)
|
||||||
exp = resolveProperties(sc, exp);
|
exp = resolveProperties(sc2, exp);
|
||||||
#endif
|
#endif
|
||||||
sc->intypeof--;
|
sc2->pop();
|
||||||
if (exp->op == TOKtype)
|
if (exp->op == TOKtype)
|
||||||
{
|
{
|
||||||
error(loc, "argument %s to typeof is not an expression", exp->toChars());
|
error(loc, "argument %s to typeof is not an expression", exp->toChars());
|
||||||
@@ -4959,8 +5004,8 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
|
|||||||
e = vd->init->toExpression();
|
e = vd->init->toExpression();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
e = vd->type->defaultInitLiteral();
|
e = vd->type->defaultInitLiteral(loc);
|
||||||
structelems->tdata()[j] = e;
|
(*structelems)[j] = e;
|
||||||
}
|
}
|
||||||
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
|
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
|
||||||
// Why doesn't the StructLiteralExp constructor do this, when
|
// Why doesn't the StructLiteralExp constructor do this, when
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -254,7 +254,8 @@ struct Type : Object
|
|||||||
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
virtual unsigned memalign(unsigned salign);
|
virtual unsigned memalign(unsigned salign);
|
||||||
virtual Expression *defaultInit(Loc loc = 0);
|
virtual Expression *defaultInit(Loc loc = 0);
|
||||||
virtual Expression *defaultInitLiteral(Loc loc = 0);
|
virtual Expression *defaultInitLiteral(Loc loc);
|
||||||
|
virtual Expression *voidInitLiteral(VarDeclaration *var);
|
||||||
virtual int isZeroInit(Loc loc = 0); // if initializer is 0
|
virtual int isZeroInit(Loc loc = 0); // if initializer is 0
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
virtual dt_t **toDt(dt_t **pdt);
|
virtual dt_t **toDt(dt_t **pdt);
|
||||||
@@ -391,6 +392,7 @@ struct TypeSArray : TypeArray
|
|||||||
MATCH implicitConvTo(Type *to);
|
MATCH implicitConvTo(Type *to);
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
Expression *defaultInitLiteral(Loc loc);
|
Expression *defaultInitLiteral(Loc loc);
|
||||||
|
Expression *voidInitLiteral(VarDeclaration *var);
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
dt_t **toDt(dt_t **pdt);
|
dt_t **toDt(dt_t **pdt);
|
||||||
dt_t **toDtElem(dt_t **pdt, Expression *e);
|
dt_t **toDtElem(dt_t **pdt, Expression *e);
|
||||||
@@ -451,6 +453,7 @@ struct TypeAArray : TypeArray
|
|||||||
int isZeroInit(Loc loc);
|
int isZeroInit(Loc loc);
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||||
|
Expression *toExpression();
|
||||||
int hasPointers();
|
int hasPointers();
|
||||||
TypeTuple *toArgTypes();
|
TypeTuple *toArgTypes();
|
||||||
|
|
||||||
@@ -644,6 +647,7 @@ struct TypeStruct : Type
|
|||||||
unsigned memalign(unsigned salign);
|
unsigned memalign(unsigned salign);
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
Expression *defaultInitLiteral(Loc loc);
|
Expression *defaultInitLiteral(Loc loc);
|
||||||
|
Expression *voidInitLiteral(VarDeclaration *var);
|
||||||
int isZeroInit(Loc loc);
|
int isZeroInit(Loc loc);
|
||||||
int checkBoolean();
|
int checkBoolean();
|
||||||
#if IN_DMD
|
#if IN_DMD
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -129,7 +129,7 @@ Dsymbols *Parser::parseModule()
|
|||||||
|
|
||||||
decldefs = parseDeclDefs(0);
|
decldefs = parseDeclDefs(0);
|
||||||
if (token.value != TOKeof)
|
if (token.value != TOKeof)
|
||||||
{ error("unrecognized declaration");
|
{ error(loc, "unrecognized declaration");
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
}
|
}
|
||||||
return decldefs;
|
return decldefs;
|
||||||
@@ -5565,6 +5565,7 @@ void initPrecedence()
|
|||||||
precedence[TOKtraits] = PREC_primary;
|
precedence[TOKtraits] = PREC_primary;
|
||||||
precedence[TOKdefault] = PREC_primary;
|
precedence[TOKdefault] = PREC_primary;
|
||||||
precedence[TOKoverloadset] = PREC_primary;
|
precedence[TOKoverloadset] = PREC_primary;
|
||||||
|
precedence[TOKvoid] = PREC_primary;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// post
|
// post
|
||||||
|
|||||||
376
dmd/root/aav.c
376
dmd/root/aav.c
@@ -1,188 +1,188 @@
|
|||||||
/**
|
/**
|
||||||
* Implementation of associative arrays.
|
* Implementation of associative arrays.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "aav.h"
|
#include "aav.h"
|
||||||
|
|
||||||
static const size_t prime_list[] = {
|
static const size_t prime_list[] = {
|
||||||
31UL,
|
31UL,
|
||||||
97UL, 389UL,
|
97UL, 389UL,
|
||||||
1543UL, 6151UL,
|
1543UL, 6151UL,
|
||||||
24593UL, 98317UL,
|
24593UL, 98317UL,
|
||||||
393241UL, 1572869UL,
|
393241UL, 1572869UL,
|
||||||
6291469UL, 25165843UL,
|
6291469UL, 25165843UL,
|
||||||
100663319UL, 402653189UL,
|
100663319UL, 402653189UL,
|
||||||
1610612741UL, 4294967291UL,
|
1610612741UL, 4294967291UL,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aaA
|
struct aaA
|
||||||
{
|
{
|
||||||
aaA *next;
|
aaA *next;
|
||||||
Key key;
|
Key key;
|
||||||
Value value;
|
Value value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AA
|
struct AA
|
||||||
{
|
{
|
||||||
aaA* *b;
|
aaA* *b;
|
||||||
size_t b_length;
|
size_t b_length;
|
||||||
size_t nodes; // total number of aaA nodes
|
size_t nodes; // total number of aaA nodes
|
||||||
aaA* binit[4]; // initial value of b[]
|
aaA* binit[4]; // initial value of b[]
|
||||||
};
|
};
|
||||||
|
|
||||||
static const AA bbinit = { NULL, };
|
static const AA bbinit = { NULL, };
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Determine number of entries in associative array.
|
* Determine number of entries in associative array.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t _aaLen(AA* aa)
|
size_t _aaLen(AA* aa)
|
||||||
{
|
{
|
||||||
return aa ? aa->nodes : 0;
|
return aa ? aa->nodes : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Get pointer to value in associative array indexed by key.
|
* Get pointer to value in associative array indexed by key.
|
||||||
* Add entry for key if it is not already there.
|
* Add entry for key if it is not already there.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Value* _aaGet(AA** paa, Key key)
|
Value* _aaGet(AA** paa, Key key)
|
||||||
{
|
{
|
||||||
//printf("paa = %p\n", paa);
|
//printf("paa = %p\n", paa);
|
||||||
|
|
||||||
if (!*paa)
|
if (!*paa)
|
||||||
{ AA *a = new AA();
|
{ AA *a = new AA();
|
||||||
*a = bbinit;
|
*a = bbinit;
|
||||||
a->b = a->binit;
|
a->b = a->binit;
|
||||||
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
|
a->b_length = sizeof(a->binit) / sizeof(a->binit[0]);
|
||||||
*paa = a;
|
*paa = a;
|
||||||
assert((*paa)->b_length == 4);
|
assert((*paa)->b_length == 4);
|
||||||
}
|
}
|
||||||
//printf("paa = %p, *paa = %p\n", paa, *paa);
|
//printf("paa = %p, *paa = %p\n", paa, *paa);
|
||||||
|
|
||||||
assert((*paa)->b_length);
|
assert((*paa)->b_length);
|
||||||
size_t i = (size_t)key % (*paa)->b_length;
|
size_t i = (size_t)key % (*paa)->b_length;
|
||||||
aaA** pe = &(*paa)->b[i];
|
aaA** pe = &(*paa)->b[i];
|
||||||
aaA *e;
|
aaA *e;
|
||||||
while ((e = *pe) != NULL)
|
while ((e = *pe) != NULL)
|
||||||
{
|
{
|
||||||
if (key == e->key)
|
if (key == e->key)
|
||||||
return &e->value;
|
return &e->value;
|
||||||
pe = &e->next;
|
pe = &e->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not found, create new elem
|
// Not found, create new elem
|
||||||
//printf("create new one\n");
|
//printf("create new one\n");
|
||||||
e = new aaA();
|
e = new aaA();
|
||||||
e->next = NULL;
|
e->next = NULL;
|
||||||
e->key = key;
|
e->key = key;
|
||||||
e->value = NULL;
|
e->value = NULL;
|
||||||
*pe = e;
|
*pe = e;
|
||||||
|
|
||||||
size_t nodes = ++(*paa)->nodes;
|
size_t nodes = ++(*paa)->nodes;
|
||||||
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
|
//printf("length = %d, nodes = %d\n", paa.a.b.length, nodes);
|
||||||
if (nodes > (*paa)->b_length * 4)
|
if (nodes > (*paa)->b_length * 4)
|
||||||
{
|
{
|
||||||
//printf("rehash\n");
|
//printf("rehash\n");
|
||||||
_aaRehash(paa);
|
_aaRehash(paa);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &e->value;
|
return &e->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
* Get value in associative array indexed by key.
|
* Get value in associative array indexed by key.
|
||||||
* Returns NULL if it is not already there.
|
* Returns NULL if it is not already there.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Value _aaGetRvalue(AA* aa, Key key)
|
Value _aaGetRvalue(AA* aa, Key key)
|
||||||
{
|
{
|
||||||
//printf("_aaGetRvalue(key = %p)\n", key);
|
//printf("_aaGetRvalue(key = %p)\n", key);
|
||||||
if (!aa)
|
if (!aa)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
size_t len = aa->b_length;
|
size_t len = aa->b_length;
|
||||||
|
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
size_t i = (size_t)key % len;
|
size_t i = (size_t)key % len;
|
||||||
aaA* e = aa->b[i];
|
aaA* e = aa->b[i];
|
||||||
while (e)
|
while (e)
|
||||||
{
|
{
|
||||||
if (key == e->key)
|
if (key == e->key)
|
||||||
return e->value;
|
return e->value;
|
||||||
e = e->next;
|
e = e->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL; // not found
|
return NULL; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/********************************************
|
/********************************************
|
||||||
* Rehash an array.
|
* Rehash an array.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void _aaRehash(AA** paa)
|
void _aaRehash(AA** paa)
|
||||||
{
|
{
|
||||||
//printf("Rehash\n");
|
//printf("Rehash\n");
|
||||||
if (*paa)
|
if (*paa)
|
||||||
{
|
{
|
||||||
AA newb = bbinit;
|
AA newb = bbinit;
|
||||||
AA *aa = *paa;
|
AA *aa = *paa;
|
||||||
size_t len = _aaLen(*paa);
|
size_t len = _aaLen(*paa);
|
||||||
if (len)
|
if (len)
|
||||||
{ size_t i;
|
{ size_t i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
|
for (i = 0; i < sizeof(prime_list)/sizeof(prime_list[0]) - 1; i++)
|
||||||
{
|
{
|
||||||
if (len <= prime_list[i])
|
if (len <= prime_list[i])
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = prime_list[i];
|
len = prime_list[i];
|
||||||
newb.b = new aaA*[len];
|
newb.b = new aaA*[len];
|
||||||
memset(newb.b, 0, len * sizeof(aaA*));
|
memset(newb.b, 0, len * sizeof(aaA*));
|
||||||
newb.b_length = len;
|
newb.b_length = len;
|
||||||
|
|
||||||
for (size_t k = 0; k < aa->b_length; k++)
|
for (size_t k = 0; k < aa->b_length; k++)
|
||||||
{ aaA *e = aa->b[k];
|
{ aaA *e = aa->b[k];
|
||||||
while (e)
|
while (e)
|
||||||
{ aaA* enext = e->next;
|
{ aaA* enext = e->next;
|
||||||
size_t j = (size_t)e->key % len;
|
size_t j = (size_t)e->key % len;
|
||||||
e->next = newb.b[j];
|
e->next = newb.b[j];
|
||||||
newb.b[j] = e;
|
newb.b[j] = e;
|
||||||
e = enext;
|
e = enext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aa->b != aa->binit)
|
if (aa->b != aa->binit)
|
||||||
delete[] aa->b;
|
delete[] aa->b;
|
||||||
|
|
||||||
newb.nodes = aa->nodes;
|
newb.nodes = aa->nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
**paa = newb;
|
**paa = newb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if UNITTEST
|
#if UNITTEST
|
||||||
|
|
||||||
void unittest_aa()
|
void unittest_aa()
|
||||||
{
|
{
|
||||||
AA* aa = NULL;
|
AA* aa = NULL;
|
||||||
Value v = _aaGetRvalue(aa, NULL);
|
Value v = _aaGetRvalue(aa, NULL);
|
||||||
assert(!v);
|
assert(!v);
|
||||||
Value *pv = _aaGet(&aa, NULL);
|
Value *pv = _aaGet(&aa, NULL);
|
||||||
assert(pv);
|
assert(pv);
|
||||||
*pv = (void *)3;
|
*pv = (void *)3;
|
||||||
v = _aaGetRvalue(aa, NULL);
|
v = _aaGetRvalue(aa, NULL);
|
||||||
assert(v == (void *)3);
|
assert(v == (void *)3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
typedef void* Value;
|
typedef void* Value;
|
||||||
typedef void* Key;
|
typedef void* Key;
|
||||||
|
|
||||||
struct AA;
|
struct AA;
|
||||||
|
|
||||||
size_t _aaLen(AA* aa);
|
size_t _aaLen(AA* aa);
|
||||||
Value* _aaGet(AA** aa, Key key);
|
Value* _aaGet(AA** aa, Key key);
|
||||||
Value _aaGetRvalue(AA* aa, Key key);
|
Value _aaGetRvalue(AA* aa, Key key);
|
||||||
void _aaRehash(AA** paa);
|
void _aaRehash(AA** paa);
|
||||||
|
|
||||||
|
|||||||
514
dmd/root/array.c
514
dmd/root/array.c
@@ -1,257 +1,257 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2010 by Digital Mars
|
// Copyright (c) 1999-2010 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if (defined (__SVR4) && defined (__sun))
|
#if (defined (__SVR4) && defined (__sun))
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _MSC_VER || __MINGW32__
|
#if _MSC_VER || __MINGW32__
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_GCC
|
#if IN_GCC
|
||||||
#include "gdc_alloca.h"
|
#include "gdc_alloca.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
|
|
||||||
|
|
||||||
/********************************* Array ****************************/
|
/********************************* Array ****************************/
|
||||||
|
|
||||||
Array::Array()
|
Array::Array()
|
||||||
{
|
{
|
||||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||||
dim = 0;
|
dim = 0;
|
||||||
allocdim = SMALLARRAYCAP;
|
allocdim = SMALLARRAYCAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array::~Array()
|
Array::~Array()
|
||||||
{
|
{
|
||||||
if (data != &smallarray[0])
|
if (data != &smallarray[0])
|
||||||
mem.free(data);
|
mem.free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::mark()
|
void Array::mark()
|
||||||
{ unsigned u;
|
{ unsigned u;
|
||||||
|
|
||||||
mem.mark(data);
|
mem.mark(data);
|
||||||
for (u = 0; u < dim; u++)
|
for (u = 0; u < dim; u++)
|
||||||
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
mem.mark(data[u]); // BUG: what if arrays of Object's?
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::reserve(unsigned nentries)
|
void Array::reserve(unsigned nentries)
|
||||||
{
|
{
|
||||||
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
|
//printf("Array::reserve: dim = %d, allocdim = %d, nentries = %d\n", dim, allocdim, nentries);
|
||||||
if (allocdim - dim < nentries)
|
if (allocdim - dim < nentries)
|
||||||
{
|
{
|
||||||
if (allocdim == 0)
|
if (allocdim == 0)
|
||||||
{ // Not properly initialized, someone memset it to zero
|
{ // Not properly initialized, someone memset it to zero
|
||||||
if (nentries <= SMALLARRAYCAP)
|
if (nentries <= SMALLARRAYCAP)
|
||||||
{ allocdim = SMALLARRAYCAP;
|
{ allocdim = SMALLARRAYCAP;
|
||||||
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
data = SMALLARRAYCAP ? &smallarray[0] : NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ allocdim = nentries;
|
{ allocdim = nentries;
|
||||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (allocdim == SMALLARRAYCAP)
|
else if (allocdim == SMALLARRAYCAP)
|
||||||
{
|
{
|
||||||
allocdim = dim + nentries;
|
allocdim = dim + nentries;
|
||||||
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
data = (void **)mem.malloc(allocdim * sizeof(*data));
|
||||||
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
memcpy(data, &smallarray[0], dim * sizeof(*data));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ allocdim = dim + nentries;
|
{ allocdim = dim + nentries;
|
||||||
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
data = (void **)mem.realloc(data, allocdim * sizeof(*data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::setDim(unsigned newdim)
|
void Array::setDim(unsigned newdim)
|
||||||
{
|
{
|
||||||
if (dim < newdim)
|
if (dim < newdim)
|
||||||
{
|
{
|
||||||
reserve(newdim - dim);
|
reserve(newdim - dim);
|
||||||
}
|
}
|
||||||
dim = newdim;
|
dim = newdim;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::fixDim()
|
void Array::fixDim()
|
||||||
{
|
{
|
||||||
if (dim != allocdim)
|
if (dim != allocdim)
|
||||||
{
|
{
|
||||||
if (allocdim >= SMALLARRAYCAP)
|
if (allocdim >= SMALLARRAYCAP)
|
||||||
{
|
{
|
||||||
if (dim <= SMALLARRAYCAP)
|
if (dim <= SMALLARRAYCAP)
|
||||||
{
|
{
|
||||||
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
memcpy(&smallarray[0], data, dim * sizeof(*data));
|
||||||
mem.free(data);
|
mem.free(data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data = (void **)mem.realloc(data, dim * sizeof(*data));
|
data = (void **)mem.realloc(data, dim * sizeof(*data));
|
||||||
}
|
}
|
||||||
allocdim = dim;
|
allocdim = dim;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::push(void *ptr)
|
void Array::push(void *ptr)
|
||||||
{
|
{
|
||||||
reserve(1);
|
reserve(1);
|
||||||
data[dim++] = ptr;
|
data[dim++] = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Array::pop()
|
void *Array::pop()
|
||||||
{
|
{
|
||||||
return data[--dim];
|
return data[--dim];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::shift(void *ptr)
|
void Array::shift(void *ptr)
|
||||||
{
|
{
|
||||||
reserve(1);
|
reserve(1);
|
||||||
memmove(data + 1, data, dim * sizeof(*data));
|
memmove(data + 1, data, dim * sizeof(*data));
|
||||||
data[0] = ptr;
|
data[0] = ptr;
|
||||||
dim++;
|
dim++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::insert(unsigned index, void *ptr)
|
void Array::insert(unsigned index, void *ptr)
|
||||||
{
|
{
|
||||||
reserve(1);
|
reserve(1);
|
||||||
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
memmove(data + index + 1, data + index, (dim - index) * sizeof(*data));
|
||||||
data[index] = ptr;
|
data[index] = ptr;
|
||||||
dim++;
|
dim++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Array::insert(unsigned index, Array *a)
|
void Array::insert(unsigned index, Array *a)
|
||||||
{
|
{
|
||||||
if (a)
|
if (a)
|
||||||
{ unsigned d;
|
{ unsigned d;
|
||||||
|
|
||||||
d = a->dim;
|
d = a->dim;
|
||||||
reserve(d);
|
reserve(d);
|
||||||
if (dim != index)
|
if (dim != index)
|
||||||
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
memmove(data + index + d, data + index, (dim - index) * sizeof(*data));
|
||||||
memcpy(data + index, a->data, d * sizeof(*data));
|
memcpy(data + index, a->data, d * sizeof(*data));
|
||||||
dim += d;
|
dim += d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* Append array a to this array.
|
* Append array a to this array.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Array::append(Array *a)
|
void Array::append(Array *a)
|
||||||
{
|
{
|
||||||
insert(dim, a);
|
insert(dim, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::remove(unsigned i)
|
void Array::remove(unsigned i)
|
||||||
{
|
{
|
||||||
if (dim - i - 1)
|
if (dim - i - 1)
|
||||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||||
dim--;
|
dim--;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Array::toChars()
|
char *Array::toChars()
|
||||||
{
|
{
|
||||||
unsigned len;
|
unsigned len;
|
||||||
unsigned u;
|
unsigned u;
|
||||||
char **buf;
|
char **buf;
|
||||||
char *str;
|
char *str;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
buf = (char **)malloc(dim * sizeof(char *));
|
buf = (char **)malloc(dim * sizeof(char *));
|
||||||
assert(buf);
|
assert(buf);
|
||||||
len = 2;
|
len = 2;
|
||||||
for (u = 0; u < dim; u++)
|
for (u = 0; u < dim; u++)
|
||||||
{
|
{
|
||||||
buf[u] = ((Object *)data[u])->toChars();
|
buf[u] = ((Object *)data[u])->toChars();
|
||||||
len += strlen(buf[u]) + 1;
|
len += strlen(buf[u]) + 1;
|
||||||
}
|
}
|
||||||
str = (char *)mem.malloc(len);
|
str = (char *)mem.malloc(len);
|
||||||
|
|
||||||
str[0] = '[';
|
str[0] = '[';
|
||||||
p = str + 1;
|
p = str + 1;
|
||||||
for (u = 0; u < dim; u++)
|
for (u = 0; u < dim; u++)
|
||||||
{
|
{
|
||||||
if (u)
|
if (u)
|
||||||
*p++ = ',';
|
*p++ = ',';
|
||||||
len = strlen(buf[u]);
|
len = strlen(buf[u]);
|
||||||
memcpy(p,buf[u],len);
|
memcpy(p,buf[u],len);
|
||||||
p += len;
|
p += len;
|
||||||
}
|
}
|
||||||
*p++ = ']';
|
*p++ = ']';
|
||||||
*p = 0;
|
*p = 0;
|
||||||
free(buf);
|
free(buf);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::zero()
|
void Array::zero()
|
||||||
{
|
{
|
||||||
memset(data,0,dim * sizeof(data[0]));
|
memset(data,0,dim * sizeof(data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Array::tos()
|
void *Array::tos()
|
||||||
{
|
{
|
||||||
return dim ? data[dim - 1] : NULL;
|
return dim ? data[dim - 1] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
__cdecl
|
__cdecl
|
||||||
#endif
|
#endif
|
||||||
Array_sort_compare(const void *x, const void *y)
|
Array_sort_compare(const void *x, const void *y)
|
||||||
{
|
{
|
||||||
Object *ox = *(Object **)x;
|
Object *ox = *(Object **)x;
|
||||||
Object *oy = *(Object **)y;
|
Object *oy = *(Object **)y;
|
||||||
|
|
||||||
return ox->compare(oy);
|
return ox->compare(oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Array::sort()
|
void Array::sort()
|
||||||
{
|
{
|
||||||
if (dim)
|
if (dim)
|
||||||
{
|
{
|
||||||
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
qsort(data, dim, sizeof(Object *), Array_sort_compare);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array *Array::copy()
|
Array *Array::copy()
|
||||||
{
|
{
|
||||||
Array *a = new Array();
|
Array *a = new Array();
|
||||||
|
|
||||||
a->setDim(dim);
|
a->setDim(dim);
|
||||||
memcpy(a->data, data, dim * sizeof(void *));
|
memcpy(a->data, data, dim * sizeof(void *));
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
650
dmd/root/async.c
650
dmd/root/async.c
@@ -1,325 +1,325 @@
|
|||||||
|
|
||||||
#define _MT 1
|
#define _MT 1
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
|
|
||||||
static unsigned __stdcall startthread(void *p);
|
static unsigned __stdcall startthread(void *p);
|
||||||
|
|
||||||
struct FileData
|
struct FileData
|
||||||
{
|
{
|
||||||
File *file;
|
File *file;
|
||||||
int result;
|
int result;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsyncRead
|
struct AsyncRead
|
||||||
{
|
{
|
||||||
static AsyncRead *create(size_t nfiles);
|
static AsyncRead *create(size_t nfiles);
|
||||||
void addFile(File *file);
|
void addFile(File *file);
|
||||||
void start();
|
void start();
|
||||||
int read(size_t i);
|
int read(size_t i);
|
||||||
static void dispose(AsyncRead *);
|
static void dispose(AsyncRead *);
|
||||||
|
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
|
|
||||||
size_t filesdim;
|
size_t filesdim;
|
||||||
size_t filesmax;
|
size_t filesmax;
|
||||||
FileData files[1];
|
FileData files[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||||
{
|
{
|
||||||
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
||||||
(nfiles - 1) * sizeof(FileData));
|
(nfiles - 1) * sizeof(FileData));
|
||||||
aw->filesmax = nfiles;
|
aw->filesmax = nfiles;
|
||||||
return aw;
|
return aw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::addFile(File *file)
|
void AsyncRead::addFile(File *file)
|
||||||
{
|
{
|
||||||
//printf("addFile(file = %p)\n", file);
|
//printf("addFile(file = %p)\n", file);
|
||||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||||
assert(filesdim < filesmax);
|
assert(filesdim < filesmax);
|
||||||
files[filesdim].file = file;
|
files[filesdim].file = file;
|
||||||
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
ResetEvent(files[filesdim].event);
|
ResetEvent(files[filesdim].event);
|
||||||
filesdim++;
|
filesdim++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::start()
|
void AsyncRead::start()
|
||||||
{
|
{
|
||||||
//printf("aw->filesdim = %p %d\n", this, filesdim);
|
//printf("aw->filesdim = %p %d\n", this, filesdim);
|
||||||
if (filesdim)
|
if (filesdim)
|
||||||
{
|
{
|
||||||
unsigned threadaddr;
|
unsigned threadaddr;
|
||||||
hThread = (HANDLE) _beginthreadex(NULL,
|
hThread = (HANDLE) _beginthreadex(NULL,
|
||||||
0,
|
0,
|
||||||
&startthread,
|
&startthread,
|
||||||
this,
|
this,
|
||||||
0,
|
0,
|
||||||
(unsigned *)&threadaddr);
|
(unsigned *)&threadaddr);
|
||||||
|
|
||||||
if (hThread)
|
if (hThread)
|
||||||
{
|
{
|
||||||
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsyncRead::read(size_t i)
|
int AsyncRead::read(size_t i)
|
||||||
{
|
{
|
||||||
FileData *f = &files[i];
|
FileData *f = &files[i];
|
||||||
WaitForSingleObject(f->event, INFINITE);
|
WaitForSingleObject(f->event, INFINITE);
|
||||||
Sleep(0); // give up time slice
|
Sleep(0); // give up time slice
|
||||||
return f->result;
|
return f->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::dispose(AsyncRead *aw)
|
void AsyncRead::dispose(AsyncRead *aw)
|
||||||
{
|
{
|
||||||
free(aw);
|
free(aw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned __stdcall startthread(void *p)
|
unsigned __stdcall startthread(void *p)
|
||||||
{
|
{
|
||||||
AsyncRead *aw = (AsyncRead *)p;
|
AsyncRead *aw = (AsyncRead *)p;
|
||||||
|
|
||||||
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
|
//printf("aw->filesdim = %p %d\n", aw, aw->filesdim);
|
||||||
for (size_t i = 0; i < aw->filesdim; i++)
|
for (size_t i = 0; i < aw->filesdim; i++)
|
||||||
{ FileData *f = &aw->files[i];
|
{ FileData *f = &aw->files[i];
|
||||||
|
|
||||||
f->result = f->file->read();
|
f->result = f->file->read();
|
||||||
SetEvent(f->event);
|
SetEvent(f->event);
|
||||||
}
|
}
|
||||||
_endthreadex(EXIT_SUCCESS);
|
_endthreadex(EXIT_SUCCESS);
|
||||||
return EXIT_SUCCESS; // if skidding
|
return EXIT_SUCCESS; // if skidding
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif linux // Posix
|
#elif linux // Posix
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
|
|
||||||
void *startthread(void *arg);
|
void *startthread(void *arg);
|
||||||
|
|
||||||
void err_abort(int status, const char *msg)
|
void err_abort(int status, const char *msg)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
|
fprintf(stderr, "fatal error = %d, %s\n", status, msg);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FileData
|
struct FileData
|
||||||
{
|
{
|
||||||
File *file;
|
File *file;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsyncRead
|
struct AsyncRead
|
||||||
{
|
{
|
||||||
static AsyncRead *create(size_t nfiles);
|
static AsyncRead *create(size_t nfiles);
|
||||||
void addFile(File *file);
|
void addFile(File *file);
|
||||||
void start();
|
void start();
|
||||||
int read(size_t i);
|
int read(size_t i);
|
||||||
static void dispose(AsyncRead *);
|
static void dispose(AsyncRead *);
|
||||||
|
|
||||||
size_t filesdim;
|
size_t filesdim;
|
||||||
size_t filesmax;
|
size_t filesmax;
|
||||||
FileData files[1];
|
FileData files[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||||
{
|
{
|
||||||
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
||||||
(nfiles - 1) * sizeof(FileData));
|
(nfiles - 1) * sizeof(FileData));
|
||||||
aw->filesmax = nfiles;
|
aw->filesmax = nfiles;
|
||||||
return aw;
|
return aw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::addFile(File *file)
|
void AsyncRead::addFile(File *file)
|
||||||
{
|
{
|
||||||
//printf("addFile(file = %p)\n", file);
|
//printf("addFile(file = %p)\n", file);
|
||||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||||
assert(filesdim < filesmax);
|
assert(filesdim < filesmax);
|
||||||
FileData *f = &files[filesdim];
|
FileData *f = &files[filesdim];
|
||||||
f->file = file;
|
f->file = file;
|
||||||
|
|
||||||
int status = pthread_mutex_init(&f->mutex, NULL);
|
int status = pthread_mutex_init(&f->mutex, NULL);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "init mutex");
|
err_abort(status, "init mutex");
|
||||||
status = pthread_cond_init(&f->cond, NULL);
|
status = pthread_cond_init(&f->cond, NULL);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "init cond");
|
err_abort(status, "init cond");
|
||||||
|
|
||||||
filesdim++;
|
filesdim++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::start()
|
void AsyncRead::start()
|
||||||
{
|
{
|
||||||
//printf("aw->filesdim = %p %d\n", this, filesdim);
|
//printf("aw->filesdim = %p %d\n", this, filesdim);
|
||||||
if (filesdim)
|
if (filesdim)
|
||||||
{
|
{
|
||||||
pthread_t thread_id;
|
pthread_t thread_id;
|
||||||
int status = pthread_create(&thread_id,
|
int status = pthread_create(&thread_id,
|
||||||
NULL,
|
NULL,
|
||||||
&startthread,
|
&startthread,
|
||||||
this);
|
this);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "create thread");
|
err_abort(status, "create thread");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsyncRead::read(size_t i)
|
int AsyncRead::read(size_t i)
|
||||||
{
|
{
|
||||||
FileData *f = &files[i];
|
FileData *f = &files[i];
|
||||||
|
|
||||||
// Wait for the event
|
// Wait for the event
|
||||||
int status = pthread_mutex_lock(&f->mutex);
|
int status = pthread_mutex_lock(&f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "lock mutex");
|
err_abort(status, "lock mutex");
|
||||||
while (f->value == 0)
|
while (f->value == 0)
|
||||||
{
|
{
|
||||||
status = pthread_cond_wait(&f->cond, &f->mutex);
|
status = pthread_cond_wait(&f->cond, &f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "wait on condition");
|
err_abort(status, "wait on condition");
|
||||||
}
|
}
|
||||||
status = pthread_mutex_unlock(&f->mutex);
|
status = pthread_mutex_unlock(&f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "unlock mutex");
|
err_abort(status, "unlock mutex");
|
||||||
|
|
||||||
return f->result;
|
return f->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::dispose(AsyncRead *aw)
|
void AsyncRead::dispose(AsyncRead *aw)
|
||||||
{
|
{
|
||||||
//printf("AsyncRead::dispose()\n");
|
//printf("AsyncRead::dispose()\n");
|
||||||
for (int i = 0; i < aw->filesdim; i++)
|
for (int i = 0; i < aw->filesdim; i++)
|
||||||
{
|
{
|
||||||
FileData *f = &aw->files[i];
|
FileData *f = &aw->files[i];
|
||||||
int status = pthread_cond_destroy(&f->cond);
|
int status = pthread_cond_destroy(&f->cond);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "cond destroy");
|
err_abort(status, "cond destroy");
|
||||||
status = pthread_mutex_destroy(&f->mutex);
|
status = pthread_mutex_destroy(&f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "mutex destroy");
|
err_abort(status, "mutex destroy");
|
||||||
}
|
}
|
||||||
free(aw);
|
free(aw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *startthread(void *p)
|
void *startthread(void *p)
|
||||||
{
|
{
|
||||||
AsyncRead *aw = (AsyncRead *)p;
|
AsyncRead *aw = (AsyncRead *)p;
|
||||||
|
|
||||||
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
|
//printf("startthread: aw->filesdim = %p %d\n", aw, aw->filesdim);
|
||||||
size_t dim = aw->filesdim;
|
size_t dim = aw->filesdim;
|
||||||
for (size_t i = 0; i < dim; i++)
|
for (size_t i = 0; i < dim; i++)
|
||||||
{ FileData *f = &aw->files[i];
|
{ FileData *f = &aw->files[i];
|
||||||
|
|
||||||
f->result = f->file->read();
|
f->result = f->file->read();
|
||||||
|
|
||||||
// Set event
|
// Set event
|
||||||
int status = pthread_mutex_lock(&f->mutex);
|
int status = pthread_mutex_lock(&f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "lock mutex");
|
err_abort(status, "lock mutex");
|
||||||
f->value = 1;
|
f->value = 1;
|
||||||
status = pthread_cond_signal(&f->cond);
|
status = pthread_cond_signal(&f->cond);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "signal condition");
|
err_abort(status, "signal condition");
|
||||||
status = pthread_mutex_unlock(&f->mutex);
|
status = pthread_mutex_unlock(&f->mutex);
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
err_abort(status, "unlock mutex");
|
err_abort(status, "unlock mutex");
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL; // end thread
|
return NULL; // end thread
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
|
|
||||||
struct FileData
|
struct FileData
|
||||||
{
|
{
|
||||||
File *file;
|
File *file;
|
||||||
int result;
|
int result;
|
||||||
//HANDLE event;
|
//HANDLE event;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AsyncRead
|
struct AsyncRead
|
||||||
{
|
{
|
||||||
static AsyncRead *create(size_t nfiles);
|
static AsyncRead *create(size_t nfiles);
|
||||||
void addFile(File *file);
|
void addFile(File *file);
|
||||||
void start();
|
void start();
|
||||||
int read(size_t i);
|
int read(size_t i);
|
||||||
static void dispose(AsyncRead *);
|
static void dispose(AsyncRead *);
|
||||||
|
|
||||||
//HANDLE hThread;
|
//HANDLE hThread;
|
||||||
|
|
||||||
size_t filesdim;
|
size_t filesdim;
|
||||||
size_t filesmax;
|
size_t filesmax;
|
||||||
FileData files[1];
|
FileData files[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AsyncRead *AsyncRead::create(size_t nfiles)
|
AsyncRead *AsyncRead::create(size_t nfiles)
|
||||||
{
|
{
|
||||||
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
|
||||||
(nfiles - 1) * sizeof(FileData));
|
(nfiles - 1) * sizeof(FileData));
|
||||||
aw->filesmax = nfiles;
|
aw->filesmax = nfiles;
|
||||||
return aw;
|
return aw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::addFile(File *file)
|
void AsyncRead::addFile(File *file)
|
||||||
{
|
{
|
||||||
//printf("addFile(file = %p)\n", file);
|
//printf("addFile(file = %p)\n", file);
|
||||||
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
//printf("filesdim = %d, filesmax = %d\n", filesdim, filesmax);
|
||||||
assert(filesdim < filesmax);
|
assert(filesdim < filesmax);
|
||||||
files[filesdim].file = file;
|
files[filesdim].file = file;
|
||||||
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
//files[filesdim].event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
//ResetEvent(files[filesdim].event);
|
//ResetEvent(files[filesdim].event);
|
||||||
filesdim++;
|
filesdim++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::start()
|
void AsyncRead::start()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int AsyncRead::read(size_t i)
|
int AsyncRead::read(size_t i)
|
||||||
{
|
{
|
||||||
FileData *f = &files[i];
|
FileData *f = &files[i];
|
||||||
f->result = f->file->read();
|
f->result = f->file->read();
|
||||||
return f->result;
|
return f->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncRead::dispose(AsyncRead *aw)
|
void AsyncRead::dispose(AsyncRead *aw)
|
||||||
{
|
{
|
||||||
free(aw);
|
free(aw);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
|
|
||||||
// Copyright (c) 2009-2009 by Digital Mars
|
// Copyright (c) 2009-2009 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#ifndef ASYNC_H
|
#ifndef ASYNC_H
|
||||||
#define ASYNC_H
|
#define ASYNC_H
|
||||||
|
|
||||||
#if __DMC__
|
#if __DMC__
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*******************
|
/*******************
|
||||||
* Simple interface to read files asynchronously in another
|
* Simple interface to read files asynchronously in another
|
||||||
* thread.
|
* thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct AsyncRead
|
struct AsyncRead
|
||||||
{
|
{
|
||||||
static AsyncRead *create(size_t nfiles);
|
static AsyncRead *create(size_t nfiles);
|
||||||
void addFile(File *file);
|
void addFile(File *file);
|
||||||
void start();
|
void start();
|
||||||
int read(size_t i);
|
int read(size_t i);
|
||||||
static void dispose(AsyncRead *);
|
static void dispose(AsyncRead *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
964
dmd/root/dchar.c
964
dmd/root/dchar.c
@@ -1,482 +1,482 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2006 by Digital Mars
|
// Copyright (c) 1999-2006 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
|
|
||||||
#if M_UNICODE
|
#if M_UNICODE
|
||||||
|
|
||||||
// Converts a char string to Unicode
|
// Converts a char string to Unicode
|
||||||
|
|
||||||
dchar *Dchar::dup(char *p)
|
dchar *Dchar::dup(char *p)
|
||||||
{
|
{
|
||||||
dchar *s;
|
dchar *s;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
|
s = (dchar *)mem.malloc((len + 1) * sizeof(dchar));
|
||||||
for (unsigned i = 0; i < len; i++)
|
for (unsigned i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
s[i] = (dchar)(p[i] & 0xFF);
|
s[i] = (dchar)(p[i] & 0xFF);
|
||||||
}
|
}
|
||||||
s[len] = 0;
|
s[len] = 0;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
dchar *Dchar::memchr(dchar *p, int c, int count)
|
dchar *Dchar::memchr(dchar *p, int c, int count)
|
||||||
{
|
{
|
||||||
int u;
|
int u;
|
||||||
|
|
||||||
for (u = 0; u < count; u++)
|
for (u = 0; u < count; u++)
|
||||||
{
|
{
|
||||||
if (p[u] == c)
|
if (p[u] == c)
|
||||||
return p + u;
|
return p + u;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if _WIN32 && __DMC__
|
#if _WIN32 && __DMC__
|
||||||
__declspec(naked)
|
__declspec(naked)
|
||||||
unsigned Dchar::calcHash(const dchar *str, unsigned len)
|
unsigned Dchar::calcHash(const dchar *str, unsigned len)
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
mov ECX,4[ESP]
|
mov ECX,4[ESP]
|
||||||
mov EDX,8[ESP]
|
mov EDX,8[ESP]
|
||||||
xor EAX,EAX
|
xor EAX,EAX
|
||||||
test EDX,EDX
|
test EDX,EDX
|
||||||
je L92
|
je L92
|
||||||
|
|
||||||
LC8: cmp EDX,1
|
LC8: cmp EDX,1
|
||||||
je L98
|
je L98
|
||||||
cmp EDX,2
|
cmp EDX,2
|
||||||
je LAE
|
je LAE
|
||||||
|
|
||||||
add EAX,[ECX]
|
add EAX,[ECX]
|
||||||
// imul EAX,EAX,025h
|
// imul EAX,EAX,025h
|
||||||
lea EAX,[EAX][EAX*8]
|
lea EAX,[EAX][EAX*8]
|
||||||
add ECX,4
|
add ECX,4
|
||||||
sub EDX,2
|
sub EDX,2
|
||||||
jmp LC8
|
jmp LC8
|
||||||
|
|
||||||
L98: mov DX,[ECX]
|
L98: mov DX,[ECX]
|
||||||
and EDX,0FFFFh
|
and EDX,0FFFFh
|
||||||
add EAX,EDX
|
add EAX,EDX
|
||||||
ret
|
ret
|
||||||
|
|
||||||
LAE: add EAX,[ECX]
|
LAE: add EAX,[ECX]
|
||||||
L92: ret
|
L92: ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
unsigned hash = 0;
|
unsigned hash = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash += *(const uint16_t *)str;
|
hash += *(const uint16_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash += *(const uint32_t *)str;
|
hash += *(const uint32_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash += *(const uint32_t *)str;
|
hash += *(const uint32_t *)str;
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
str += 2;
|
str += 2;
|
||||||
len -= 2;
|
len -= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash += *(const uint16_t *)str | 0x20;
|
hash += *(const uint16_t *)str | 0x20;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash += *(const uint32_t *)str | 0x200020;
|
hash += *(const uint32_t *)str | 0x200020;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash += *(const uint32_t *)str | 0x200020;
|
hash += *(const uint32_t *)str | 0x200020;
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
str += 2;
|
str += 2;
|
||||||
len -= 2;
|
len -= 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif MCBS
|
#elif MCBS
|
||||||
|
|
||||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint8_t *)str;
|
hash += *(const uint8_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint16_t *)str;
|
hash += *(const uint16_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += (*(const uint16_t *)str << 8) +
|
hash += (*(const uint16_t *)str << 8) +
|
||||||
((const uint8_t *)str)[2];
|
((const uint8_t *)str)[2];
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint32_t *)str;
|
hash += *(const uint32_t *)str;
|
||||||
str += 4;
|
str += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif UTF8
|
#elif UTF8
|
||||||
|
|
||||||
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
|
// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
|
||||||
|
|
||||||
char Dchar::mblen[256] =
|
char Dchar::mblen[256] =
|
||||||
{
|
{
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
|
4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1,
|
||||||
};
|
};
|
||||||
|
|
||||||
dchar *Dchar::dec(dchar *pstart, dchar *p)
|
dchar *Dchar::dec(dchar *pstart, dchar *p)
|
||||||
{
|
{
|
||||||
while ((p[-1] & 0xC0) == 0x80)
|
while ((p[-1] & 0xC0) == 0x80)
|
||||||
p--;
|
p--;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Dchar::get(dchar *p)
|
int Dchar::get(dchar *p)
|
||||||
{
|
{
|
||||||
unsigned c;
|
unsigned c;
|
||||||
unsigned char *q = (unsigned char *)p;
|
unsigned char *q = (unsigned char *)p;
|
||||||
|
|
||||||
c = q[0];
|
c = q[0];
|
||||||
switch (mblen[c])
|
switch (mblen[c])
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
c = ((c - 0xC0) << 6) |
|
c = ((c - 0xC0) << 6) |
|
||||||
(q[1] - 0x80);
|
(q[1] - 0x80);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
c = ((c - 0xE0) << 12) |
|
c = ((c - 0xE0) << 12) |
|
||||||
((q[1] - 0x80) << 6) |
|
((q[1] - 0x80) << 6) |
|
||||||
(q[2] - 0x80);
|
(q[2] - 0x80);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
c = ((c - 0xF0) << 18) |
|
c = ((c - 0xF0) << 18) |
|
||||||
((q[1] - 0x80) << 12) |
|
((q[1] - 0x80) << 12) |
|
||||||
((q[2] - 0x80) << 6) |
|
((q[2] - 0x80) << 6) |
|
||||||
(q[3] - 0x80);
|
(q[3] - 0x80);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
c = ((c - 0xF8) << 24) |
|
c = ((c - 0xF8) << 24) |
|
||||||
((q[1] - 0x80) << 18) |
|
((q[1] - 0x80) << 18) |
|
||||||
((q[2] - 0x80) << 12) |
|
((q[2] - 0x80) << 12) |
|
||||||
((q[3] - 0x80) << 6) |
|
((q[3] - 0x80) << 6) |
|
||||||
(q[4] - 0x80);
|
(q[4] - 0x80);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
c = ((c - 0xFC) << 30) |
|
c = ((c - 0xFC) << 30) |
|
||||||
((q[1] - 0x80) << 24) |
|
((q[1] - 0x80) << 24) |
|
||||||
((q[2] - 0x80) << 18) |
|
((q[2] - 0x80) << 18) |
|
||||||
((q[3] - 0x80) << 12) |
|
((q[3] - 0x80) << 12) |
|
||||||
((q[4] - 0x80) << 6) |
|
((q[4] - 0x80) << 6) |
|
||||||
(q[5] - 0x80);
|
(q[5] - 0x80);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
dchar *Dchar::put(dchar *p, unsigned c)
|
dchar *Dchar::put(dchar *p, unsigned c)
|
||||||
{
|
{
|
||||||
if (c <= 0x7F)
|
if (c <= 0x7F)
|
||||||
{
|
{
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
}
|
}
|
||||||
else if (c <= 0x7FF)
|
else if (c <= 0x7FF)
|
||||||
{
|
{
|
||||||
p[0] = 0xC0 + (c >> 6);
|
p[0] = 0xC0 + (c >> 6);
|
||||||
p[1] = 0x80 + (c & 0x3F);
|
p[1] = 0x80 + (c & 0x3F);
|
||||||
p += 2;
|
p += 2;
|
||||||
}
|
}
|
||||||
else if (c <= 0xFFFF)
|
else if (c <= 0xFFFF)
|
||||||
{
|
{
|
||||||
p[0] = 0xE0 + (c >> 12);
|
p[0] = 0xE0 + (c >> 12);
|
||||||
p[1] = 0x80 + ((c >> 6) & 0x3F);
|
p[1] = 0x80 + ((c >> 6) & 0x3F);
|
||||||
p[2] = 0x80 + (c & 0x3F);
|
p[2] = 0x80 + (c & 0x3F);
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
else if (c <= 0x1FFFFF)
|
else if (c <= 0x1FFFFF)
|
||||||
{
|
{
|
||||||
p[0] = 0xF0 + (c >> 18);
|
p[0] = 0xF0 + (c >> 18);
|
||||||
p[1] = 0x80 + ((c >> 12) & 0x3F);
|
p[1] = 0x80 + ((c >> 12) & 0x3F);
|
||||||
p[2] = 0x80 + ((c >> 6) & 0x3F);
|
p[2] = 0x80 + ((c >> 6) & 0x3F);
|
||||||
p[3] = 0x80 + (c & 0x3F);
|
p[3] = 0x80 + (c & 0x3F);
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
else if (c <= 0x3FFFFFF)
|
else if (c <= 0x3FFFFFF)
|
||||||
{
|
{
|
||||||
p[0] = 0xF8 + (c >> 24);
|
p[0] = 0xF8 + (c >> 24);
|
||||||
p[1] = 0x80 + ((c >> 18) & 0x3F);
|
p[1] = 0x80 + ((c >> 18) & 0x3F);
|
||||||
p[2] = 0x80 + ((c >> 12) & 0x3F);
|
p[2] = 0x80 + ((c >> 12) & 0x3F);
|
||||||
p[3] = 0x80 + ((c >> 6) & 0x3F);
|
p[3] = 0x80 + ((c >> 6) & 0x3F);
|
||||||
p[4] = 0x80 + (c & 0x3F);
|
p[4] = 0x80 + (c & 0x3F);
|
||||||
p += 5;
|
p += 5;
|
||||||
}
|
}
|
||||||
else if (c <= 0x7FFFFFFF)
|
else if (c <= 0x7FFFFFFF)
|
||||||
{
|
{
|
||||||
p[0] = 0xFC + (c >> 30);
|
p[0] = 0xFC + (c >> 30);
|
||||||
p[1] = 0x80 + ((c >> 24) & 0x3F);
|
p[1] = 0x80 + ((c >> 24) & 0x3F);
|
||||||
p[2] = 0x80 + ((c >> 18) & 0x3F);
|
p[2] = 0x80 + ((c >> 18) & 0x3F);
|
||||||
p[3] = 0x80 + ((c >> 12) & 0x3F);
|
p[3] = 0x80 + ((c >> 12) & 0x3F);
|
||||||
p[4] = 0x80 + ((c >> 6) & 0x3F);
|
p[4] = 0x80 + ((c >> 6) & 0x3F);
|
||||||
p[5] = 0x80 + (c & 0x3F);
|
p[5] = 0x80 + (c & 0x3F);
|
||||||
p += 6;
|
p += 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
assert(0); // not a UCS-4 character
|
assert(0); // not a UCS-4 character
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint8_t *)str;
|
hash += *(const uint8_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += *(const uint16_t *)str;
|
hash += *(const uint16_t *)str;
|
||||||
#else
|
#else
|
||||||
hash += str[0] * 256 + str[1];
|
hash += str[0] * 256 + str[1];
|
||||||
#endif
|
#endif
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += (*(const uint16_t *)str << 8) +
|
hash += (*(const uint16_t *)str << 8) +
|
||||||
((const uint8_t *)str)[2];
|
((const uint8_t *)str)[2];
|
||||||
#else
|
#else
|
||||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||||
#endif
|
#endif
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += *(const uint32_t *)str;
|
hash += *(const uint32_t *)str;
|
||||||
#else
|
#else
|
||||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
str += 4;
|
str += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // ascii
|
#else // ascii
|
||||||
|
|
||||||
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
hash_t Dchar::calcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint8_t *)str;
|
hash += *(const uint8_t *)str;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += *(const uint16_t *)str;
|
hash += *(const uint16_t *)str;
|
||||||
#else
|
#else
|
||||||
hash += str[0] * 256 + str[1];
|
hash += str[0] * 256 + str[1];
|
||||||
#endif
|
#endif
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += (*(const uint16_t *)str << 8) +
|
hash += (*(const uint16_t *)str << 8) +
|
||||||
((const uint8_t *)str)[2];
|
((const uint8_t *)str)[2];
|
||||||
#else
|
#else
|
||||||
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
hash += (str[0] * 256 + str[1]) * 256 + str[2];
|
||||||
#endif
|
#endif
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
#if LITTLE_ENDIAN
|
#if LITTLE_ENDIAN
|
||||||
hash += *(const uint32_t *)str;
|
hash += *(const uint32_t *)str;
|
||||||
#else
|
#else
|
||||||
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
|
||||||
#endif
|
#endif
|
||||||
str += 4;
|
str += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
hash_t Dchar::icalcHash(const dchar *str, size_t len)
|
||||||
{
|
{
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
switch (len)
|
switch (len)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint8_t *)str | 0x20;
|
hash += *(const uint8_t *)str | 0x20;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint16_t *)str | 0x2020;
|
hash += *(const uint16_t *)str | 0x2020;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += ((*(const uint16_t *)str << 8) +
|
hash += ((*(const uint16_t *)str << 8) +
|
||||||
((const uint8_t *)str)[2]) | 0x202020;
|
((const uint8_t *)str)[2]) | 0x202020;
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hash *= 37;
|
hash *= 37;
|
||||||
hash += *(const uint32_t *)str | 0x20202020;
|
hash += *(const uint32_t *)str | 0x20202020;
|
||||||
str += 4;
|
str += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// Print out values to hardcode into Dchar::mblen[]
|
// Print out values to hardcode into Dchar::mblen[]
|
||||||
int c;
|
int c;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
for (c = 0; c < 256; c++)
|
for (c = 0; c < 256; c++)
|
||||||
{
|
{
|
||||||
s = 1;
|
s = 1;
|
||||||
if (c >= 0xC0 && c <= 0xDF)
|
if (c >= 0xC0 && c <= 0xDF)
|
||||||
s = 2;
|
s = 2;
|
||||||
if (c >= 0xE0 && c <= 0xEF)
|
if (c >= 0xE0 && c <= 0xEF)
|
||||||
s = 3;
|
s = 3;
|
||||||
if (c >= 0xF0 && c <= 0xF7)
|
if (c >= 0xF0 && c <= 0xF7)
|
||||||
s = 4;
|
s = 4;
|
||||||
if (c >= 0xF8 && c <= 0xFB)
|
if (c >= 0xF8 && c <= 0xFB)
|
||||||
s = 5;
|
s = 5;
|
||||||
if (c >= 0xFC && c <= 0xFD)
|
if (c >= 0xFC && c <= 0xFD)
|
||||||
s = 6;
|
s = 6;
|
||||||
|
|
||||||
printf("%d", s);
|
printf("%d", s);
|
||||||
if ((c & 15) == 15)
|
if ((c & 15) == 15)
|
||||||
printf(",\n");
|
printf(",\n");
|
||||||
else
|
else
|
||||||
printf(",");
|
printf(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
388
dmd/root/dchar.h
388
dmd/root/dchar.h
@@ -1,194 +1,194 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2011 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
|
|
||||||
#ifndef DCHAR_H
|
#ifndef DCHAR_H
|
||||||
#define DCHAR_H
|
#define DCHAR_H
|
||||||
|
|
||||||
#if __GNUC__ && !_WIN32
|
#if __GNUC__ && !_WIN32
|
||||||
#include "gnuc.h"
|
#include "gnuc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _MSC_VER
|
#if _MSC_VER
|
||||||
// Disable useless warnings about unreferenced functions
|
// Disable useless warnings about unreferenced functions
|
||||||
#pragma warning (disable : 4514)
|
#pragma warning (disable : 4514)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#include "root.h"
|
//#include "root.h"
|
||||||
typedef size_t hash_t;
|
typedef size_t hash_t;
|
||||||
|
|
||||||
#undef TEXT
|
#undef TEXT
|
||||||
|
|
||||||
// NOTE: All functions accepting pointer arguments must not be NULL
|
// NOTE: All functions accepting pointer arguments must not be NULL
|
||||||
|
|
||||||
#if M_UNICODE
|
#if M_UNICODE
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
typedef wchar_t dchar;
|
typedef wchar_t dchar;
|
||||||
#define TEXT(x) L##x
|
#define TEXT(x) L##x
|
||||||
|
|
||||||
#define Dchar_mbmax 1
|
#define Dchar_mbmax 1
|
||||||
|
|
||||||
struct Dchar
|
struct Dchar
|
||||||
{
|
{
|
||||||
static dchar *inc(dchar *p) { return p + 1; }
|
static dchar *inc(dchar *p) { return p + 1; }
|
||||||
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
|
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
|
||||||
static int len(const dchar *p) { return wcslen(p); }
|
static int len(const dchar *p) { return wcslen(p); }
|
||||||
static dchar get(dchar *p) { return *p; }
|
static dchar get(dchar *p) { return *p; }
|
||||||
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
|
static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; }
|
||||||
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
|
static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; }
|
||||||
static int cmp(dchar *s1, dchar *s2)
|
static int cmp(dchar *s1, dchar *s2)
|
||||||
{
|
{
|
||||||
#if __DMC__
|
#if __DMC__
|
||||||
if (!*s1 && !*s2) // wcscmp is broken
|
if (!*s1 && !*s2) // wcscmp is broken
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
return wcscmp(s1, s2);
|
return wcscmp(s1, s2);
|
||||||
#if 0
|
#if 0
|
||||||
return (*s1 == *s2)
|
return (*s1 == *s2)
|
||||||
? wcscmp(s1, s2)
|
? wcscmp(s1, s2)
|
||||||
: ((int)*s1 - (int)*s2);
|
: ((int)*s1 - (int)*s2);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
|
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); }
|
||||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||||
static int isAlpha(dchar c) { return iswalpha(c); }
|
static int isAlpha(dchar c) { return iswalpha(c); }
|
||||||
static int isUpper(dchar c) { return iswupper(c); }
|
static int isUpper(dchar c) { return iswupper(c); }
|
||||||
static int isLower(dchar c) { return iswlower(c); }
|
static int isLower(dchar c) { return iswlower(c); }
|
||||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||||
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
|
static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; }
|
||||||
static int toLower(dchar *p) { return toLower(*p); }
|
static int toLower(dchar *p) { return toLower(*p); }
|
||||||
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
|
static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; }
|
||||||
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
|
static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory?
|
||||||
static dchar *dup(char *p);
|
static dchar *dup(char *p);
|
||||||
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
|
static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); }
|
||||||
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
|
static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); }
|
||||||
static dchar *memchr(dchar *p, int c, int count);
|
static dchar *memchr(dchar *p, int c, int count);
|
||||||
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
|
static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); }
|
||||||
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
|
static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); }
|
||||||
static hash_t calcHash(const dchar *str, size_t len);
|
static hash_t calcHash(const dchar *str, size_t len);
|
||||||
|
|
||||||
// Case insensitive versions
|
// Case insensitive versions
|
||||||
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
|
static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); }
|
||||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
|
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); }
|
||||||
static hash_t icalcHash(const dchar *str, size_t len);
|
static hash_t icalcHash(const dchar *str, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif MCBS
|
#elif MCBS
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <mbstring.h>
|
#include <mbstring.h>
|
||||||
|
|
||||||
typedef char dchar;
|
typedef char dchar;
|
||||||
#define TEXT(x) x
|
#define TEXT(x) x
|
||||||
|
|
||||||
#define Dchar_mbmax MB_LEN_MAX
|
#define Dchar_mbmax MB_LEN_MAX
|
||||||
|
|
||||||
#elif UTF8
|
#elif UTF8
|
||||||
|
|
||||||
typedef char dchar;
|
typedef char dchar;
|
||||||
#define TEXT(x) x
|
#define TEXT(x) x
|
||||||
|
|
||||||
#define Dchar_mbmax 6
|
#define Dchar_mbmax 6
|
||||||
|
|
||||||
struct Dchar
|
struct Dchar
|
||||||
{
|
{
|
||||||
static char mblen[256];
|
static char mblen[256];
|
||||||
|
|
||||||
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
|
static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; }
|
||||||
static dchar *dec(dchar *pstart, dchar *p);
|
static dchar *dec(dchar *pstart, dchar *p);
|
||||||
static int len(const dchar *p) { return strlen(p); }
|
static int len(const dchar *p) { return strlen(p); }
|
||||||
static int get(dchar *p);
|
static int get(dchar *p);
|
||||||
static int getprev(dchar *pstart, dchar *p)
|
static int getprev(dchar *pstart, dchar *p)
|
||||||
{ return *dec(pstart, p) & 0xFF; }
|
{ return *dec(pstart, p) & 0xFF; }
|
||||||
static dchar *put(dchar *p, unsigned c);
|
static dchar *put(dchar *p, unsigned c);
|
||||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||||
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
|
static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; }
|
||||||
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
|
static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; }
|
||||||
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
|
static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; }
|
||||||
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
static int isLocaleUpper(dchar c) { return isUpper(c); }
|
||||||
static int isLocaleLower(dchar c) { return isLower(c); }
|
static int isLocaleLower(dchar c) { return isLower(c); }
|
||||||
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
|
static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; }
|
||||||
static int toLower(dchar *p) { return toLower(*p); }
|
static int toLower(dchar *p) { return toLower(*p); }
|
||||||
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
|
static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; }
|
||||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||||
static dchar *memchr(dchar *p, int c, int count)
|
static dchar *memchr(dchar *p, int c, int count)
|
||||||
{ return (dchar *)::memchr(p, c, count); }
|
{ return (dchar *)::memchr(p, c, count); }
|
||||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||||
static hash_t calcHash(const dchar *str, size_t len);
|
static hash_t calcHash(const dchar *str, size_t len);
|
||||||
|
|
||||||
// Case insensitive versions
|
// Case insensitive versions
|
||||||
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
|
static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); }
|
||||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
|
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef GCC_SAFE_DMD
|
#ifndef GCC_SAFE_DMD
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef char dchar;
|
typedef char dchar;
|
||||||
#define TEXT(x) x
|
#define TEXT(x) x
|
||||||
|
|
||||||
#define Dchar_mbmax 1
|
#define Dchar_mbmax 1
|
||||||
|
|
||||||
struct Dchar
|
struct Dchar
|
||||||
{
|
{
|
||||||
static dchar *inc(dchar *p) { return p + 1; }
|
static dchar *inc(dchar *p) { return p + 1; }
|
||||||
static dchar *dec(dchar *pstart, dchar *p) { return p - 1; }
|
static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; }
|
||||||
static int len(const dchar *p) { return strlen(p); }
|
static int len(const dchar *p) { return strlen(p); }
|
||||||
static int get(dchar *p) { return *p & 0xFF; }
|
static int get(dchar *p) { return *p & 0xFF; }
|
||||||
static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; }
|
static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; }
|
||||||
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
|
static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; }
|
||||||
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); }
|
||||||
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); }
|
||||||
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
static int isDigit(dchar c) { return '0' <= c && c <= '9'; }
|
||||||
#ifndef GCC_SAFE_DMD
|
#ifndef GCC_SAFE_DMD
|
||||||
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
|
static int isAlpha(dchar c) { return isalpha((unsigned char)c); }
|
||||||
static int isUpper(dchar c) { return isupper((unsigned char)c); }
|
static int isUpper(dchar c) { return isupper((unsigned char)c); }
|
||||||
static int isLower(dchar c) { return islower((unsigned char)c); }
|
static int isLower(dchar c) { return islower((unsigned char)c); }
|
||||||
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
|
static int isLocaleUpper(dchar c) { return isupper((unsigned char)c); }
|
||||||
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
|
static int isLocaleLower(dchar c) { return islower((unsigned char)c); }
|
||||||
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
|
static int toLower(dchar c) { return isupper((unsigned char)c) ? tolower(c) : c; }
|
||||||
static int toLower(dchar *p) { return toLower(*p); }
|
static int toLower(dchar *p) { return toLower(*p); }
|
||||||
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
|
static int toUpper(dchar c) { return islower((unsigned char)c) ? toupper(c) : c; }
|
||||||
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory?
|
||||||
#endif
|
#endif
|
||||||
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
static dchar *chr(dchar *p, int c) { return strchr(p, c); }
|
||||||
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
static dchar *rchr(dchar *p, int c) { return strrchr(p, c); }
|
||||||
static dchar *memchr(dchar *p, int c, int count)
|
static dchar *memchr(dchar *p, int c, int count)
|
||||||
{ return (dchar *)::memchr(p, c, count); }
|
{ return (dchar *)::memchr(p, c, count); }
|
||||||
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); }
|
||||||
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); }
|
||||||
static hash_t calcHash(const dchar *str, size_t len);
|
static hash_t calcHash(const dchar *str, size_t len);
|
||||||
|
|
||||||
// Case insensitive versions
|
// Case insensitive versions
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
|
static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); }
|
||||||
#else
|
#else
|
||||||
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
|
static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); }
|
||||||
#endif
|
#endif
|
||||||
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
|
static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); }
|
||||||
static hash_t icalcHash(const dchar *str, size_t len);
|
static hash_t icalcHash(const dchar *str, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
636
dmd/root/longdouble.c
Normal file
636
dmd/root/longdouble.c
Normal 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
254
dmd/root/longdouble.h
Normal 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__
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
// lstring.c
|
// lstring.c
|
||||||
|
|
||||||
// Copyright (c) 1999-2002 by Digital Mars
|
// Copyright (c) 1999-2002 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER // prevent compiler internal crash
|
#ifdef _MSC_VER // prevent compiler internal crash
|
||||||
Lstring Lstring::zero;
|
Lstring Lstring::zero;
|
||||||
#else
|
#else
|
||||||
Lstring Lstring::zero = LSTRING_EMPTY();
|
Lstring Lstring::zero = LSTRING_EMPTY();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Lstring *Lstring::ctor(const dchar *p, unsigned length)
|
Lstring *Lstring::ctor(const dchar *p, unsigned length)
|
||||||
{
|
{
|
||||||
Lstring *s;
|
Lstring *s;
|
||||||
|
|
||||||
s = alloc(length);
|
s = alloc(length);
|
||||||
memcpy(s->string, p, length * sizeof(dchar));
|
memcpy(s->string, p, length * sizeof(dchar));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lstring *Lstring::alloc(unsigned length)
|
Lstring *Lstring::alloc(unsigned length)
|
||||||
{
|
{
|
||||||
Lstring *s;
|
Lstring *s;
|
||||||
|
|
||||||
s = (Lstring *)mem.malloc(size(length));
|
s = (Lstring *)mem.malloc(size(length));
|
||||||
s->length = length;
|
s->length = length;
|
||||||
s->string[length] = 0;
|
s->string[length] = 0;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lstring *Lstring::append(const Lstring *s)
|
Lstring *Lstring::append(const Lstring *s)
|
||||||
{
|
{
|
||||||
Lstring *t;
|
Lstring *t;
|
||||||
|
|
||||||
if (!s->length)
|
if (!s->length)
|
||||||
return this;
|
return this;
|
||||||
t = alloc(length + s->length);
|
t = alloc(length + s->length);
|
||||||
memcpy(t->string, string, length * sizeof(dchar));
|
memcpy(t->string, string, length * sizeof(dchar));
|
||||||
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
|
memcpy(t->string + length, s->string, s->length * sizeof(dchar));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lstring *Lstring::substring(int start, int end)
|
Lstring *Lstring::substring(int start, int end)
|
||||||
{
|
{
|
||||||
Lstring *t;
|
Lstring *t;
|
||||||
|
|
||||||
if (start == end)
|
if (start == end)
|
||||||
return &zero;
|
return &zero;
|
||||||
t = alloc(end - start);
|
t = alloc(end - start);
|
||||||
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
|
memcpy(t->string, string + start, (end - start) * sizeof(dchar));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +1,74 @@
|
|||||||
|
|
||||||
// lstring.h
|
// lstring.h
|
||||||
// length-prefixed strings
|
// length-prefixed strings
|
||||||
|
|
||||||
// Copyright (c) 1999-2002 by Digital Mars
|
// Copyright (c) 1999-2002 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// www.digitalmars.com
|
// www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#ifndef LSTRING_H
|
#ifndef LSTRING_H
|
||||||
#define LSTRING_H 1
|
#define LSTRING_H 1
|
||||||
|
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
|
|
||||||
struct Lstring
|
struct Lstring
|
||||||
{
|
{
|
||||||
unsigned length;
|
unsigned length;
|
||||||
|
|
||||||
// Disable warning about nonstandard extension
|
#ifndef IN_GCC
|
||||||
#pragma warning (disable : 4200)
|
// Disable warning about nonstandard extension
|
||||||
dchar string[];
|
#pragma warning (disable : 4200)
|
||||||
|
#endif
|
||||||
static Lstring zero; // 0 length string
|
dchar string[];
|
||||||
|
|
||||||
// No constructors because we want to be able to statically
|
static Lstring zero; // 0 length string
|
||||||
// initialize Lstring's, and Lstrings are of variable size.
|
|
||||||
|
// No constructors because we want to be able to statically
|
||||||
#if M_UNICODE
|
// initialize Lstring's, and Lstrings are of variable size.
|
||||||
#define LSTRING(p,length) { length, L##p }
|
|
||||||
#else
|
#if M_UNICODE
|
||||||
#define LSTRING(p,length) { length, p }
|
#define LSTRING(p,length) { length, L##p }
|
||||||
#endif
|
#else
|
||||||
|
#define LSTRING(p,length) { length, p }
|
||||||
#if __GNUC__
|
#endif
|
||||||
#define LSTRING_EMPTY() { 0 }
|
|
||||||
#else
|
#if __GNUC__
|
||||||
#define LSTRING_EMPTY() LSTRING("", 0)
|
#define LSTRING_EMPTY() { 0 }
|
||||||
#endif
|
#else
|
||||||
|
#define LSTRING_EMPTY() LSTRING("", 0)
|
||||||
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
|
#endif
|
||||||
static Lstring *ctor(const dchar *p, unsigned length);
|
|
||||||
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
|
static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); }
|
||||||
static Lstring *alloc(unsigned length);
|
static Lstring *ctor(const dchar *p, unsigned length);
|
||||||
Lstring *clone();
|
static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); }
|
||||||
|
static Lstring *alloc(unsigned length);
|
||||||
unsigned len() { return length; }
|
Lstring *clone();
|
||||||
|
|
||||||
dchar *toDchars() { return string; }
|
unsigned len() { return length; }
|
||||||
|
|
||||||
hash_t hash() { return Dchar::calcHash(string, length); }
|
dchar *toDchars() { return string; }
|
||||||
hash_t ihash() { return Dchar::icalcHash(string, length); }
|
|
||||||
|
hash_t hash() { return Dchar::calcHash(string, length); }
|
||||||
static int cmp(const Lstring *s1, const Lstring *s2)
|
hash_t ihash() { return Dchar::icalcHash(string, length); }
|
||||||
{
|
|
||||||
int c = s2->length - s1->length;
|
static int cmp(const Lstring *s1, const Lstring *s2)
|
||||||
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
|
{
|
||||||
}
|
int c = s2->length - s1->length;
|
||||||
|
return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length);
|
||||||
static int icmp(const Lstring *s1, const Lstring *s2)
|
}
|
||||||
{
|
|
||||||
int c = s2->length - s1->length;
|
static int icmp(const Lstring *s1, const Lstring *s2)
|
||||||
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
|
{
|
||||||
}
|
int c = s2->length - s1->length;
|
||||||
|
return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length);
|
||||||
Lstring *append(const Lstring *s);
|
}
|
||||||
Lstring *substring(int start, int end);
|
|
||||||
};
|
Lstring *append(const Lstring *s);
|
||||||
|
Lstring *substring(int start, int end);
|
||||||
#endif
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
200
dmd/root/man.c
200
dmd/root/man.c
@@ -1,100 +1,100 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 2008-2009 by Digital Mars
|
// Copyright (c) 2008-2009 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#pragma comment(lib,"shell32.lib")
|
#pragma comment(lib,"shell32.lib")
|
||||||
|
|
||||||
void browse(const char *url)
|
void browse(const char *url)
|
||||||
{
|
{
|
||||||
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
|
#if linux || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void browse(const char *url)
|
void browse(const char *url)
|
||||||
{
|
{
|
||||||
pid_t childpid;
|
pid_t childpid;
|
||||||
const char *args[3];
|
const char *args[3];
|
||||||
|
|
||||||
const char *browser = getenv("BROWSER");
|
const char *browser = getenv("BROWSER");
|
||||||
if (browser)
|
if (browser)
|
||||||
browser = strdup(browser);
|
browser = strdup(browser);
|
||||||
else
|
else
|
||||||
browser = "x-www-browser";
|
browser = "x-www-browser";
|
||||||
|
|
||||||
args[0] = browser;
|
args[0] = browser;
|
||||||
args[1] = url;
|
args[1] = url;
|
||||||
args[2] = NULL;
|
args[2] = NULL;
|
||||||
|
|
||||||
childpid = fork();
|
childpid = fork();
|
||||||
if (childpid == 0)
|
if (childpid == 0)
|
||||||
{
|
{
|
||||||
execvp(args[0], (char**)args);
|
execvp(args[0], (char**)args);
|
||||||
perror(args[0]); // failed to execute
|
perror(args[0]); // failed to execute
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
void browse(const char *url)
|
void browse(const char *url)
|
||||||
{
|
{
|
||||||
pid_t childpid;
|
pid_t childpid;
|
||||||
const char *args[5];
|
const char *args[5];
|
||||||
|
|
||||||
char *browser = getenv("BROWSER");
|
char *browser = getenv("BROWSER");
|
||||||
if (browser)
|
if (browser)
|
||||||
{ browser = strdup(browser);
|
{ browser = strdup(browser);
|
||||||
args[0] = browser;
|
args[0] = browser;
|
||||||
args[1] = url;
|
args[1] = url;
|
||||||
args[2] = NULL;
|
args[2] = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
|
//browser = "/Applications/Safari.app/Contents/MacOS/Safari";
|
||||||
args[0] = "open";
|
args[0] = "open";
|
||||||
args[1] = "-a";
|
args[1] = "-a";
|
||||||
args[2] = "/Applications/Safari.app";
|
args[2] = "/Applications/Safari.app";
|
||||||
args[3] = url;
|
args[3] = url;
|
||||||
args[4] = NULL;
|
args[4] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
childpid = fork();
|
childpid = fork();
|
||||||
if (childpid == 0)
|
if (childpid == 0)
|
||||||
{
|
{
|
||||||
execvp(args[0], (char**)args);
|
execvp(args[0], (char**)args);
|
||||||
perror(args[0]); // failed to execute
|
perror(args[0]); // failed to execute
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1451
dmd/root/port.c
1451
dmd/root/port.c
File diff suppressed because it is too large
Load Diff
164
dmd/root/port.h
164
dmd/root/port.h
@@ -1,81 +1,83 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2009 by Digital Mars
|
// Copyright (c) 1999-2009 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
|
|
||||||
#ifndef PORT_H
|
#ifndef PORT_H
|
||||||
#define PORT_H
|
#define PORT_H
|
||||||
|
|
||||||
// Portable wrapper around compiler/system specific things.
|
// Portable wrapper around compiler/system specific things.
|
||||||
// The idea is to minimize #ifdef's in the app code.
|
// The idea is to minimize #ifdef's in the app code.
|
||||||
|
|
||||||
#ifndef TYPEDEFS
|
#include "longdouble.h"
|
||||||
#define TYPEDEFS
|
|
||||||
|
#ifndef TYPEDEFS
|
||||||
#include <wchar.h>
|
#define TYPEDEFS
|
||||||
|
|
||||||
#if _MSC_VER
|
#include <wchar.h>
|
||||||
typedef __int64 longlong;
|
|
||||||
typedef unsigned __int64 ulonglong;
|
#if _MSC_VER
|
||||||
|
typedef __int64 longlong;
|
||||||
// According to VC 8.0 docs, long double is the same as double
|
typedef unsigned __int64 ulonglong;
|
||||||
#define strtold strtod
|
|
||||||
#define strtof strtod
|
// According to VC 8.0 docs, long double is the same as double
|
||||||
|
longdouble strtold(const char *p,char **endp);
|
||||||
#else
|
#define strtof strtod
|
||||||
typedef long long longlong;
|
|
||||||
typedef unsigned long long ulonglong;
|
#else
|
||||||
#endif
|
typedef long long longlong;
|
||||||
|
typedef unsigned long long ulonglong;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef double d_time;
|
#endif
|
||||||
|
|
||||||
struct Port
|
typedef double d_time;
|
||||||
{
|
|
||||||
static double nan;
|
struct Port
|
||||||
static double infinity;
|
{
|
||||||
static double dbl_max;
|
static double nan;
|
||||||
static double dbl_min;
|
static double infinity;
|
||||||
static long double ldbl_max;
|
static double dbl_max;
|
||||||
|
static double dbl_min;
|
||||||
#if __OpenBSD__
|
static longdouble ldbl_max;
|
||||||
#elif __GNUC__ && !defined __HAIKU__
|
|
||||||
// These conflict with macros in math.h, should rename them
|
#if __OpenBSD__
|
||||||
#undef isnan
|
#elif __GNUC__ && !defined __HAIKU__
|
||||||
#undef isfinite
|
// These conflict with macros in math.h, should rename them
|
||||||
#undef isinfinity
|
#undef isnan
|
||||||
#undef signbit
|
#undef isfinite
|
||||||
#endif
|
#undef isinfinity
|
||||||
static int isNan(double);
|
#undef signbit
|
||||||
static int isNan(long double);
|
#endif
|
||||||
|
static int isNan(double);
|
||||||
static int isSignallingNan(double);
|
static int isNan(longdouble);
|
||||||
static int isSignallingNan(long double);
|
|
||||||
|
static int isSignallingNan(double);
|
||||||
static int isFinite(double);
|
static int isSignallingNan(longdouble);
|
||||||
static int isInfinity(double);
|
|
||||||
static int Signbit(double);
|
static int isFinite(double);
|
||||||
|
static int isInfinity(double);
|
||||||
static double floor(double);
|
static int Signbit(double);
|
||||||
static double pow(double x, double y);
|
|
||||||
|
static double floor(double);
|
||||||
static long double fmodl(long double x, long double y);
|
static double pow(double x, double y);
|
||||||
|
|
||||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
static longdouble fmodl(longdouble x, longdouble y);
|
||||||
|
|
||||||
static char *ull_to_string(char *buffer, ulonglong ull);
|
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||||
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
|
||||||
|
static char *ull_to_string(char *buffer, ulonglong ull);
|
||||||
// Convert ulonglong to double
|
static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull);
|
||||||
static double ull_to_double(ulonglong ull);
|
|
||||||
|
// Convert ulonglong to double
|
||||||
// Get locale-dependent list separator
|
static double ull_to_double(ulonglong ull);
|
||||||
static const char *list_separator();
|
|
||||||
static const wchar_t *wlist_separator();
|
// Get locale-dependent list separator
|
||||||
|
static const char *list_separator();
|
||||||
static char *strupr(char *);
|
static const wchar_t *wlist_separator();
|
||||||
};
|
|
||||||
|
static char *strupr(char *);
|
||||||
#endif
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2011 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#ifndef POSIX
|
#ifndef POSIX
|
||||||
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
|
#define POSIX (linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
#ifdef __HAIKU__
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if POSIX
|
#if POSIX
|
||||||
@@ -364,21 +364,21 @@ FileName::FileName(char *path, char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Split a path into an Array of paths
|
// Split a path into an Array of paths
|
||||||
Strings *FileName::splitPath(const char *path)
|
Strings *FileName::splitPath(const char *path)
|
||||||
{
|
{
|
||||||
char c = 0; // unnecessary initializer is for VC /W4
|
char c = 0; // unnecessary initializer is for VC /W4
|
||||||
const char *p;
|
const char *p;
|
||||||
OutBuffer buf;
|
OutBuffer buf;
|
||||||
Strings *array;
|
Strings *array;
|
||||||
|
|
||||||
array = new Strings();
|
array = new Strings();
|
||||||
if (path)
|
if (path)
|
||||||
{
|
{
|
||||||
p = path;
|
p = path;
|
||||||
do
|
do
|
||||||
{ char instring = 0;
|
{ char instring = 0;
|
||||||
|
|
||||||
while (isspace((unsigned char)*p)) // skip leading whitespace
|
while (isspace((unsigned char)*p)) // skip leading whitespace
|
||||||
p++;
|
p++;
|
||||||
buf.reserve(strlen(p) + 1); // guess size of path
|
buf.reserve(strlen(p) + 1); // guess size of path
|
||||||
// LDC remember first character
|
// LDC remember first character
|
||||||
@@ -799,7 +799,7 @@ void FileName::CopyTo(FileName *to)
|
|||||||
* cwd if !=0, search current directory before searching path
|
* cwd if !=0, search current directory before searching path
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
||||||
{
|
{
|
||||||
if (absolute(name))
|
if (absolute(name))
|
||||||
{
|
{
|
||||||
@@ -815,7 +815,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
|||||||
|
|
||||||
for (i = 0; i < path->dim; i++)
|
for (i = 0; i < path->dim; i++)
|
||||||
{
|
{
|
||||||
char *p = path->tdata()[i];
|
char *p = path->tdata()[i];
|
||||||
char *n = combine(p, name);
|
char *n = combine(p, name);
|
||||||
|
|
||||||
if (exists(n))
|
if (exists(n))
|
||||||
@@ -839,7 +839,7 @@ char *FileName::searchPath(Strings *path, const char *name, int cwd)
|
|||||||
* !=NULL mem.malloc'd file name
|
* !=NULL mem.malloc'd file name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *FileName::safeSearchPath(Strings *path, const char *name)
|
char *FileName::safeSearchPath(Strings *path, const char *name)
|
||||||
{
|
{
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
/* Disallow % / \ : and .. in name characters
|
/* Disallow % / \ : and .. in name characters
|
||||||
@@ -876,7 +876,7 @@ char *FileName::safeSearchPath(Strings *path, const char *name)
|
|||||||
for (i = 0; i < path->dim; i++)
|
for (i = 0; i < path->dim; i++)
|
||||||
{
|
{
|
||||||
char *cname = NULL;
|
char *cname = NULL;
|
||||||
char *cpath = canonicalName(path->tdata()[i]);
|
char *cpath = canonicalName(path->tdata()[i]);
|
||||||
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
//printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n",
|
||||||
// name, (char *)path->data[i], cpath);
|
// name, (char *)path->data[i], cpath);
|
||||||
if (cpath == NULL)
|
if (cpath == NULL)
|
||||||
@@ -966,7 +966,7 @@ void FileName::ensurePathExists(const char *path)
|
|||||||
{
|
{
|
||||||
//printf("mkdir(%s)\n", path);
|
//printf("mkdir(%s)\n", path);
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
if (_mkdir(path))
|
if (_mkdir(path))
|
||||||
#endif
|
#endif
|
||||||
#if POSIX
|
#if POSIX
|
||||||
if (mkdir(path, 0777))
|
if (mkdir(path, 0777))
|
||||||
@@ -1088,13 +1088,13 @@ int File::read()
|
|||||||
//printf("File::read('%s')\n",name);
|
//printf("File::read('%s')\n",name);
|
||||||
fd = open(name, O_RDONLY);
|
fd = open(name, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
//printf("\topen error, errno = %d\n",errno);
|
//printf("\topen error, errno = %d\n",errno);
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
::free(buffer);
|
::free(buffer);
|
||||||
ref = 0; // we own the buffer now
|
ref = 0; // we own the buffer now
|
||||||
|
|
||||||
//printf("\tfile opened\n");
|
//printf("\tfile opened\n");
|
||||||
@@ -1104,7 +1104,7 @@ int File::read()
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
size = buf.st_size;
|
size = buf.st_size;
|
||||||
buffer = (unsigned char *) ::malloc(size + 2);
|
buffer = (unsigned char *) ::malloc(size + 2);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
{
|
{
|
||||||
printf("\tmalloc error, errno = %d\n",errno);
|
printf("\tmalloc error, errno = %d\n",errno);
|
||||||
@@ -1137,7 +1137,7 @@ int File::read()
|
|||||||
err2:
|
err2:
|
||||||
close(fd);
|
close(fd);
|
||||||
err:
|
err:
|
||||||
::free(buffer);
|
::free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
@@ -1158,11 +1158,11 @@ err1:
|
|||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
::free(buffer);
|
::free(buffer);
|
||||||
ref = 0;
|
ref = 0;
|
||||||
|
|
||||||
size = GetFileSize(h,NULL);
|
size = GetFileSize(h,NULL);
|
||||||
buffer = (unsigned char *) ::malloc(size + 2);
|
buffer = (unsigned char *) ::malloc(size + 2);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
@@ -1191,7 +1191,7 @@ err1:
|
|||||||
err2:
|
err2:
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
err:
|
err:
|
||||||
::free(buffer);
|
::free(buffer);
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
@@ -1454,23 +1454,23 @@ void File::remove()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Files *File::match(char *n)
|
Files *File::match(char *n)
|
||||||
{
|
{
|
||||||
return match(new FileName(n, 0));
|
return match(new FileName(n, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
Files *File::match(FileName *n)
|
Files *File::match(FileName *n)
|
||||||
{
|
{
|
||||||
#if POSIX
|
#if POSIX
|
||||||
return NULL;
|
return NULL;
|
||||||
#elif _WIN32
|
#elif _WIN32
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
WIN32_FIND_DATAA fileinfo;
|
WIN32_FIND_DATAA fileinfo;
|
||||||
Files *a;
|
Files *a;
|
||||||
char *c;
|
char *c;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
a = new Files();
|
a = new Files();
|
||||||
c = n->toChars();
|
c = n->toChars();
|
||||||
name = n->name();
|
name = n->name();
|
||||||
h = FindFirstFileA(c,&fileinfo);
|
h = FindFirstFileA(c,&fileinfo);
|
||||||
@@ -1540,7 +1540,7 @@ void File::stat()
|
|||||||
void File::checkoffset(size_t offset, size_t nbytes)
|
void File::checkoffset(size_t offset, size_t nbytes)
|
||||||
{
|
{
|
||||||
if (offset > len || offset + nbytes > len)
|
if (offset > len || offset + nbytes > len)
|
||||||
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
|
error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *File::toChars()
|
char *File::toChars()
|
||||||
@@ -1563,11 +1563,11 @@ OutBuffer::~OutBuffer()
|
|||||||
mem.free(data);
|
mem.free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *OutBuffer::extractData()
|
char *OutBuffer::extractData()
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = (char *)data;
|
p = (char *)data;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
size = 0;
|
size = 0;
|
||||||
@@ -1813,7 +1813,7 @@ void OutBuffer::align(unsigned size)
|
|||||||
// The compiler shipped with Visual Studio 2005 (and possible
|
// The compiler shipped with Visual Studio 2005 (and possible
|
||||||
// other versions) does not support C99 printf format specfiers
|
// other versions) does not support C99 printf format specfiers
|
||||||
// such as %z and %j
|
// such as %z and %j
|
||||||
#if _MSC_VER || __MINGW32__
|
#if 0 && _MSC_VER
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
|
||||||
@@ -1832,7 +1832,7 @@ search_and_replace(S& str, const S& what, const S& replacement)
|
|||||||
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
|
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
|
||||||
S tmp = f; \
|
S tmp = f; \
|
||||||
search_and_replace(fmt, S("%z"), S("%l")); \
|
search_and_replace(fmt, S("%z"), S("%l")); \
|
||||||
search_and_replace(fmt, S("%j"), S("%i")); \
|
search_and_replace(fmt, S("%j"), S("%l")); \
|
||||||
f = tmp.c_str();
|
f = tmp.c_str();
|
||||||
#else
|
#else
|
||||||
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
|
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
|
||||||
|
|||||||
853
dmd/root/root.h
853
dmd/root/root.h
@@ -1,425 +1,428 @@
|
|||||||
|
|
||||||
|
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2011 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
#ifndef ROOT_H
|
#ifndef ROOT_H
|
||||||
#define ROOT_H
|
#define ROOT_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __DMC__
|
#if __DMC__
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IS_PRINTF
|
#ifndef IS_PRINTF
|
||||||
# ifdef __GNUC__
|
# ifdef __GNUC__
|
||||||
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
|
# define IS_PRINTF(FMTARG) __attribute((__format__ (__printf__, (FMTARG), (FMTARG)+1) ))
|
||||||
# else
|
# else
|
||||||
# define IS_PRINTF(FMTARG)
|
# define IS_PRINTF(FMTARG)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef size_t hash_t;
|
typedef size_t hash_t;
|
||||||
|
|
||||||
#include "dchar.h"
|
#include "longdouble.h"
|
||||||
|
#include "dchar.h"
|
||||||
char *wchar2ascii(wchar_t *);
|
|
||||||
int wcharIsAscii(wchar_t *);
|
char *wchar2ascii(wchar_t *);
|
||||||
char *wchar2ascii(wchar_t *, unsigned len);
|
int wcharIsAscii(wchar_t *);
|
||||||
int wcharIsAscii(wchar_t *, unsigned len);
|
char *wchar2ascii(wchar_t *, unsigned len);
|
||||||
|
int wcharIsAscii(wchar_t *, unsigned len);
|
||||||
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
|
||||||
char *bstr2str(unsigned char *b);
|
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
||||||
void error(const char *format, ...) IS_PRINTF(1);
|
char *bstr2str(unsigned char *b);
|
||||||
void error(const wchar_t *format, ...);
|
void error(const char *format, ...) IS_PRINTF(1);
|
||||||
void warning(const char *format, ...) IS_PRINTF(1);
|
#if M_UNICODE
|
||||||
|
void error(const dchar *format, ...);
|
||||||
#ifndef TYPEDEFS
|
#endif
|
||||||
#define TYPEDEFS
|
void warning(const char *format, ...) IS_PRINTF(1);
|
||||||
|
|
||||||
#if _MSC_VER
|
#ifndef TYPEDEFS
|
||||||
#include <float.h> // for _isnan
|
#define TYPEDEFS
|
||||||
#include <malloc.h> // for alloca
|
|
||||||
// According to VC 8.0 docs, long double is the same as double
|
#if _MSC_VER
|
||||||
#define strtold strtod
|
#include <float.h> // for _isnan
|
||||||
#define strtof strtod
|
#include <malloc.h> // for alloca
|
||||||
#define isnan _isnan
|
// According to VC 8.0 docs, long double is the same as double
|
||||||
|
longdouble strtold(const char *p,char **endp);
|
||||||
typedef __int64 longlong;
|
#define strtof strtod
|
||||||
typedef unsigned __int64 ulonglong;
|
#define isnan _isnan
|
||||||
#else
|
|
||||||
typedef long long longlong;
|
typedef __int64 longlong;
|
||||||
typedef unsigned long long ulonglong;
|
typedef unsigned __int64 ulonglong;
|
||||||
#endif
|
#else
|
||||||
|
typedef long long longlong;
|
||||||
#endif
|
typedef unsigned long long ulonglong;
|
||||||
|
#endif
|
||||||
longlong randomx();
|
|
||||||
|
#endif
|
||||||
/*
|
|
||||||
* Root of our class library.
|
longlong randomx();
|
||||||
*/
|
|
||||||
|
/*
|
||||||
struct OutBuffer;
|
* Root of our class library.
|
||||||
|
*/
|
||||||
// Can't include arraytypes.h here, need to declare these directly.
|
|
||||||
template <typename TYPE> struct ArrayBase;
|
struct OutBuffer;
|
||||||
typedef ArrayBase<struct File> Files;
|
|
||||||
typedef ArrayBase<char> Strings;
|
// Can't include arraytypes.h here, need to declare these directly.
|
||||||
|
template <typename TYPE> struct ArrayBase;
|
||||||
|
typedef ArrayBase<struct File> Files;
|
||||||
struct Object
|
typedef ArrayBase<char> Strings;
|
||||||
{
|
|
||||||
Object() { }
|
|
||||||
virtual ~Object() { }
|
struct Object
|
||||||
|
{
|
||||||
virtual int equals(Object *o);
|
Object() { }
|
||||||
|
virtual ~Object() { }
|
||||||
/**
|
|
||||||
* Returns a hash code, useful for things like building hash tables of Objects.
|
virtual int equals(Object *o);
|
||||||
*/
|
|
||||||
virtual hash_t hashCode();
|
/**
|
||||||
|
* Returns a hash code, useful for things like building hash tables of Objects.
|
||||||
/**
|
*/
|
||||||
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
virtual hash_t hashCode();
|
||||||
* Useful for sorting Objects.
|
|
||||||
*/
|
/**
|
||||||
virtual int compare(Object *obj);
|
* Return <0, ==0, or >0 if this is less than, equal to, or greater than obj.
|
||||||
|
* Useful for sorting Objects.
|
||||||
/**
|
*/
|
||||||
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
virtual int compare(Object *obj);
|
||||||
*/
|
|
||||||
virtual void print();
|
/**
|
||||||
|
* Pretty-print an Object. Useful for debugging the old-fashioned way.
|
||||||
virtual char *toChars();
|
*/
|
||||||
virtual dchar *toDchars();
|
virtual void print();
|
||||||
virtual void toBuffer(OutBuffer *buf);
|
|
||||||
|
virtual char *toChars();
|
||||||
/**
|
virtual dchar *toDchars();
|
||||||
* Used as a replacement for dynamic_cast. Returns a unique number
|
virtual void toBuffer(OutBuffer *buf);
|
||||||
* defined by the library user. For Object, the return value is 0.
|
|
||||||
*/
|
/**
|
||||||
virtual int dyncast();
|
* Used as a replacement for dynamic_cast. Returns a unique number
|
||||||
|
* defined by the library user. For Object, the return value is 0.
|
||||||
/**
|
*/
|
||||||
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
|
virtual int dyncast();
|
||||||
*/
|
|
||||||
/*virtual*/ // not used, disable for now
|
/**
|
||||||
void mark();
|
* Marks pointers for garbage collector by calling mem.mark() for all pointers into heap.
|
||||||
};
|
*/
|
||||||
|
/*virtual*/ // not used, disable for now
|
||||||
struct String : Object
|
void mark();
|
||||||
{
|
};
|
||||||
int ref; // != 0 if this is a reference to someone else's string
|
|
||||||
char *str; // the string itself
|
struct String : Object
|
||||||
|
{
|
||||||
String(char *str, int ref = 1);
|
int ref; // != 0 if this is a reference to someone else's string
|
||||||
|
char *str; // the string itself
|
||||||
~String();
|
|
||||||
|
String(char *str, int ref = 1);
|
||||||
static hash_t calcHash(const char *str, size_t len);
|
|
||||||
static hash_t calcHash(const char *str);
|
~String();
|
||||||
hash_t hashCode();
|
|
||||||
unsigned len();
|
static hash_t calcHash(const char *str, size_t len);
|
||||||
int equals(Object *obj);
|
static hash_t calcHash(const char *str);
|
||||||
int compare(Object *obj);
|
hash_t hashCode();
|
||||||
char *toChars();
|
unsigned len();
|
||||||
void print();
|
int equals(Object *obj);
|
||||||
void mark();
|
int compare(Object *obj);
|
||||||
};
|
char *toChars();
|
||||||
|
void print();
|
||||||
struct FileName : String
|
void mark();
|
||||||
{
|
};
|
||||||
FileName(char *str, int ref);
|
|
||||||
FileName(char *path, char *name);
|
struct FileName : String
|
||||||
hash_t hashCode();
|
{
|
||||||
int equals(Object *obj);
|
FileName(char *str, int ref);
|
||||||
static int equals(const char *name1, const char *name2);
|
FileName(char *path, char *name);
|
||||||
int compare(Object *obj);
|
hash_t hashCode();
|
||||||
static int compare(const char *name1, const char *name2);
|
int equals(Object *obj);
|
||||||
static int absolute(const char *name);
|
static int equals(const char *name1, const char *name2);
|
||||||
static char *ext(const char *);
|
int compare(Object *obj);
|
||||||
char *ext();
|
static int compare(const char *name1, const char *name2);
|
||||||
static char *removeExt(const char *str);
|
static int absolute(const char *name);
|
||||||
static char *name(const char *);
|
static char *ext(const char *);
|
||||||
char *name();
|
char *ext();
|
||||||
static char *path(const char *);
|
static char *removeExt(const char *str);
|
||||||
static const char *replaceName(const char *path, const char *name);
|
static char *name(const char *);
|
||||||
|
char *name();
|
||||||
static char *combine(const char *path, const char *name);
|
static char *path(const char *);
|
||||||
static Strings *splitPath(const char *path);
|
static const char *replaceName(const char *path, const char *name);
|
||||||
static FileName *defaultExt(const char *name, const char *ext);
|
|
||||||
static FileName *forceExt(const char *name, const char *ext);
|
static char *combine(const char *path, const char *name);
|
||||||
int equalsExt(const char *ext);
|
static Strings *splitPath(const char *path);
|
||||||
|
static FileName *defaultExt(const char *name, const char *ext);
|
||||||
void CopyTo(FileName *to);
|
static FileName *forceExt(const char *name, const char *ext);
|
||||||
static char *searchPath(Strings *path, const char *name, int cwd);
|
int equalsExt(const char *ext);
|
||||||
static char *safeSearchPath(Strings *path, const char *name);
|
|
||||||
static int exists(const char *name);
|
void CopyTo(FileName *to);
|
||||||
static void ensurePathExists(const char *path);
|
static char *searchPath(Strings *path, const char *name, int cwd);
|
||||||
static char *canonicalName(const char *name);
|
static char *safeSearchPath(Strings *path, const char *name);
|
||||||
};
|
static int exists(const char *name);
|
||||||
|
static void ensurePathExists(const char *path);
|
||||||
struct File : Object
|
static char *canonicalName(const char *name);
|
||||||
{
|
};
|
||||||
int ref; // != 0 if this is a reference to someone else's buffer
|
|
||||||
unsigned char *buffer; // data for our file
|
struct File : Object
|
||||||
unsigned len; // amount of data in buffer[]
|
{
|
||||||
void *touchtime; // system time to use for file
|
int ref; // != 0 if this is a reference to someone else's buffer
|
||||||
|
unsigned char *buffer; // data for our file
|
||||||
FileName *name; // name of our file
|
unsigned len; // amount of data in buffer[]
|
||||||
|
void *touchtime; // system time to use for file
|
||||||
File(char *);
|
|
||||||
File(FileName *);
|
FileName *name; // name of our file
|
||||||
~File();
|
|
||||||
|
File(char *);
|
||||||
void mark();
|
File(FileName *);
|
||||||
|
~File();
|
||||||
char *toChars();
|
|
||||||
|
void mark();
|
||||||
/* Read file, return !=0 if error
|
|
||||||
*/
|
char *toChars();
|
||||||
|
|
||||||
int read();
|
/* Read file, return !=0 if error
|
||||||
|
*/
|
||||||
/* Write file, either succeed or fail
|
|
||||||
* with error message & exit.
|
int read();
|
||||||
*/
|
|
||||||
|
/* Write file, either succeed or fail
|
||||||
void readv();
|
* with error message & exit.
|
||||||
|
*/
|
||||||
/* Read file, return !=0 if error
|
|
||||||
*/
|
void readv();
|
||||||
|
|
||||||
int mmread();
|
/* Read file, return !=0 if error
|
||||||
|
*/
|
||||||
/* Write file, either succeed or fail
|
|
||||||
* with error message & exit.
|
int mmread();
|
||||||
*/
|
|
||||||
|
/* Write file, either succeed or fail
|
||||||
void mmreadv();
|
* with error message & exit.
|
||||||
|
*/
|
||||||
/* Write file, return !=0 if error
|
|
||||||
*/
|
void mmreadv();
|
||||||
|
|
||||||
int write();
|
/* Write file, return !=0 if error
|
||||||
|
*/
|
||||||
/* Write file, either succeed or fail
|
|
||||||
* with error message & exit.
|
int write();
|
||||||
*/
|
|
||||||
|
/* Write file, either succeed or fail
|
||||||
void writev();
|
* with error message & exit.
|
||||||
|
*/
|
||||||
/* Return !=0 if file exists.
|
|
||||||
* 0: file doesn't exist
|
void writev();
|
||||||
* 1: normal file
|
|
||||||
* 2: directory
|
/* Return !=0 if file exists.
|
||||||
*/
|
* 0: file doesn't exist
|
||||||
|
* 1: normal file
|
||||||
/* Append to file, return !=0 if error
|
* 2: directory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int append();
|
/* Append to file, return !=0 if error
|
||||||
|
*/
|
||||||
/* Append to file, either succeed or fail
|
|
||||||
* with error message & exit.
|
int append();
|
||||||
*/
|
|
||||||
|
/* Append to file, either succeed or fail
|
||||||
void appendv();
|
* with error message & exit.
|
||||||
|
*/
|
||||||
/* Return !=0 if file exists.
|
|
||||||
* 0: file doesn't exist
|
void appendv();
|
||||||
* 1: normal file
|
|
||||||
* 2: directory
|
/* Return !=0 if file exists.
|
||||||
*/
|
* 0: file doesn't exist
|
||||||
|
* 1: normal file
|
||||||
int exists();
|
* 2: directory
|
||||||
|
*/
|
||||||
/* Given wildcard filespec, return an array of
|
|
||||||
* matching File's.
|
int exists();
|
||||||
*/
|
|
||||||
|
/* Given wildcard filespec, return an array of
|
||||||
static Files *match(char *);
|
* matching File's.
|
||||||
static Files *match(FileName *);
|
*/
|
||||||
|
|
||||||
// Compare file times.
|
static Files *match(char *);
|
||||||
// Return <0 this < f
|
static Files *match(FileName *);
|
||||||
// =0 this == f
|
|
||||||
// >0 this > f
|
// Compare file times.
|
||||||
int compareTime(File *f);
|
// Return <0 this < f
|
||||||
|
// =0 this == f
|
||||||
// Read system file statistics
|
// >0 this > f
|
||||||
void stat();
|
int compareTime(File *f);
|
||||||
|
|
||||||
/* Set buffer
|
// Read system file statistics
|
||||||
*/
|
void stat();
|
||||||
|
|
||||||
void setbuffer(void *buffer, unsigned len)
|
/* Set buffer
|
||||||
{
|
*/
|
||||||
this->buffer = (unsigned char *)buffer;
|
|
||||||
this->len = len;
|
void setbuffer(void *buffer, unsigned len)
|
||||||
}
|
{
|
||||||
|
this->buffer = (unsigned char *)buffer;
|
||||||
void checkoffset(size_t offset, size_t nbytes);
|
this->len = len;
|
||||||
|
}
|
||||||
void remove(); // delete file
|
|
||||||
};
|
void checkoffset(size_t offset, size_t nbytes);
|
||||||
|
|
||||||
struct OutBuffer : Object
|
void remove(); // delete file
|
||||||
{
|
};
|
||||||
unsigned char *data;
|
|
||||||
unsigned offset;
|
struct OutBuffer : Object
|
||||||
unsigned size;
|
{
|
||||||
|
unsigned char *data;
|
||||||
OutBuffer();
|
unsigned offset;
|
||||||
~OutBuffer();
|
unsigned size;
|
||||||
char *extractData();
|
|
||||||
void mark();
|
OutBuffer();
|
||||||
|
~OutBuffer();
|
||||||
void reserve(unsigned nbytes);
|
char *extractData();
|
||||||
void setsize(unsigned size);
|
void mark();
|
||||||
void reset();
|
|
||||||
void write(const void *data, unsigned nbytes);
|
void reserve(unsigned nbytes);
|
||||||
void writebstring(unsigned char *string);
|
void setsize(unsigned size);
|
||||||
void writestring(const char *string);
|
void reset();
|
||||||
void writedstring(const char *string);
|
void write(const void *data, unsigned nbytes);
|
||||||
void writedstring(const wchar_t *string);
|
void writebstring(unsigned char *string);
|
||||||
void prependstring(const char *string);
|
void writestring(const char *string);
|
||||||
void writenl(); // write newline
|
void writedstring(const char *string);
|
||||||
void writeByte(unsigned b);
|
void writedstring(const wchar_t *string);
|
||||||
void writebyte(unsigned b) { writeByte(b); }
|
void prependstring(const char *string);
|
||||||
void writeUTF8(unsigned b);
|
void writenl(); // write newline
|
||||||
void writedchar(unsigned b);
|
void writeByte(unsigned b);
|
||||||
void prependbyte(unsigned b);
|
void writebyte(unsigned b) { writeByte(b); }
|
||||||
void writeword(unsigned w);
|
void writeUTF8(unsigned b);
|
||||||
void writeUTF16(unsigned w);
|
void writedchar(unsigned b);
|
||||||
void write4(unsigned w);
|
void prependbyte(unsigned b);
|
||||||
void write(OutBuffer *buf);
|
void writeword(unsigned w);
|
||||||
void write(Object *obj);
|
void writeUTF16(unsigned w);
|
||||||
void fill0(unsigned nbytes);
|
void write4(unsigned w);
|
||||||
void align(unsigned size);
|
void write(OutBuffer *buf);
|
||||||
void vprintf(const char *format, va_list args);
|
void write(Object *obj);
|
||||||
void printf(const char *format, ...) IS_PRINTF(2);
|
void fill0(unsigned nbytes);
|
||||||
#if M_UNICODE
|
void align(unsigned size);
|
||||||
void vprintf(const unsigned short *format, va_list args);
|
void vprintf(const char *format, va_list args);
|
||||||
void printf(const unsigned short *format, ...);
|
void printf(const char *format, ...) IS_PRINTF(2);
|
||||||
#endif
|
#if M_UNICODE
|
||||||
void bracket(char left, char right);
|
void vprintf(const unsigned short *format, va_list args);
|
||||||
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
|
void printf(const unsigned short *format, ...);
|
||||||
void spread(unsigned offset, unsigned nbytes);
|
#endif
|
||||||
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
|
void bracket(char left, char right);
|
||||||
void remove(unsigned offset, unsigned nbytes);
|
unsigned bracket(unsigned i, const char *left, unsigned j, const char *right);
|
||||||
char *toChars();
|
void spread(unsigned offset, unsigned nbytes);
|
||||||
char *extractString();
|
unsigned insert(unsigned offset, const void *data, unsigned nbytes);
|
||||||
};
|
void remove(unsigned offset, unsigned nbytes);
|
||||||
|
char *toChars();
|
||||||
struct Array : Object
|
char *extractString();
|
||||||
{
|
};
|
||||||
unsigned dim;
|
|
||||||
void **data;
|
struct Array : Object
|
||||||
|
{
|
||||||
private:
|
unsigned dim;
|
||||||
unsigned allocdim;
|
void **data;
|
||||||
#define SMALLARRAYCAP 1
|
|
||||||
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
private:
|
||||||
|
unsigned allocdim;
|
||||||
public:
|
#define SMALLARRAYCAP 1
|
||||||
Array();
|
void *smallarray[SMALLARRAYCAP]; // inline storage for small arrays
|
||||||
~Array();
|
|
||||||
//Array(const Array&);
|
public:
|
||||||
void mark();
|
Array();
|
||||||
char *toChars();
|
~Array();
|
||||||
|
//Array(const Array&);
|
||||||
void reserve(unsigned nentries);
|
void mark();
|
||||||
void setDim(unsigned newdim);
|
char *toChars();
|
||||||
void fixDim();
|
|
||||||
void push(void *ptr);
|
void reserve(unsigned nentries);
|
||||||
void *pop();
|
void setDim(unsigned newdim);
|
||||||
void shift(void *ptr);
|
void fixDim();
|
||||||
void insert(unsigned index, void *ptr);
|
void push(void *ptr);
|
||||||
void insert(unsigned index, Array *a);
|
void *pop();
|
||||||
void append(Array *a);
|
void shift(void *ptr);
|
||||||
void remove(unsigned i);
|
void insert(unsigned index, void *ptr);
|
||||||
void zero();
|
void insert(unsigned index, Array *a);
|
||||||
void *tos();
|
void append(Array *a);
|
||||||
void sort();
|
void remove(unsigned i);
|
||||||
Array *copy();
|
void zero();
|
||||||
};
|
void *tos();
|
||||||
|
void sort();
|
||||||
template <typename TYPE>
|
Array *copy();
|
||||||
struct ArrayBase : Array
|
};
|
||||||
{
|
|
||||||
TYPE **tdata()
|
template <typename TYPE>
|
||||||
{
|
struct ArrayBase : Array
|
||||||
return (TYPE **)data;
|
{
|
||||||
}
|
TYPE **tdata()
|
||||||
|
{
|
||||||
TYPE*& operator[] (size_t index)
|
return (TYPE **)data;
|
||||||
{
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
assert(index < dim);
|
TYPE*& operator[] (size_t index)
|
||||||
#endif
|
{
|
||||||
return ((TYPE **)data)[index];
|
#ifdef DEBUG
|
||||||
}
|
assert(index < dim);
|
||||||
|
#endif
|
||||||
void insert(size_t index, TYPE *v)
|
return ((TYPE **)data)[index];
|
||||||
{
|
}
|
||||||
Array::insert(index, (void *)v);
|
|
||||||
}
|
void insert(size_t index, TYPE *v)
|
||||||
|
{
|
||||||
void insert(size_t index, ArrayBase *a)
|
Array::insert(index, (void *)v);
|
||||||
{
|
}
|
||||||
Array::insert(index, (Array *)a);
|
|
||||||
}
|
void insert(size_t index, ArrayBase *a)
|
||||||
|
{
|
||||||
void append(ArrayBase *a)
|
Array::insert(index, (Array *)a);
|
||||||
{
|
}
|
||||||
Array::append((Array *)a);
|
|
||||||
}
|
void append(ArrayBase *a)
|
||||||
|
{
|
||||||
void push(TYPE *a)
|
Array::append((Array *)a);
|
||||||
{
|
}
|
||||||
Array::push((void *)a);
|
|
||||||
}
|
void push(TYPE *a)
|
||||||
|
{
|
||||||
ArrayBase *copy()
|
Array::push((void *)a);
|
||||||
{
|
}
|
||||||
return (ArrayBase *)Array::copy();
|
|
||||||
}
|
ArrayBase *copy()
|
||||||
};
|
{
|
||||||
|
return (ArrayBase *)Array::copy();
|
||||||
struct Bits : Object
|
}
|
||||||
{
|
};
|
||||||
unsigned bitdim;
|
|
||||||
unsigned allocdim;
|
struct Bits : Object
|
||||||
unsigned *data;
|
{
|
||||||
|
unsigned bitdim;
|
||||||
Bits();
|
unsigned allocdim;
|
||||||
~Bits();
|
unsigned *data;
|
||||||
void mark();
|
|
||||||
|
Bits();
|
||||||
void resize(unsigned bitdim);
|
~Bits();
|
||||||
|
void mark();
|
||||||
void set(unsigned bitnum);
|
|
||||||
void clear(unsigned bitnum);
|
void resize(unsigned bitdim);
|
||||||
int test(unsigned bitnum);
|
|
||||||
|
void set(unsigned bitnum);
|
||||||
void set();
|
void clear(unsigned bitnum);
|
||||||
void clear();
|
int test(unsigned bitnum);
|
||||||
void copy(Bits *from);
|
|
||||||
Bits *clone();
|
void set();
|
||||||
|
void clear();
|
||||||
void sub(Bits *b);
|
void copy(Bits *from);
|
||||||
};
|
Bits *clone();
|
||||||
|
|
||||||
#endif
|
void sub(Bits *b);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,139 +1,139 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2011 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
#include "rmem.h"
|
#include "rmem.h"
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
#include "stringtable.h"
|
#include "stringtable.h"
|
||||||
|
|
||||||
void StringTable::init(unsigned size)
|
void StringTable::init(unsigned size)
|
||||||
{
|
{
|
||||||
table = (void **)mem.calloc(size, sizeof(void *));
|
table = (void **)mem.calloc(size, sizeof(void *));
|
||||||
tabledim = size;
|
tabledim = size;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTable::~StringTable()
|
StringTable::~StringTable()
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
// Zero out dangling pointers to help garbage collector.
|
// Zero out dangling pointers to help garbage collector.
|
||||||
// Should zero out StringEntry's too.
|
// Should zero out StringEntry's too.
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
table[i] = NULL;
|
table[i] = NULL;
|
||||||
|
|
||||||
mem.free(table);
|
mem.free(table);
|
||||||
table = NULL;
|
table = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StringEntry
|
struct StringEntry
|
||||||
{
|
{
|
||||||
StringEntry *left;
|
StringEntry *left;
|
||||||
StringEntry *right;
|
StringEntry *right;
|
||||||
hash_t hash;
|
hash_t hash;
|
||||||
|
|
||||||
StringValue value;
|
StringValue value;
|
||||||
|
|
||||||
static StringEntry *alloc(const dchar *s, unsigned len);
|
static StringEntry *alloc(const dchar *s, unsigned len);
|
||||||
};
|
};
|
||||||
|
|
||||||
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
|
StringEntry *StringEntry::alloc(const dchar *s, unsigned len)
|
||||||
{
|
{
|
||||||
StringEntry *se;
|
StringEntry *se;
|
||||||
|
|
||||||
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
|
se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len));
|
||||||
se->value.lstring.length = len;
|
se->value.lstring.length = len;
|
||||||
se->hash = Dchar::calcHash(s,len);
|
se->hash = Dchar::calcHash(s,len);
|
||||||
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
|
memcpy(se->value.lstring.string, s, len * sizeof(dchar));
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
void **StringTable::search(const dchar *s, unsigned len)
|
void **StringTable::search(const dchar *s, unsigned len)
|
||||||
{
|
{
|
||||||
hash_t hash;
|
hash_t hash;
|
||||||
unsigned u;
|
unsigned u;
|
||||||
int cmp;
|
int cmp;
|
||||||
StringEntry **se;
|
StringEntry **se;
|
||||||
|
|
||||||
//printf("StringTable::search(%p,%d)\n",s,len);
|
//printf("StringTable::search(%p,%d)\n",s,len);
|
||||||
hash = Dchar::calcHash(s,len);
|
hash = Dchar::calcHash(s,len);
|
||||||
u = hash % tabledim;
|
u = hash % tabledim;
|
||||||
se = (StringEntry **)&table[u];
|
se = (StringEntry **)&table[u];
|
||||||
//printf("\thash = %d, u = %d\n",hash,u);
|
//printf("\thash = %d, u = %d\n",hash,u);
|
||||||
while (*se)
|
while (*se)
|
||||||
{
|
{
|
||||||
cmp = (*se)->hash - hash;
|
cmp = (*se)->hash - hash;
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
cmp = (*se)->value.lstring.len() - len;
|
cmp = (*se)->value.lstring.len() - len;
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
{
|
{
|
||||||
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
|
cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len);
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
se = &(*se)->left;
|
se = &(*se)->left;
|
||||||
else
|
else
|
||||||
se = &(*se)->right;
|
se = &(*se)->right;
|
||||||
}
|
}
|
||||||
//printf("\treturn %p, %p\n",se, (*se));
|
//printf("\treturn %p, %p\n",se, (*se));
|
||||||
return (void **)se;
|
return (void **)se;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringValue *StringTable::lookup(const dchar *s, unsigned len)
|
StringValue *StringTable::lookup(const dchar *s, unsigned len)
|
||||||
{ StringEntry *se;
|
{ StringEntry *se;
|
||||||
|
|
||||||
se = *(StringEntry **)search(s,len);
|
se = *(StringEntry **)search(s,len);
|
||||||
if (se)
|
if (se)
|
||||||
return &se->value;
|
return &se->value;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringValue *StringTable::update(const dchar *s, unsigned len)
|
StringValue *StringTable::update(const dchar *s, unsigned len)
|
||||||
{ StringEntry **pse;
|
{ StringEntry **pse;
|
||||||
StringEntry *se;
|
StringEntry *se;
|
||||||
|
|
||||||
pse = (StringEntry **)search(s,len);
|
pse = (StringEntry **)search(s,len);
|
||||||
se = *pse;
|
se = *pse;
|
||||||
if (!se) // not in table: so create new entry
|
if (!se) // not in table: so create new entry
|
||||||
{
|
{
|
||||||
se = StringEntry::alloc(s, len);
|
se = StringEntry::alloc(s, len);
|
||||||
*pse = se;
|
*pse = se;
|
||||||
}
|
}
|
||||||
return &se->value;
|
return &se->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringValue *StringTable::insert(const dchar *s, unsigned len)
|
StringValue *StringTable::insert(const dchar *s, unsigned len)
|
||||||
{ StringEntry **pse;
|
{ StringEntry **pse;
|
||||||
StringEntry *se;
|
StringEntry *se;
|
||||||
|
|
||||||
pse = (StringEntry **)search(s,len);
|
pse = (StringEntry **)search(s,len);
|
||||||
se = *pse;
|
se = *pse;
|
||||||
if (se)
|
if (se)
|
||||||
return NULL; // error: already in table
|
return NULL; // error: already in table
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
se = StringEntry::alloc(s, len);
|
se = StringEntry::alloc(s, len);
|
||||||
*pse = se;
|
*pse = se;
|
||||||
}
|
}
|
||||||
return &se->value;
|
return &se->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2011 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
// License for redistribution is by either the Artistic License
|
// License for redistribution is by either the Artistic License
|
||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
|
|
||||||
#ifndef STRINGTABLE_H
|
#ifndef STRINGTABLE_H
|
||||||
#define STRINGTABLE_H
|
#define STRINGTABLE_H
|
||||||
|
|
||||||
#if __SC__
|
#if __SC__
|
||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "root.h"
|
#include "root.h"
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
#include "lstring.h"
|
#include "lstring.h"
|
||||||
|
|
||||||
struct StringValue
|
struct StringValue
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{ int intvalue;
|
{ int intvalue;
|
||||||
void *ptrvalue;
|
void *ptrvalue;
|
||||||
dchar *string;
|
dchar *string;
|
||||||
};
|
};
|
||||||
Lstring lstring;
|
Lstring lstring;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringTable
|
struct StringTable
|
||||||
{
|
{
|
||||||
void **table;
|
void **table;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
unsigned tabledim;
|
unsigned tabledim;
|
||||||
|
|
||||||
void init(unsigned size = 37);
|
void init(unsigned size = 37);
|
||||||
~StringTable();
|
~StringTable();
|
||||||
|
|
||||||
StringValue *lookup(const dchar *s, unsigned len);
|
StringValue *lookup(const dchar *s, unsigned len);
|
||||||
StringValue *insert(const dchar *s, unsigned len);
|
StringValue *insert(const dchar *s, unsigned len);
|
||||||
StringValue *update(const dchar *s, unsigned len);
|
StringValue *update(const dchar *s, unsigned len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void **search(const dchar *s, unsigned len);
|
void **search(const dchar *s, unsigned len);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ Scope::Scope()
|
|||||||
this->parameterSpecialization = 0;
|
this->parameterSpecialization = 0;
|
||||||
this->callSuper = 0;
|
this->callSuper = 0;
|
||||||
this->flags = 0;
|
this->flags = 0;
|
||||||
this->anonAgg = NULL;
|
|
||||||
this->lastdc = NULL;
|
this->lastdc = NULL;
|
||||||
this->lastoffset = 0;
|
this->lastoffset = 0;
|
||||||
this->docbuf = NULL;
|
this->docbuf = NULL;
|
||||||
@@ -127,7 +126,6 @@ Scope::Scope(Scope *enclosing)
|
|||||||
this->parameterSpecialization = enclosing->parameterSpecialization;
|
this->parameterSpecialization = enclosing->parameterSpecialization;
|
||||||
this->callSuper = enclosing->callSuper;
|
this->callSuper = enclosing->callSuper;
|
||||||
this->flags = 0;
|
this->flags = 0;
|
||||||
this->anonAgg = NULL;
|
|
||||||
this->lastdc = NULL;
|
this->lastdc = NULL;
|
||||||
this->lastoffset = 0;
|
this->lastoffset = 0;
|
||||||
this->docbuf = enclosing->docbuf;
|
this->docbuf = enclosing->docbuf;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// Copyright (c) 1999-2009 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -64,6 +64,10 @@ struct Scope
|
|||||||
Statement *scontinue; // enclosing statement that supports "continue"
|
Statement *scontinue; // enclosing statement that supports "continue"
|
||||||
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
|
||||||
unsigned offset; // next offset to use in aggregate
|
unsigned offset; // next offset to use in aggregate
|
||||||
|
// This really shouldn't be a part of Scope, because it requires
|
||||||
|
// semantic() to be done in the lexical field order. It should be
|
||||||
|
// set in a pass after semantic() on all fields so they can be
|
||||||
|
// semantic'd in any order.
|
||||||
int inunion; // we're processing members of a union
|
int inunion; // we're processing members of a union
|
||||||
int incontract; // we're inside contract code
|
int incontract; // we're inside contract code
|
||||||
int nofree; // set if shouldn't free it
|
int nofree; // set if shouldn't free it
|
||||||
@@ -95,7 +99,6 @@ struct Scope
|
|||||||
#define SCOPEstaticif 2 // inside static if
|
#define SCOPEstaticif 2 // inside static if
|
||||||
#define SCOPEfree 4 // is on free list
|
#define SCOPEfree 4 // is on free list
|
||||||
|
|
||||||
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
|
|
||||||
|
|
||||||
DocComment *lastdc; // documentation comment for last symbol at this scope
|
DocComment *lastdc; // documentation comment for last symbol at this scope
|
||||||
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
unsigned lastoffset; // offset in docbuf of where to insert next dec
|
||||||
|
|||||||
@@ -4,9 +4,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#if __sun&&__SVR4
|
#if __sun&&__SVR4 || _MSC_VER
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if _MSC_VER
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "speller.h"
|
#include "speller.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -1441,7 +1441,13 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||||||
s =((ScopeExp *)e)->sds;
|
s =((ScopeExp *)e)->sds;
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
|
{
|
||||||
var = new AliasDeclaration(loc, arg->ident, s);
|
var = new AliasDeclaration(loc, arg->ident, s);
|
||||||
|
}
|
||||||
|
else if (e->op == TOKtype)
|
||||||
|
{
|
||||||
|
var = new AliasDeclaration(loc, arg->ident, e->type);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
arg->type = e->type;
|
arg->type = e->type;
|
||||||
@@ -3783,6 +3789,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
exp = exp->semantic(sc);
|
exp = exp->semantic(sc);
|
||||||
exp = resolveProperties(sc, exp);
|
exp = resolveProperties(sc, exp);
|
||||||
|
if (exp->op == TOKerror)
|
||||||
|
goto Lbody;
|
||||||
ClassDeclaration *cd = exp->type->isClassHandle();
|
ClassDeclaration *cd = exp->type->isClassHandle();
|
||||||
if (!cd)
|
if (!cd)
|
||||||
error("can only synchronize on class objects, not '%s'", exp->type->toChars());
|
error("can only synchronize on class objects, not '%s'", exp->type->toChars());
|
||||||
@@ -3797,6 +3805,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||||||
exp = exp->semantic(sc);
|
exp = exp->semantic(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
/* Rewrite as:
|
/* Rewrite as:
|
||||||
* auto tmp = exp;
|
* auto tmp = exp;
|
||||||
* _d_monitorenter(tmp);
|
* _d_monitorenter(tmp);
|
||||||
@@ -3827,7 +3836,9 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||||||
|
|
||||||
s = new CompoundStatement(loc, cs);
|
s = new CompoundStatement(loc, cs);
|
||||||
return s->semantic(sc);
|
return s->semantic(sc);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
else
|
else
|
||||||
{ /* Generate our own critical section, then rewrite as:
|
{ /* Generate our own critical section, then rewrite as:
|
||||||
* __gshared byte[CriticalSection.sizeof] critsec;
|
* __gshared byte[CriticalSection.sizeof] critsec;
|
||||||
@@ -3869,6 +3880,11 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
|
|||||||
s = new CompoundStatement(loc, cs);
|
s = new CompoundStatement(loc, cs);
|
||||||
return s->semantic(sc);
|
return s->semantic(sc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Lbody:
|
||||||
|
if (body)
|
||||||
|
body = body->semantic(sc);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SynchronizedStatement::hasBreak()
|
int SynchronizedStatement::hasBreak()
|
||||||
@@ -4141,7 +4157,9 @@ Catch *Catch::syntaxCopy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Catch::semantic(Scope *sc)
|
void Catch::semantic(Scope *sc)
|
||||||
{ ScopeDsymbol *sym;
|
{
|
||||||
|
if (type && type->deco)
|
||||||
|
return;
|
||||||
|
|
||||||
//printf("Catch::semantic(%s)\n", ident->toChars());
|
//printf("Catch::semantic(%s)\n", ident->toChars());
|
||||||
|
|
||||||
@@ -4158,7 +4176,7 @@ void Catch::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sym = new ScopeDsymbol();
|
ScopeDsymbol *sym = new ScopeDsymbol();
|
||||||
sym->parent = sc->scopesym;
|
sym->parent = sc->scopesym;
|
||||||
sc = sc->push(sym);
|
sc = sc->push(sym);
|
||||||
|
|
||||||
|
|||||||
188
dmd/struct.c
188
dmd/struct.c
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -36,7 +36,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
|||||||
alignsize = 0; // size of struct for alignment purposes
|
alignsize = 0; // size of struct for alignment purposes
|
||||||
structalign = 0; // struct member alignment in effect
|
structalign = 0; // struct member alignment in effect
|
||||||
hasUnions = 0;
|
hasUnions = 0;
|
||||||
sizeok = 0; // size not determined yet
|
sizeok = SIZEOKnone; // size not determined yet
|
||||||
isdeprecated = 0;
|
isdeprecated = 0;
|
||||||
inv = NULL;
|
inv = NULL;
|
||||||
aggNew = NULL;
|
aggNew = NULL;
|
||||||
@@ -123,9 +123,9 @@ unsigned AggregateDeclaration::size(Loc loc)
|
|||||||
//printf("AggregateDeclaration::size() = %d\n", structsize);
|
//printf("AggregateDeclaration::size() = %d\n", structsize);
|
||||||
if (!members)
|
if (!members)
|
||||||
error(loc, "unknown size");
|
error(loc, "unknown size");
|
||||||
if (sizeok != 1 && scope)
|
if (sizeok != SIZEOKdone && scope)
|
||||||
semantic(NULL);
|
semantic(NULL);
|
||||||
if (sizeok != 1)
|
if (sizeok != SIZEOKdone)
|
||||||
{ error(loc, "no size yet for forward reference");
|
{ error(loc, "no size yet for forward reference");
|
||||||
//*(char*)0=0;
|
//*(char*)0=0;
|
||||||
}
|
}
|
||||||
@@ -169,73 +169,41 @@ void AggregateDeclaration::alignmember(
|
|||||||
//printf("result = %d\n", *poffset);
|
//printf("result = %d\n", *poffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************
|
||||||
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
|
* Place a member (mem) into an aggregate (agg), which can be a struct, union or class
|
||||||
|
* Returns:
|
||||||
|
* offset to place field at
|
||||||
|
*/
|
||||||
|
unsigned AggregateDeclaration::placeField(
|
||||||
|
unsigned *nextoffset, // next location in aggregate
|
||||||
|
unsigned memsize, // size of member
|
||||||
|
unsigned memalignsize, // size of member for alignment purposes
|
||||||
|
unsigned memalign, // alignment in effect for this member
|
||||||
|
unsigned *paggsize, // size of aggregate (updated)
|
||||||
|
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
|
||||||
|
bool isunion // the aggregate is a union
|
||||||
|
)
|
||||||
{
|
{
|
||||||
unsigned memsize; // size of member
|
unsigned ofs = *nextoffset;
|
||||||
unsigned memalignsize; // size of member for alignment purposes
|
alignmember(memalign, memalignsize, &ofs);
|
||||||
unsigned xalign; // alignment boundaries
|
unsigned memoffset = ofs;
|
||||||
|
|
||||||
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
|
|
||||||
|
|
||||||
// Check for forward referenced types which will fail the size() call
|
|
||||||
Type *t = v->type->toBasetype();
|
|
||||||
if (t->ty == Tstruct /*&& isStructDeclaration()*/)
|
|
||||||
{ TypeStruct *ts = (TypeStruct *)t;
|
|
||||||
#if DMDV2
|
|
||||||
if (ts->sym == this)
|
|
||||||
{
|
|
||||||
error("cannot have field %s with same struct type", v->toChars());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ts->sym->sizeok != 1 && ts->sym->scope)
|
|
||||||
ts->sym->semantic(NULL);
|
|
||||||
if (ts->sym->sizeok != 1)
|
|
||||||
{
|
|
||||||
sizeok = 2; // cannot finish; flag as forward referenced
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (t->ty == Tident)
|
|
||||||
{
|
|
||||||
sizeok = 2; // cannot finish; flag as forward referenced
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memsize = v->type->size(loc);
|
|
||||||
memalignsize = v->type->alignsize();
|
|
||||||
xalign = v->type->memalign(sc->structalign);
|
|
||||||
#if 0
|
|
||||||
alignmember(xalign, memalignsize, &sc->offset);
|
|
||||||
v->offset = sc->offset;
|
|
||||||
sc->offset += memsize;
|
|
||||||
if (sc->offset > structsize)
|
|
||||||
structsize = sc->offset;
|
|
||||||
#else
|
|
||||||
unsigned ofs = sc->offset;
|
|
||||||
alignmember(xalign, memalignsize, &ofs);
|
|
||||||
v->offset = ofs;
|
|
||||||
ofs += memsize;
|
ofs += memsize;
|
||||||
if (ofs > structsize)
|
if (ofs > *paggsize)
|
||||||
structsize = ofs;
|
*paggsize = ofs;
|
||||||
if (!isUnionDeclaration())
|
if (!isunion)
|
||||||
sc->offset = ofs;
|
*nextoffset = ofs;
|
||||||
#endif
|
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
|
||||||
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16)
|
|
||||||
/* Not sure how to handle this */
|
/* Not sure how to handle this */
|
||||||
;
|
;
|
||||||
else if (sc->structalign < memalignsize)
|
else if (memalign < memalignsize)
|
||||||
memalignsize = sc->structalign;
|
memalignsize = memalign;
|
||||||
if (alignsize < memalignsize)
|
if (*paggalignsize < memalignsize)
|
||||||
alignsize = memalignsize;
|
*paggalignsize = memalignsize;
|
||||||
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
|
|
||||||
|
|
||||||
v->storage_class |= STCfield;
|
return memoffset;
|
||||||
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
|
|
||||||
fields.push(v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
* If field[indx] is not part of a union, return indx.
|
* If field[indx] is not part of a union, return indx.
|
||||||
* Otherwise, return the lowest field index of the union.
|
* Otherwise, return the lowest field index of the union.
|
||||||
@@ -330,7 +298,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (symtab)
|
if (symtab)
|
||||||
{ if (sizeok == 1 || !scope)
|
{ if (sizeok == SIZEOKdone || !scope)
|
||||||
{ //printf("already completed\n");
|
{ //printf("already completed\n");
|
||||||
scope = NULL;
|
scope = NULL;
|
||||||
return; // semantic() already completed
|
return; // semantic() already completed
|
||||||
@@ -369,7 +337,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
type = type->constOf();
|
type = type->constOf();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sizeok == 0) // if not already done the addMember step
|
if (sizeok == SIZEOKnone) // if not already done the addMember step
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
@@ -379,7 +347,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sizeok = 0;
|
sizeok = SIZEOKnone;
|
||||||
sc2 = sc->push(this);
|
sc2 = sc->push(this);
|
||||||
sc2->stc = 0;
|
sc2->stc = 0;
|
||||||
sc2->parent = this;
|
sc2->parent = this;
|
||||||
@@ -394,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
* resolve individual members like enums.
|
* resolve individual members like enums.
|
||||||
*/
|
*/
|
||||||
for (size_t i = 0; i < members_dim; i++)
|
for (size_t i = 0; i < members_dim; i++)
|
||||||
{ Dsymbol *s = members->tdata()[i];
|
{ Dsymbol *s = (*members)[i];
|
||||||
/* There are problems doing this in the general case because
|
/* There are problems doing this in the general case because
|
||||||
* Scope keeps track of things like 'offset'
|
* Scope keeps track of things like 'offset'
|
||||||
*/
|
*/
|
||||||
@@ -407,8 +375,13 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
|
|
||||||
for (size_t i = 0; i < members_dim; i++)
|
for (size_t i = 0; i < members_dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = members->tdata()[i];
|
Dsymbol *s = (*members)[i];
|
||||||
|
// Ungag errors when not speculative
|
||||||
|
unsigned oldgag = global.gag;
|
||||||
|
if (global.isSpeculativeGagging() && !isSpeculative())
|
||||||
|
global.gag = 0;
|
||||||
s->semantic(sc2);
|
s->semantic(sc2);
|
||||||
|
global.gag = oldgag;
|
||||||
#if 0
|
#if 0
|
||||||
if (sizeok == 2)
|
if (sizeok == 2)
|
||||||
{ //printf("forward reference\n");
|
{ //printf("forward reference\n");
|
||||||
@@ -416,6 +389,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
finalizeSize(sc2);
|
||||||
|
|
||||||
#if DMDV1
|
#if DMDV1
|
||||||
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
|
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
|
||||||
@@ -480,44 +454,14 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
/* Try to find the opEquals function. Build it if necessary.
|
|
||||||
*/
|
|
||||||
TypeFunction *tfeqptr;
|
|
||||||
{ // bool opEquals(const T*) const;
|
|
||||||
Parameters *parameters = new Parameters;
|
|
||||||
#if STRUCTTHISREF
|
|
||||||
// bool opEquals(ref const T) const;
|
|
||||||
Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL);
|
|
||||||
#else
|
|
||||||
// bool opEquals(const T*) const;
|
|
||||||
Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
parameters->push(param);
|
|
||||||
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
|
|
||||||
tfeqptr->mod = MODconst;
|
|
||||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2);
|
|
||||||
|
|
||||||
Dsymbol *s = search_function(this, Id::eq);
|
|
||||||
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
|
|
||||||
if (fdx)
|
|
||||||
{
|
|
||||||
eq = fdx->overloadExactMatch(tfeqptr);
|
|
||||||
if (!eq)
|
|
||||||
fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL;
|
|
||||||
// BUG: should also check that td is a function template, not just a template
|
|
||||||
|
|
||||||
if (!eq && !td)
|
|
||||||
eq = buildOpEquals(sc2);
|
|
||||||
}
|
|
||||||
|
|
||||||
dtor = buildDtor(sc2);
|
dtor = buildDtor(sc2);
|
||||||
postblit = buildPostBlit(sc2);
|
postblit = buildPostBlit(sc2);
|
||||||
cpctor = buildCpCtor(sc2);
|
cpctor = buildCpCtor(sc2);
|
||||||
|
|
||||||
buildOpAssign(sc2);
|
buildOpAssign(sc2);
|
||||||
|
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
|
||||||
|
|
||||||
|
xeq = buildXopEquals(sc2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sc2->pop();
|
sc2->pop();
|
||||||
@@ -525,6 +469,12 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
if (sizeok == 2)
|
if (sizeok == 2)
|
||||||
{ // semantic() failed because of forward references.
|
{ // semantic() failed because of forward references.
|
||||||
// Unwind what we did, and defer it for later
|
// Unwind what we did, and defer it for later
|
||||||
|
for (size_t i = 0; i < fields.dim; i++)
|
||||||
|
{ Dsymbol *s = fields[i];
|
||||||
|
VarDeclaration *vd = s->isVarDeclaration();
|
||||||
|
if (vd)
|
||||||
|
vd->offset = 0;
|
||||||
|
}
|
||||||
fields.setDim(0);
|
fields.setDim(0);
|
||||||
structsize = 0;
|
structsize = 0;
|
||||||
alignsize = 0;
|
alignsize = 0;
|
||||||
@@ -551,7 +501,7 @@ void StructDeclaration::semantic(Scope *sc)
|
|||||||
// aligned properly.
|
// aligned properly.
|
||||||
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
|
||||||
sizeok = 1;
|
sizeok = SIZEOKdone;
|
||||||
Module::dprogress++;
|
Module::dprogress++;
|
||||||
|
|
||||||
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
|
||||||
@@ -613,6 +563,36 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
|
|||||||
return ScopeDsymbol::search(loc, ident, flags);
|
return ScopeDsymbol::search(loc, ident, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StructDeclaration::finalizeSize(Scope *sc)
|
||||||
|
{
|
||||||
|
if (sizeok != SIZEOKnone)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set the offsets of the fields and determine the size of the struct
|
||||||
|
unsigned offset = 0;
|
||||||
|
bool isunion = isUnionDeclaration() != NULL;
|
||||||
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
|
{ Dsymbol *s = (*members)[i];
|
||||||
|
s->setFieldOffset(this, &offset, isunion);
|
||||||
|
}
|
||||||
|
if (sizeok == SIZEOKfwd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 0 sized struct's are set to 1 byte
|
||||||
|
if (structsize == 0)
|
||||||
|
{
|
||||||
|
structsize = 1;
|
||||||
|
alignsize = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round struct size up to next alignsize boundary.
|
||||||
|
// This will ensure that arrays of structs will get their internals
|
||||||
|
// aligned properly.
|
||||||
|
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
|
||||||
|
sizeok = SIZEOKdone;
|
||||||
|
}
|
||||||
|
|
||||||
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||||
{
|
{
|
||||||
buf->printf("%s ", kind());
|
buf->printf("%s ", kind());
|
||||||
|
|||||||
271
dmd/template.c
271
dmd/template.c
@@ -202,7 +202,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
|||||||
{
|
{
|
||||||
if (sc1->scopesym == ti1)
|
if (sc1->scopesym == ti1)
|
||||||
{
|
{
|
||||||
error("recursive template expansion for template argument %s", t1->toChars());
|
tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
|
||||||
return 1; // fake a match
|
return 1; // fake a match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
|
|||||||
this->members = decldefs;
|
this->members = decldefs;
|
||||||
this->overnext = NULL;
|
this->overnext = NULL;
|
||||||
this->overroot = NULL;
|
this->overroot = NULL;
|
||||||
this->semanticRun = 0;
|
this->semanticRun = PASSinit;
|
||||||
this->onemember = NULL;
|
this->onemember = NULL;
|
||||||
|
|
||||||
// Compute in advance for Ddoc's use
|
// Compute in advance for Ddoc's use
|
||||||
@@ -438,7 +438,7 @@ void TemplateDeclaration::semantic(Scope *sc)
|
|||||||
#endif
|
#endif
|
||||||
if (semanticRun)
|
if (semanticRun)
|
||||||
return; // semantic() already run
|
return; // semantic() already run
|
||||||
semanticRun = 1;
|
semanticRun = PASSsemantic;
|
||||||
|
|
||||||
if (sc->func)
|
if (sc->func)
|
||||||
{
|
{
|
||||||
@@ -994,12 +994,17 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Loc loc, Objects *targsi,
|
|||||||
* now form the tuple argument.
|
* now form the tuple argument.
|
||||||
*/
|
*/
|
||||||
Tuple *t = new Tuple();
|
Tuple *t = new Tuple();
|
||||||
dedargs->data[parameters->dim - 1] = (void *)t;
|
dedargs->tdata()[parameters->dim - 1] = t;
|
||||||
|
|
||||||
tuple_dim = nfargs - (nfparams - 1);
|
tuple_dim = nfargs - (nfparams - 1);
|
||||||
t->objects.setDim(tuple_dim);
|
t->objects.setDim(tuple_dim);
|
||||||
for (size_t i = 0; i < tuple_dim; i++)
|
for (size_t i = 0; i < tuple_dim; i++)
|
||||||
{ Expression *farg = (Expression *)fargs->data[fptupindex + i];
|
{ Expression *farg = fargs->tdata()[fptupindex + i];
|
||||||
|
|
||||||
|
// Check invalid arguments to detect errors early.
|
||||||
|
if (farg->op == TOKerror || farg->type->ty == Terror)
|
||||||
|
goto Lnomatch;
|
||||||
|
|
||||||
t->objects.data[i] = (void *)farg->type;
|
t->objects.data[i] = (void *)farg->type;
|
||||||
}
|
}
|
||||||
declareParameter(paramscope, tp, t);
|
declareParameter(paramscope, tp, t);
|
||||||
@@ -1025,7 +1030,7 @@ L2:
|
|||||||
{
|
{
|
||||||
// Match 'ethis' to any TemplateThisParameter's
|
// Match 'ethis' to any TemplateThisParameter's
|
||||||
for (size_t i = 0; i < parameters->dim; i++)
|
for (size_t i = 0; i < parameters->dim; i++)
|
||||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
{ TemplateParameter *tp = parameters->tdata()[i];
|
||||||
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
|
TemplateThisParameter *ttp = tp->isTemplateThisParameter();
|
||||||
if (ttp)
|
if (ttp)
|
||||||
{ MATCH m;
|
{ MATCH m;
|
||||||
@@ -1101,7 +1106,13 @@ L2:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ Expression *farg = (Expression *)fargs->data[i];
|
{
|
||||||
|
Expression *farg = fargs->tdata()[i];
|
||||||
|
|
||||||
|
// Check invalid arguments to detect errors early.
|
||||||
|
if (farg->op == TOKerror || farg->type->ty == Terror)
|
||||||
|
goto Lnomatch;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("\tfarg->type = %s\n", farg->type->toChars());
|
printf("\tfarg->type = %s\n", farg->type->toChars());
|
||||||
printf("\tfparam->type = %s\n", fparam->type->toChars());
|
printf("\tfparam->type = %s\n", fparam->type->toChars());
|
||||||
@@ -1121,10 +1132,34 @@ L2:
|
|||||||
argtype = argtype->invariantOf();
|
argtype = argtype->invariantOf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allow implicit function literals to delegate conversion
|
||||||
|
*/
|
||||||
|
if (farg->op == TOKfunction)
|
||||||
|
{ FuncExp *fe = (FuncExp *)farg;
|
||||||
|
Type *tp = fparam->type;
|
||||||
|
Expression *e = fe->inferType(tp, 1, parameters);
|
||||||
|
if (!e)
|
||||||
|
goto Lvarargs;
|
||||||
|
farg = e;
|
||||||
|
argtype = farg->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(fparam->storageClass & STClazy) && argtype->ty == Tvoid)
|
||||||
|
goto Lnomatch;
|
||||||
|
|
||||||
|
/* Remove top const for dynamic array types and pointer types
|
||||||
|
*/
|
||||||
|
if ((argtype->ty == Tarray || argtype->ty == Tpointer) &&
|
||||||
|
!argtype->isMutable() &&
|
||||||
|
(!(fparam->storageClass & STCref) ||
|
||||||
|
(fparam->storageClass & STCauto) && !farg->isLvalue()))
|
||||||
|
{
|
||||||
|
argtype = argtype->mutableOf();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MATCH m;
|
MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
|
||||||
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
|
|
||||||
//printf("\tdeduceType m = %d\n", m);
|
//printf("\tdeduceType m = %d\n", m);
|
||||||
|
|
||||||
/* If no match, see if there's a conversion to a delegate
|
/* If no match, see if there's a conversion to a delegate
|
||||||
@@ -1428,7 +1463,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
|||||||
}
|
}
|
||||||
printf(" fargs:\n");
|
printf(" fargs:\n");
|
||||||
for (size_t i = 0; i < fargs->dim; i++)
|
for (size_t i = 0; i < fargs->dim; i++)
|
||||||
{ Expression *arg = (Expression *)fargs->data[i];
|
{ Expression *arg = fargs->tdata()[i];
|
||||||
printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
|
printf("\t%s %s\n", arg->type->toChars(), arg->toChars());
|
||||||
//printf("\tty = %d\n", arg->type->ty);
|
//printf("\tty = %d\n", arg->type->ty);
|
||||||
}
|
}
|
||||||
@@ -1499,8 +1534,8 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
|||||||
}
|
}
|
||||||
if (td_ambig)
|
if (td_ambig)
|
||||||
{
|
{
|
||||||
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||||
toChars(),
|
kind(), parent->toPrettyChars(), ident->toChars(),
|
||||||
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
||||||
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
||||||
}
|
}
|
||||||
@@ -1514,6 +1549,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
|||||||
fd = ti->toAlias()->isFuncDeclaration();
|
fd = ti->toAlias()->isFuncDeclaration();
|
||||||
if (!fd)
|
if (!fd)
|
||||||
goto Lerror;
|
goto Lerror;
|
||||||
|
|
||||||
|
/* As Bugzilla 3682 shows, a template instance can be matched while instantiating
|
||||||
|
* that same template. Thus, the function type can be incomplete. Complete it.
|
||||||
|
*/
|
||||||
|
{ TypeFunction *tf = (TypeFunction *)fd->type;
|
||||||
|
assert(tf->ty == Tfunction);
|
||||||
|
if (tf->next)
|
||||||
|
fd->type = tf->semantic(loc, sc);
|
||||||
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
Lerror:
|
Lerror:
|
||||||
@@ -1530,14 +1575,19 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
|
|||||||
{
|
{
|
||||||
if (i)
|
if (i)
|
||||||
bufa.writeByte(',');
|
bufa.writeByte(',');
|
||||||
Object *oarg = (Object *)args->data[i];
|
Object *oarg = args->tdata()[i];
|
||||||
ObjectToCBuffer(&bufa, &hgs, oarg);
|
ObjectToCBuffer(&bufa, &hgs, oarg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OutBuffer buf;
|
OutBuffer buf;
|
||||||
argExpTypesToCBuffer(&buf, fargs, &hgs);
|
argExpTypesToCBuffer(&buf, fargs, &hgs);
|
||||||
error(loc, "cannot deduce template function from argument types !(%s)(%s)",
|
if (this->overnext)
|
||||||
|
::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
|
||||||
|
kind(), parent->toPrettyChars(), ident->toChars(),
|
||||||
|
bufa.toChars(), buf.toChars());
|
||||||
|
else
|
||||||
|
error("cannot deduce template function from argument types !(%s)(%s)",
|
||||||
bufa.toChars(), buf.toChars());
|
bufa.toChars(), buf.toChars());
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1633,7 +1683,7 @@ char *TemplateDeclaration::toChars()
|
|||||||
int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
|
int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < parameters->dim; i++)
|
for (size_t i = 0; i < parameters->dim; i++)
|
||||||
{ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
{ TemplateParameter *tp = parameters->tdata()[i];
|
||||||
|
|
||||||
if (tp->ident->equals(id))
|
if (tp->ident->equals(id))
|
||||||
return i;
|
return i;
|
||||||
@@ -1662,7 +1712,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
|
|||||||
* Foo!(int*) // template instantiation
|
* Foo!(int*) // template instantiation
|
||||||
* Input:
|
* Input:
|
||||||
* this = int*
|
* this = int*
|
||||||
* tparam = T
|
* tparam = T*
|
||||||
* parameters = [ T:T* ] // Array of TemplateParameter's
|
* parameters = [ T:T* ] // Array of TemplateParameter's
|
||||||
* Output:
|
* Output:
|
||||||
* dedtypes = [ int ] // Array of Expression/Type's
|
* dedtypes = [ int ] // Array of Expression/Type's
|
||||||
@@ -1696,7 +1746,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
|||||||
Loc loc;
|
Loc loc;
|
||||||
if (parameters->dim)
|
if (parameters->dim)
|
||||||
{
|
{
|
||||||
TemplateParameter *tp = (TemplateParameter *)parameters->data[0];
|
TemplateParameter *tp = parameters->tdata()[0];
|
||||||
loc = tp->loc;
|
loc = tp->loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1708,7 +1758,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
|||||||
return deduceType(sc, tparam, parameters, dedtypes);
|
return deduceType(sc, tparam, parameters, dedtypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
TemplateParameter *tp = parameters->tdata()[i];
|
||||||
|
|
||||||
// Found the corresponding parameter tp
|
// Found the corresponding parameter tp
|
||||||
if (!tp->isTemplateTypeParameter())
|
if (!tp->isTemplateTypeParameter())
|
||||||
@@ -2840,14 +2890,14 @@ MATCH TemplateAliasParameter::matchArg(Scope *sc,
|
|||||||
//printf("TemplateAliasParameter::matchArg()\n");
|
//printf("TemplateAliasParameter::matchArg()\n");
|
||||||
|
|
||||||
if (i < tiargs->dim)
|
if (i < tiargs->dim)
|
||||||
oarg = (Object *)tiargs->data[i];
|
oarg = tiargs->tdata()[i];
|
||||||
else
|
else
|
||||||
{ // Get default argument instead
|
{ // Get default argument instead
|
||||||
oarg = defaultArg(loc, sc);
|
oarg = defaultArg(loc, sc);
|
||||||
if (!oarg)
|
if (!oarg)
|
||||||
{ assert(i < dedtypes->dim);
|
{ assert(i < dedtypes->dim);
|
||||||
// It might have already been deduced
|
// It might have already been deduced
|
||||||
oarg = (Object *)dedtypes->data[i];
|
oarg = dedtypes->tdata()[i];
|
||||||
if (!oarg)
|
if (!oarg)
|
||||||
goto Lnomatch;
|
goto Lnomatch;
|
||||||
}
|
}
|
||||||
@@ -2937,7 +2987,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
|
|||||||
{
|
{
|
||||||
s = defaultAlias->toDsymbol(sc);
|
s = defaultAlias->toDsymbol(sc);
|
||||||
if (!s)
|
if (!s)
|
||||||
error("%s is not a symbol", defaultAlias->toChars());
|
error(Loc(0), "%s is not a symbol", defaultAlias->toChars());
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -2986,7 +3036,13 @@ void TemplateValueParameter::declareParameter(Scope *sc)
|
|||||||
|
|
||||||
void TemplateValueParameter::semantic(Scope *sc)
|
void TemplateValueParameter::semantic(Scope *sc)
|
||||||
{
|
{
|
||||||
|
bool wasSame = (sparam->type == valType);
|
||||||
sparam->semantic(sc);
|
sparam->semantic(sc);
|
||||||
|
if (sparam->type == Type::terror && wasSame)
|
||||||
|
{ // If sparam has a type error, avoid duplicate errors
|
||||||
|
valType = Type::terror;
|
||||||
|
return;
|
||||||
|
}
|
||||||
valType = valType->semantic(loc, sc);
|
valType = valType->semantic(loc, sc);
|
||||||
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
|
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
|
||||||
valType->ty != Tident)
|
valType->ty != Tident)
|
||||||
@@ -3344,13 +3400,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
|
|||||||
this->tinst = NULL;
|
this->tinst = NULL;
|
||||||
this->argsym = NULL;
|
this->argsym = NULL;
|
||||||
this->aliasdecl = NULL;
|
this->aliasdecl = NULL;
|
||||||
this->semanticRun = 0;
|
this->semanticRun = PASSinit;
|
||||||
this->semantictiargsdone = 0;
|
this->semantictiargsdone = 0;
|
||||||
this->withsym = NULL;
|
this->withsym = NULL;
|
||||||
this->nest = 0;
|
this->nest = 0;
|
||||||
this->havetempdecl = 0;
|
this->havetempdecl = 0;
|
||||||
this->isnested = NULL;
|
this->isnested = NULL;
|
||||||
this->errors = 0;
|
|
||||||
this->speculative = 0;
|
this->speculative = 0;
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -3379,13 +3434,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
|
|||||||
this->tinst = NULL;
|
this->tinst = NULL;
|
||||||
this->argsym = NULL;
|
this->argsym = NULL;
|
||||||
this->aliasdecl = NULL;
|
this->aliasdecl = NULL;
|
||||||
this->semanticRun = 0;
|
this->semanticRun = PASSinit;
|
||||||
this->semantictiargsdone = 1;
|
this->semantictiargsdone = 1;
|
||||||
this->withsym = NULL;
|
this->withsym = NULL;
|
||||||
this->nest = 0;
|
this->nest = 0;
|
||||||
this->havetempdecl = 1;
|
this->havetempdecl = 1;
|
||||||
this->isnested = NULL;
|
this->isnested = NULL;
|
||||||
this->errors = 0;
|
|
||||||
this->speculative = 0;
|
this->speculative = 0;
|
||||||
|
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
@@ -3463,7 +3517,7 @@ void TemplateInstance::semantic(Scope *sc)
|
|||||||
// get the enclosing template instance from the scope tinst
|
// get the enclosing template instance from the scope tinst
|
||||||
tinst = sc->tinst;
|
tinst = sc->tinst;
|
||||||
|
|
||||||
if (semanticRun != 0)
|
if (semanticRun != PASSinit)
|
||||||
{
|
{
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("Recursive template expansion\n");
|
printf("Recursive template expansion\n");
|
||||||
@@ -3472,7 +3526,7 @@ void TemplateInstance::semantic(Scope *sc)
|
|||||||
// inst = this;
|
// inst = this;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
semanticRun = 1;
|
semanticRun = PASSsemantic;
|
||||||
|
|
||||||
// get the enclosing template instance from the scope tinst
|
// get the enclosing template instance from the scope tinst
|
||||||
tinst = sc->tinst;
|
tinst = sc->tinst;
|
||||||
@@ -3579,7 +3633,7 @@ void TemplateInstance::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("\tit's a match with instance %p\n", inst);
|
printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -3866,7 +3920,7 @@ void TemplateInstance::semantic(Scope *sc)
|
|||||||
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
|
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
|
||||||
target_symbol_list->remove(target_symbol_list_idx);
|
target_symbol_list->remove(target_symbol_list_idx);
|
||||||
}
|
}
|
||||||
semanticRun = 0;
|
semanticRun = PASSinit;
|
||||||
inst = NULL;
|
inst = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4208,13 +4262,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc)
|
|||||||
// Only one template, so we can give better error message
|
// Only one template, so we can give better error message
|
||||||
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
|
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
|
||||||
else
|
else
|
||||||
error("%s does not match any template declaration", toChars());
|
::error(loc, "%s %s.%s does not match any template declaration",
|
||||||
|
tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (td_ambig)
|
if (td_ambig)
|
||||||
{
|
{
|
||||||
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
|
||||||
toChars(),
|
td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(),
|
||||||
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
|
||||||
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
|
||||||
}
|
}
|
||||||
@@ -4275,7 +4330,12 @@ int TemplateInstance::hasNestedArgs(Objects *args)
|
|||||||
sa = ((VarExp *)ea)->var;
|
sa = ((VarExp *)ea)->var;
|
||||||
goto Lsa;
|
goto Lsa;
|
||||||
}
|
}
|
||||||
if (ea->op == TOKfunction)
|
if (ea->op == TOKthis)
|
||||||
|
{
|
||||||
|
sa = ((ThisExp *)ea)->var;
|
||||||
|
goto Lsa;
|
||||||
|
}
|
||||||
|
if (ea->op == TOKfunction)
|
||||||
{
|
{
|
||||||
sa = ((FuncExp *)ea)->fd;
|
sa = ((FuncExp *)ea)->fd;
|
||||||
goto Lsa;
|
goto Lsa;
|
||||||
@@ -4472,16 +4532,15 @@ void TemplateInstance::declareParameters(Scope *sc)
|
|||||||
//printf("TemplateInstance::declareParameters()\n");
|
//printf("TemplateInstance::declareParameters()\n");
|
||||||
for (size_t i = 0; i < tdtypes.dim; i++)
|
for (size_t i = 0; i < tdtypes.dim; i++)
|
||||||
{
|
{
|
||||||
TemplateParameter *tp = (TemplateParameter *)tempdecl->parameters->data[i];
|
TemplateParameter *tp = tempdecl->parameters->tdata()[i];
|
||||||
//Object *o = (Object *)tiargs->data[i];
|
//Object *o = tiargs->tdata()[i];
|
||||||
Object *o = (Object *)tdtypes.data[i]; // initializer for tp
|
Object *o = tdtypes.tdata()[i]; // initializer for tp
|
||||||
|
|
||||||
//printf("\ttdtypes[%d] = %p\n", i, o);
|
//printf("\ttdtypes[%d] = %p\n", i, o);
|
||||||
tempdecl->declareParameter(sc, tp, o);
|
tempdecl->declareParameter(sc, tp, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************
|
/*****************************************************
|
||||||
* Determine if template instance is really a template function,
|
* Determine if template instance is really a template function,
|
||||||
* and that template function needs to infer types from the function
|
* and that template function needs to infer types from the function
|
||||||
@@ -4493,6 +4552,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
|
|||||||
//printf("TemplateInstance::needsTypeInference() %s\n", toChars());
|
//printf("TemplateInstance::needsTypeInference() %s\n", toChars());
|
||||||
if (!tempdecl)
|
if (!tempdecl)
|
||||||
tempdecl = findTemplateDeclaration(sc);
|
tempdecl = findTemplateDeclaration(sc);
|
||||||
|
int multipleMatches = FALSE;
|
||||||
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
|
for (TemplateDeclaration *td = tempdecl; td; td = td->overnext)
|
||||||
{
|
{
|
||||||
/* If any of the overloaded template declarations need inference,
|
/* If any of the overloaded template declarations need inference,
|
||||||
@@ -4518,23 +4578,44 @@ int TemplateInstance::needsTypeInference(Scope *sc)
|
|||||||
/* Determine if the instance arguments, tiargs, are all that is necessary
|
/* Determine if the instance arguments, tiargs, are all that is necessary
|
||||||
* to instantiate the template.
|
* to instantiate the template.
|
||||||
*/
|
*/
|
||||||
TemplateTupleParameter *tp = td->isVariadic();
|
|
||||||
//printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
|
//printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
|
||||||
TypeFunction *fdtype = (TypeFunction *)fd->type;
|
TypeFunction *fdtype = (TypeFunction *)fd->type;
|
||||||
if (Parameter::dim(fdtype->parameters) &&
|
if (Parameter::dim(fdtype->parameters))
|
||||||
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim))
|
{
|
||||||
return TRUE;
|
TemplateParameter *tp = td->isVariadic();
|
||||||
|
if (tp && td->parameters->dim > 1)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (tiargs->dim < td->parameters->dim)
|
||||||
|
{ // Can remain tiargs be filled by default arguments?
|
||||||
|
for (size_t i = tiargs->dim; i < td->parameters->dim; i++)
|
||||||
|
{ tp = (*td->parameters)[i];
|
||||||
|
if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter())
|
||||||
|
{ if (!ttp->defaultType)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter())
|
||||||
|
{ if (!tap->defaultAlias)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter())
|
||||||
|
{ if (!tvp->defaultValue)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//printf("false\n");
|
//printf("false\n");
|
||||||
return FALSE;
|
return multipleMatches;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateInstance::semantic2(Scope *sc)
|
void TemplateInstance::semantic2(Scope *sc)
|
||||||
{ int i;
|
{ int i;
|
||||||
|
|
||||||
if (semanticRun >= 2)
|
if (semanticRun >= PASSsemantic2)
|
||||||
return;
|
return;
|
||||||
semanticRun = 2;
|
semanticRun = PASSsemantic2;
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("+TemplateInstance::semantic2('%s')\n", toChars());
|
printf("+TemplateInstance::semantic2('%s')\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
@@ -4567,9 +4648,9 @@ void TemplateInstance::semantic3(Scope *sc)
|
|||||||
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
|
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
|
||||||
#endif
|
#endif
|
||||||
//if (toChars()[0] == 'D') *(char*)0=0;
|
//if (toChars()[0] == 'D') *(char*)0=0;
|
||||||
if (semanticRun >= 3)
|
if (semanticRun >= PASSsemantic3)
|
||||||
return;
|
return;
|
||||||
semanticRun = 3;
|
semanticRun = PASSsemantic3;
|
||||||
if (!errors && members)
|
if (!errors && members)
|
||||||
{
|
{
|
||||||
sc = tempdecl->scope;
|
sc = tempdecl->scope;
|
||||||
@@ -4752,9 +4833,24 @@ Dsymbol *TemplateInstance::toAlias()
|
|||||||
printf("TemplateInstance::toAlias()\n");
|
printf("TemplateInstance::toAlias()\n");
|
||||||
#endif
|
#endif
|
||||||
if (!inst)
|
if (!inst)
|
||||||
{ error("cannot resolve forward reference");
|
{
|
||||||
errors = 1;
|
// Maybe we can resolve it
|
||||||
return this;
|
if (scope)
|
||||||
|
{
|
||||||
|
/* Anything that affects scope->offset must be
|
||||||
|
* done in lexical order. Fwd ref error if it is affected, otherwise allow.
|
||||||
|
*/
|
||||||
|
unsigned offset = scope->offset;
|
||||||
|
Scope *sc = scope;
|
||||||
|
semantic(scope);
|
||||||
|
// if (offset != sc->offset)
|
||||||
|
// inst = NULL; // trigger fwd ref error
|
||||||
|
}
|
||||||
|
if (!inst)
|
||||||
|
{ error("cannot resolve forward reference");
|
||||||
|
errors = 1;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst != this)
|
if (inst != this)
|
||||||
@@ -4865,7 +4961,7 @@ Dsymbol *TemplateMixin::syntaxCopy(Dsymbol *s)
|
|||||||
ti = (TemplateInstance *)ti->syntaxCopy(NULL);
|
ti = (TemplateInstance *)ti->syntaxCopy(NULL);
|
||||||
id = (Identifier *)ti;
|
id = (Identifier *)ti;
|
||||||
}
|
}
|
||||||
ids->data[i] = id;
|
ids->tdata()[i] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
tm = new TemplateMixin(loc, ident,
|
tm = new TemplateMixin(loc, ident,
|
||||||
@@ -4886,7 +4982,7 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
// This for when a class/struct contains mixin members, and
|
// This for when a class/struct contains mixin members, and
|
||||||
// is done over because of forward references
|
// is done over because of forward references
|
||||||
if (parent && toParent()->isAggregateDeclaration())
|
if (parent && toParent()->isAggregateDeclaration())
|
||||||
semanticRun = 1; // do over
|
semanticRun = PASSsemantic; // do over
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if LOG
|
#if LOG
|
||||||
@@ -4896,7 +4992,7 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!semanticRun)
|
if (!semanticRun)
|
||||||
semanticRun = 1;
|
semanticRun = PASSsemantic;
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("\tdo semantic\n");
|
printf("\tdo semantic\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -4979,10 +5075,10 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
* runDeferred will re-run mixin's semantic outside of the struct's
|
* runDeferred will re-run mixin's semantic outside of the struct's
|
||||||
* semantic.
|
* semantic.
|
||||||
*/
|
*/
|
||||||
semanticRun = 0;
|
semanticRun = PASSinit;
|
||||||
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
|
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
|
||||||
if (ad)
|
if (ad)
|
||||||
ad->sizeok = 2;
|
ad->sizeok = SIZEOKfwd;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Forward reference
|
// Forward reference
|
||||||
@@ -5027,11 +5123,11 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (size_t i = 0; i < tiargs->dim; i++)
|
for (size_t i = 0; i < tiargs->dim; i++)
|
||||||
{ Object *o = (Object *)tiargs->data[i];
|
{ Object *o = (*tiargs)[i];
|
||||||
Type *ta = isType(o);
|
Type *ta = isType(o);
|
||||||
Expression *ea = isExpression(o);
|
Expression *ea = isExpression(o);
|
||||||
Dsymbol *sa = isDsymbol(o);
|
Dsymbol *sa = isDsymbol(o);
|
||||||
Object *tmo = (Object *)tm->tiargs->data[i];
|
Object *tmo = (*tm->tiargs)[i];
|
||||||
if (ta)
|
if (ta)
|
||||||
{
|
{
|
||||||
Type *tmta = isType(tmo);
|
Type *tmta = isType(tmo);
|
||||||
@@ -5095,10 +5191,8 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
declareParameters(argscope);
|
declareParameters(argscope);
|
||||||
|
|
||||||
// Add members to enclosing scope, as well as this scope
|
// Add members to enclosing scope, as well as this scope
|
||||||
for (unsigned i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{ Dsymbol *s;
|
{ Dsymbol *s = (*members)[i];
|
||||||
|
|
||||||
s = (Dsymbol *)members->data[i];
|
|
||||||
s->addMember(argscope, this, i);
|
s->addMember(argscope, this, i);
|
||||||
//sc->insert(s);
|
//sc->insert(s);
|
||||||
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
|
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
|
||||||
@@ -5124,7 +5218,7 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
|
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
Dsymbol *s = (*members)[i];
|
||||||
s->semantic(sc2);
|
s->semantic(sc2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5166,9 +5260,9 @@ void TemplateMixin::semantic(Scope *sc)
|
|||||||
|
|
||||||
void TemplateMixin::semantic2(Scope *sc)
|
void TemplateMixin::semantic2(Scope *sc)
|
||||||
{
|
{
|
||||||
if (semanticRun >= 2)
|
if (semanticRun >= PASSsemantic2)
|
||||||
return;
|
return;
|
||||||
semanticRun = 2;
|
semanticRun = PASSsemantic2;
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("+TemplateMixin::semantic2('%s')\n", toChars());
|
printf("+TemplateMixin::semantic2('%s')\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
@@ -5179,7 +5273,7 @@ void TemplateMixin::semantic2(Scope *sc)
|
|||||||
sc = sc->push(this);
|
sc = sc->push(this);
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
Dsymbol *s = (*members)[i];
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
|
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
|
||||||
#endif
|
#endif
|
||||||
@@ -5195,9 +5289,9 @@ void TemplateMixin::semantic2(Scope *sc)
|
|||||||
|
|
||||||
void TemplateMixin::semantic3(Scope *sc)
|
void TemplateMixin::semantic3(Scope *sc)
|
||||||
{
|
{
|
||||||
if (semanticRun >= 3)
|
if (semanticRun >= PASSsemantic3)
|
||||||
return;
|
return;
|
||||||
semanticRun = 3;
|
semanticRun = PASSsemantic3;
|
||||||
#if LOG
|
#if LOG
|
||||||
printf("TemplateMixin::semantic3('%s')\n", toChars());
|
printf("TemplateMixin::semantic3('%s')\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
@@ -5207,7 +5301,7 @@ void TemplateMixin::semantic3(Scope *sc)
|
|||||||
sc = sc->push(this);
|
sc = sc->push(this);
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
{
|
||||||
Dsymbol *s = (Dsymbol *)members->data[i];
|
Dsymbol *s = members->tdata()[i];
|
||||||
s->semantic3(sc);
|
s->semantic3(sc);
|
||||||
}
|
}
|
||||||
sc = sc->pop();
|
sc = sc->pop();
|
||||||
@@ -5230,21 +5324,48 @@ int TemplateMixin::oneMember(Dsymbol **ps)
|
|||||||
return Dsymbol::oneMember(ps);
|
return Dsymbol::oneMember(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param)
|
||||||
|
{
|
||||||
|
if (members)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
|
{ Dsymbol *s = (*members)[i];
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
if (s->apply(fp, param))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int TemplateMixin::hasPointers()
|
int TemplateMixin::hasPointers()
|
||||||
{
|
{
|
||||||
//printf("TemplateMixin::hasPointers() %s\n", toChars());
|
//printf("TemplateMixin::hasPointers() %s\n", toChars());
|
||||||
|
|
||||||
if (members)
|
if (members)
|
||||||
for (size_t i = 0; i < members->dim; i++)
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
{
|
|
||||||
Dsymbol *s = (*members)[i];
|
|
||||||
//printf(" s = %s %s\n", s->kind(), s->toChars());
|
|
||||||
if (s->hasPointers())
|
|
||||||
{
|
{
|
||||||
return 1;
|
Dsymbol *s = (*members)[i];
|
||||||
|
//printf(" s = %s %s\n", s->kind(), s->toChars());
|
||||||
|
if (s->hasPointers())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
|
||||||
|
{
|
||||||
|
if (members)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < members->dim; i++)
|
||||||
|
{ Dsymbol *s = (*members)[i];
|
||||||
|
s->setFieldOffset(ad, poffset, isunion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *TemplateMixin::toChars()
|
char *TemplateMixin::toChars()
|
||||||
@@ -5264,7 +5385,7 @@ void TemplateMixin::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring("mixin ");
|
buf->writestring("mixin ");
|
||||||
|
|
||||||
for (size_t i = 0; i < idents->dim; i++)
|
for (size_t i = 0; i < idents->dim; i++)
|
||||||
{ Identifier *id = (Identifier *)idents->data[i];
|
{ Identifier *id = idents->tdata()[i];
|
||||||
|
|
||||||
if (i)
|
if (i)
|
||||||
buf->writeByte('.');
|
buf->writeByte('.');
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// Compiler implementation of the D programming language
|
// Compiler implementation of the D programming language
|
||||||
// Copyright (c) 1999-2011 by Digital Mars
|
// Copyright (c) 1999-2012 by Digital Mars
|
||||||
// All Rights Reserved
|
// All Rights Reserved
|
||||||
// written by Walter Bright
|
// written by Walter Bright
|
||||||
// http://www.digitalmars.com
|
// http://www.digitalmars.com
|
||||||
@@ -40,6 +40,7 @@ struct AliasDeclaration;
|
|||||||
struct FuncDeclaration;
|
struct FuncDeclaration;
|
||||||
struct HdrGenState;
|
struct HdrGenState;
|
||||||
enum MATCH;
|
enum MATCH;
|
||||||
|
enum PASS;
|
||||||
|
|
||||||
struct Tuple : Object
|
struct Tuple : Object
|
||||||
{
|
{
|
||||||
@@ -60,7 +61,7 @@ struct TemplateDeclaration : ScopeDsymbol
|
|||||||
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
|
||||||
TemplateDeclaration *overroot; // first in overnext list
|
TemplateDeclaration *overroot; // first in overnext list
|
||||||
|
|
||||||
int semanticRun; // 1 semantic() run
|
enum PASS semanticRun; // 1 semantic() run
|
||||||
|
|
||||||
Dsymbol *onemember; // if !=NULL then one member of this template
|
Dsymbol *onemember; // if !=NULL then one member of this template
|
||||||
|
|
||||||
@@ -287,12 +288,11 @@ struct TemplateInstance : ScopeDsymbol
|
|||||||
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
|
||||||
// sole member
|
// sole member
|
||||||
WithScopeSymbol *withsym; // if a member of a with statement
|
WithScopeSymbol *withsym; // if a member of a with statement
|
||||||
int semanticRun; // has semantic() been done?
|
enum PASS semanticRun; // has semantic() been done?
|
||||||
int semantictiargsdone; // has semanticTiargs() been done?
|
int semantictiargsdone; // has semanticTiargs() been done?
|
||||||
int nest; // for recursion detection
|
int nest; // for recursion detection
|
||||||
int havetempdecl; // 1 if used second constructor
|
int havetempdecl; // 1 if used second constructor
|
||||||
Dsymbol *isnested; // if referencing local symbols, this is the context
|
Dsymbol *isnested; // if referencing local symbols, this is the context
|
||||||
int errors; // 1 if compiled with errors
|
|
||||||
int speculative; // 1 if only instantiated with errors gagged
|
int speculative; // 1 if only instantiated with errors gagged
|
||||||
#ifdef IN_GCC
|
#ifdef IN_GCC
|
||||||
/* On some targets, it is necessary to know whether a symbol
|
/* On some targets, it is necessary to know whether a symbol
|
||||||
@@ -356,7 +356,9 @@ struct TemplateMixin : TemplateInstance
|
|||||||
void inlineScan();
|
void inlineScan();
|
||||||
const char *kind();
|
const char *kind();
|
||||||
int oneMember(Dsymbol **ps);
|
int oneMember(Dsymbol **ps);
|
||||||
|
int apply(Dsymbol_apply_ft_t fp, void *param);
|
||||||
int hasPointers();
|
int hasPointers();
|
||||||
|
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
|
||||||
char *toChars();
|
char *toChars();
|
||||||
char *mangle();
|
char *mangle();
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
|||||||
Reference in New Issue
Block a user