Merge dmd-1.074 into ldc.

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
View File

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

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

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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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