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
|
||||||
|
|||||||
@@ -152,10 +152,10 @@ typedef char dchar;
|
|||||||
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); }
|
||||||
|
|||||||
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__
|
||||||
@@ -19,8 +19,10 @@ struct Lstring
|
|||||||
{
|
{
|
||||||
unsigned length;
|
unsigned length;
|
||||||
|
|
||||||
|
#ifndef IN_GCC
|
||||||
// Disable warning about nonstandard extension
|
// Disable warning about nonstandard extension
|
||||||
#pragma warning (disable : 4200)
|
#pragma warning (disable : 4200)
|
||||||
|
#endif
|
||||||
dchar string[];
|
dchar string[];
|
||||||
|
|
||||||
static Lstring zero; // 0 length string
|
static Lstring zero; // 0 length string
|
||||||
|
|||||||
179
dmd/root/port.c
179
dmd/root/port.c
@@ -17,14 +17,14 @@ double Port::nan = NAN;
|
|||||||
double Port::infinity = INFINITY;
|
double Port::infinity = INFINITY;
|
||||||
double Port::dbl_max = DBL_MAX;
|
double Port::dbl_max = DBL_MAX;
|
||||||
double Port::dbl_min = DBL_MIN;
|
double Port::dbl_min = DBL_MIN;
|
||||||
long double Port::ldbl_max = LDBL_MAX;
|
longdouble Port::ldbl_max = LDBL_MAX;
|
||||||
|
|
||||||
int Port::isNan(double r)
|
int Port::isNan(double r)
|
||||||
{
|
{
|
||||||
return ::isnan(r);
|
return ::isnan(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isNan(long double r)
|
int Port::isNan(longdouble r)
|
||||||
{
|
{
|
||||||
return ::isnan(r);
|
return ::isnan(r);
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ int Port::isSignallingNan(double r)
|
|||||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isSignallingNan(long double r)
|
int Port::isSignallingNan(longdouble r)
|
||||||
{
|
{
|
||||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||||
@@ -70,7 +70,7 @@ double Port::pow(double x, double y)
|
|||||||
return ::pow(x, y);
|
return ::pow(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double Port::fmodl(long double x, long double y)
|
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||||
{
|
{
|
||||||
return ::fmodl(x, y);
|
return ::fmodl(x, y);
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ double Port::infinity = 1 / zero;
|
|||||||
|
|
||||||
double Port::dbl_max = DBL_MAX;
|
double Port::dbl_max = DBL_MAX;
|
||||||
double Port::dbl_min = DBL_MIN;
|
double Port::dbl_min = DBL_MIN;
|
||||||
long double Port::ldbl_max = LDBL_MAX;
|
longdouble Port::ldbl_max = LDBL_MAX;
|
||||||
|
|
||||||
struct PortInitializer
|
struct PortInitializer
|
||||||
{
|
{
|
||||||
@@ -151,7 +151,7 @@ static PortInitializer portinitializer;
|
|||||||
|
|
||||||
PortInitializer::PortInitializer()
|
PortInitializer::PortInitializer()
|
||||||
{
|
{
|
||||||
Port::infinity = std::numeric_limits<long double>::infinity();
|
Port::infinity = std::numeric_limits<double>::infinity();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isNan(double r)
|
int Port::isNan(double r)
|
||||||
@@ -159,7 +159,7 @@ int Port::isNan(double r)
|
|||||||
return ::_isnan(r);
|
return ::_isnan(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isNan(long double r)
|
int Port::isNan(longdouble r)
|
||||||
{
|
{
|
||||||
return ::_isnan(r);
|
return ::_isnan(r);
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ int Port::isSignallingNan(double r)
|
|||||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isSignallingNan(long double r)
|
int Port::isSignallingNan(longdouble r)
|
||||||
{
|
{
|
||||||
/* MSVC doesn't have 80 bit long doubles
|
/* MSVC doesn't have 80 bit long doubles
|
||||||
*/
|
*/
|
||||||
@@ -206,7 +206,7 @@ double Port::pow(double x, double y)
|
|||||||
return ::pow(x, y);
|
return ::pow(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double Port::fmodl(long double x, long double y)
|
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||||
{
|
{
|
||||||
return ::fmodl(x, y);
|
return ::fmodl(x, y);
|
||||||
}
|
}
|
||||||
@@ -351,7 +351,7 @@ double Port::nan = copysign(NAN, 1.0);
|
|||||||
double Port::infinity = 1 / zero;
|
double Port::infinity = 1 / zero;
|
||||||
double Port::dbl_max = 1.7976931348623157e308;
|
double Port::dbl_max = 1.7976931348623157e308;
|
||||||
double Port::dbl_min = 5e-324;
|
double Port::dbl_min = 5e-324;
|
||||||
long double Port::ldbl_max = LDBL_MAX;
|
longdouble Port::ldbl_max = LDBL_MAX;
|
||||||
|
|
||||||
struct PortInitializer
|
struct PortInitializer
|
||||||
{
|
{
|
||||||
@@ -366,9 +366,9 @@ PortInitializer::PortInitializer()
|
|||||||
|
|
||||||
#if __FreeBSD__ && __i386__
|
#if __FreeBSD__ && __i386__
|
||||||
// LDBL_MAX comes out as infinity. Fix.
|
// LDBL_MAX comes out as infinity. Fix.
|
||||||
static unsigned char x[sizeof(long double)] =
|
static unsigned char x[sizeof(longdouble)] =
|
||||||
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
|
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
|
||||||
Port::ldbl_max = *(long double *)&x[0];
|
Port::ldbl_max = *(longdouble *)&x[0];
|
||||||
// FreeBSD defaults to double precision. Switch to extended precision.
|
// FreeBSD defaults to double precision. Switch to extended precision.
|
||||||
fpsetprec(FP_PE);
|
fpsetprec(FP_PE);
|
||||||
#endif
|
#endif
|
||||||
@@ -386,7 +386,7 @@ int Port::isNan(double r)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isNan(long double r)
|
int Port::isNan(longdouble r)
|
||||||
{
|
{
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
return __inline_isnan(r);
|
return __inline_isnan(r);
|
||||||
@@ -406,7 +406,7 @@ int Port::isSignallingNan(double r)
|
|||||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isSignallingNan(long double r)
|
int Port::isSignallingNan(longdouble r)
|
||||||
{
|
{
|
||||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||||
@@ -450,7 +450,7 @@ double Port::pow(double x, double y)
|
|||||||
return ::pow(x, y);
|
return ::pow(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double Port::fmodl(long double x, long double y)
|
longdouble Port::fmodl(longdouble x, longdouble y)
|
||||||
{
|
{
|
||||||
#if __FreeBSD__ || __OpenBSD__
|
#if __FreeBSD__ || __OpenBSD__
|
||||||
return ::fmod(x, y); // hack for now, fix later
|
return ::fmod(x, y); // hack for now, fix later
|
||||||
@@ -532,7 +532,7 @@ double Port::nan = NAN;
|
|||||||
double Port::infinity = 1 / zero;
|
double Port::infinity = 1 / zero;
|
||||||
double Port::dbl_max = 1.7976931348623157e308;
|
double Port::dbl_max = 1.7976931348623157e308;
|
||||||
double Port::dbl_min = 5e-324;
|
double Port::dbl_min = 5e-324;
|
||||||
long double Port::ldbl_max = LDBL_MAX;
|
longdouble Port::ldbl_max = LDBL_MAX;
|
||||||
|
|
||||||
struct PortInitializer
|
struct PortInitializer
|
||||||
{
|
{
|
||||||
@@ -546,7 +546,7 @@ PortInitializer::PortInitializer()
|
|||||||
// gcc nan's have the sign bit set by default, so turn it off
|
// gcc nan's have the sign bit set by default, so turn it off
|
||||||
// Need the volatile to prevent gcc from doing incorrect
|
// Need the volatile to prevent gcc from doing incorrect
|
||||||
// constant folding.
|
// constant folding.
|
||||||
volatile long double foo;
|
volatile longdouble foo;
|
||||||
foo = NAN;
|
foo = NAN;
|
||||||
if (signbit(foo)) // signbit sometimes, not always, set
|
if (signbit(foo)) // signbit sometimes, not always, set
|
||||||
foo = -foo; // turn off sign bit
|
foo = -foo; // turn off sign bit
|
||||||
@@ -558,7 +558,7 @@ int Port::isNan(double r)
|
|||||||
return isnan(r);
|
return isnan(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isNan(long double r)
|
int Port::isNan(longdouble r)
|
||||||
{
|
{
|
||||||
return isnan(r);
|
return isnan(r);
|
||||||
}
|
}
|
||||||
@@ -571,7 +571,7 @@ int Port::isSignallingNan(double r)
|
|||||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Port::isSignallingNan(long double r)
|
int Port::isSignallingNan(longdouble r)
|
||||||
{
|
{
|
||||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
||||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
||||||
@@ -653,144 +653,3 @@ char *Port::strupr(char *s)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IN_GCC
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <bits/nan.h>
|
|
||||||
#include <bits/mathdef.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
static double zero = 0;
|
|
||||||
double Port::nan = NAN;
|
|
||||||
double Port::infinity = 1 / zero;
|
|
||||||
double Port::dbl_max = 1.7976931348623157e308;
|
|
||||||
double Port::dbl_min = 5e-324;
|
|
||||||
long double Port::ldbl_max = LDBL_MAX;
|
|
||||||
|
|
||||||
#include "d-gcc-real.h"
|
|
||||||
extern "C" bool real_isnan (const real_t *);
|
|
||||||
|
|
||||||
struct PortInitializer
|
|
||||||
{
|
|
||||||
PortInitializer();
|
|
||||||
};
|
|
||||||
|
|
||||||
static PortInitializer portinitializer;
|
|
||||||
|
|
||||||
PortInitializer::PortInitializer()
|
|
||||||
{
|
|
||||||
Port::infinity = real_t::getinfinity();
|
|
||||||
Port::nan = real_t::getnan(real_t::LongDouble);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef isnan
|
|
||||||
int Port::isNan(double r)
|
|
||||||
{
|
|
||||||
#if __APPLE__
|
|
||||||
return __inline_isnan(r);
|
|
||||||
#else
|
|
||||||
return ::isnan(r);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int Port::isNan(long double r)
|
|
||||||
{
|
|
||||||
return real_isnan(&r);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Port::isSignallingNan(double r)
|
|
||||||
{
|
|
||||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
|
||||||
* its significand, which is bit 51 of 0..63 for 64 bit doubles.
|
|
||||||
*/
|
|
||||||
return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Port::isSignallingNan(long double r)
|
|
||||||
{
|
|
||||||
/* A signalling NaN is a NaN with 0 as the most significant bit of
|
|
||||||
* its significand, which is bit 62 of 0..79 for 80 bit reals.
|
|
||||||
*/
|
|
||||||
return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef isfinite
|
|
||||||
int Port::isFinite(double r)
|
|
||||||
{
|
|
||||||
return ::finite(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef isinf
|
|
||||||
int Port::isInfinity(double r)
|
|
||||||
{
|
|
||||||
return ::isinf(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef signbit
|
|
||||||
int Port::Signbit(double r)
|
|
||||||
{
|
|
||||||
return (long)(((long *)&r)[1] & 0x80000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Port::floor(double d)
|
|
||||||
{
|
|
||||||
return ::floor(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Port::pow(double x, double y)
|
|
||||||
{
|
|
||||||
return ::pow(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long long Port::strtoull(const char *p, char **pend, int base)
|
|
||||||
{
|
|
||||||
return ::strtoull(p, pend, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Port::ull_to_string(char *buffer, ulonglong ull)
|
|
||||||
{
|
|
||||||
sprintf(buffer, "%llu", ull);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
|
|
||||||
{
|
|
||||||
swprintf(buffer, L"%llu", ull);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
double Port::ull_to_double(ulonglong ull)
|
|
||||||
{
|
|
||||||
return (double) ull;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Port::list_separator()
|
|
||||||
{
|
|
||||||
return ",";
|
|
||||||
}
|
|
||||||
|
|
||||||
const wchar_t *Port::wlist_separator()
|
|
||||||
{
|
|
||||||
return L",";
|
|
||||||
}
|
|
||||||
|
|
||||||
char *Port::strupr(char *s)
|
|
||||||
{
|
|
||||||
char *t = s;
|
|
||||||
|
|
||||||
while (*s)
|
|
||||||
{
|
|
||||||
*s = toupper(*s);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
#include "longdouble.h"
|
||||||
|
|
||||||
#ifndef TYPEDEFS
|
#ifndef TYPEDEFS
|
||||||
#define TYPEDEFS
|
#define TYPEDEFS
|
||||||
|
|
||||||
@@ -20,7 +22,7 @@ typedef __int64 longlong;
|
|||||||
typedef unsigned __int64 ulonglong;
|
typedef unsigned __int64 ulonglong;
|
||||||
|
|
||||||
// According to VC 8.0 docs, long double is the same as double
|
// According to VC 8.0 docs, long double is the same as double
|
||||||
#define strtold strtod
|
longdouble strtold(const char *p,char **endp);
|
||||||
#define strtof strtod
|
#define strtof strtod
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -38,7 +40,7 @@ struct Port
|
|||||||
static double infinity;
|
static double infinity;
|
||||||
static double dbl_max;
|
static double dbl_max;
|
||||||
static double dbl_min;
|
static double dbl_min;
|
||||||
static long double ldbl_max;
|
static longdouble ldbl_max;
|
||||||
|
|
||||||
#if __OpenBSD__
|
#if __OpenBSD__
|
||||||
#elif __GNUC__ && !defined __HAIKU__
|
#elif __GNUC__ && !defined __HAIKU__
|
||||||
@@ -49,10 +51,10 @@ struct Port
|
|||||||
#undef signbit
|
#undef signbit
|
||||||
#endif
|
#endif
|
||||||
static int isNan(double);
|
static int isNan(double);
|
||||||
static int isNan(long double);
|
static int isNan(longdouble);
|
||||||
|
|
||||||
static int isSignallingNan(double);
|
static int isSignallingNan(double);
|
||||||
static int isSignallingNan(long double);
|
static int isSignallingNan(longdouble);
|
||||||
|
|
||||||
static int isFinite(double);
|
static int isFinite(double);
|
||||||
static int isInfinity(double);
|
static int isInfinity(double);
|
||||||
@@ -61,7 +63,7 @@ struct Port
|
|||||||
static double floor(double);
|
static double floor(double);
|
||||||
static double pow(double x, double y);
|
static double pow(double x, double y);
|
||||||
|
|
||||||
static long double fmodl(long double x, long double y);
|
static longdouble fmodl(longdouble x, longdouble y);
|
||||||
|
|
||||||
static ulonglong strtoull(const char *p, char **pend, int base);
|
static ulonglong strtoull(const char *p, char **pend, int base);
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
typedef size_t hash_t;
|
typedef size_t hash_t;
|
||||||
|
|
||||||
|
#include "longdouble.h"
|
||||||
#include "dchar.h"
|
#include "dchar.h"
|
||||||
|
|
||||||
char *wchar2ascii(wchar_t *);
|
char *wchar2ascii(wchar_t *);
|
||||||
@@ -41,7 +42,9 @@ int wcharIsAscii(wchar_t *, unsigned len);
|
|||||||
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
int bstrcmp(unsigned char *s1, unsigned char *s2);
|
||||||
char *bstr2str(unsigned char *b);
|
char *bstr2str(unsigned char *b);
|
||||||
void error(const char *format, ...) IS_PRINTF(1);
|
void error(const char *format, ...) IS_PRINTF(1);
|
||||||
void error(const wchar_t *format, ...);
|
#if M_UNICODE
|
||||||
|
void error(const dchar *format, ...);
|
||||||
|
#endif
|
||||||
void warning(const char *format, ...) IS_PRINTF(1);
|
void warning(const char *format, ...) IS_PRINTF(1);
|
||||||
|
|
||||||
#ifndef TYPEDEFS
|
#ifndef TYPEDEFS
|
||||||
@@ -51,7 +54,7 @@ void warning(const char *format, ...) IS_PRINTF(1);
|
|||||||
#include <float.h> // for _isnan
|
#include <float.h> // for _isnan
|
||||||
#include <malloc.h> // for alloca
|
#include <malloc.h> // for alloca
|
||||||
// According to VC 8.0 docs, long double is the same as double
|
// According to VC 8.0 docs, long double is the same as double
|
||||||
#define strtold strtod
|
longdouble strtold(const char *p,char **endp);
|
||||||
#define strtof strtod
|
#define strtof strtod
|
||||||
#define isnan _isnan
|
#define isnan _isnan
|
||||||
|
|
||||||
|
|||||||
@@ -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