Merged dmd 2.059beta

This commit is contained in:
Alexey Prokhin
2012-04-05 15:30:00 +04:00
77 changed files with 6909 additions and 2243 deletions
+16 -8
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -40,6 +40,13 @@ struct TypeInfoClassDeclaration;
struct VarDeclaration;
struct dt_t;
enum Sizeok
{
SIZEOKnone, // size of aggregate is not computed yet
SIZEOKdone, // size of aggregate is set correctly
SIZEOKfwd, // error in computing size of aggregate
};
#if IN_LLVM
struct ClassInfoDeclaration;
namespace llvm
@@ -63,10 +70,7 @@ struct AggregateDeclaration : ScopeDsymbol
unsigned structalign; // struct member alignment in effect
int hasUnions; // set if aggregate has overlapping fields
VarDeclarations fields; // VarDeclaration fields
unsigned sizeok; // set when structsize contains valid data
// 0: no size
// 1: size is correct
// 2: cannot determine size; fwd referenced
enum Sizeok sizeok; // set when structsize contains valid data
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
bool isdeprecated; // !=0 if deprecated
@@ -91,7 +95,8 @@ struct AggregateDeclaration : ScopeDsymbol
FuncDeclaration *dtor; // aggregate destructor
#ifdef IN_GCC
Array methods; // flat list of all methods for debug information
Expressions *attributes; // GCC decl/type attributes
FuncDeclarations methods; // flat list of all methods for debug information
#endif
AggregateDeclaration(Loc loc, Identifier *id);
@@ -100,8 +105,10 @@ struct AggregateDeclaration : ScopeDsymbol
void inlineScan();
unsigned size(Loc loc);
static void alignmember(unsigned salign, unsigned size, unsigned *poffset);
static unsigned placeField(unsigned *nextoffset,
unsigned memsize, unsigned memalignsize, unsigned memalign,
unsigned *paggsize, unsigned *paggalignsize, bool isunion);
Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int firstFieldInUnion(int indx); // first field in union that includes indx
int numFieldsInUnion(int firstIndex); // #fields in union starting at index
int isDeprecated(); // is aggregate deprecated?
@@ -167,7 +174,7 @@ struct StructDeclaration : AggregateDeclaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
void finalizeSize();
void finalizeSize(Scope *sc);
#if DMDV1
Expression *cloneMembers();
#endif
@@ -235,6 +242,7 @@ struct BaseClass
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#else
#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size
#endif
struct ClassDeclaration : AggregateDeclaration
+23
View File
@@ -17,9 +17,32 @@
#include "scope.h"
#include "aggregate.h"
#include "dsymbol.h"
#include "mtype.h"
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e)
{
Type *t = e->type->toBasetype();
AggregateDeclaration *ad;
if (t->ty == Tclass)
{ ad = ((TypeClass *)t)->sym;
goto L1;
}
else if (t->ty == Tstruct)
{ ad = ((TypeStruct *)t)->sym;
L1:
if (ad && ad->aliasthis)
{
e = new DotIdExp(e->loc, e, ad->aliasthis->ident);
e = e->semantic(sc);
e = resolveProperties(sc, e);
}
}
return e;
}
AliasThis::AliasThis(Loc loc, Identifier *ident)
: Dsymbol(NULL) // it's anonymous (no identifier)
+145 -165
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -54,6 +54,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
return decl;
}
int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
{
Dsymbols *d = include(NULL, NULL);
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
if (s)
{
if (s->apply(fp, param))
return 1;
}
}
}
return 0;
}
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int m = 0;
@@ -61,8 +79,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
m |= s->addMember(sc, sd, m | memnum);
}
@@ -92,8 +110,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i];
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->setScope(newsc); // yes, the only difference from semanticNewSc()
}
@@ -127,8 +145,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc,
newsc->explicitProtection = explicitProtection;
newsc->structalign = structalign;
}
for (unsigned i = 0; i < decl->dim; i++)
{ Dsymbol *s = decl->tdata()[i];
for (size_t i = 0; i < decl->dim; i++)
{ Dsymbol *s = (*decl)[i];
s->semantic(newsc);
}
@@ -149,7 +167,7 @@ void AttribDeclaration::semantic(Scope *sc)
{
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
s->semantic(sc);
}
@@ -163,7 +181,7 @@ void AttribDeclaration::semantic2(Scope *sc)
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
{ Dsymbol *s = (*d)[i];
s->semantic2(sc);
}
}
@@ -176,7 +194,7 @@ void AttribDeclaration::semantic3(Scope *sc)
if (d)
{
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
{ Dsymbol *s = (*d)[i];
s->semantic3(sc);
}
}
@@ -188,8 +206,8 @@ void AttribDeclaration::inlineScan()
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::inlineScan %s\n", s->toChars());
s->inlineScan();
}
@@ -205,8 +223,8 @@ void AttribDeclaration::addComment(unsigned char *comment)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::addComment %s\n", s->toChars());
s->addComment(comment);
}
@@ -230,8 +248,8 @@ void AttribDeclaration::emitComment(Scope *sc)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("AttribDeclaration::emitComment %s\n", s->toChars());
s->emitComment(sc);
}
@@ -246,32 +264,26 @@ void AttribDeclaration::toObjFile(int multiobj)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->toObjFile(multiobj);
}
}
}
#endif
int AttribDeclaration::cvMember(unsigned char *p)
void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
int nwritten = 0;
int n;
Dsymbols *d = include(NULL, NULL);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
n = s->cvMember(p);
if (p)
p += n;
nwritten += n;
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->setFieldOffset(ad, poffset, isunion);
}
}
return nwritten;
}
#endif
int AttribDeclaration::hasPointers()
{
@@ -281,7 +293,7 @@ int AttribDeclaration::hasPointers()
{
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
if (s->hasPointers())
return 1;
}
@@ -323,8 +335,8 @@ void AttribDeclaration::checkCtorConstInit()
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->checkCtorConstInit();
}
}
@@ -339,8 +351,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->addLocalClass(aclasses);
}
}
@@ -354,15 +366,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (decl->dim == 0)
buf->writestring("{}");
else if (decl->dim == 1)
(decl->tdata()[0])->toCBuffer(buf, hgs);
((*decl)[0])->toCBuffer(buf, hgs);
else
{
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
@@ -581,9 +593,9 @@ void LinkDeclaration::semantic3(Scope *sc)
{ enum LINK linkage_save = sc->linkage;
sc->linkage = linkage;
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
s->semantic3(sc);
}
@@ -757,6 +769,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
: AttribDeclaration(decl)
{
this->loc = loc;
this->alignment = 0;
this->isunion = isunion;
this->sem = 0;
}
@@ -774,21 +787,6 @@ void AnonDeclaration::semantic(Scope *sc)
{
//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
if (sem == 1)
{ //printf("already completed\n");
scope = NULL;
return; // semantic() already completed
}
Scope *scx = NULL;
if (scope)
{ sc = scope;
scx = scope;
scope = NULL;
}
unsigned dprogress_save = Module::dprogress;
assert(sc->parent);
Dsymbol *parent = sc->parent->pastMixin();
@@ -800,106 +798,85 @@ void AnonDeclaration::semantic(Scope *sc)
return;
}
alignment = sc->structalign;
if (decl)
{
AnonymousAggregateDeclaration aad;
int adisunion;
if (sc->anonAgg)
{ ad = sc->anonAgg;
adisunion = sc->inunion;
}
else
adisunion = ad->isUnionDeclaration() != NULL;
// printf("\tsc->anonAgg = %p\n", sc->anonAgg);
// printf("\tad = %p\n", ad);
// printf("\taad = %p\n", &aad);
sc = sc->push();
sc->anonAgg = &aad;
sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
sc->inunion = isunion;
sc->offset = 0;
sc->flags = 0;
aad.structalign = sc->structalign;
aad.parent = ad;
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
s->semantic(sc);
if (isunion)
sc->offset = 0;
if (aad.sizeok == 2)
{
break;
}
}
sc = sc->pop();
}
}
// If failed due to forward references, unwind and try again later
if (aad.sizeok == 2)
void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
//printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
if (decl)
{
/* This works by treating an AnonDeclaration as an aggregate 'member',
* so in order to place that member we need to compute the member's
* size and alignment.
*/
size_t fieldstart = ad->fields.dim;
/* Hackishly hijack ad's structsize and alignsize fields
* for use in our fake anon aggregate member.
*/
unsigned savestructsize = ad->structsize;
unsigned savealignsize = ad->alignsize;
ad->structsize = 0;
ad->alignsize = 0;
unsigned offset = 0;
for (size_t i = 0; i < decl->dim; i++)
{
ad->sizeok = 2;
//printf("\tsetting ad->sizeok %p to 2\n", ad);
if (!sc->anonAgg)
{
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
}
Module::dprogress = dprogress_save;
//printf("\tforward reference %p\n", this);
return;
Dsymbol *s = (*decl)[i];
s->setFieldOffset(ad, &offset, this->isunion);
if (this->isunion)
offset = 0;
}
if (sem == 0)
{ Module::dprogress++;
sem = 1;
//printf("\tcompleted %p\n", this);
}
else
;//printf("\talready completed %p\n", this);
unsigned anonstructsize = ad->structsize;
unsigned anonalignsize = ad->alignsize;
ad->structsize = savestructsize;
ad->alignsize = savealignsize;
// 0 sized structs are set to 1 byte
if (aad.structsize == 0)
if (anonstructsize == 0)
{
aad.structsize = 1;
aad.alignsize = 1;
anonstructsize = 1;
anonalignsize = 1;
}
// Align size of anonymous aggregate
//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
//ad->structsize = sc->offset;
//printf("sc->offset = %d\n", sc->offset);
/* Given the anon 'member's size and alignment,
* go ahead and place it.
*/
unsigned anonoffset = AggregateDeclaration::placeField(
poffset,
anonstructsize, anonalignsize, alignment,
&ad->structsize, &ad->alignsize,
isunion);
// Add members of aad to ad
//printf("\tadding members of aad to '%s'\n", ad->toChars());
for (unsigned i = 0; i < aad.fields.dim; i++)
// Add to the anon fields the base offset of this anonymous aggregate
//printf("anon fields, anonoffset = %d\n", anonoffset);
for (size_t i = fieldstart; i < ad->fields.dim; i++)
{
VarDeclaration *v = aad.fields.tdata()[i];
v->offset += sc->offset;
ad->fields.push(v);
VarDeclaration *v = ad->fields[i];
//printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
v->offset += anonoffset;
}
// Add size of aad to ad
if (adisunion)
{
if (aad.structsize > ad->structsize)
ad->structsize = aad.structsize;
sc->offset = 0;
}
else
{
ad->structsize = sc->offset + aad.structsize;
sc->offset = ad->structsize;
}
if (ad->alignsize < aad.alignsize)
ad->alignsize = aad.alignsize;
}
}
@@ -910,9 +887,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writestring("\n{\n");
if (decl)
{
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
//buf->writestring(" ");
s->toCBuffer(buf, hgs);
@@ -958,10 +935,10 @@ void PragmaDeclaration::setScope(Scope *sc)
}
else
{
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e;
(*args)[0] = e;
StringExp* se = e->toString();
if (!se)
{
@@ -996,10 +973,15 @@ void PragmaDeclaration::semantic(Scope *sc)
{
for (size_t i = 0; i < args->dim; i++)
{
Expression *e = args->tdata()[i];
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op != TOKerror)
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op == TOKerror)
{ errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
return;
}
StringExp *se = e->toString();
if (se)
{
@@ -1018,11 +1000,11 @@ void PragmaDeclaration::semantic(Scope *sc)
error("string expected for library name");
else
{
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e;
(*args)[0] = e;
if (e->op == TOKerror)
goto Lnodecl;
StringExp *se = e->toString();
@@ -1050,7 +1032,7 @@ void PragmaDeclaration::semantic(Scope *sc)
Declaration *d = NULL;
StringExp *s = NULL;
e = args->tdata()[0];
e = (*args)[0];
e = e->semantic(sc);
if (e->op == TOKvar)
{
@@ -1061,14 +1043,14 @@ void PragmaDeclaration::semantic(Scope *sc)
if (!d)
error("first argument of GNU_asm must be a function or variable declaration");
e = args->tdata()[1];
e = (*args)[1];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
e = e->toString();
if (e && ((StringExp *)e)->sz == 1)
s = ((StringExp *)e);
else
error("second argument of GNU_asm must be a char string");
error("second argument of GNU_asm must be a character string");
if (d && s)
d->c_ident = Lexer::idPool((char*) s->string);
@@ -1083,10 +1065,10 @@ void PragmaDeclaration::semantic(Scope *sc)
error("function name expected for start address");
else
{
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
args->tdata()[0] = e;
(*args)[0] = e;
Dsymbol *sa = getDsymbol(e);
if (!sa || !sa->isFuncDeclaration())
error("function name expected for start address, not '%s'", e->toChars());
@@ -1116,7 +1098,7 @@ void PragmaDeclaration::semantic(Scope *sc)
{
for (size_t i = 0; i < args->dim; i++)
{
Expression *e = args->tdata()[i];
Expression *e = (*args)[i];
// ignore errors in ignored pragmas.
global.gag++;
unsigned errors_save = global.errors;
@@ -1145,9 +1127,9 @@ void PragmaDeclaration::semantic(Scope *sc)
Ldecl:
if (decl)
{
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
s->semantic(sc);
@@ -1184,7 +1166,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
{
assert(args && args->dim == 1);
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
assert(e->op == TOKstring);
@@ -1212,7 +1194,7 @@ void PragmaDeclaration::toObjFile(int multiobj)
else if (ident == Id::startaddress)
{
assert(args && args->dim == 1);
Expression *e = args->tdata()[0];
Expression *e = (*args)[0];
Dsymbol *sa = getDsymbol(e);
FuncDeclaration *f = sa->isFuncDeclaration();
assert(f);
@@ -1284,8 +1266,8 @@ void ConditionalDeclaration::emitComment(Scope *sc)
* a template, then include(NULL, NULL) will fail.
*/
Dsymbols *d = decl ? decl : elsedecl;
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
s->emitComment(sc);
}
}
@@ -1307,9 +1289,9 @@ void ConditionalDeclaration::setScope(Scope *sc)
//printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
s->setScope(sc);
}
@@ -1323,9 +1305,9 @@ void ConditionalDeclaration::importAll(Scope *sc)
//printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
s->importAll(sc);
}
@@ -1348,10 +1330,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment)
{
if (d)
{
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s;
s = d->tdata()[i];
for (size_t i = 0; i < d->dim; i++)
{ Dsymbol *s = (*d)[i];
//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
s->addComment(comment);
}
@@ -1371,9 +1351,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
if (decl)
{
for (unsigned i = 0; i < decl->dim; i++)
for (size_t i = 0; i < decl->dim; i++)
{
Dsymbol *s = decl->tdata()[i];
Dsymbol *s = (*decl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
@@ -1387,9 +1367,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
buf->writeByte('{');
buf->writenl();
for (unsigned i = 0; i < elsedecl->dim; i++)
for (size_t i = 0; i < elsedecl->dim; i++)
{
Dsymbol *s = elsedecl->tdata()[i];
Dsymbol *s = (*elsedecl)[i];
buf->writestring(" ");
s->toCBuffer(buf, hgs);
@@ -1473,9 +1453,9 @@ void StaticIfDeclaration::semantic(Scope *sc)
addisdone = 1;
}
for (unsigned i = 0; i < d->dim; i++)
for (size_t i = 0; i < d->dim; i++)
{
Dsymbol *s = d->tdata()[i];
Dsymbol *s = (*d)[i];
s->semantic(sc);
}
+6 -3
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol
AttribDeclaration(Dsymbols *decl);
virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s);
int apply(Dsymbol_apply_ft_t fp, void *param);
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
void setScopeNewSc(Scope *sc,
StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection,
@@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol
void emitComment(Scope *sc);
const char *kind();
int oneMember(Dsymbol **ps, Identifier *ident);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
int hasPointers();
bool hasStaticCtorOrDtor();
void checkCtorConstInit();
@@ -58,7 +60,6 @@ struct AttribDeclaration : Dsymbol
#if IN_DMD
void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
#endif
#if IN_LLVM
@@ -120,12 +121,14 @@ struct AlignDeclaration : AttribDeclaration
struct AnonDeclaration : AttribDeclaration
{
int isunion;
bool isunion;
unsigned alignment;
int sem; // 1 if successful semantic()
AnonDeclaration(Loc loc, int isunion, Dsymbols *decl);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
};
+10 -9
View File
@@ -12,15 +12,6 @@
#include <assert.h>
#include <math.h>
#if __FreeBSD__
extern "C"
{
long double sinl(long double);
long double cosl(long double);
long double tanl(long double);
long double sqrtl(long double);
}
#endif
#include "mars.h"
#include "declaration.h"
@@ -33,6 +24,16 @@ extern "C"
#include "id.h"
#include "module.h"
#if __FreeBSD__
extern "C"
{
longdouble sinl(longdouble);
longdouble cosl(longdouble);
longdouble tanl(longdouble);
longdouble sqrtl(longdouble);
}
#endif
#if DMDV2
/**********************************
+231 -48
View File
@@ -17,6 +17,7 @@
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "template.h"
#include "scope.h"
//#define DUMP .dump(__PRETTY_FUNCTION__, this)
@@ -107,6 +108,9 @@ fflush(stdout);
else if (t->reliesOnTident())
error("forward reference to type %s", t->reliesOnTident()->toChars());
//printf("type %p ty %d deco %p\n", type, type->ty, type->deco);
//type = type->semantic(loc, sc);
//printf("type %s t %s\n", type->deco, t->deco);
error("cannot implicitly convert expression (%s) of type %s to %s",
toChars(), type->toChars(), t->toChars());
}
@@ -131,6 +135,12 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t)
return this;
}
Expression *FuncExp::implicitCastTo(Scope *sc, Type *t)
{
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
return inferType(t);
}
/*******************************************
* Return !=0 if we can implicitly convert this to type t.
* Don't do the actual cast.
@@ -352,16 +362,16 @@ MATCH IntegerExp::implicitConvTo(Type *t)
case Tfloat80:
{
volatile long double f;
volatile_longdouble f;
if (type->isunsigned())
{
f = (long double)value;
if (f != value)
f = ldouble(value);
if (f != value) // isn't this a noop, because the compiler prefers ld
goto Lno;
}
else
{
f = (long double)(long long)value;
f = ldouble((long long)value);
if (f != (long long)value)
goto Lno;
}
@@ -490,14 +500,17 @@ MATCH StringExp::implicitConvTo(Type *t)
return MATCHnomatch;
m = MATCHconst;
}
switch (tn->ty)
if (!committed)
{
case Tchar:
case Twchar:
case Tdchar:
if (!committed)
return m;
break;
switch (tn->ty)
{
case Tchar:
return (postfix != 'w' && postfix != 'd' ? m : MATCHconvert);
case Twchar:
return (postfix == 'w' ? m : MATCHconvert);
case Tdchar:
return (postfix == 'd' ? m : MATCHconvert);
}
}
break;
}
@@ -721,12 +734,24 @@ MATCH DelegateExp::implicitConvTo(Type *t)
MATCH FuncExp::implicitConvTo(Type *t)
{
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer
&& (t->ty == Tpointer || t->ty == Tdelegate))
{ // Allow implicit function to delegate conversion
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
//printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
Expression *e = inferType(t, 1);
if (e)
{
if (e != this)
return e->implicitConvTo(t);
/* MATCHconst: Conversion from implicit to explicit function pointer
* MATCHconvert: Conversion from impliict funciton pointer to delegate
*/
if (tok == TOKreserved && type->ty == Tpointer &&
(t->ty == Tpointer || t->ty == Tdelegate))
{
if (type == t)
return MATCHexact;
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
}
}
return Expression::implicitConvTo(t);
}
@@ -850,7 +875,7 @@ Expression *Expression::castTo(Scope *sc, Type *t)
{ /* Forward the cast to our alias this member, rewrite to:
* cast(to)e1.aliasthis
*/
Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
Expression *e1 = resolveAliasThis(sc, this);
Expression *e2 = new CastExp(loc, e1, tb);
e2 = e2->semantic(sc);
return e2;
@@ -871,7 +896,7 @@ Expression *Expression::castTo(Scope *sc, Type *t)
/* Forward the cast to our alias this member, rewrite to:
* cast(to)e1.aliasthis
*/
Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident);
Expression *e1 = resolveAliasThis(sc, this);
Expression *e2 = new CastExp(loc, e1, tb);
e2 = e2->semantic(sc);
return e2;
@@ -1508,7 +1533,7 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t)
Expression *e = this;
Type *tb = t->toBasetype();
Type *typeb = type->toBasetype();
if (tb != typeb)
if (tb != typeb || hasOverloads)
{
// Look for delegates to functions where the functions are overloaded.
FuncDeclaration *f;
@@ -1549,15 +1574,11 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t)
Expression *FuncExp::castTo(Scope *sc, Type *t)
{
//printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars());
if (tok == TOKreserved)
{ assert(type && type != Type::tvoid);
if (type->ty == Tpointer && t->ty == Tdelegate)
{
Expression *e = copy();
e->type = new TypeDelegate(fd->type);
e->type = e->type->semantic(loc, sc);
return e;
}
Expression *e = inferType(t, 1);
if (e)
{ if (e != this)
e = e->castTo(sc, t);
return e;
}
return Expression::castTo(sc, t);
}
@@ -1595,6 +1616,180 @@ Expression *CommaExp::castTo(Scope *sc, Type *t)
return e;
}
/* ==================== inferType ====================== */
/****************************************
* Set type inference target
* flag 1: don't put an error when inference fails
*/
Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams)
{
return this;
}
Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
{
if (t)
{
t = t->toBasetype();
if (t->ty == Tarray || t->ty == Tsarray)
{
Type *tn = t->nextOf();
for (size_t i = 0; i < elements->dim; i++)
{ Expression *e = (*elements)[i];
if (e)
{ e = e->inferType(tn, flag, tparams);
(*elements)[i] = e;
}
}
}
}
return this;
}
Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams)
{
if (t)
{
t = t->toBasetype();
if (t->ty == Taarray)
{ TypeAArray *taa = (TypeAArray *)t;
Type *ti = taa->index;
Type *tv = taa->nextOf();
for (size_t i = 0; i < keys->dim; i++)
{ Expression *e = (*keys)[i];
if (e)
{ e = e->inferType(ti, flag, tparams);
(*keys)[i] = e;
}
}
for (size_t i = 0; i < values->dim; i++)
{ Expression *e = (*values)[i];
if (e)
{ e = e->inferType(tv, flag, tparams);
(*values)[i] = e;
}
}
}
}
return this;
}
Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams)
{
if (!to)
return this;
//printf("FuncExp::interType('%s'), to=%s\n", type?type->toChars():"null", to->toChars());
if (!type) // semantic is not yet done
{
if (to->ty == Tdelegate ||
to->ty == Tpointer && to->nextOf()->ty == Tfunction)
{ treq = to;
}
return this;
}
Expression *e = NULL;
Type *t = to;
if (t->ty == Tdelegate)
{ if (tok == TOKfunction)
goto L1;
t = t->nextOf();
}
else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction)
{ if (tok == TOKdelegate)
goto L1;
t = t->nextOf();
}
if (td)
{ /// Parameter types inference from
assert(td->scope);
if (t->ty == Tfunction)
{
TypeFunction *tfv = (TypeFunction *)t;
TypeFunction *tfl = (TypeFunction *)fd->type;
size_t dim = Parameter::dim(tfl->parameters);
if (Parameter::dim(tfv->parameters) == dim &&
tfv->varargs == tfl->varargs)
{
Objects *tiargs = new Objects();
tiargs->reserve(td->parameters->dim);
for (size_t i = 0; i < td->parameters->dim; i++)
{
TemplateParameter *tp = (*td->parameters)[i];
for (size_t u = 0; u < dim; u++)
{ Parameter *p = Parameter::getNth(tfl->parameters, u);
if (p->type->ty == Tident &&
((TypeIdentifier *)p->type)->ident == tp->ident)
{ p = Parameter::getNth(tfv->parameters, u);
Type *tprm = p->type;
if (tprm->reliesOnTident(tparams))
goto L1;
tprm = tprm->semantic(loc, td->scope);
tiargs->push(tprm);
u = dim; // break inner loop
}
}
}
TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
e = (new ScopeExp(loc, ti))->semantic(td->scope);
if (e->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)e;
assert(fe->td == NULL);
e = fe->inferType(to, flag);
}
}
}
}
else if (type)
{
assert(type != Type::tvoid); // semantic is already done
// Allow conversion from implicit function pointer to delegate
if (tok == TOKreserved && type->ty == Tpointer &&
to->ty == Tdelegate)
{
Type *typen = type->nextOf();
assert(typen->deco);
//if (typen->covariant(to->nextOf()) == 1)
{
FuncExp *fe = (FuncExp *)copy();
fe->tok = TOKdelegate;
fe->type = (new TypeDelegate(typen))->merge();
e = fe;
//e = fe->Expression::implicitCastTo(sc, to);
}
}
else
e = this;
}
L1:
if (!flag && !e)
{ error("cannot infer function literal type from %s", to->toChars());
e = new ErrorExp();
}
return e;
}
Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams)
{
if (t)
{
t = t->toBasetype();
e1 = e1->inferType(t, flag, tparams);
e2 = e2->inferType(t, flag, tparams);
}
return this;
}
/* ==================== ====================== */
/****************************************
@@ -1718,6 +1913,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
#endif
assert(t2);
Lagain:
Type *t1b = t1->toBasetype();
Type *t2b = t2->toBasetype();
@@ -1757,7 +1953,6 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression
t1 = t1b;
t2 = t2b;
Lagain:
if (t1 == t2)
{
}
@@ -2007,17 +2202,13 @@ Lcc:
}
else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident);
e1 = e1->semantic(sc);
e1 = resolveProperties(sc, e1);
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
continue;
}
else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident);
e2 = e2->semantic(sc);
e2 = resolveProperties(sc, e2);
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
continue;
}
@@ -2052,16 +2243,12 @@ Lcc:
Expression *e2b = NULL;
if (ts2->sym->aliasthis)
{
e2b = new DotIdExp(e2->loc, e2, ts2->sym->aliasthis->ident);
e2b = e2b->semantic(sc);
e2b = resolveProperties(sc, e2b);
e2b = resolveAliasThis(sc, e2);
i1 = e2b->implicitConvTo(t1);
}
if (ts1->sym->aliasthis)
{
e1b = new DotIdExp(e1->loc, e1, ts1->sym->aliasthis->ident);
e1b = e1b->semantic(sc);
e1b = resolveProperties(sc, e1b);
e1b = resolveAliasThis(sc, e1);
i2 = e1b->implicitConvTo(t2);
}
if (i1 && i2)
@@ -2088,18 +2275,14 @@ Lcc:
{
if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident);
e1 = e1->semantic(sc);
e1 = resolveProperties(sc, e1);
e1 = resolveAliasThis(sc, e1);
t1 = e1->type;
t = t1;
goto Lagain;
}
if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis)
{
e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident);
e2 = e2->semantic(sc);
e2 = resolveProperties(sc, e2);
e2 = resolveAliasThis(sc, e2);
t2 = e2->type;
t = t2;
goto Lagain;
+57 -34
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -277,7 +277,7 @@ void ClassDeclaration::semantic(Scope *sc)
return;
}
if (symtab)
{ if (sizeok == 1 || !scope)
{ if (sizeok == SIZEOKdone || !scope)
{ //printf("\tsemantic for '%s' is already completed\n", toChars());
return; // semantic() already completed
}
@@ -337,7 +337,8 @@ void ClassDeclaration::semantic(Scope *sc)
//b->type = b->type->semantic(loc, sc);
tb = b->type->toBasetype();
if (tb->ty != Tclass)
{ error("base type must be class or interface, not %s", b->type->toChars());
{ if (b->type != Type::terror)
error("base type must be class or interface, not %s", b->type->toChars());
baseclasses->remove(0);
}
else
@@ -368,12 +369,12 @@ void ClassDeclaration::semantic(Scope *sc)
goto L7;
}
}
if (!tc->sym->symtab || tc->sym->sizeok == 0)
if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone)
{ // Try to resolve forward reference
if (/*sc->mustsemantic &&*/ tc->sym->scope)
tc->sym->semantic(NULL);
}
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone)
{
//printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
//error("forward reference of base class %s", baseClass->toChars());
@@ -410,8 +411,8 @@ void ClassDeclaration::semantic(Scope *sc)
else
tc = NULL;
if (!tc || !tc->sym->isInterfaceDeclaration())
{
error("base type must be interface, not %s", b->type->toChars());
{ if (b->type != Type::terror)
error("base type must be interface, not %s", b->type->toChars());
baseclasses->remove(i);
continue;
}
@@ -516,13 +517,13 @@ void ClassDeclaration::semantic(Scope *sc)
protection = sc->protection;
storage_class |= sc->stc;
if (sizeok == 0)
if (sizeok == SIZEOKnone)
{
interfaceSemantic(sc);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->addMember(sc, this, 1);
}
@@ -593,13 +594,6 @@ void ClassDeclaration::semantic(Scope *sc)
if (storage_class & STCabstract)
isabstract = 1;
if (storage_class & STCimmutable)
type = type->addMod(MODimmutable);
if (storage_class & STCconst)
type = type->addMod(MODconst);
if (storage_class & STCshared)
type = type->addMod(MODshared);
sc = sc->push(this);
//sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
//sc->stc |= storage_class & STC_TYPECTOR;
@@ -635,17 +629,20 @@ void ClassDeclaration::semantic(Scope *sc)
structsize = sc->offset;
Scope scsave = *sc;
size_t members_dim = members->dim;
sizeok = 0;
sizeok = SIZEOKnone;
/* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums.
*/
for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because
* Scope keeps track of things like 'offset'
*/
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
if (s->isEnumDeclaration() ||
(s->isAggregateDeclaration() && s->ident) ||
s->isTemplateMixin() ||
s->isAliasDeclaration())
{
//printf("setScope %s %s\n", s->kind(), s->toChars());
s->setScope(sc);
@@ -653,19 +650,35 @@ void ClassDeclaration::semantic(Scope *sc)
}
for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
s->semantic(sc);
}
// Set the offsets of the fields and determine the size of the class
unsigned offset = structsize;
bool isunion = isUnionDeclaration() != NULL;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setFieldOffset(this, &offset, false);
}
sc->offset = structsize;
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
type = Type::terror;
}
if (sizeok == 2) // failed due to forward references
if (sizeok == SIZEOKfwd) // failed due to forward references
{ // semantic() failed due to forward references
// Unwind what we did, and defer it for later
for (size_t i = 0; i < fields.dim; i++)
{ Dsymbol *s = fields[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd)
vd->offset = 0;
}
fields.setDim(0);
structsize = 0;
alignsize = 0;
@@ -685,15 +698,19 @@ void ClassDeclaration::semantic(Scope *sc)
//printf("\tsemantic('%s') successful\n", toChars());
structsize = sc->offset;
//members->print();
/* Look for special member functions.
* They must be in this class, not in a base class.
*/
ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
ctor = search(0, Id::ctor, 0);
#if DMDV1
if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
ctor = NULL;
#else
if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration())))
ctor = NULL; // search() looks through ancestor classes
#endif
// dtor = (DtorDeclaration *)search(Id::dtor, 0);
// if (dtor && dtor->toParent() != this)
@@ -719,7 +736,6 @@ void ClassDeclaration::semantic(Scope *sc)
members->push(ctor);
ctor->addMember(sc, this, 1);
*sc = scsave; // why? What about sc->nofree?
sc->offset = structsize;
ctor->semantic(sc);
this->ctor = ctor;
defaultCtor = ctor;
@@ -735,9 +751,10 @@ void ClassDeclaration::semantic(Scope *sc)
#endif
// Allocate instance of each new interface
sc->offset = structsize;
for (size_t i = 0; i < vtblInterfaces->dim; i++)
{
BaseClass *b = vtblInterfaces->tdata()[i];
BaseClass *b = (*vtblInterfaces)[i];
unsigned thissize = PTRSIZE;
alignmember(structalign, thissize, &sc->offset);
@@ -760,7 +777,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (global.params.is64bit)
structsize = (structsize + structalign - 1) & ~(structalign - 1);
#endif
sizeok = 1;
sizeok = SIZEOKdone;
Module::dprogress++;
dtor = buildDtor(sc);
@@ -906,7 +923,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
if (scope && !symtab)
{ Scope *sc = scope;
sc->mustsemantic++;
// If speculatively gagged, ungag now.
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging())
global.gag = 0;
semantic(sc);
global.gag = oldgag;
sc->mustsemantic--;
}
@@ -1025,7 +1047,7 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
{
for (size_t i = 0; i < vtbl->dim; i++)
{
FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration();
FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration();
if (!fd)
continue; // the first entry might be a ClassInfo
@@ -1244,7 +1266,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = baseclasses->tdata()[0];
{ BaseClass *b = (*baseclasses)[0];
b->type = b->type->semantic(loc, sc);
Type *tb = b->type->toBasetype();
@@ -1280,8 +1302,8 @@ void InterfaceDeclaration::semantic(Scope *sc)
else
tc = NULL;
if (!tc || !tc->sym->isInterfaceDeclaration())
{
error("base type must be interface, not %s", b->type->toChars());
{ if (b->type != Type::terror)
error("base type must be interface, not %s", b->type->toChars());
baseclasses->remove(i);
continue;
}
@@ -1338,7 +1360,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
{ BaseClass *b = interfaces[i];
// Skip if b has already appeared
for (int k = 0; k < i; k++)
for (size_t k = 0; k < i; k++)
{
if (b == interfaces[k])
goto Lcontinue;
@@ -1346,11 +1368,11 @@ void InterfaceDeclaration::semantic(Scope *sc)
// Copy vtbl[] from base class
if (b->base->vtblOffset())
{ int d = b->base->vtbl.dim;
{ size_t d = b->base->vtbl.dim;
if (d > 1)
{
vtbl.reserve(d - 1);
for (int j = 1; j < d; j++)
for (size_t j = 1; j < d; j++)
vtbl.push(b->base->vtbl.tdata()[j]);
}
}
@@ -1368,7 +1390,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->addMember(sc, this, 1);
}
@@ -1384,6 +1406,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
sc->explicitProtection = 0;
structalign = sc->structalign;
sc->offset = PTRSIZE * 2;
structsize = sc->offset;
inuse++;
/* Set scope so if there are forward references, we still might be able to
+14
View File
@@ -204,6 +204,11 @@ int StructDeclaration::needOpEquals()
if (hasIdentityEquals)
goto Lneed;
#if 0
if (isUnionDeclaration())
goto Ldontneed;
#endif
/* If any of the fields has an opEquals, then we
* need it too.
*/
@@ -215,6 +220,14 @@ int StructDeclaration::needOpEquals()
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
#if 0
if (tv->isfloating())
goto Lneed;
if (tv->ty == Tarray)
goto Lneed;
if (tv->ty == Tclass)
goto Lneed;
#endif
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
@@ -226,6 +239,7 @@ int StructDeclaration::needOpEquals()
goto Lneed;
}
}
Ldontneed:
if (X) printf("\tdontneed\n");
return 0;
+14 -12
View File
@@ -16,12 +16,14 @@
struct complex_t
{
long double re;
long double im;
longdouble re;
longdouble im;
complex_t() { this->re = 0; this->im = 0; }
complex_t(long double re) { this->re = re; this->im = 0; }
complex_t(long double re, long double im) { this->re = re; this->im = im; }
complex_t(longdouble re) { this->re = re; this->im = 0; }
complex_t(double re) { this->re = re; this->im = 0; }
complex_t(longdouble re, longdouble im) { this->re = re; this->im = im; }
complex_t(double re, double im) { this->re = re; this->im = im; }
complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; }
complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; }
@@ -30,9 +32,9 @@ struct complex_t
complex_t operator / (complex_t y)
{
long double abs_y_re = y.re < 0 ? -y.re : y.re;
long double abs_y_im = y.im < 0 ? -y.im : y.im;
long double r, den;
longdouble abs_y_re = y.re < 0 ? -y.re : y.re;
longdouble abs_y_im = y.im < 0 ? -y.im : y.im;
longdouble r, den;
if (abs_y_re < abs_y_im)
{
@@ -56,17 +58,17 @@ struct complex_t
int operator != (complex_t y) { return re != y.re || im != y.im; }
};
inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; }
inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); }
inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); }
inline complex_t operator * (longdouble x, complex_t y) { return complex_t(x) * y; }
inline complex_t operator * (complex_t x, longdouble y) { return x * complex_t(y); }
inline complex_t operator / (complex_t x, longdouble y) { return x / complex_t(y); }
inline long double creall(complex_t x)
inline longdouble creall(complex_t x)
{
return x.re;
}
inline long double cimagl(complex_t x)
inline longdouble cimagl(complex_t x)
{
return x.im;
}
+9 -9
View File
@@ -585,12 +585,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
if (e1->type->isfloating())
{
r = new RealExp(loc, e1->toReal(), e1->type);
v = new RealExp(loc, 1.0, e1->type);
v = new RealExp(loc, ldouble(1.0), e1->type);
}
else
{
r = new RealExp(loc, e1->toReal(), Type::tfloat64);
v = new RealExp(loc, 1.0, Type::tfloat64);
v = new RealExp(loc, ldouble(1.0), Type::tfloat64);
}
while (n != 0)
@@ -602,7 +602,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
}
if (neg)
v = Div(v->type, new RealExp(loc, 1.0, v->type), v);
v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v);
if (type->isintegral())
e = new IntegerExp(loc, v->toInteger(), type);
@@ -614,7 +614,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2)
// x ^^ y for x < 0 and y not an integer is not defined
if (e1->toReal() < 0.0)
{
e = new RealExp(loc, Port::nan, type);
e = new RealExp(loc, ldouble(Port::nan), type);
}
else if (e2->toReal() == 0.5)
{
@@ -1354,7 +1354,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (i >= es1->len)
{
e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len);
e1->error("string index %llu is out of bounds [0 .. %llu]", i, (ulonglong)es1->len);
e = new ErrorExp();
}
else
@@ -1369,7 +1369,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (i >= length)
{
e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
e1->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length);
e = new ErrorExp();
}
else if (e1->op == TOKarrayliteral)
@@ -1388,7 +1388,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
if (i >= ale->elements->dim)
{
e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
e1->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
e = new ErrorExp();
}
else
@@ -1444,7 +1444,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
if (iupr > es1->len || ilwr > iupr)
{
e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr);
e = new ErrorExp();
}
else
@@ -1474,7 +1474,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
if (iupr > es1->elements->dim || ilwr > iupr)
{
e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr);
e = new ErrorExp();
}
else
+1 -1
View File
@@ -277,7 +277,7 @@ void TypeVector::toCppMangle(OutBuffer *buf, CppMangleState *cms)
void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->printf("A%ju_", dim ? dim->toInteger() : 0);
{ buf->printf("A%llu_", dim ? dim->toInteger() : 0);
next->toCppMangle(buf, cms);
}
}
+117 -16
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -512,7 +512,8 @@ void AliasDeclaration::semantic(Scope *sc)
if (s)
goto L2;
error("cannot alias an expression %s", e->toChars());
if (e->op != TOKerror)
error("cannot alias an expression %s", e->toChars());
t = e->type;
}
else if (t)
@@ -524,7 +525,7 @@ void AliasDeclaration::semantic(Scope *sc)
ScopeDsymbol::multiplyDefined(0, this, overnext);
this->inSemantic = 0;
if (errors != global.errors)
if (global.gag && errors != global.errors)
type = savedtype;
return;
@@ -563,7 +564,7 @@ void AliasDeclaration::semantic(Scope *sc)
assert(global.errors);
s = NULL;
}
if (errors != global.errors)
if (global.gag && errors != global.errors)
{
type = savedtype;
overnext = savedovernext;
@@ -698,6 +699,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
#if DMDV1
nestedref = 0;
#endif
alignment = 0;
ctorinit = 0;
aliassym = NULL;
onstack = 0;
@@ -1012,7 +1014,7 @@ Lnomatch:
{ Parameter *arg = Parameter::getNth(tt->arguments, i);
OutBuffer buf;
buf.printf("_%s_field_%zu", ident->toChars(), i);
buf.printf("_%s_field_%llu", ident->toChars(), (ulonglong)i);
buf.writeByte(0);
const char *name = (const char *)buf.extractData();
Identifier *id = Lexer::idPool(name);
@@ -1090,9 +1092,7 @@ Lnomatch:
}
else
{
AggregateDeclaration *aad = sc->anonAgg;
if (!aad)
aad = parent->isAggregateDeclaration();
AggregateDeclaration *aad = parent->isAggregateDeclaration();
if (aad)
{
#if DMDV2
@@ -1104,15 +1104,16 @@ Lnomatch:
storage_class |= STCstatic;
}
else
#endif
{
aad->addField(sc, this);
storage_class |= STCfield;
alignment = sc->structalign;
#if DMDV2
if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor ||
tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor)
aad->noDefaultCtor = TRUE;
}
#else
aad->addField(sc, this);
#endif
}
}
InterfaceDeclaration *id = parent->isInterfaceDeclaration();
@@ -1165,7 +1166,7 @@ Lnomatch:
{
if (func->fes)
func = func->fes->func;
if (!func->type->hasWild())
if (!((TypeFunction *)func->type)->iswild)
{
error("inout variables can only be declared inside inout functions");
}
@@ -1271,9 +1272,6 @@ Lnomatch:
StructInitializer *si = init->isStructInitializer();
ExpInitializer *ei = init->isExpInitializer();
if (ei && ei->exp->op == TOKfunction && !inferred)
((FuncExp *)ei->exp)->setType(type);
if (ei && isScope())
{
// See if initializer is a NewExp that can be allocated on the stack
@@ -1322,6 +1320,8 @@ Lnomatch:
Expression *e1 = new VarExp(loc, this);
Type *t = type->toBasetype();
if (ei && !inferred)
ei->exp = ei->exp->inferType(t);
Linit2:
if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
@@ -1597,6 +1597,31 @@ Ldtor:
void VarDeclaration::semantic2(Scope *sc)
{
//printf("VarDeclaration::semantic2('%s')\n", toChars());
// Inside unions, default to void initializers
if (!init && sc->inunion && !toParent()->isFuncDeclaration())
{
AggregateDeclaration *aad = parent->isAggregateDeclaration();
if (aad)
{
if (aad->fields[0] == this)
{
int hasinit = 0;
for (size_t i = 1; i < aad->fields.dim; i++)
{
if (aad->fields[i]->init &&
!aad->fields[i]->init->isVoidInitializer())
{
hasinit = 1;
break;
}
}
if (!hasinit)
init = new ExpInitializer(loc, type->defaultInitLiteral(loc));
}
else
init = new VoidInitializer(loc);
}
}
if (init && !toParent()->isFuncDeclaration())
{ inuse++;
#if 0
@@ -1613,6 +1638,82 @@ void VarDeclaration::semantic2(Scope *sc)
sem = Semantic2Done;
}
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);
}
void VarDeclaration::semantic3(Scope *sc)
{
// LDC
+19 -1
View File
@@ -132,6 +132,10 @@ struct Declaration : Dsymbol
enum LINK linkage;
int inuse; // used to detect cycles
#if IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
enum Semantic sem;
Declaration(Identifier *id);
@@ -280,6 +284,7 @@ struct VarDeclaration : Declaration
#else
int nestedref; // referenced by a lexically nested function
#endif
unsigned short alignment;
int ctorinit; // it has been initialized in a ctor
int onstack; // 1: it has been allocated on the stack
// 2: on stack, run destructor anyway
@@ -306,6 +311,7 @@ struct VarDeclaration : Declaration
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
void semantic2(Scope *sc);
const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -700,6 +706,9 @@ enum BUILTIN
BUILTINbsr, // core.bitop.bsr
BUILTINbsf, // core.bitop.bsf
BUILTINbswap, // core.bitop.bswap
#if IN_GCC
BUILTINgcc, // GCC builtin
#endif
};
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments);
@@ -778,6 +787,7 @@ struct FuncDeclaration : Declaration
VarDeclarations closureVars; // local variables in this function
// which are referenced by nested
// functions
FuncDeclarations deferred; // toObjFile() these functions after this one
unsigned flags;
#define FUNCFLAGpurityInprocess 1 // working on determining purity
@@ -822,10 +832,12 @@ struct FuncDeclaration : Declaration
int isAbstract();
int isCodeseg();
int isOverloadable();
int hasOverloads();
enum PURE isPure();
enum PURE isPureBypassingInference();
bool setImpure();
int isSafe();
bool isSafeBypassingInference();
int isTrusted();
bool setUnsafe();
virtual int isNested();
@@ -862,6 +874,8 @@ struct FuncDeclaration : Declaration
#endif
FuncDeclaration *isFuncDeclaration() { return this; }
virtual FuncDeclaration *toAliasFunc() { return this; }
#if IN_LLVM
// LDC stuff
@@ -905,15 +919,19 @@ FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
struct FuncAliasDeclaration : FuncDeclaration
{
FuncDeclaration *funcalias;
int hasOverloads;
PROT importprot; // if generated by import, store its protection
FuncAliasDeclaration(FuncDeclaration *funcalias);
FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1);
FuncAliasDeclaration *isFuncAliasDeclaration() { return this; }
const char *kind();
#if IN_DMD
Symbol *toSymbol();
char *mangle() { return toAliasFunc()->mangle(); }
#endif
FuncDeclaration *toAliasFunc();
};
struct FuncLiteralDeclaration : FuncDeclaration
+4 -1
View File
@@ -34,7 +34,10 @@ int lambdaCheckForNestedRef(Expression *e, void *param);
Expression *Expression::toDelegate(Scope *sc, Type *t)
{
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd);
Type *tw = t->semantic(loc, sc);
Type *tc = t->substWildTo(MODconst)->semantic(loc, sc);
TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd);
(tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
Expression *e;
+2088
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -261,6 +261,9 @@ void Module::gendocfile()
Macro::define(&macrotable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
}
char *srcfilename = srcfile->toChars();
Macro::define(&macrotable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
char *docfilename = docfile->toChars();
Macro::define(&macrotable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
+61 -9
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -50,6 +50,7 @@ Dsymbol::Dsymbol()
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
this->errors = false;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -70,6 +71,7 @@ Dsymbol::Dsymbol(Identifier *ident)
this->loc = 0;
this->comment = NULL;
this->scope = NULL;
this->errors = false;
#if IN_LLVM
this->llvmInternal = LLVMnone;
@@ -147,12 +149,15 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
if (!(*ps)->ident || !(*ps)->ident->equals(ident))
continue;
}
if (s) // more than one symbol
if (!s)
s = *ps;
else if (s->isOverloadable() && (*ps)->isOverloadable())
; // keep head of overload set
else // more than one symbol
{ *ps = NULL;
//printf("\tfalse 2\n");
return FALSE;
}
s = *ps;
}
}
}
@@ -177,6 +182,10 @@ bool Dsymbol::hasStaticCtorOrDtor()
return FALSE;
}
void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
}
char *Dsymbol::toChars()
{
return ident ? ident->toChars() : (char *)"__anonymous";
@@ -291,6 +300,23 @@ TemplateInstance *Dsymbol::inTemplateInstance()
return NULL;
}
// Check if this function is a member of a template which has only been
// instantiated speculatively, eg from inside is(typeof()).
// Return the speculative template instance it is part of,
// or NULL if not speculative.
TemplateInstance *Dsymbol::isSpeculative()
{
Dsymbol * par = parent;
while (par)
{
TemplateInstance *ti = par->isTemplateInstance();
if (ti && ti->speculative)
return ti;
par = par->toParent();
}
return NULL;
}
int Dsymbol::isAnonymous()
{
return ident ? 0 : 1;
@@ -375,11 +401,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
void *symbol_search_fp(void *arg, const char *seed)
{
/* If not in the lexer's string table, it certainly isn't in the symbol table.
* Doing this first is a lot faster.
*/
size_t len = strlen(seed);
if (!len)
return NULL;
StringValue *sv = Lexer::stringtable.lookup(seed, len);
if (!sv)
return NULL;
Identifier *id = (Identifier *)sv->ptrvalue;
assert(id);
Dsymbol *s = (Dsymbol *)arg;
Identifier id(seed, 0);
Module::clearCache();
s = s->search(0, &id, 4|2);
return s;
return s->search(0, id, 4|2);
}
Dsymbol *Dsymbol::search_correct(Identifier *ident)
@@ -417,8 +453,14 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
id = ti->name;
sm = s->search(loc, id, 0);
if (!sm)
{ error("template identifier %s is not a member of %s %s",
id->toChars(), s->kind(), s->toChars());
{
sm = s->search_correct(id);
if (sm)
error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?",
id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars());
else
error("template identifier '%s' is not a member of '%s %s'",
id->toChars(), s->kind(), s->toChars());
return NULL;
}
sm = sm->toAlias();
@@ -507,6 +549,11 @@ int Dsymbol::isOverloadable()
{
return 0;
}
int Dsymbol::hasOverloads()
{
return 0;
}
#endif
LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
@@ -532,6 +579,11 @@ int Dsymbol::needThis()
return FALSE;
}
int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param)
{
return (*fp)(this, param);
}
int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
//printf("Dsymbol::addMember('%s')\n", toChars());
@@ -1118,7 +1170,7 @@ int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *c
{ Dsymbol *s = (*members)[i];
if (AttribDeclaration *a = s->isAttribDeclaration())
result = foreach(a->decl, dg, ctx, &n);
result = foreach(a->include(NULL, NULL), dg, ctx, &n);
else if (TemplateMixin *tm = s->isTemplateMixin())
result = foreach(tm->members, dg, ctx, &n);
else if (s->isTemplateInstance())
+8 -1
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -134,6 +134,8 @@ enum PASS
PASSobj, // toObjFile() run
};
typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *);
struct Dsymbol : Object
{
Identifier *ident;
@@ -146,6 +148,7 @@ struct Dsymbol : Object
unsigned char *comment; // documentation comment for this Dsymbol
Loc loc; // where defined
Scope *scope; // !=NULL means context to use for semantic()
bool errors; // this symbol failed to pass semantic()
Dsymbol();
Dsymbol(Identifier *);
@@ -163,6 +166,7 @@ struct Dsymbol : Object
Dsymbol *toParent();
Dsymbol *toParent2();
TemplateInstance *inTemplateInstance();
TemplateInstance *isSpeculative();
int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol()
@@ -171,6 +175,7 @@ struct Dsymbol : Object
virtual const char *toPrettyChars();
virtual const char *kind();
virtual Dsymbol *toAlias(); // resolve real symbol
virtual int apply(Dsymbol_apply_ft_t fp, void *param);
virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
@@ -199,6 +204,7 @@ struct Dsymbol : Object
virtual int isDeprecated(); // is Dsymbol deprecated?
#if DMDV2
virtual int isOverloadable();
virtual int hasOverloads();
#endif
virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol?
virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration?
@@ -209,6 +215,7 @@ struct Dsymbol : Object
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps, Identifier *ident);
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
virtual int hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addLocalClass(ClassDeclarations *) { }
+1 -1
View File
@@ -55,7 +55,7 @@ void Expression::dump(int i)
void IntegerExp::dump(int i)
{
indent(i);
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
printf("%p %lld type=%s\n", this, (ulonglong)value, type_print(type));
}
void IdentifierExp::dump(int i)
+20 -1
View File
@@ -169,6 +169,7 @@ void EnumDeclaration::semantic(Scope *sc)
{
EnumMember *em = (*members)[i]->isEnumMember();
Expression *e;
Expression *emax = NULL;
if (!em)
/* The e->semantic(sce) can insert other symbols, such as
@@ -219,10 +220,18 @@ void EnumDeclaration::semantic(Scope *sc)
}
else
{
// Lazily evaluate enum.max
if (!emax)
{
emax = t->getProperty(0, Id::max);
emax = emax->semantic(sce);
emax = emax->optimize(WANTvalue | WANTinterpret);
}
// Set value to (elast + 1).
// But first check that (elast != t.max)
assert(elast);
e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max));
e = new EqualExp(TOKequal, em->loc, elast, emax);
e = e->semantic(sce);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->toInteger())
@@ -233,6 +242,16 @@ void EnumDeclaration::semantic(Scope *sc)
e = e->semantic(sce);
e = e->castTo(sce, elast->type);
e = e->optimize(WANTvalue | WANTinterpret);
if (t->isfloating())
{
// Check that e != elast (not always true for floats)
Expression *etest = new EqualExp(TOKequal, em->loc, e, elast);
etest = etest->semantic(sce);
etest = etest->optimize(WANTvalue | WANTinterpret);
if (etest->toInteger())
error("enum member %s has inexact value, due to loss of precision", em->toChars());
}
}
elast = e;
em->value = e;
+3
View File
@@ -42,6 +42,9 @@ struct EnumDeclaration : ScopeDsymbol
int isdeprecated;
int isdone; // 0: not done
// 1: semantic() successfully completed
#if IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
EnumDeclaration(Loc loc, Identifier *id, Type *memtype);
Dsymbol *syntaxCopy(Dsymbol *s);
+723 -928
View File
File diff suppressed because it is too large Load Diff
+29 -13
View File
@@ -97,7 +97,9 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s);
void valueNoDtor(Expression *e);
void modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1);
#if DMDV2
Expression *resolveAliasThis(Scope *sc, Expression *e);
#endif
/* Interpreter: what form of return value expression is required?
*/
@@ -151,6 +153,7 @@ struct Expression : Object
virtual MATCH implicitConvTo(Type *t);
virtual IntRange getIntRange();
virtual Expression *castTo(Scope *sc, Type *t);
virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
virtual void checkEscape();
virtual void checkEscapeRef();
virtual Expression *resolveLoc(Loc loc, Scope *sc);
@@ -503,6 +506,7 @@ struct ArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -537,6 +541,7 @@ struct AssocArrayLiteralExp : Expression
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -555,6 +560,7 @@ struct StructLiteralExp : Expression
Type *stype; // final type of result (can be different from sd's type)
#if IN_DMD
Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer
Symbol *sym; // back end symbol to initialize with literal
#endif
size_t soffset; // offset from start of s
@@ -572,8 +578,6 @@ struct StructLiteralExp : Expression
void toMangleBuffer(OutBuffer *buf);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
MATCH implicitConvTo(Type *t);
int inlineCost3(InlineCostState *ics);
@@ -789,18 +793,17 @@ struct FuncExp : Expression
FuncLiteralDeclaration *fd;
TemplateDeclaration *td;
enum TOK tok;
Type *tded;
Scope *scope;
Type *treq;
FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, Expressions *arguments);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *implicitCastTo(Scope *sc, Type *t);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Scope *sc, Type *t);
void setType(Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -932,8 +935,7 @@ struct BinExp : Expression
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *semanticp(Scope *sc);
void checkComplexMulAssign();
void checkComplexAddAssign();
Expression *checkComplexOpAssign(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *scaleFactor(Scope *sc);
Expression *typeCombine(Scope *sc);
@@ -941,6 +943,7 @@ struct BinExp : Expression
int isunsigned();
Expression *incompatibleTypes();
void dump(int indent);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCommon2(InterState *istate, CtfeGoal goal,
@@ -967,8 +970,7 @@ struct BinAssignExp : BinExp
{
}
Expression *commonSemanticAssign(Scope *sc);
Expression *commonSemanticAssignIntegral(Scope *sc);
Expression *semantic(Scope *sc);
Expression *op_overload(Scope *sc);
@@ -1067,6 +1069,7 @@ struct DotTemplateInstanceExp : UnaExp
Expression *syntaxCopy();
TemplateDeclaration *getTempdecl(Scope *sc);
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
};
@@ -1542,7 +1545,7 @@ struct ConstructExp : AssignExp
struct op##AssignExp : BinAssignExp \
{ \
op##AssignExp(Loc loc, Expression *e1, Expression *e2); \
Expression *semantic(Scope *sc); \
S(Expression *semantic(Scope *sc);) \
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \
X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \
X(Expression *buildArrayLoop(Parameters *fparams);) \
@@ -1553,6 +1556,7 @@ struct op##AssignExp : BinAssignExp \
};
#define X(a) a
#define S(a)
ASSIGNEXP(Add)
ASSIGNEXP(Min)
ASSIGNEXP(Mul)
@@ -1561,17 +1565,28 @@ ASSIGNEXP(Mod)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#undef S
#if DMDV2
#define S(a) a
ASSIGNEXP(Pow)
#undef S
#endif
#undef S
#undef X
#define X(a)
#define S(a)
ASSIGNEXP(Shl)
ASSIGNEXP(Shr)
ASSIGNEXP(Ushr)
#undef S
#define S(a) a
ASSIGNEXP(Cat)
#undef S
#undef X
#undef ASSIGNEXP
@@ -1991,7 +2006,7 @@ struct EqualExp : BinExp
#endif
};
// === and !===
// is and !is
struct IdentityExp : BinExp
{
@@ -2030,6 +2045,7 @@ struct CondExp : BinExp
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
+104 -40
View File
@@ -1,5 +1,5 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -341,13 +341,6 @@ void FuncDeclaration::semantic(Scope *sc)
}
#endif
#ifdef IN_GCC
{
AggregateDeclaration *ad = parent->isAggregateDeclaration();
if (ad)
ad->methods.push(this);
}
#endif
sd = parent->isStructDeclaration();
if (sd)
{
@@ -468,6 +461,9 @@ void FuncDeclaration::semantic(Scope *sc)
//printf("\tnot virtual\n");
goto Ldone;
}
// Suppress further errors if the return type is an error
if (type->nextOf() == Type::terror)
goto Ldone;
/* Find index of existing function in base class's vtbl[] to override
* (the index will be the same as in cd's current vtbl[])
@@ -479,6 +475,7 @@ void FuncDeclaration::semantic(Scope *sc)
switch (vi)
{
case -1:
Lintro:
/* Didn't find one, so
* This is an 'introducing' function which gets a new
* slot in the vtbl[].
@@ -515,7 +512,7 @@ void FuncDeclaration::semantic(Scope *sc)
break;
case -2: // can't determine because of fwd refs
cd->sizeok = 2; // can't finish due to forward reference
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save;
return;
@@ -534,9 +531,12 @@ void FuncDeclaration::semantic(Scope *sc)
FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
if (fdc->toParent() == parent)
{
// fdc overrides fdv exactly, then this introduces new function.
if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod)
goto Lintro;
// If both are mixins, then error.
// If either is not, the one that is not overrides the other.
if (this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
error("multiple overrides of same function");
@@ -600,7 +600,7 @@ void FuncDeclaration::semantic(Scope *sc)
break;
case -2:
cd->sizeok = 2; // can't finish due to forward reference
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save;
return;
@@ -636,7 +636,7 @@ void FuncDeclaration::semantic(Scope *sc)
{
// any error in isBaseOf() is a forward reference error, so we bail out
global.errors = errors;
cd->sizeok = 2; // can't finish due to forward reference
cd->sizeok = SIZEOKfwd; // can't finish due to forward reference
Module::dprogress = dprogress_save;
return;
}
@@ -647,9 +647,14 @@ void FuncDeclaration::semantic(Scope *sc)
}
if (ti)
{
if (tintro && !tintro->equals(ti))
if (tintro)
{
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
if (!tintro->nextOf()->equals(ti->nextOf()) &&
!tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) &&
!ti->nextOf()->isBaseOf(tintro->nextOf(), NULL))
{
error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars());
}
}
tintro = ti;
}
@@ -660,7 +665,11 @@ void FuncDeclaration::semantic(Scope *sc)
if (!doesoverride && isOverride())
{
error("does not override any function");
Dsymbol *s = cd->search_correct(ident);
if (s)
error("does not override any function, did you mean '%s'", s->toPrettyChars());
else
error("does not override any function");
}
L2: ;
@@ -879,7 +888,7 @@ void FuncDeclaration::semantic3(Scope *sc)
//printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
assert(0);
}
//printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
//printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars());
//fflush(stdout);
//printf("storage class = x%x %x\n", sc->stc, storage_class);
//{ static int x; if (++x == 2) *(char*)0=0; }
@@ -978,6 +987,9 @@ void FuncDeclaration::semantic3(Scope *sc)
}
else
assert(!isNested() || sc->intypeof); // can't be both member and nested
#if IN_GCC
ad->methods.push(this);
#endif
}
vthis = declareThis(sc2, ad);
@@ -989,7 +1001,7 @@ void FuncDeclaration::semantic3(Scope *sc)
#else
Type *t;
#if !IN_LLVM
#if !IN_GCC && !IN_LLVM
if (global.params.is64bit)
{ // Declare save area for varargs registers
Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
@@ -1327,7 +1339,7 @@ void FuncDeclaration::semantic3(Scope *sc)
}
}
if (inferRetType || f->retStyle() != RETstack)
if (!inferRetType && f->retStyle() != RETstack)
nrvo_can = 0;
fbody = fbody->semantic(sc2);
@@ -1915,11 +1927,13 @@ int FuncDeclaration::equals(Object *o)
Dsymbol *s = isDsymbol(o);
if (s)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd)
FuncDeclaration *fd1 = this->toAliasFunc();
FuncDeclaration *fd2 = s->isFuncDeclaration();
if (fd2)
{
return toParent()->equals(fd->toParent()) &&
ident->equals(fd->ident) && type->equals(fd->type);
fd2 = fd2->toAliasFunc();
return fd1->toParent()->equals(fd2->toParent()) &&
fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type);
}
}
return FALSE;
@@ -2137,6 +2151,8 @@ int FuncDeclaration::overrides(FuncDeclaration *fd)
int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
{
FuncDeclaration *mismatch = NULL;
StorageClass mismatchstc = 0;
int mismatchvi = -1;
int bestvi = -1;
for (int vi = 0; vi < dim; vi++)
{
@@ -2146,7 +2162,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
if (type->equals(fdv->type)) // if exact match
return vi; // no need to look further
int cov = type->covariant(fdv->type);
StorageClass stc = 0;
int cov = type->covariant(fdv->type, &stc);
//printf("\tbaseclass cov = %d\n", cov);
switch (cov)
{
@@ -2158,6 +2175,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
break; // keep looking for an exact match
case 2:
mismatchvi = vi;
mismatchstc = stc;
mismatch = fdv; // overrides, but is not covariant
break; // keep looking for an exact match
@@ -2174,8 +2193,15 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim)
//type->print();
//mismatch->type->print();
//printf("%s %s\n", type->deco, mismatch->type->deco);
error("of type %s overrides but is not covariant with %s of type %s",
type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
//printf("stc = %llx\n", mismatchstc);
if (mismatchstc)
{ // Fix it by modifying the type to add the storage classes
type = type->addStorageClass(mismatchstc);
bestvi = mismatchvi;
}
else
error("of type %s overrides but is not covariant with %s of type %s",
type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars());
}
return bestvi;
}
@@ -2262,8 +2288,21 @@ int overloadApply(FuncDeclaration *fstart,
if (fa)
{
if (overloadApply(fa->funcalias, fp, param))
return 1;
if (fa->hasOverloads)
{
if (overloadApply(fa->funcalias, fp, param))
return 1;
}
else
{
f = fa->toAliasFunc();
if (!f)
{ d->error("is aliased to a function");
break;
}
if ((*fp)(param, f))
return 1;
}
next = fa->overnext;
}
else
@@ -2611,7 +2650,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
e->type = p->type;
}
else
e = p->type->defaultInit();
e = p->type->defaultInitLiteral(0);
args.tdata()[u] = e;
}
@@ -2925,6 +2964,11 @@ int FuncDeclaration::isOverloadable()
return 1; // functions can be overloaded
}
int FuncDeclaration::hasOverloads()
{
return overnext != NULL;
}
enum PURE FuncDeclaration::isPure()
{
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
@@ -2982,6 +3026,14 @@ int FuncDeclaration::isSafe()
return ((TypeFunction *)type)->trust == TRUSTsafe;
}
bool FuncDeclaration::isSafeBypassingInference()
{
if (flags & FUNCFLAGsafetyInprocess)
return false;
else
return isSafe();
}
int FuncDeclaration::isTrusted()
{
assert(type->ty == Tfunction);
@@ -3012,21 +3064,16 @@ bool FuncDeclaration::setUnsafe()
int FuncDeclaration::isNested()
{
//if (!toParent())
//printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent);
//printf("\ttoParent2() = '%s'\n", toParent2()->toChars());
return ((storage_class & STCstatic) == 0) && toParent2() &&
(toParent2()->isFuncDeclaration() != NULL);
FuncDeclaration *f = toAliasFunc();
//printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars());
return ((f->storage_class & STCstatic) == 0) &&
(f->toParent2()->isFuncDeclaration() != NULL);
}
int FuncDeclaration::needThis()
{
//printf("FuncDeclaration::needThis() '%s'\n", toChars());
int i = isThis() != NULL;
//printf("\t%d\n", i);
if (!i && isFuncAliasDeclaration())
i = ((FuncAliasDeclaration *)this)->funcalias->needThis();
return i;
return toAliasFunc()->isThis() != NULL;
}
int FuncDeclaration::addPreInvariant()
@@ -3272,7 +3319,7 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs)
// Used as a way to import a set of functions from another scope into this one.
FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads)
: FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident,
funcalias->storage_class, funcalias->type)
{
@@ -3281,6 +3328,18 @@ FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias)
#if IN_LLVM
importprot = PROTundefined;
#endif
this->hasOverloads = hasOverloads;
if (hasOverloads)
{
if (FuncAliasDeclaration *fad = funcalias->isFuncAliasDeclaration())
this->hasOverloads = fad->hasOverloads;
}
else
{ // for internal use
assert(!funcalias->isFuncAliasDeclaration());
this->hasOverloads = 0;
}
}
const char *FuncAliasDeclaration::kind()
@@ -3288,6 +3347,11 @@ const char *FuncAliasDeclaration::kind()
return "function alias";
}
FuncDeclaration *FuncAliasDeclaration::toAliasFunc()
{
return funcalias->toAliasFunc();
}
/****************************** FuncLiteralDeclaration ************************/
@@ -3737,7 +3801,7 @@ int StaticCtorDeclaration::addPostInvariant()
void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (hgs->hdrgen)
if (hgs->hdrgen && !hgs->tpltMember)
{ buf->writestring("static this();");
buf->writenl();
return;
+4 -5
View File
@@ -18,7 +18,6 @@
#include <errno.h>
#include <wchar.h>
#define MARS 1
#include "html.h"
#if MARS
@@ -102,15 +101,15 @@ Html::Html(const char *sourcename, unsigned char *base, unsigned length)
void Html::error(const char *format, ...)
{
printf("%s(%d) : HTML Error: ", sourcename, linnum);
fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum);
va_list ap;
va_start(ap, format);
vprintf(format, ap);
vfprintf(stderr, format, ap);
va_end(ap);
printf("\n");
fflush(stdout);
fprintf(stderr, "\n");
fflush(stderr);
//#if MARS
// global.errors++;
+1
View File
@@ -7,6 +7,7 @@
// in artistic.txt, or the GNU General Public License in gpl.txt.
// See the included readme.txt for details.
#define MARS 1
#if MARS
struct OutBuffer;
+1 -1
View File
@@ -94,7 +94,7 @@ Identifier *Identifier::generateId(const char *prefix, size_t i)
{ OutBuffer buf;
buf.writestring(prefix);
buf.printf("%zu", i);
buf.printf("%llu", (ulonglong)i);
char *id = buf.toChars();
buf.data = NULL;
+1 -1
View File
@@ -293,7 +293,7 @@ Msgtable msgtable[] =
// Special functions
#if IN_DMD
{ "alloca" },
{ "__alloca", "alloca" }, // has to be mapped because alloca is #defined if _MSC_VER
#endif
{ "main" },
{ "WinMain" },
+50 -23
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -77,13 +77,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
Import *si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias(names.tdata()[i], aliases.tdata()[i]);
si->addAlias(names[i], aliases[i]);
}
return si;
@@ -95,7 +93,16 @@ void Import::load(Scope *sc)
// See if existing module
DsymbolTable *dst = Package::resolve(packages, NULL, &pkg);
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (pkg && pkg->isModule())
{
::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?",
pkg->toChars(), pkg->toPrettyChars(), id->toChars());
mod = pkg->isModule(); // Error recovery - treat as import of that module
return;
}
#endif
Dsymbol *s = dst->lookup(id);
if (s)
{
@@ -105,7 +112,8 @@ void Import::load(Scope *sc)
if (s->isModule())
mod = (Module *)s;
else
error("package and module have the same name");
::error(loc, "can only import from a module, not from package %s.%s",
pkg->toPrettyChars(), id->toChars());
#endif
}
@@ -113,10 +121,13 @@ void Import::load(Scope *sc)
{
// Load module
mod = Module::load(loc, packages, id);
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
if (mod)
{
dst->insert(id, mod); // id may be different from mod->ident,
// if so then insert alias
if (!mod->importedFrom)
mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule;
}
}
if (!pkg)
pkg = mod;
@@ -167,7 +178,8 @@ void Import::semantic(Scope *sc)
// Load if not already done so
if (!mod)
{ load(sc);
mod->importAll(0);
if (mod)
mod->importAll(0);
}
if (mod)
@@ -217,18 +229,26 @@ void Import::semantic(Scope *sc)
sc->protection = PROTpublic;
#endif
for (size_t i = 0; i < aliasdecls.dim; i++)
{ Dsymbol *s = aliasdecls.tdata()[i];
{ Dsymbol *s = aliasdecls[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, names.tdata()[i], 0))
error("%s not found", (names.tdata()[i])->toChars());
s->semantic(sc);
if (mod->search(loc, names[i], 0))
s->semantic(sc);
else
{
s = mod->search_correct(names[i]);
if (s)
mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars());
else
mod->error(loc, "import '%s' not found", names[i]->toChars());
}
}
sc = sc->pop();
}
if (global.params.moduleDeps != NULL)
if (global.params.moduleDeps != NULL &&
// object self-imports itself, so skip that (Bugzilla 7547)
!(id == Id::object && sc->module->ident == Id::object))
{
/* The grammar of the file is:
* ImportDeclaration
@@ -259,7 +279,7 @@ void Import::semantic(Scope *sc)
{
for (size_t i = 0; i < packages->dim; i++)
{
Identifier *pid = packages->tdata()[i];
Identifier *pid = (*packages)[i];
ob->printf("%s.", pid->toChars());
}
}
@@ -279,8 +299,8 @@ void Import::semantic(Scope *sc)
else
ob->writebyte(',');
Identifier *name = names.tdata()[i];
Identifier *alias = aliases.tdata()[i];
Identifier *name = names[i];
Identifier *alias = aliases[i];
if (!alias)
{
@@ -367,8 +387,15 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
/* Allow multiple imports with the same package base, but disallow
* alias collisions (Bugzilla 5412).
*/
assert(ident && ident == s->ident);
Import *imp;
if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId)
return TRUE;
else
return FALSE;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+63 -66
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
a = new Initializers();
a->setDim(ai->dim);
for (size_t i = 0; i < a->dim; i++)
{ Initializer *e = ai->tdata()[i];
{ Initializer *e = (*ai)[i];
e = e->syntaxCopy();
a->tdata()[i] = e;
(*a)[i] = e;
}
}
return a;
@@ -128,11 +128,11 @@ Initializer *StructInitializer::syntaxCopy()
ai->value.setDim(value.dim);
for (size_t i = 0; i < field.dim; i++)
{
ai->field.tdata()[i] = field.tdata()[i];
ai->field[i] = field[i];
Initializer *init = value.tdata()[i];
Initializer *init = value[i];
init = init->syntaxCopy();
ai->value.tdata()[i] = init;
ai->value[i] = init;
}
return ai;
}
@@ -164,8 +164,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
if (((StructDeclaration *)ad)->isnested) nfields--;
for (size_t i = 0; i < field.dim; i++)
{
Identifier *id = field.tdata()[i];
Initializer *val = value.tdata()[i];
Identifier *id = field[i];
Initializer *val = value[i];
Dsymbol *s;
VarDeclaration *v;
@@ -180,7 +180,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
}
else
{
s = ad->fields.tdata()[fieldi];
s = ad->fields[fieldi];
}
}
else
@@ -189,7 +189,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
s = ad->search(loc, id, 0);
if (!s)
{
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
s = ad->search_correct(id);
if (s)
error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
id->toChars(), t->toChars(), s->kind(), s->toChars());
else
error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
errors = 1;
continue;
}
@@ -205,15 +210,15 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
errors = 1;
break;
}
if (s == ad->fields.tdata()[fieldi])
if (s == ad->fields[fieldi])
break;
}
}
if (s && (v = s->isVarDeclaration()) != NULL)
{
val = val->semantic(sc, v->type, needInterpret);
value.tdata()[i] = val;
vars.tdata()[i] = v;
value[i] = val;
vars[i] = v;
}
else
{ error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
@@ -274,12 +279,12 @@ Expression *StructInitializer::toExpression()
elements->setDim(nfields);
for (size_t i = 0; i < elements->dim; i++)
{
elements->tdata()[i] = NULL;
(*elements)[i] = NULL;
}
unsigned fieldi = 0;
for (size_t i = 0; i < value.dim; i++)
{
Identifier *id = field.tdata()[i];
Identifier *id = field[i];
if (id)
{
Dsymbol * s = ad->search(loc, id, 0);
@@ -298,7 +303,7 @@ Expression *StructInitializer::toExpression()
s->error("is not a per-instance initializable field");
goto Lno;
}
if (s == ad->fields.tdata()[fieldi])
if (s == ad->fields[fieldi])
break;
}
}
@@ -306,18 +311,18 @@ Expression *StructInitializer::toExpression()
{ error(loc, "too many initializers for '%s'", ad->toChars());
goto Lno;
}
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
if (!ex)
goto Lno;
if (elements->tdata()[fieldi])
if ((*elements)[fieldi])
{ error(loc, "duplicate initializer for field '%s'",
ad->fields.tdata()[fieldi]->toChars());
ad->fields[fieldi]->toChars());
goto Lno;
}
elements->tdata()[fieldi] = ex;
(*elements)[fieldi] = ex;
++fieldi;
}
// Now, fill in any missing elements with default initializers.
@@ -325,20 +330,20 @@ Expression *StructInitializer::toExpression()
offset = 0;
for (size_t i = 0; i < elements->dim; )
{
VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration();
VarDeclaration * vd = ad->fields[i]->isVarDeclaration();
//printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset);
if (vd->offset < offset)
{
// Only the first field of a union can have an initializer
if (elements->tdata()[i])
if ((*elements)[i])
goto Lno;
}
else
{
if (!elements->tdata()[i])
if (!(*elements)[i])
// Default initialize
elements->tdata()[i] = vd->type->defaultInit();
(*elements)[i] = vd->type->defaultInit();
}
offset = vd->offset + vd->type->size();
i++;
@@ -346,15 +351,15 @@ Expression *StructInitializer::toExpression()
int unionSize = ad->numFieldsInUnion(i);
if (unionSize == 1)
{ // Not a union -- default initialize if missing
if (!elements->tdata()[i])
elements->tdata()[i] = vd->type->defaultInit();
if (!(*elements)[i])
(*elements)[i] = vd->type->defaultInit();
}
else
{ // anonymous union -- check for errors
int found = -1; // index of the first field with an initializer
for (int j = i; j < i + unionSize; ++j)
for (size_t j = i; j < i + unionSize; ++j)
{
if (!elements->tdata()[j])
if (!(*elements)[j])
continue;
if (found >= 0)
{
@@ -395,13 +400,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (i > 0)
buf->writebyte(',');
Identifier *id = field.tdata()[i];
Identifier *id = field[i];
if (id)
{
buf->writestring(id->toChars());
buf->writebyte(':');
}
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
@@ -428,14 +433,14 @@ Initializer *ArrayInitializer::syntaxCopy()
ai->index.setDim(index.dim);
ai->value.setDim(value.dim);
for (size_t i = 0; i < ai->value.dim; i++)
{ Expression *e = index.tdata()[i];
{ Expression *e = index[i];
if (e)
e = e->syntaxCopy();
ai->index.tdata()[i] = e;
ai->index[i] = e;
Initializer *init = value.tdata()[i];
Initializer *init = value[i];
init = init->syntaxCopy();
ai->value.tdata()[i] = init;
ai->value[i] = init;
}
return ai;
}
@@ -474,17 +479,17 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
length = 0;
for (i = 0; i < index.dim; i++)
{
Expression *idx = index.tdata()[i];
Expression *idx = index[i];
if (idx)
{ idx = idx->semantic(sc);
idx = idx->optimize(WANTvalue | WANTinterpret);
index.tdata()[i] = idx;
index[i] = idx;
length = idx->toInteger();
}
Initializer *val = value.tdata()[i];
Initializer *val = value[i];
val = val->semantic(sc, t->nextOf(), needInterpret);
value.tdata()[i] = val;
value[i] = val;
length++;
if (length == 0)
{ error(loc, "array dimension overflow");
@@ -498,7 +503,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret)
dinteger_t edim = ((TypeSArray *)t)->dim->toInteger();
if (dim > edim)
{
error(loc, "array initializer has %u elements, but array length is %jd", dim, edim);
error(loc, "array initializer has %u elements, but array length is %lld", dim, edim);
goto Lerr;
}
}
@@ -552,8 +557,8 @@ Expression *ArrayInitializer::toExpression()
edim = value.dim;
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.tdata()[i])
j = index.tdata()[i]->toInteger();
if (index[i])
j = index[i]->toInteger();
if (j >= edim)
edim = j + 1;
}
@@ -564,10 +569,10 @@ Expression *ArrayInitializer::toExpression()
elements->zero();
for (size_t i = 0, j = 0; i < value.dim; i++, j++)
{
if (index.tdata()[i])
j = (index.tdata()[i])->toInteger();
if (index[i])
j = (index[i])->toInteger();
assert(j < edim);
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (!iz)
goto Lno;
Expression *ex = iz->toExpression();
@@ -575,7 +580,7 @@ Expression *ArrayInitializer::toExpression()
{
goto Lno;
}
elements->tdata()[j] = ex;
(*elements)[j] = ex;
}
/* Fill in any missing elements with the default initializer
@@ -584,13 +589,13 @@ Expression *ArrayInitializer::toExpression()
Expression *init = NULL;
for (size_t i = 0; i < edim; i++)
{
if (!elements->tdata()[i])
if (!(*elements)[i])
{
if (!type)
goto Lno;
if (!init)
init = ((TypeNext *)t)->next->defaultInit();
elements->tdata()[i] = init;
(*elements)[i] = init;
}
}
@@ -621,18 +626,18 @@ Expression *ArrayInitializer::toAssocArrayLiteral()
for (size_t i = 0; i < value.dim; i++)
{
e = index.tdata()[i];
e = index[i];
if (!e)
goto Lno;
keys->tdata()[i] = e;
(*keys)[i] = e;
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (!iz)
goto Lno;
e = iz->toExpression();
if (!e)
goto Lno;
values->tdata()[i] = e;
(*values)[i] = e;
}
e = new AssocArrayLiteralExp(loc, keys, values);
return e;
@@ -648,7 +653,7 @@ int ArrayInitializer::isAssociativeArray()
{
for (size_t i = 0; i < value.dim; i++)
{
if (index.tdata()[i])
if (index[i])
return 1;
}
return 0;
@@ -710,13 +715,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (i > 0)
buf->writebyte(',');
Expression *ex = index.tdata()[i];
Expression *ex = index[i];
if (ex)
{
ex->toCBuffer(buf, hgs);
buf->writebyte(':');
}
Initializer *iz = value.tdata()[i];
Initializer *iz = value[i];
if (iz)
iz->toCBuffer(buf, hgs);
}
@@ -792,10 +797,8 @@ bool hasNonConstPointers(Expression *e)
bool arrayHasNonConstPointers(Expressions *elems)
{
for (size_t i = 0; i < elems->dim; i++)
{
if (!elems->tdata()[i])
continue;
if (hasNonConstPointers(elems->tdata()[i]))
{ Expression *e = (*elems)[i];
if (e && hasNonConstPointers(e))
return true;
}
return false;
@@ -816,7 +819,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
return this; // Failed, suppress duplicate error messages
if (exp->op == TOKtype)
error("initializer must be an expression, not '%s'", exp->toChars());
exp->error("initializer must be an expression, not '%s'", exp->toChars());
// Make sure all pointers are constants
if (needInterpret && hasNonConstPointers(exp))
@@ -865,12 +868,6 @@ L1:
Type *ExpInitializer::inferType(Scope *sc)
{
//printf("ExpInitializer::inferType() %s\n", toChars());
if (exp->op == TOKfunction && ((FuncExp *)exp)->td)
{
exp->error("cannot infer type from ambiguous function literal %s", exp->toChars());
return Type::terror;
}
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
@@ -884,7 +881,7 @@ Type *ExpInitializer::inferType(Scope *sc)
// Give error for overloaded function addresses
if (exp->op == TOKdelegate)
{ DelegateExp *se = (DelegateExp *)exp;
if (
if (se->hasOverloads &&
se->func->isFuncDeclaration() &&
!se->func->isFuncDeclaration()->isUnique())
exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
+16
View File
@@ -1516,6 +1516,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
if (
!fbody ||
ident == Id::ensure || // ensure() has magic properties the inliner loses
(ident == Id::require && // require() has magic properties too
toParent()->isFuncDeclaration() && // see bug 7699
toParent()->isFuncDeclaration()->needThis()) ||
!hdrscan &&
(
#if 0
@@ -1813,6 +1816,18 @@ Expression *Expression::inlineCopy(Scope *sc)
*/
return copy();
#else
if (op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)this;
if (de->func->isNested())
{ /* See Bugzilla 4820
* Defer checking until later if we actually need the 'this' pointer
*/
Expression *e = de->copy();
return e;
}
}
InlineCostState ics;
memset(&ics, 0, sizeof(ics));
@@ -1829,3 +1844,4 @@ Expression *Expression::inlineCopy(Scope *sc)
return e;
#endif
}
+299 -90
View File
@@ -27,7 +27,6 @@
#include "attrib.h" // for AttribDeclaration
#include "template.h"
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd);
#define LOG 0
@@ -45,6 +44,10 @@ private:
together with the VarDeclaration, and the previous
stack address of that variable, so that we can restore it
when we leave the stack frame.
Note that when a function is forward referenced, the interpreter must
run semantic3, and that may start CTFE again with a NULL istate. Thus
the stack might not be empty when CTFE begins.
Ctfe Stack addresses are just 0-based integers, but we save
them as 'void *' because ArrayBase can only do pointers.
*/
@@ -143,7 +146,11 @@ public:
}
void saveGlobalConstant(VarDeclaration *v, Expression *e)
{
assert(v->isDataseg() && !v->isCTFE());
#if DMDV2
assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE());
#else
assert( v->init && v->isConst() && !v->isCTFE());
#endif
v->ctfeAdrOnStack = globalValues.dim;
globalValues.push(e);
}
@@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval);
bool needToCopyLiteral(Expression *expr);
Expression *copyLiteral(Expression *e);
Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2);
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2);
Expression *evaluateIfBuiltin(InterState *istate, Loc loc,
FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
Expression *scrubReturnValue(Loc loc, Expression *e);
@@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression
{
return value->sd->isClassDeclaration();
}
VarDeclaration *getFieldAt(int index)
{
ClassDeclaration *cd = originalClass();
size_t fieldsSoFar = 0;
while (index - fieldsSoFar >= cd->fields.dim)
{ fieldsSoFar += cd->fields.dim;
cd = cd->baseClass;
}
return cd->fields.tdata()[index - fieldsSoFar];
}
// Return index of the field, or -1 if not found
int getFieldIndex(Type *fieldtype, size_t fieldoffset)
{
@@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression
}
};
struct VoidInitExp : Expression
{
VarDeclaration *var;
VoidInitExp(VarDeclaration *var, Type *type)
: Expression(var->loc, TOKvoid, sizeof(VoidInitExp))
{
this->var = var;
this->type = var->type;
}
char *toChars()
{
return (char *)"void";
}
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue)
{
error("CTFE internal error: trying to read uninitialized variable");
assert(0);
return EXP_CANT_INTERPRET;
}
};
// Return index of the field, or -1 if not found
// Same as getFieldIndex, but checks for a direct match with the VarDeclaration
int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v)
@@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0)
* arguments function arguments
* thisarg 'this', if a needThis() function, NULL if not.
*
* Return result expression if successful, EXP_CANT_INTERPRET if not.
* Return result expression if successful, EXP_CANT_INTERPRET if not,
* or EXP_VOID_INTERPRET if function returned void.
*/
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
@@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
*/
int olderrors = global.errors;
int oldgag = global.gag;
TemplateInstance *spec = isSpeculativeFunction(this);
TemplateInstance *spec = isSpeculative();
if (global.gag && !spec)
global.gag = 0;
++scope->ignoreTemplates;
@@ -578,6 +618,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
--evaluatingArgs;
if (earg == EXP_CANT_INTERPRET)
return earg;
/* Struct literals are passed by value, but we don't need to
* copy them if they are passed as const
*/
if (earg->op == TOKstructliteral
#if DMDV2
&& !(arg->storageClass & (STCconst | STCimmutable))
#endif
)
earg = copyLiteral(earg);
}
if (earg->op == TOKthrownexception)
{
@@ -677,6 +726,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
// If fell off the end of a void function, return void
if (!e && type->toBasetype()->nextOf()->ty == Tvoid)
return EXP_VOID_INTERPRET;
// If result is void, return void
if (e == EXP_VOID_INTERPRET)
return e;
// If it generated an exception, return it
if (exceptionOrCantInterpret(e))
{
@@ -685,6 +739,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
((ThrownExceptionExp *)e)->generateUncaughtError();
return EXP_CANT_INTERPRET;
}
// If we're about to leave CTFE, make sure we don't crash the
// compiler by returning a CTFE-internal expression.
if (!istate && !evaluatingArgs)
{
e = scrubReturnValue(loc, e);
@@ -898,13 +955,16 @@ uinteger_t resolveArrayLength(Expression *e)
}
// As Equal, but resolves slices before comparing
Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2)
Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2)
{
if (e1->op == TOKslice)
e1 = resolveSlice(e1);
if (e2->op == TOKslice)
e2 = resolveSlice(e2);
return Equal(op, type, e1, e2);
Expression *e = Equal(op, type, e1, e2);
if (e == EXP_CANT_INTERPRET)
error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars());
return e;
}
Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
@@ -975,7 +1035,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2)
return Cat(type, e1, e2);
}
void scrubArray(Loc loc, Expressions *elems);
bool scrubArray(Loc loc, Expressions *elems, bool structlit = false);
/* All results destined for use outside of CTFE need to have their CTFE-specific
* features removed.
@@ -988,6 +1048,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars());
return EXP_CANT_INTERPRET;
}
if (e->op == TOKvoid)
{
error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars());
e = new ErrorExp();
}
if (e->op == TOKslice)
{
e = resolveSlice(e);
@@ -996,7 +1061,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
{
StructLiteralExp *se = (StructLiteralExp *)e;
se->ownedByCtfe = false;
scrubArray(loc, se->elements);
if (!scrubArray(loc, se->elements, true))
return EXP_CANT_INTERPRET;
}
if (e->op == TOKstring)
{
@@ -1005,29 +1071,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e)
if (e->op == TOKarrayliteral)
{
((ArrayLiteralExp *)e)->ownedByCtfe = false;
scrubArray(loc, ((ArrayLiteralExp *)e)->elements);
if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements))
return EXP_CANT_INTERPRET;
}
if (e->op == TOKassocarrayliteral)
{
AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
aae->ownedByCtfe = false;
scrubArray(loc, aae->keys);
scrubArray(loc, aae->values);
if (!scrubArray(loc, aae->keys))
return EXP_CANT_INTERPRET;
if (!scrubArray(loc, aae->values))
return EXP_CANT_INTERPRET;
}
return e;
}
// Scrub all members of an array
void scrubArray(Loc loc, Expressions *elems)
// Scrub all members of an array. Return false if error
bool scrubArray(Loc loc, Expressions *elems, bool structlit)
{
for (size_t i = 0; i < elems->dim; i++)
{
Expression *m = elems->tdata()[i];
if (!m)
continue;
m = scrubReturnValue(loc, m);
if (m && m->op == TOKvoid && structlit)
m = NULL;
if (m)
m = scrubReturnValue(loc, m);
if (m == EXP_CANT_INTERPRET)
return false;
elems->tdata()[i] = m;
}
return true;
}
@@ -1362,7 +1437,7 @@ Expression *SwitchStatement::interpret(InterState *istate)
Expression * caseExp = cs->exp->interpret(istate);
if (exceptionOrCantInterpret(caseExp))
return caseExp;
e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp);
e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp);
if (exceptionOrCantInterpret(e))
return e;
if (e->isBool(TRUE))
@@ -1481,25 +1556,25 @@ Expression *TryCatchStatement::interpret(InterState *istate)
ThrownExceptionExp *ex = (ThrownExceptionExp *)e;
Type *extype = ex->thrown->originalClass()->type;
// Search for an appropriate catch clause.
for (size_t i = 0; i < catches->dim; i++)
{
for (size_t i = 0; i < catches->dim; i++)
{
#if DMDV1
Catch *ca = (Catch *)catches->data[i];
Catch *ca = (Catch *)catches->data[i];
#else
Catch *ca = catches->tdata()[i];
Catch *ca = catches->tdata()[i];
#endif
Type *catype = ca->type;
Type *catype = ca->type;
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler
if (catype->equals(extype) || catype->isBaseOf(extype, NULL))
{ // Execute the handler
if (ca->var)
{
ctfeStack.push(ca->var);
ca->var->setValue(ex->thrown);
}
return ca->handler->interpret(istate);
}
return ca->handler ? ca->handler->interpret(istate) : NULL;
}
}
return e;
}
@@ -1740,6 +1815,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
}
Type *pointee = ((TypePointer *)type)->next;
Expression *val = getVarExp(loc, istate, var, goal);
if (val == EXP_CANT_INTERPRET)
return val;
if (val->type->ty == Tarray || val->type->ty == Tsarray)
{
// Check for unsupported type painting operations
@@ -1965,10 +2042,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception)
{
e = copyLiteral(e);
if (v->isDataseg())
ctfeStack.saveGlobalConstant(v, e);
else
v->setValueWithoutChecking(e);
ctfeStack.saveGlobalConstant(v, e);
}
}
else if (v->isCTFE() && !v->hasValue())
@@ -1977,11 +2051,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
{
if (v->init->isVoidInitializer())
{
error(loc, "variable %s is used before initialization", v->toChars());
return EXP_CANT_INTERPRET;
// var should have been initialized when it was created
error(loc, "CTFE internal error - trying to access uninitialized var");
assert(0);
e = EXP_CANT_INTERPRET;
}
else
{
e = v->init->toExpression();
e = e->interpret(istate);
}
e = v->init->toExpression();
e = e->interpret(istate);
}
else
e = v->type->defaultInitLiteral(loc);
@@ -1997,7 +2076,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
e = EXP_CANT_INTERPRET;
}
else if (!e)
error(loc, "variable %s is used before initialization", v->toChars());
{
assert(0);
assert(v->init && v->init->isVoidInitializer());
e = v->type->voidInitLiteral(v);
}
else if (exceptionOrCantInterpret(e))
return e;
else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex)
@@ -2016,6 +2099,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
|| e->op == TOKassocarrayliteral || e->op == TOKslice
|| e->type->toBasetype()->ty == Tpointer)
return e; // it's already an Lvalue
else if (e->op == TOKvoid)
{
VoidInitExp *ve = (VoidInitExp *)e;
error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars());
errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars());
e = EXP_CANT_INTERPRET;
}
else
e = e->interpret(istate, goal);
}
@@ -2027,10 +2117,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal
#if !IN_LLVM
if (s->dsym->toInitializer() == s->sym)
#endif
{ e = s->dsym->type->defaultInitLiteral();
{ e = s->dsym->type->defaultInitLiteral(loc);
e = e->semantic(NULL);
if (e->op == TOKerror)
e = EXP_CANT_INTERPRET;
else // Convert NULL to VoidExp
e = e->interpret(istate, goal);
}
#if !IN_LLVM
else
@@ -2101,7 +2193,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
if (ie)
e = ie->exp->interpret(istate);
else if (v->init->isVoidInitializer())
e = NULL;
{
e = v->type->voidInitLiteral(v);
// There is no AssignExp for void initializers,
// so set it here.
v->setValue(e);
}
else
{
error("Declaration %s is not yet implemented in CTFE", toChars());
@@ -2330,7 +2427,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
ekey = resolveSlice(ekey);
for (size_t j = i; j < keysx->dim; j++)
{ Expression *ekey2 = keysx->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2);
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2);
if (ex == EXP_CANT_INTERPRET)
goto Lerr;
if (ex->isBool(TRUE)) // if a match
@@ -2504,10 +2601,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is
if (elemType->ty == Tchar || elemType->ty == Twchar
|| elemType->ty == Tdchar)
return createBlockDuplicatedStringLiteral(loc, newtype,
(unsigned)(elemType->defaultInitLiteral()->toInteger()),
(unsigned)(elemType->defaultInitLiteral(loc)->toInteger()),
len, elemType->size());
return createBlockDuplicatedArrayLiteral(loc, newtype,
elemType->defaultInitLiteral(),
elemType->defaultInitLiteral(loc),
len);
}
@@ -2521,7 +2618,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
if (newtype->toBasetype()->ty == Tstruct)
{
Expression *se = newtype->defaultInitLiteral();
Expression *se = newtype->defaultInitLiteral(loc);
#if DMDV2
if (member)
{
@@ -2558,7 +2655,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
Dsymbol *s = c->fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v);
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral();
Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc);
if (exceptionOrCantInterpret(m))
return m;
elems->tdata()[fieldsSoFar+i] = copyLiteral(m);
@@ -2735,7 +2832,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
}
if (indx < 0 || indx > len)
{
error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len);
error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len);
return EXP_CANT_INTERPRET;
}
@@ -3037,7 +3134,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi
for (size_t j = valuesx->dim; j; )
{ j--;
Expression *ekey = aae->keys->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
if (exceptionOrCantInterpret(ex))
return ex;
if (ex->isBool(TRUE))
@@ -3207,7 +3304,7 @@ Expression *copyLiteral(Expression *e)
assert(v);
// If it is a void assignment, use the default initializer
if (!m)
m = v->type->defaultInitLiteral(e->loc);
m = v->type->voidInitLiteral(v);
if (m->op == TOKslice)
m = resolveSlice(m);
if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
@@ -3234,7 +3331,8 @@ Expression *copyLiteral(Expression *e)
|| e->op == TOKsymoff || e->op == TOKnull
|| e->op == TOKvar
|| e->op == TOKint64 || e->op == TOKfloat64
|| e->op == TOKchar || e->op == TOKcomplex80)
|| e->op == TOKchar || e->op == TOKcomplex80
|| e->op == TOKvoid)
{ // Simple value types
Expression *r = e->syntaxCopy();
r->type = e->type;
@@ -3404,7 +3502,7 @@ void assignInPlace(Expression *dest, Expression *src)
assert(o->op == e->op);
assignInPlace(o, e);
}
else if (e->type->ty == Tsarray && o->type->ty == Tsarray)
else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid)
{
assignInPlace(o, e);
}
@@ -3699,7 +3797,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
Type *elemType= NULL;
elemType = ((TypeArray *)t)->next;
assert(elemType);
Expression *defaultElem = elemType->defaultInitLiteral();
Expression *defaultElem = elemType->defaultInitLiteral(loc);
Expressions *elements = new Expressions();
elements->setDim(newlen);
@@ -3807,7 +3905,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
// only modifying part of the variable. So we need to make sure
// that the parent variable exists.
if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral()));
ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc)));
// ---------------------------------------
// Deal with reference assignment
@@ -3885,7 +3983,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
indx = resolveSlice(indx);
// Look up this index in it up in the existing AA, to get the next level of AA.
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx);
AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx);
if (exceptionOrCantInterpret(newAA))
return newAA;
if (!newAA)
@@ -4031,14 +4129,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
? (StructLiteralExp *)exx
: ((ClassReferenceExp *)exx)->value;
int fieldi = exx->op == TOKstructliteral
? se->getFieldIndex(member->type, member->offset)
: ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset);
? findFieldIndexByName(se->sd, member)
: ((ClassReferenceExp *)exx)->findFieldIndexByName(member);
if (fieldi == -1)
{
error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars());
return EXP_CANT_INTERPRET;
}
assert(fieldi>=0 && fieldi < se->elements->dim);
assert(fieldi >= 0 && fieldi < se->elements->dim);
// If it's a union, set all other members of this union to void
if (exx->op == TOKstructliteral)
{
assert(se->sd);
int unionStart = se->sd->firstFieldInUnion(fieldi);
int unionSize = se->sd->numFieldsInUnion(fieldi);
for(int i = unionStart; i < unionStart + unionSize; ++i)
{ if (i == fieldi)
continue;
Expression **el = &se->elements->tdata()[i];
if ((*el)->op != TOKvoid)
*el = (*el)->type->voidInitLiteral(member);
}
}
if (newval->op == TOKstructliteral)
assignInPlace(se->elements->tdata()[fieldi], newval);
else
@@ -4113,6 +4226,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
}
aggregate = getAggregateFromPointer(aggregate, &ofs);
indexToModify += ofs;
if (aggregate->op != TOKslice && aggregate->op != TOKstring &&
aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral)
{
if (indexToModify != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]", indexToModify);
return EXP_CANT_INTERPRET;
}
// It is equivalent to *aggregate = newval.
// Aggregate could be varexp, a dotvar, ...
// TODO: we could support this
error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead",
ie->e1->toChars(), e2->toChars());
return EXP_CANT_INTERPRET;
}
destarraylen = resolveArrayLength(aggregate);
}
if (indexToModify >= destarraylen)
@@ -4138,7 +4266,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{
IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate)
{
error("key %s not found in associative array %s",
@@ -4240,6 +4368,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (isPointer(oldval->type))
{ // Slicing a pointer
oldval = oldval->interpret(istate, ctfeNeedLvalue);
if (exceptionOrCantInterpret(oldval))
return oldval;
dinteger_t ofs;
oldval = getAggregateFromPointer(oldval, &ofs);
assignmentToSlicedPointer = true;
@@ -4249,7 +4379,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
&& oldval->op != TOKslice && oldval->op != TOKnull)
{
error("CTFE ICE: cannot resolve array length");
if (assignmentToSlicedPointer)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
sexp->e1->toChars());
}
else
error("CTFE ICE: cannot resolve array length");
return EXP_CANT_INTERPRET;
}
uinteger_t dollar = resolveArrayLength(oldval);
@@ -4312,7 +4448,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral)
{
IndexExp *ix = (IndexExp *)aggregate;
aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2);
aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2);
if (!aggregate)
{
error("key %s not found in associative array %s",
@@ -4336,7 +4472,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
firstIndex = lowerbound + sexpold->lwr->toInteger();
if (hi > sexpold->upr->toInteger())
{
error("slice [%d..%d] exceeds array bounds [0..%jd]",
error("slice [%d..%d] exceeds array bounds [0..%lld]",
lowerbound, upperbound,
sexpold->upr->toInteger() - sexpold->lwr->toInteger());
return EXP_CANT_INTERPRET;
@@ -4348,11 +4484,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
dinteger_t ofs;
aggregate = getAggregateFromPointer(aggregate, &ofs);
if (aggregate->op == TOKnull)
{
error("cannot slice null pointer %s", sexp->e1->toChars());
return EXP_CANT_INTERPRET;
}
dinteger_t hi = upperbound + ofs;
firstIndex = lowerbound + ofs;
if (firstIndex < 0 || hi > dim)
{
error("slice [%d..%jd] exceeds memory block bounds [0..%jd]",
error("slice [lld..%lld] exceeds memory block bounds [0..%lld]",
firstIndex, hi, dim);
return EXP_CANT_INTERPRET;
}
@@ -4493,9 +4634,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_
else
{
error("%s cannot be evaluated at compile time", toChars());
#ifdef DEBUG
dump(0);
#endif
}
return returnValue;
}
@@ -4883,6 +5021,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
if (!global.gag)
showCtfeBackTrace(istate, this, fd);
}
else if (eresult == EXP_VOID_INTERPRET)
;
else
eresult->loc = loc;
return eresult;
}
@@ -4901,7 +5043,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
InterState istateComma;
if (!istate && firstComma->e1->op == TOKdeclaration)
{
assert(ctfeStack.stackPointer() == 0);
ctfeStack.startFrame();
istate = &istateComma;
}
@@ -4919,7 +5060,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
ctfeStack.push(v);
if (!v->init && !v->getValue())
{
v->setValue(copyLiteral(v->type->defaultInitLiteral()));
v->setValue(copyLiteral(v->type->defaultInitLiteral(loc)));
}
if (!v->getValue()) {
Expression *newval = v->init->toExpression();
@@ -5015,7 +5156,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal)
* Return ae[e2] if present, or NULL if not found.
* Return EXP_CANT_INTERPRET on error.
*/
Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2)
{
/* Search the keys backwards, in case there are duplicate keys
*/
@@ -5023,13 +5164,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
{
i--;
Expression *ekey = ae->keys->tdata()[i];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2);
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2);
if (ex == EXP_CANT_INTERPRET)
{
error("cannot evaluate %s==%s at compile time",
ekey->toChars(), e2->toChars());
return ex;
}
if (ex->isBool(TRUE))
{
return ae->values->tdata()[i];
@@ -5084,23 +5221,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
if (exceptionOrCantInterpret(e2))
return e2;
dinteger_t indx = e2->toInteger();
dinteger_t ofs;
Expression *agg = getAggregateFromPointer(e1, &ofs);
if (agg->op == TOKnull)
{
error("cannot index null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET;
}
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
Type *pointee = ((TypePointer *)agg->type)->next;
if ((indx + ofs) < 0 || (indx+ofs) > len)
if ( agg->op == TOKarrayliteral || agg->op == TOKstring)
{
error("pointer index [%jd] exceeds allocated memory block [0..%jd]",
indx+ofs, len);
return EXP_CANT_INTERPRET;
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
Type *pointee = ((TypePointer *)agg->type)->next;
if ((indx + ofs) < 0 || (indx+ofs) > len)
{
error("pointer index [%lld] exceeds allocated memory block [0..%lld]",
indx+ofs, len);
return EXP_CANT_INTERPRET;
}
return ctfeIndex(loc, type, agg, indx+ofs);
}
else
{ // Pointer to a non-array variable
if ((indx + ofs) != 0)
{
error("pointer index [%lld] lies outside memory block [0..1]",
indx+ofs);
return EXP_CANT_INTERPRET;
}
return agg->interpret(istate);
}
return ctfeIndex(loc, type, agg, indx+ofs);
}
e1 = this->e1;
if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe))
@@ -5141,7 +5292,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
if (indx > iup - ilo)
{
error("index %ju exceeds array length %ju", indx, iup - ilo);
error("index %llu exceeds array length %llu", indx, iup - ilo);
return EXP_CANT_INTERPRET;
}
indx += ilo;
@@ -5162,7 +5313,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
{
if (e2->op == TOKslice)
e2 = resolveSlice(e2);
e = findKeyInAA((AssocArrayLiteralExp *)e1, e2);
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2);
if (!e)
{
error("key %s not found in associative array %s",
@@ -5183,6 +5334,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
return e;
if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
e = e->interpret(istate);
if (goal == ctfeNeedRvalue && e->op == TOKvoid)
{
error("%s is used before initialized", toChars());
errorSupplemental(e->loc, "originally uninitialized here");
return EXP_CANT_INTERPRET;
}
e = paintTypeOntoLiteral(type, e);
return e;
}
@@ -5237,12 +5394,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
error("cannot slice null pointer %s", this->e1->toChars());
return EXP_CANT_INTERPRET;
}
if (agg->op != TOKarrayliteral && agg->op != TOKstring)
{
error("pointer %s cannot be sliced at compile time (it does not point to an array)",
this->e1->toChars());
return EXP_CANT_INTERPRET;
}
assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
Type *pointee = ((TypePointer *)agg->type)->next;
if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
{
error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]",
error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]",
ilwr+ofs, iupr+ofs, len);
return EXP_CANT_INTERPRET;
}
@@ -5306,7 +5469,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{
if (ilwr== 0 && iupr == 0)
return e1;
e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr);
e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr);
return EXP_CANT_INTERPRET;
}
if (e1->op == TOKslice)
@@ -5318,7 +5481,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
uinteger_t up1 = se->upr->toInteger();
if (ilwr > iupr || iupr > up1 - lo1)
{
error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]",
error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]",
ilwr, iupr, lo1, up1);
return EXP_CANT_INTERPRET;
}
@@ -5335,7 +5498,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
{
if (iupr < ilwr || ilwr < 0 || iupr > dollar)
{
error("slice [%jd..%jd] exceeds array bounds [0..%jd]",
error("slice [%lld..%lld] exceeds array bounds [0..%lld]",
ilwr, iupr, dollar);
return EXP_CANT_INTERPRET;
}
@@ -5366,7 +5529,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
}
if (e1->op == TOKslice)
e1 = resolveSlice(e1);
e = findKeyInAA((AssocArrayLiteralExp *)e2, e1);
e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1);
if (exceptionOrCantInterpret(e))
return e;
if (!e)
@@ -5425,8 +5588,12 @@ bool isAssocArray(Type *t)
if (t->ty != Tstruct)
return false;
StructDeclaration *sym = ((TypeStruct *)t)->sym;
if (sym->ident == Id::AssociativeArray)
if (sym->ident == Id::AssociativeArray && sym->parent &&
sym->parent->parent &&
sym->parent->parent->ident == Id::object)
{
return true;
}
#endif
return false;
}
@@ -5581,9 +5748,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
e->type = type;
return e;
}
error("pointer cast from %s to %s is not supported at compile time",
// Check if we have a null pointer (eg, inside a struct)
e1 = e1->interpret(istate);
if (e1->op != TOKnull)
{
error("pointer cast from %s to %s is not supported at compile time",
e1->type->toChars(), to->toChars());
return EXP_CANT_INTERPRET;
return EXP_CANT_INTERPRET;
}
}
if (to->ty == Tarray && e1->op == TOKslice)
{
@@ -5731,7 +5904,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
assert(indx >=0 && indx <= len); // invalid pointer
if (indx == len)
{
error("dereference of pointer %s one past end of memory block limits [0..%jd]",
error("dereference of pointer %s one past end of memory block limits [0..%lld]",
toChars(), len);
return EXP_CANT_INTERPRET;
}
@@ -5776,7 +5949,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
}
else if (e->op == TOKaddress)
e = ((AddrExp*)e)->e1; // *(&x) ==> x
if (e->op == TOKnull)
else if (e->op == TOKnull)
{
error("dereference of null pointer '%s'", e1->toChars());
return EXP_CANT_INTERPRET;
@@ -5865,6 +6038,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
e->op == TOKassocarrayliteral || e->op == TOKstring)
return e;
if (e->op == TOKvoid)
{
VoidInitExp *ve = (VoidInitExp *)e;
error("cannot read uninitialized variable %s in ctfe", toChars());
ve->var->error("was uninitialized and used before set");
return EXP_CANT_INTERPRET;
}
if ( isPointer(type) )
{
return paintTypeOntoLiteral(type, e);
@@ -5909,7 +6089,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal)
size_t removed = 0;
for (size_t j = 0; j < valuesx->dim; ++j)
{ Expression *ekey = keysx->tdata()[j];
Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index);
if (exceptionOrCantInterpret(ex))
return ex;
if (ex->isBool(TRUE))
@@ -6088,7 +6268,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del
else if (str->op == TOKarrayliteral)
ale = (ArrayLiteralExp *)str;
else
{ error("CTFE internal error: cannot foreach %s", str->toChars());
{ str->error("CTFE internal error: cannot foreach %s", str->toChars());
return EXP_CANT_INTERPRET;
}
Expressions args;
@@ -6552,6 +6732,10 @@ bool isCtfeValueValid(Expression *newval)
assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe);
return true;
}
if (newval->op == TOKvoid)
{
return true;
}
newval->error("CTFE internal error: illegal value %s\n", newval->toChars());
return false;
}
@@ -6584,3 +6768,28 @@ void VarDeclaration::setValue(Expression *newval)
assert(isCtfeValueValid(newval));
ctfeStack.setValue(this, newval);
}
Expression *Type::voidInitLiteral(VarDeclaration *var)
{
return new VoidInitExp(var, this);
}
Expression *TypeSArray::voidInitLiteral(VarDeclaration *var)
{
return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger());
}
Expression *TypeStruct::voidInitLiteral(VarDeclaration *var)
{
Expressions *exps = new Expressions();
exps->setDim(sym->fields.dim);
for (size_t i = 0; i < sym->fields.dim; i++)
{
(*exps)[i] = new VoidInitExp(var, sym->fields[i]->type);
}
StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps);
se->type = this;
se->ownedByCtfe = true;
return se;
}
+63 -19
View File
@@ -119,11 +119,11 @@ const char *Token::toChars()
break;
case TOKint64v:
sprintf(buffer,"%jdL",(intmax_t)int64value);
sprintf(buffer,"%lldL",(intmax_t)int64value);
break;
case TOKuns64v:
sprintf(buffer,"%juUL",(uintmax_t)uns64value);
sprintf(buffer,"%lluUL",(uintmax_t)uns64value);
break;
#if IN_GCC
@@ -141,27 +141,32 @@ const char *Token::toChars()
break;
#else
case TOKfloat32v:
sprintf(buffer,"%Lgf", float80value);
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "f");
break;
case TOKfloat64v:
sprintf(buffer,"%Lg", float80value);
ld_sprint(buffer, 'g', float80value);
break;
case TOKfloat80v:
sprintf(buffer,"%LgL", float80value);
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "L");
break;
case TOKimaginary32v:
sprintf(buffer,"%Lgfi", float80value);
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "fi");
break;
case TOKimaginary64v:
sprintf(buffer,"%Lgi", float80value);
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "i");
break;
case TOKimaginary80v:
sprintf(buffer,"%LgLi", float80value);
ld_sprint(buffer, 'g', float80value);
strcat(buffer, "Li");
break;
#endif
@@ -300,7 +305,7 @@ void Lexer::error(const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
verror(tokenLoc(), format, ap);
va_end(ap);
}
@@ -363,7 +368,6 @@ Token *Lexer::peek(Token *ct)
{
t = new Token();
scan(t);
t->next = NULL;
ct->next = t;
}
return t;
@@ -1222,9 +1226,21 @@ void Lexer::scan(Token *t)
#undef DOUBLE
case '#':
{
p++;
pragma();
continue;
Token *n = peek(t);
if (n->value == TOKidentifier && n->ident == Id::line)
{
nextToken();
poundLine();
continue;
}
else
{
t->value = TOKpound;
return;
}
}
default:
{ unsigned c = *p;
@@ -2567,22 +2583,17 @@ done:
}
/*********************************************
* Do pragma.
* Currently, the only pragma supported is:
* parse:
* #line linnum [filespec]
*/
void Lexer::pragma()
void Lexer::poundLine()
{
Token tok;
int linnum;
char *filespec = NULL;
Loc loc = this->loc;
scan(&tok);
if (tok.value != TOKidentifier || tok.ident != Id::line)
goto Lerr;
scan(&tok);
if (tok.value == TOKint32v || tok.value == TOKint64v)
{ linnum = tok.uns64value - 1;
@@ -2866,6 +2877,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2)
return c;
}
/*******************************************
* Search actual location of current token
* even when infinite look-ahead was done.
*/
Loc Lexer::tokenLoc()
{
Loc result = this->loc;
Token* last = &token;
while (last->next)
last = last->next;
unsigned char* start = token.ptr;
unsigned char* stop = last->ptr;
for (unsigned char* p = start; p < stop; ++p)
{
switch (*p)
{
case '\n':
result.linnum--;
break;
case '\r':
if (p[1] != '\n')
result.linnum--;
break;
default:
break;
}
}
return result;
}
/********************************************
* Create an identifier in the string table.
*/
@@ -3165,6 +3208,7 @@ void Lexer::initKeywords()
Token::tochars[TOKpow] = "^^";
Token::tochars[TOKpowass] = "^^=";
Token::tochars[TOKgoesto] = "=>";
Token::tochars[TOKpound] = "#";
#endif
// For debugging
+5 -1
View File
@@ -170,6 +170,7 @@ enum TOK
TOKpowass,
TOKgoesto,
TOKvector,
TOKpound,
#endif
// LDC specific
@@ -256,6 +257,7 @@ struct Token
static const char *tochars[TOKMAX];
static void *operator new(size_t sz);
Token() : next(NULL) {}
int isKeyword();
void print();
const char *toChars();
@@ -310,12 +312,14 @@ struct Lexer
void error(const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void verror(Loc loc, const char *format, va_list ap);
void pragma();
void poundLine();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);
static int isValidIdentifier(char *p);
static unsigned char *combineComments(unsigned char *c1, unsigned char *c2);
Loc tokenLoc();
};
#endif /* DMD_LEXER_H */
+14
View File
@@ -48,6 +48,20 @@ struct Library
unsigned short numDictPages(unsigned padding);
int FillDict(unsigned char *bucketsP, unsigned short uNumPages);
void WriteLibToBuffer(OutBuffer *libbuf);
void error(const char *format, ...)
{
Loc loc;
if (libfile)
{
loc.filename = libfile->name->toChars();
loc.linnum = 0;
}
va_list ap;
va_start(ap, format);
::verror(loc, format, ap);
va_end(ap);
}
};
#endif /* DMD_LIB_H */
+2 -2
View File
@@ -239,7 +239,7 @@ char *TemplateInstance::mangle()
buf.writestring(p);
}
}
buf.printf("%zu%s", strlen(id), id);
buf.printf("%llu%s", (ulonglong)strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
@@ -293,7 +293,7 @@ char *Dsymbol::mangle()
p += 2;
buf.writestring(p);
}
buf.printf("%zu%s", strlen(id), id);
buf.printf("%llu%s", (ulonglong)strlen(id), id);
id = buf.toChars();
buf.data = NULL;
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
+47 -33
View File
@@ -100,7 +100,7 @@ Global::Global()
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.058";
version = "v2.059";
#if IN_LLVM
ldc_version = "LDC trunk";
llvm_version = "LLVM 3.0";
@@ -132,6 +132,11 @@ bool Global::endGagging(unsigned oldGagged)
return anyErrs;
}
bool Global::isSpeculativeGagging()
{
return gag && gag == speculativeGag;
}
char *Loc::toChars()
{
@@ -375,7 +380,7 @@ Usage:\n\
extern signed char tyalignsize[];
#if _WIN32
#if _WIN32 && __DMC__
extern "C"
{
extern int _xi_a;
@@ -383,11 +388,11 @@ extern "C"
}
#endif
int main(int argc, char *argv[])
int tryMain(int argc, char *argv[])
{
mem.init(); // initialize storage allocator
mem.setStackBottom(&argv);
#if _WIN32
#if _WIN32 && __DMC__
mem.addroots((char *)&_xi_a, (char *)&_end);
#endif
@@ -411,7 +416,7 @@ int main(int argc, char *argv[])
if (argc < 1 || !argv)
{
Largs:
error("missing or null command line arguments");
error(0, "missing or null command line arguments");
fatal();
}
for (size_t i = 0; i < argc; i++)
@@ -421,7 +426,7 @@ int main(int argc, char *argv[])
}
if (response_expand(&argc,&argv)) // expand response files
error("can't open response file");
error(0, "can't open response file");
files.reserve(argc - 1);
@@ -448,6 +453,7 @@ int main(int argc, char *argv[])
global.params.is64bit = (sizeof(size_t) == 8);
#if TARGET_WINDOS
global.params.is64bit = 0;
global.params.defaultlibname = "phobos";
#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
global.params.defaultlibname = "phobos2";
@@ -549,7 +555,7 @@ int main(int argc, char *argv[])
else if (strcmp(p + 1, "gs") == 0)
global.params.alwaysframe = 1;
else if (strcmp(p + 1, "gt") == 0)
{ error("use -profile instead of -gt\n");
{ error(0, "use -profile instead of -gt\n");
global.params.trace = 1;
}
else if (strcmp(p + 1, "m32") == 0)
@@ -569,7 +575,7 @@ int main(int argc, char *argv[])
#if DMDV1
global.params.Dversion = 1;
#else
error("use DMD 1.0 series compilers for -v1 switch");
error(0, "use DMD 1.0 series compilers for -v1 switch");
break;
#endif
}
@@ -606,7 +612,7 @@ int main(int argc, char *argv[])
break;
case 0:
error("-o no longer supported, use -of or -od");
error(0, "-o no longer supported, use -of or -od");
break;
default:
@@ -851,11 +857,11 @@ int main(int argc, char *argv[])
else
{
Lerror:
error("unrecognized switch '%s'", argv[i]);
error(0, "unrecognized switch '%s'", argv[i]);
continue;
Lnoarg:
error("argument expected for switch '%s'", argv[i]);
error(0, "argument expected for switch '%s'", argv[i]);
continue;
}
}
@@ -890,7 +896,7 @@ int main(int argc, char *argv[])
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
if (global.params.lib && global.params.dll)
error("cannot mix -lib and -shared\n");
error(0, "cannot mix -lib and -shared\n");
#endif
if (global.params.release)
@@ -952,7 +958,7 @@ int main(int argc, char *argv[])
}
else if (global.params.run)
{
error("flags conflict with -run");
error(0, "flags conflict with -run");
fatal();
}
else
@@ -1058,10 +1064,10 @@ int main(int argc, char *argv[])
#if _WIN32
// Convert / to \ so linker will work
for (size_t i = 0; p[i]; i++)
for (size_t j = 0; p[j]; j++)
{
if (p[i] == '/')
p[i] = '\\';
if (p[j] == '/')
p[j] = '\\';
}
#endif
@@ -1143,12 +1149,12 @@ int main(int argc, char *argv[])
strcmp(name, ".") == 0)
{
Linvalid:
error("invalid file name '%s'", files.tdata()[i]);
error(0, "invalid file name '%s'", files.tdata()[i]);
fatal();
}
}
else
{ error("unrecognized file extension %s\n", ext);
{ error(0, "unrecognized file extension %s\n", ext);
fatal();
}
}
@@ -1172,10 +1178,6 @@ int main(int argc, char *argv[])
}
}
#if WINDOWS_SEH
__try
{
#endif
// Read files
#define ASYNCREAD 1
#if ASYNCREAD
@@ -1212,7 +1214,8 @@ int main(int argc, char *argv[])
#if ASYNCREAD
if (aw->read(filei))
{
error("cannot read file %s", m->srcfile->name->toChars());
error(0, "cannot read file %s", m->srcfile->name->toChars());
fatal();
}
#endif
m->parse();
@@ -1246,7 +1249,7 @@ int main(int argc, char *argv[])
if (anydocfiles && modules.dim &&
(global.params.oneobj || global.params.objname))
{
error("conflicting Ddoc and obj generation options");
error(0, "conflicting Ddoc and obj generation options");
fatal();
}
if (global.errors)
@@ -1433,14 +1436,6 @@ int main(int argc, char *argv[])
if (global.params.lib && !global.errors)
library->write();
#if WINDOWS_SEH
}
__except (__ehfilter(GetExceptionInformation()))
{
printf("Stack overflow\n");
fatal();
}
#endif
backend_term();
if (global.errors)
fatal();
@@ -1448,7 +1443,7 @@ int main(int argc, char *argv[])
if (!global.params.objfiles->dim)
{
if (global.params.link)
error("no object files to link");
error(0, "no object files to link");
}
else
{
@@ -1478,6 +1473,25 @@ int main(int argc, char *argv[])
return status;
}
int main(int argc, char *argv[])
{
int status = -1;
#if WINDOWS_SEH
__try
{
#endif
status = tryMain(argc, argv);
#if WINDOWS_SEH
}
__except (__ehfilter(GetExceptionInformation()))
{
printf("Stack overflow\n");
fatal();
}
#endif
return status;
}
#endif // !IN_LLVM
/***********************************
+12 -3
View File
@@ -312,6 +312,12 @@ struct Global
unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned gaggedErrors; // number of errors reported while gagged
/* Gagging can either be speculative (is(typeof()), etc)
* or because of forward references
*/
unsigned speculativeGag; // == gag means gagging is for is(typeof);
bool isSpeculativeGagging();
// Start gagging. Return the current number of gagged errors
unsigned startGagging();
@@ -328,10 +334,12 @@ extern Global global;
/* Set if Windows Structured Exception Handling C extensions are supported.
* Apparently, VC has dropped support for these?
*/
#define WINDOWS_SEH (_WIN32 && __DMC__)
#define WINDOWS_SEH _WIN32
#include "longdouble.h"
#ifdef __DMC__
#include <complex.h>
typedef _Complex long double complex_t;
#else
#ifndef IN_GCC
@@ -362,7 +370,7 @@ typedef uint64_t d_uns64;
typedef float d_float32;
typedef double d_float64;
typedef long double d_float80;
typedef longdouble d_float80;
typedef d_uns8 d_char;
typedef d_uns16 d_wchar;
@@ -371,7 +379,7 @@ typedef d_uns32 d_dchar;
#ifdef IN_GCC
#include "d-gcc-real.h"
#else
typedef long double real_t;
typedef longdouble real_t;
#endif
// Modify OutBuffer::writewchar to write the correct size of wchar
@@ -470,6 +478,7 @@ void fatal();
void err_nomem();
#if IN_LLVM
void inifile(char *argv0, const char *inifile);
void error(const char *format, ...) IS_PRINTF(1);
#else
int runLINK();
void deleteExeFile();
+21 -14
View File
@@ -37,7 +37,6 @@
#include "hdrgen.h"
#include "lexer.h"
#define MARS 1
#include "html.h"
#ifdef IN_GCC
@@ -342,7 +341,7 @@ static void check_and_add_output_file(Module* NewMod, const std::string& str)
if (i != files.end())
{
Module* ThisMod = i->second;
error("Output file '%s' for module '%s' collides with previous module '%s'. See the -oq option",
error(Loc(), "Output file '%s' for module '%s' collides with previous module '%s'. See the -oq option",
str.c_str(), NewMod->toPrettyChars(), ThisMod->toPrettyChars());
fatal();
}
@@ -507,7 +506,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
}
m->read(loc);
if (!m->read(loc))
return NULL;
m->parse();
#ifdef IN_GCC
@@ -517,7 +518,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
return m;
}
void Module::read(Loc loc)
bool Module::read(Loc loc)
{
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
if (srcfile->read())
@@ -530,14 +531,16 @@ void Module::read(Loc loc)
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = global.path->tdata()[i];
fprintf(stdmsg, "import path[%zd] = %s\n", i, p);
fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p);
}
}
else
fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
fatal();
}
fatal();
return false;
}
return true;
}
inline unsigned readwordLE(unsigned short *p)
@@ -1342,19 +1345,23 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package
else
{
assert(p->isPackage());
#if TARGET_NET //dot net needs modules and packages with same name
#else
if (p->isModule())
{ p->error("module and package have the same name");
fatal();
break;
}
#endif
// It might already be a module, not a package, but that needs
// to be checked at a higher level, where a nice error message
// can be generated.
// dot net needs modules and packages with same name
}
parent = p;
dst = ((Package *)p)->symtab;
if (ppkg && !*ppkg)
*ppkg = (Package *)p;
#if TARGET_NET
#else
if (p->isModule())
{ // Return the module so that a nice error message can be generated
*ppkg = (Package *)p;
break;
}
#endif
}
if (pparent)
{
+1 -1
View File
@@ -138,7 +138,7 @@ struct Module : Package
#if !IN_LLVM
void setDocfile(); // set docfile member
#endif
void read(Loc loc); // read file
bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise.
#if IN_LLVM
void parse(bool gen_docs = false); // syntactic parse
#elif IN_GCC
+319 -126
View File
@@ -87,6 +87,10 @@ int REALALIGNSIZE = 16;
int REALSIZE = 12;
int REALPAD = 2;
int REALALIGNSIZE = 4;
#elif IN_GCC
int REALSIZE = 0;
int REALPAD = 0;
int REALALIGNSIZE = 0;
#else
int REALSIZE = 10;
int REALPAD = 0;
@@ -279,7 +283,7 @@ void Type::init()
for (size_t i = 0; i < TMAX; i++)
{ if (!mangleChar[i])
fprintf(stdmsg, "ty = %zd\n", i);
fprintf(stdmsg, "ty = %llu\n", (ulonglong)i);
assert(mangleChar[i]);
}
@@ -461,6 +465,8 @@ Type *Type::mutableOf()
t = t->merge();
t->fixTo(this);
}
else
t = t->merge();
assert(t->isMutable());
return t;
}
@@ -552,6 +558,8 @@ Type *Type::unSharedOf()
t->fixTo(this);
}
else
t = t->merge();
assert(!t->isShared());
return t;
}
@@ -1342,7 +1350,19 @@ Type *Type::aliasthisOf()
Expression *ethis = this->defaultInit(0);
fd = fd->overloadResolve(0, ethis, NULL);
if (fd)
{ TypeFunction *tf = (TypeFunction *)fd->type;
if (!tf->next && fd->inferRetType)
{
TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors;
fd->semantic3(fd->scope);
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}
t = ((TypeFunction *)fd->type)->next;
}
}
return t;
}
@@ -1352,6 +1372,32 @@ Type *Type::aliasthisOf()
Type *t = ed->type;
return t;
}
TemplateDeclaration *td = ad->aliasthis->isTemplateDeclaration();
if (td)
{ assert(td->scope);
Expression *ethis = defaultInit(0);
FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1);
if (fd)
{
//if (!fd->type->nextOf() && fd->inferRetType)
{
TemplateInstance *spec = fd->isSpeculative();
int olderrs = global.errors;
fd->semantic3(fd->scope);
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}
if (!global.errors)
{
Type *t = fd->type->nextOf();
t = t->substWildTo(mod == 0 ? MODmutable : mod);
return t;
}
}
return Type::terror;
}
//printf("%s\n", ad->aliasthis->kind());
}
return NULL;
@@ -1642,6 +1688,8 @@ Type *Type::merge()
if (ty == Ttypeof) return this;
if (ty == Tident) return this;
if (ty == Tinstance) return this;
if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco)
return this;
if (nextOf() && !nextOf()->merge()->deco)
return this;
@@ -1918,12 +1966,12 @@ Type *Type::substWildTo(unsigned mod)
else if (ty == Taarray)
{
t = new TypeAArray(t, ((TypeAArray *)this)->index->syntaxCopy());
t = t->merge();
((TypeAArray *)t)->sc = ((TypeAArray *)this)->sc; // duplicate scope
}
else
assert(0);
t = t->addMod(this->mod);
t = t->merge();
}
}
else
@@ -2060,35 +2108,6 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
}
else if (ident == Id::init)
{
#if 0
if (v->init)
{
if (v->init->isVoidInitializer())
error(e->loc, "%s.init is void", v->toChars());
else
{ Loc loc = e->loc;
e = v->init->toExpression();
if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit)
{
e = ((AssignExp *)e)->e2;
/* Take care of case where we used a 0
* to initialize the struct.
*/
if (e->type == Type::tint32 &&
e->isBool(0) &&
v->type->toBasetype()->ty == Tstruct)
{
e = v->type->defaultInit(e->loc);
}
}
e = e->optimize(WANTvalue | WANTinterpret);
// if (!e->isConst())
// error(loc, ".init cannot be evaluated at compile time");
}
goto Lreturn;
}
#endif
e = defaultInitLiteral(e->loc);
goto Lreturn;
}
@@ -2164,7 +2183,6 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident)
tiargs->push(se);
e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs);
((DotTemplateInstanceExp *)e)->ti->tempdecl = td;
//return e;
e = e->semantic(sc);
return e;
}
@@ -2175,7 +2193,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident)
{ /* Rewrite e.ident as:
* e.aliasthis.ident
*/
e = new DotIdExp(e->loc, e, sym->aliasthis->ident);
e = resolveAliasThis(sc, e);
e = new DotIdExp(e->loc, e, ident);
return e->semantic(sc);
}
@@ -2254,11 +2272,15 @@ void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
}
/*******************************
* If one of the subtypes of this type is a TypeIdentifier,
* i.e. it's an unresolved type, return that type.
* tparams == NULL:
* If one of the subtypes of this type is a TypeIdentifier,
* i.e. it's an unresolved type, return that type.
* tparams != NULL:
* Only when the TypeIdentifier is one of template parameters,
* return that type.
*/
Type *Type::reliesOnTident()
Type *Type::reliesOnTident(TemplateParameters *tparams)
{
return NULL;
}
@@ -2378,9 +2400,9 @@ void TypeNext::checkDeprecated(Loc loc, Scope *sc)
}
Type *TypeNext::reliesOnTident()
Type *TypeNext::reliesOnTident(TemplateParameters *tparams)
{
return next->reliesOnTident();
return next->reliesOnTident(tparams);
}
int TypeNext::hasWild()
@@ -2547,9 +2569,7 @@ Type *TypeNext::makeMutable()
{
//printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
TypeNext *t = (TypeNext *)Type::makeMutable();
if ((ty != Tfunction && next->ty != Tfunction &&
//(next->deco || next->ty == Tfunction) &&
next->isWild()) || ty == Tsarray)
if (ty == Tsarray)
{
t->next = next->mutableOf();
}
@@ -3124,7 +3144,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Timaginary64: t = tfloat64; goto L2;
case Timaginary80: t = tfloat80; goto L2;
L2:
e = new RealExp(0, 0.0, t);
e = new RealExp(e->loc, ldouble(0.0), t);
break;
default:
@@ -3156,7 +3176,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
case Tfloat32:
case Tfloat64:
case Tfloat80:
e = new RealExp(0, 0.0, this);
e = new RealExp(e->loc, ldouble(0.0), this);
break;
default:
@@ -3183,7 +3203,7 @@ Expression *TypeBasic::defaultInit(Loc loc)
*/
union
{ unsigned short us[8];
long double ld;
longdouble ld;
} snan = {{ 0, 0, 0, 0xA000, 0x7FFF }};
/*
* Although long doubles are 10 bytes long, some
@@ -3411,11 +3431,25 @@ Type *TypeVector::semantic(Loc loc, Scope *sc)
if (errors != global.errors)
return terror;
basetype = basetype->toBasetype()->mutableOf();
if (basetype->ty != Tsarray || basetype->size() != 16)
{ error(loc, "base type of __vector must be a 16 byte static array, not %s", basetype->toChars());
if (basetype->ty != Tsarray)
{ error(loc, "T in __vector(T) must be a static array, not %s", basetype->toChars());
return terror;
}
TypeSArray *t = (TypeSArray *)basetype;
if (sc && sc->parameterSpecialization && t->dim->op == TOKvar &&
((VarExp *)t->dim)->var->storage_class & STCtemplateparameter)
{
/* It could be a template parameter N which has no value yet:
* template Foo(T : __vector(T[N]), size_t N);
*/
return this;
}
if (t->size(loc) != 16)
{ error(loc, "base type of __vector must be a 16 byte static array, not %s", t->toChars());
return terror;
}
TypeBasic *tb = t->nextOf()->isTypeBasic();
if (!tb || !(tb->flags & TFLAGSvector))
{ error(loc, "base type of __vector must be a static array of an arithmetic type, not %s", t->toChars());
@@ -3757,7 +3791,7 @@ d_uns64 TypeSArray::size(Loc loc)
return sz;
Loverflow:
error(loc, "index %jd overflow for static array", sz);
error(loc, "index %lld overflow for static array", sz);
return 1;
}
@@ -3805,7 +3839,10 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
//printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
if (*pe)
{ // It's really an index expression
Expression *e = new IndexExp(loc, *pe, dim);
Expressions *exps = new Expressions();
exps->setDim(1);
(*exps)[0] = dim;
Expression *e = new ArrayExp(loc, *pe, exps);
*pe = e;
}
else if (*ps)
@@ -3824,7 +3861,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
sc = sc->pop();
if (d >= td->objects->dim)
{ error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim);
{ error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim);
goto Ldefault;
}
Object *o = td->objects->tdata()[(size_t)d];
@@ -3884,7 +3921,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
uinteger_t d = dim->toUInteger();
if (d >= sd->objects->dim)
{ error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
{ error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim);
return Type::terror;
}
Object *o = sd->objects->tdata()[(size_t)d];
@@ -3951,7 +3988,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
if (n && n2 / n != d2)
{
Loverflow:
error(loc, "index %jd overflow for static array", d1);
error(loc, "index %lld overflow for static array", d1);
goto Lerror;
}
}
@@ -3965,7 +4002,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
uinteger_t d = dim->toUInteger();
if (d >= tt->arguments->dim)
{ error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
{ error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim);
goto Lerror;
}
Parameter *arg = tt->arguments->tdata()[(size_t)d];
@@ -4006,7 +4043,7 @@ void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
{
Type::toDecoBuffer(buf, flag, mangle);
if (dim)
buf->printf("%ju", dim->toInteger());
buf->printf("%llu", dim->toInteger());
if (next)
/* Note that static arrays are value types, so
* for a parameter, propagate the 0x100 to the next
@@ -4258,6 +4295,31 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc)
return merge();
}
void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
{
//printf("TypeDArray::resolve() %s\n", toChars());
next->resolve(loc, sc, pe, pt, ps);
//printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
if (*pe)
{ // It's really a slice expression
Expression *e = new SliceExp(loc, *pe, NULL, NULL);
*pe = e;
}
else if (*ps)
{
TupleDeclaration *td = (*ps)->isTupleDeclaration();
if (td)
; // keep *ps
else
goto Ldefault;
}
else
{
Ldefault:
Type::resolve(loc, sc, pe, pt, ps);
}
}
void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
{
Type::toDecoBuffer(buf, flag, mangle);
@@ -4529,8 +4591,8 @@ StructDeclaration *TypeAArray::getImpl()
* which has Tident's instead of real types.
*/
Objects *tiargs = new Objects();
tiargs->push(index);
tiargs->push(next);
tiargs->push(index->substWildTo(MODconst)); // hack for bug7757
tiargs->push(next ->substWildTo(MODconst)); // hack for bug7757
// Create AssociativeArray!(index, next)
#if 1
@@ -4698,8 +4760,12 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
ident != Id::stringof &&
ident != Id::offsetof)
{
e->type = getImpl()->type;
e = e->type->dotExp(sc, e, ident);
//printf("test1: %s, %s\n", e->toChars(), e->type->toChars());
Type *t = getImpl()->type;
//printf("test2: %s, %s\n", e->toChars(), e->type->toChars());
e->type = t;
e = t->dotExp(sc, e, ident);
//printf("test3: %s, %s\n", e->toChars(), e->type->toChars());
}
else
e = Type::dotExp(sc, e, ident);
@@ -4743,6 +4809,22 @@ int TypeAArray::checkBoolean()
return TRUE;
}
Expression *TypeAArray::toExpression()
{
Expression *e = next->toExpression();
if (e)
{
Expression *ei = index->toExpression();
if (ei)
{
Expressions *arguments = new Expressions();
arguments->push(ei);
return new ArrayExp(loc, e, arguments);
}
}
return NULL;
}
int TypeAArray::hasPointers()
{
return TRUE;
@@ -4774,11 +4856,7 @@ MATCH TypeAArray::implicitConvTo(Type *to)
MATCH mi = index->constConv(ta->index);
if (m != MATCHnomatch && mi != MATCHnomatch)
{
if (m == MATCHexact && mod != to->mod)
m = MATCHconst;
if (mi < m)
m = mi;
return m;
return MODimplicitConv(mod, to->mod) ? MATCHconst : MATCHnomatch;
}
}
else if (to->ty == Tstruct && ((TypeStruct *)to)->sym->ident == Id::AssociativeArray)
@@ -4844,7 +4922,8 @@ Type *TypePointer::semantic(Loc loc, Scope *sc)
deco = NULL;
}
next = n;
transitive();
if (next->ty != Tfunction)
transitive();
return merge();
}
@@ -5049,6 +5128,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
this->purity = PUREimpure;
this->isproperty = false;
this->isref = false;
this->iswild = false;
this->fargs = NULL;
#if IN_LLVM
@@ -5097,9 +5177,10 @@ Type *TypeFunction::syntaxCopy()
* 2 arguments match as far as overloading goes,
* but types are not covariant
* 3 cannot determine covariance because of forward references
* *pstc STCxxxx which would make it covariant
*/
int Type::covariant(Type *t)
int Type::covariant(Type *t, StorageClass *pstc)
{
#if 0
printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
@@ -5108,6 +5189,10 @@ int Type::covariant(Type *t)
printf("mod = %x, %x\n", mod, t->mod);
#endif
if (pstc)
*pstc = 0;
StorageClass stc = 0;
int inoutmismatch = 0;
TypeFunction *t1;
@@ -5211,35 +5296,39 @@ int Type::covariant(Type *t)
goto Lnotcovariant;
Lcovariant:
if (t1->isref != t2->isref)
goto Lnotcovariant;
/* Can convert mutable to const
*/
if (!MODimplicitConv(t2->mod, t1->mod))
goto Lnotcovariant;
#if 0
if (t1->mod != t2->mod)
{
if (!(t1->mod & MODconst) && (t2->mod & MODconst))
goto Lnotcovariant;
if (!(t1->mod & MODshared) && (t2->mod & MODshared))
// If adding 'const' will make it covariant
if (MODimplicitConv(t2->mod, MODmerge(t1->mod, MODconst)))
stc |= STCconst;
else
goto Lnotcovariant;
}
#endif
/* Can convert pure to impure, and nothrow to throw
*/
if (!t1->purity && t2->purity)
goto Lnotcovariant;
stc |= STCpure;
if (!t1->isnothrow && t2->isnothrow)
goto Lnotcovariant;
if (t1->isref != t2->isref)
goto Lnotcovariant;
stc |= STCnothrow;
/* Can convert safe/trusted to system
*/
if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted)
// Should we infer trusted or safe? Go with safe.
stc |= STCsafe;
if (stc)
{ if (pstc)
*pstc = stc;
goto Lnotcovariant;
}
//printf("\tcovaraint: 1\n");
return 1;
@@ -5551,10 +5640,14 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
tf->isnothrow = TRUE;
if (sc->stc & STCref)
tf->isref = TRUE;
if (sc->stc & STCsafe)
tf->trust = TRUSTsafe;
if (sc->stc & STCsystem)
tf->trust = TRUSTsystem;
if (sc->stc & STCtrusted)
tf->trust = TRUSTtrusted;
if (sc->stc & STCproperty)
tf->isproperty = TRUE;
@@ -5562,13 +5655,15 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
/* If the parent is @safe, then this function defaults to safe
* too.
* If the parent's @safe-ty is inferred, then this function's @safe-ty needs
* to be inferred first.
*/
if (tf->trust == TRUSTdefault)
for (Dsymbol *p = sc->func; p; p = p->toParent2())
{ FuncDeclaration *fd = p->isFuncDeclaration();
if (fd)
{
if (fd->isSafe())
if (fd->isSafeBypassingInference())
tf->trust = TRUSTsafe; // default to @safe
break;
}
@@ -5605,7 +5700,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
bool wildparams = FALSE;
bool wildsubparams = FALSE;
if (tf->parameters)
{
/* Create a scope for evaluating the default arguments for the parameters
@@ -5647,17 +5741,38 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
!(t->ty == Tpointer && t->nextOf()->ty == Tfunction || t->ty == Tdelegate))
{
wildparams = TRUE;
if (tf->next && !wildreturn)
error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
//if (tf->next && !wildreturn)
// error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
}
else if (!wildsubparams && t->hasWild())
wildsubparams = TRUE;
if (fparam->defaultArg)
{
fparam->defaultArg = fparam->defaultArg->semantic(argsc);
fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg);
fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type);
{ Expression *e = fparam->defaultArg;
e = e->inferType(fparam->type);
e = e->semantic(argsc);
e = resolveProperties(argsc, e);
if (e->op == TOKfunction) // see Bugzilla 4820
{ FuncExp *fe = (FuncExp *)e;
if (fe->fd)
{ if (fe->fd->tok == TOKreserved)
{
if (fe->type->ty == Tpointer)
{
fe->fd->vthis = NULL;
fe->fd->tok = TOKfunction;
}
else
fe->fd->tok = TOKdelegate;
}
// 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, 0);
e = new AddrExp(e->loc, e);
e = e->semantic(argsc);
}
}
e = e->implicitCastTo(argsc, fparam->type);
fparam->defaultArg = e;
}
/* If fparam after semantic() turns out to be a tuple, the number of parameters may
@@ -5718,8 +5833,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (wildreturn && !wildparams)
error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
if (wildsubparams && wildparams)
error(loc, "inout must be all or none on top level for %s", toChars());
tf->iswild = wildparams;
if (tf->next)
tf->deco = tf->merge()->deco;
@@ -5730,8 +5844,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
return terror;
}
if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 1))
error(loc, "properties can only have zero or one parameter");
if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2))
error(loc, "properties can only have zero, one, or two parameter");
if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0)
error(loc, "variadic functions with non-D linkage must have at least one parameter");
@@ -5924,9 +6038,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
assert(arg);
if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
Type *pt = p->type;
arg = ((FuncExp *)arg)->inferType(NULL, pt);
{
arg = ((FuncExp *)arg)->inferType(p->type, 1);
if (!arg)
goto L1; // try typesafe variadics
}
@@ -6013,9 +6126,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
assert(arg);
#if 1
if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
Type *pt = tb->nextOf();
arg = ((FuncExp *)arg)->inferType(NULL, pt);
{
arg = ((FuncExp *)arg)->inferType(tb->nextOf(), 1);
if (!arg)
goto Nomatch;
}
@@ -6075,16 +6187,16 @@ Nomatch:
return MATCHnomatch;
}
Type *TypeFunction::reliesOnTident()
Type *TypeFunction::reliesOnTident(TemplateParameters *tparams)
{
size_t dim = Parameter::dim(parameters);
for (size_t i = 0; i < dim; i++)
{ Parameter *fparam = Parameter::getNth(parameters, i);
Type *t = fparam->type->reliesOnTident();
Type *t = fparam->type->reliesOnTident(tparams);
if (t)
return t;
}
return next ? next->reliesOnTident() : NULL;
return next ? next->reliesOnTident(tparams) : NULL;
}
/********************************************
@@ -6142,6 +6254,40 @@ Expression *TypeFunction::defaultInit(Loc loc)
return new ErrorExp();
}
Type *TypeFunction::addStorageClass(StorageClass stc)
{
TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc);
if ((stc & STCpure && !t->purity) ||
(stc & STCnothrow && !t->isnothrow) ||
(stc & STCsafe && t->trust < TRUSTtrusted))
{
// Klunky to change these
TypeFunction *tf = new TypeFunction(t->parameters, t->next, t->varargs, t->linkage, 0);
tf->mod = t->mod;
tf->fargs = fargs;
tf->purity = t->purity;
tf->isnothrow = t->isnothrow;
tf->isproperty = t->isproperty;
tf->isref = t->isref;
tf->trust = t->trust;
if (stc & STCpure)
tf->purity = PUREfwdref;
if (stc & STCnothrow)
tf->isnothrow = true;
if (stc & STCsafe)
tf->trust = TRUSTsafe;
#if IN_LLVM
tf->funcdecl = t->funcdecl;
#endif
tf->deco = tf->merge()->deco;
t = tf;
}
return t;
}
/***************************** TypeDelegate *****************************/
TypeDelegate::TypeDelegate(Type *t)
@@ -6429,7 +6575,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
else
{
Lerror:
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
if (id->dyncast() == DYNCAST_DSYMBOL)
{ // searchX already handles errors for template instances
assert(global.errors);
}
else
{
sm = s->search_correct(id);
if (sm)
error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?",
id->toChars(), toChars(), sm->kind(), sm->toChars());
else
error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
}
*pe = new ErrorExp();
}
return;
@@ -6666,10 +6824,6 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
}
else
{
#ifdef DEBUG
if (!global.gag)
printf("1: ");
#endif
if (s)
{
s->error(loc, "is used as a type");
@@ -6683,9 +6837,23 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
return t;
}
Type *TypeIdentifier::reliesOnTident()
Type *TypeIdentifier::reliesOnTident(TemplateParameters *tparams)
{
return this;
if (tparams)
{
if (idents.dim == 0)
{
for (size_t i = 0; i < tparams->dim; i++)
{ TemplateParameter *tp = tparams->tdata()[i];
if (tp->ident->equals(ident))
return this;
}
}
return NULL;
}
else
return this;
}
Expression *TypeIdentifier::toExpression()
@@ -6766,12 +6934,11 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
Expression *e;
Dsymbol *s;
//printf("TypeInstance::semantic(%s)\n", toChars());
//printf("TypeInstance::semantic(%p, %s)\n", this, toChars());
if (sc->parameterSpecialization)
{
unsigned errors = global.startGagging();
resolve(loc, sc, &e, &t, &s);
if (global.endGagging(errors))
@@ -6920,9 +7087,15 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
{
Scope *sc2 = sc->push();
sc2->intypeof++;
sc2->speculative = true;
sc2->ignoreTemplates++;
sc2->flags |= sc->flags & SCOPEstaticif;
unsigned oldspecgag = global.speculativeGag;
if (global.gag)
global.speculativeGag = global.gag;
exp = exp->semantic(sc2);
global.speculativeGag = oldspecgag;
#if DMDV2
if (exp->type && exp->type->ty == Tfunction &&
((TypeFunction *)exp->type)->isproperty)
@@ -7113,9 +7286,6 @@ unsigned TypeEnum::alignsize()
{
if (!sym->memtype)
{
#ifdef DEBUG
printf("1: ");
#endif
error(0, "enum %s is forward referenced", sym->toChars());
return 4;
}
@@ -7142,9 +7312,6 @@ Type *TypeEnum::toBasetype()
}
if (!sym->memtype)
{
#ifdef DEBUG
printf("2: ");
#endif
error(sym->loc, "enum %s is forward referenced", sym->toChars());
return tint32;
}
@@ -7329,9 +7496,6 @@ int TypeEnum::isZeroInit(Loc loc)
}
if (!sym->defaultval)
{
#ifdef DEBUG
printf("3: ");
#endif
error(loc, "enum %s is forward referenced", sym->toChars());
return 0;
}
@@ -7939,10 +8103,19 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc)
e = vd->init->toExpression();
}
else
e = vd->type->defaultInitLiteral();
structelems->tdata()[j] = e;
e = vd->type->defaultInitLiteral(loc);
(*structelems)[j] = e;
}
StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
#if IN_DMD
/* Copy from the initializer symbol for larger symbols,
* otherwise the literals expressed as code get excessively large.
*/
if (size(loc) > PTRSIZE * 4)
structinit->sinit = sym->toInitializer();
#endif
// Why doesn't the StructLiteralExp constructor do this, when
// sym->type != NULL ?
structinit->type = sym->type;
@@ -8020,7 +8193,7 @@ MATCH TypeStruct::implicitConvTo(Type *to)
{ MATCH m;
//printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars());
if (to->ty == Taarray)
if (to->ty == Taarray && sym->ident == Id::AssociativeArray)
{
/* If there is an error instantiating AssociativeArray!(), it shouldn't
* be reported -- it just means implicit conversion is impossible.
@@ -8525,7 +8698,7 @@ L1:
return e;
}
DotVarExp *de = new DotVarExp(e->loc, e, d);
DotVarExp *de = new DotVarExp(e->loc, e, d, d->hasOverloads());
return de->semantic(sc);
}
@@ -8761,14 +8934,14 @@ int TypeTuple::equals(Object *o)
return 0;
}
Type *TypeTuple::reliesOnTident()
Type *TypeTuple::reliesOnTident(TemplateParameters *tparams)
{
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{
Parameter *arg = arguments->tdata()[i];
Type *t = arg->type->reliesOnTident();
Type *t = arg->type->reliesOnTident(tparams);
if (t)
return t;
}
@@ -8819,6 +8992,10 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
{
e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
}
else if (ident == Id::init)
{
e = defaultInitLiteral(loc);
}
else
{
error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
@@ -8827,6 +9004,22 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
return e;
}
Expression *TypeTuple::defaultInit(Loc loc)
{
Expressions *exps = new Expressions();
exps->setDim(arguments->dim);
for (size_t i = 0; i < arguments->dim; i++)
{
Parameter *p = (*arguments)[i];
assert(p->type);
Expression *e = p->type->defaultInitLiteral(loc);
if (e->op == TOKerror)
return e;
(*exps)[i] = e;
}
return new TupleExp(loc, exps);
}
/***************************** TypeSlice *****************************/
/* This is so we can slice a TypeTuple */
@@ -8869,7 +9062,7 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc)
uinteger_t i2 = upr->toUInteger();
if (!(i1 <= i2 && i2 <= tt->arguments->dim))
{ error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
{ error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
return Type::terror;
}
@@ -8915,7 +9108,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
sc = sc->pop();
if (!(i1 <= i2 && i2 <= td->objects->dim))
{ error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim);
{ error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim);
goto Ldefault;
}
+18 -8
View File
@@ -237,7 +237,7 @@ struct Type : Object
virtual Type *syntaxCopy();
int equals(Object *o);
int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType()
int covariant(Type *t);
int covariant(Type *t, StorageClass *pstc = NULL);
char *toChars();
static char needThisPrefix();
#if IN_LLVM
@@ -294,7 +294,7 @@ struct Type : Object
Type *addSTC(StorageClass stc);
Type *castMod(unsigned mod);
Type *addMod(unsigned mod);
Type *addStorageClass(StorageClass stc);
virtual Type *addStorageClass(StorageClass stc);
Type *pointerTo();
Type *referenceTo();
Type *arrayOf();
@@ -320,7 +320,8 @@ struct Type : Object
Expression *noMember(Scope *sc, Expression *e, Identifier *ident);
virtual unsigned memalign(unsigned salign);
virtual Expression *defaultInit(Loc loc = 0);
virtual Expression *defaultInitLiteral(Loc loc = 0);
virtual Expression *defaultInitLiteral(Loc loc);
virtual Expression *voidInitLiteral(VarDeclaration *var);
virtual int isZeroInit(Loc loc = 0); // if initializer is 0
#if IN_DMD
virtual dt_t **toDt(dt_t **pdt);
@@ -332,7 +333,7 @@ struct Type : Object
Expression *getTypeInfo(Scope *sc);
virtual TypeInfoDeclaration *getTypeInfoDeclaration();
virtual int builtinTypeInfo();
virtual Type *reliesOnTident();
virtual Type *reliesOnTident(TemplateParameters *tparams = NULL);
virtual int hasWild();
virtual Expression *toExpression();
virtual int hasPointers();
@@ -383,7 +384,7 @@ struct TypeNext : Type
TypeNext(TY ty, Type *next);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void checkDeprecated(Loc loc, Scope *sc);
Type *reliesOnTident();
Type *reliesOnTident(TemplateParameters *tparams = NULL);
int hasWild();
Type *nextOf();
Type *makeConst();
@@ -448,6 +449,7 @@ struct TypeVector : Type
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
@@ -491,6 +493,7 @@ struct TypeSArray : TypeArray
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
#if IN_DMD
dt_t **toDt(dt_t **pdt);
dt_t **toDtElem(dt_t **pdt, Expression *e);
@@ -519,6 +522,7 @@ struct TypeDArray : TypeArray
d_uns64 size(Loc loc);
unsigned alignsize();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
@@ -563,6 +567,7 @@ struct TypeAArray : TypeArray
int isZeroInit(Loc loc);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *toExpression();
int hasPointers();
TypeTuple *toArgTypes();
MATCH implicitConvTo(Type *to);
@@ -656,6 +661,7 @@ struct TypeFunction : TypeNext
enum LINK linkage; // calling convention
enum TRUST trust; // level of trust
enum PURE purity; // PURExxxx
bool iswild; // is inout function
Expressions *fargs; // function arguments
int inuse;
@@ -671,12 +677,13 @@ struct TypeFunction : TypeNext
void attributesToCBuffer(OutBuffer *buf, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident();
Type *reliesOnTident(TemplateParameters *tparams = NULL);
bool hasLazyParameters();
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
bool parameterEscapes(Parameter *p);
Type *addStorageClass(StorageClass stc);
int callMatch(Expression *ethis, Expressions *toargs, int flag = 0);
#if IN_DMD
@@ -753,7 +760,7 @@ struct TypeIdentifier : TypeQualified
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
Type *reliesOnTident();
Type *reliesOnTident(TemplateParameters *tparams = NULL);
Expression *toExpression();
};
@@ -813,6 +820,7 @@ struct TypeStruct : Type
unsigned memalign(unsigned salign);
Expression *defaultInit(Loc loc);
Expression *defaultInitLiteral(Loc loc);
Expression *voidInitLiteral(VarDeclaration *var);
int isZeroInit(Loc loc);
int isAssignable();
int checkBoolean();
@@ -986,10 +994,11 @@ struct TypeTuple : Type
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
int equals(Object *o);
Type *reliesOnTident();
Type *reliesOnTident(TemplateParameters *tparams = NULL);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf, int flag, bool mangle);
Expression *getProperty(Loc loc, Identifier *ident);
Expression *defaultInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
};
@@ -1054,6 +1063,7 @@ struct Parameter : Object
extern int PTRSIZE;
extern int REALSIZE;
extern int REALPAD;
extern int REALALIGNSIZE;
extern int Tsize_t;
extern int Tptrdiff_t;
+31 -45
View File
@@ -355,11 +355,9 @@ Expression *UnaExp::op_overload(Scope *sc)
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *e = (UnaExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
return e->trySemantic(sc);
}
#endif
}
@@ -414,11 +412,9 @@ Expression *ArrayExp::op_overload(Scope *sc)
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *e = (UnaExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
return e->trySemantic(sc);
}
}
return NULL;
@@ -461,11 +457,9 @@ Expression *CastExp::op_overload(Scope *sc)
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident);
Expression *e = copy();
((UnaExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
UnaExp *e = (UnaExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident);
return e->trySemantic(sc);
}
}
return NULL;
@@ -721,11 +715,9 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
return e->trySemantic(sc);
}
// Try alias this on second operand
@@ -738,11 +730,9 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
return e->trySemantic(sc);
}
#endif
return NULL;
@@ -894,11 +884,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
return e->trySemantic(sc);
}
// Try alias this on second operand
@@ -907,11 +895,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id)
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
return e->trySemantic(sc);
}
return NULL;
@@ -1056,6 +1042,10 @@ Expression *BinAssignExp::op_overload(Scope *sc)
e1 = resolveProperties(sc, e1);
e2 = resolveProperties(sc, e2);
// Don't attempt 'alias this' if an error occured
if (e1->type->ty == Terror || e2->type->ty == Terror)
return new ErrorExp();
Identifier *id = opId();
Expressions args2;
@@ -1142,11 +1132,9 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1.aliasthis op e2)
*/
Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e1 = e1;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident);
return e->trySemantic(sc);
}
// Try alias this on second operand
@@ -1156,11 +1144,9 @@ L1:
/* Rewrite (e1 op e2) as:
* (e1 op e2.aliasthis)
*/
Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident);
Expression *e = copy();
((BinExp *)e)->e2 = e2;
e = e->trySemantic(sc);
return e;
BinExp *e = (BinExp *)syntaxCopy();
e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident);
return e->trySemantic(sc);
}
#endif
return NULL;
+6 -6
View File
@@ -406,7 +406,7 @@ Expression *AddrExp::optimize(int result)
TypeSArray *ts = (TypeSArray *)ve->type;
dinteger_t dim = ts->dim->toInteger();
if (index < 0 || index >= dim)
error("array index %jd is out of bounds [0..%jd]", index, dim);
error("array index %lld is out of bounds [0..%lld]", index, dim);
e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
e->type = type;
return e;
@@ -670,7 +670,7 @@ Expression *CastExp::optimize(int result)
}
// We can convert 'head const' to mutable
if (to->constOf()->equals(e1->type->constOf()))
if (to->mutableOf()->constOf()->equals(e1->type->mutableOf()->constOf()))
{
e1->type = type;
if (X) printf(" returning5 %s\n", e1->toChars());
@@ -716,7 +716,7 @@ Expression *BinExp::optimize(int result)
dinteger_t i2 = e2->toInteger();
d_uns64 sz = e1->type->size() * 8;
if (i2 < 0 || i2 >= sz)
{ error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1);
{ error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
e2 = new IntegerExp(0);
}
}
@@ -811,7 +811,7 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
dinteger_t i2 = e->e2->toInteger();
d_uns64 sz = e->e1->type->size() * 8;
if (i2 < 0 || i2 >= sz)
{ e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1);
{ e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1);
e->e2 = new IntegerExp(0);
}
if (e->e1->isConst() == 1)
@@ -900,7 +900,7 @@ Expression *PowExp::optimize(int result)
if (e1->type->isintegral())
e = new IntegerExp(loc, 1, e1->type);
else
e = new RealExp(loc, 1.0, e1->type);
e = new RealExp(loc, ldouble(1.0), e1->type);
e = new CommaExp(loc, e1, e);
}
@@ -913,7 +913,7 @@ Expression *PowExp::optimize(int result)
// Replace x ^^ -1.0 by (1.0 / x)
else if ((e2->op == TOKfloat64 && e2->toReal() == -1.0))
{
e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1);
e = new DivExp(loc, new RealExp(loc, ldouble(1.0), e2->type), e1);
}
// All other negative integral powers are illegal
else if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
+24 -10
View File
@@ -130,7 +130,7 @@ Dsymbols *Parser::parseModule()
decldefs = parseDeclDefs(0);
if (token.value != TOKeof)
{ error("unrecognized declaration");
{ error(loc, "unrecognized declaration");
goto Lerr;
}
return decldefs;
@@ -1380,8 +1380,15 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl)
error("scope cannot be ref or out");
Token *t;
#if 0
if (tpl && !stc && token.value == TOKidentifier &&
(t = peek(&token), (t->value == TOKcomma || t->value == TOKrparen)))
#else
if (tpl && token.value == TOKidentifier &&
(t = peek(&token), (t->value == TOKcomma ||
t->value == TOKrparen ||
t->value == TOKdotdotdot)))
#endif
{ Identifier *id = Lexer::uniqueId("__T");
at = new TypeIdentifier(loc, id);
if (!*tpl)
@@ -3564,6 +3571,9 @@ Statement *Parser::parseStatement(int flags)
goto Ldeclaration;
case BASIC_TYPES:
// bug 7773: int.max is always a part of expression
if (peekNext() == TOKdot)
goto Lexp;
case TOKtypedef:
case TOKalias:
case TOKconst:
@@ -5475,15 +5485,18 @@ Expression *Parser::parsePrimaryExp()
}
case TOKlparen:
{ enum TOK past = peekPastParen(&token)->value;
if (past == TOKgoesto)
{ // (arguments) => expression
goto case_delegate;
}
else if (past == TOKlcurly)
{ // (arguments) { statements... }
goto case_delegate;
{ Token *tk = peekPastParen(&token);
if (skipAttributes(tk, &tk))
{
enum TOK past = tk->value;
if (past == TOKgoesto)
{ // (arguments) => expression
goto case_delegate;
}
else if (past == TOKlcurly)
{ // (arguments) { statements... }
goto case_delegate;
}
}
// ( expression )
nextToken();
@@ -6592,6 +6605,7 @@ void initPrecedence()
precedence[TOKtraits] = PREC_primary;
precedence[TOKdefault] = PREC_primary;
precedence[TOKoverloadset] = PREC_primary;
precedence[TOKvoid] = PREC_primary;
#endif
// post
+2 -2
View File
@@ -152,10 +152,10 @@ typedef char dchar;
struct Dchar
{
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 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 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); }
+636
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
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__
+2
View File
@@ -19,8 +19,10 @@ struct Lstring
{
unsigned length;
#ifndef IN_GCC
// Disable warning about nonstandard extension
#pragma warning (disable : 4200)
#endif
dchar string[];
static Lstring zero; // 0 length string
+19 -160
View File
@@ -17,14 +17,14 @@ double Port::nan = NAN;
double Port::infinity = INFINITY;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
long double Port::ldbl_max = LDBL_MAX;
longdouble Port::ldbl_max = LDBL_MAX;
int Port::isNan(double r)
{
return ::isnan(r);
}
int Port::isNan(long double r)
int Port::isNan(longdouble r)
{
return ::isnan(r);
}
@@ -37,7 +37,7 @@ int Port::isSignallingNan(double r)
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
* 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);
}
long double Port::fmodl(long double x, long double y)
longdouble Port::fmodl(longdouble x, longdouble y)
{
return ::fmodl(x, y);
}
@@ -140,7 +140,7 @@ double Port::infinity = 1 / zero;
double Port::dbl_max = DBL_MAX;
double Port::dbl_min = DBL_MIN;
long double Port::ldbl_max = LDBL_MAX;
longdouble Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
@@ -151,7 +151,7 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
Port::infinity = std::numeric_limits<long double>::infinity();
Port::infinity = std::numeric_limits<double>::infinity();
}
int Port::isNan(double r)
@@ -159,7 +159,7 @@ int Port::isNan(double r)
return ::_isnan(r);
}
int Port::isNan(long double r)
int Port::isNan(longdouble r)
{
return ::_isnan(r);
}
@@ -172,7 +172,7 @@ int Port::isSignallingNan(double r)
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
*/
@@ -206,7 +206,7 @@ double Port::pow(double x, double 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);
}
@@ -351,7 +351,7 @@ double Port::nan = copysign(NAN, 1.0);
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
long double Port::ldbl_max = LDBL_MAX;
longdouble Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
@@ -366,9 +366,9 @@ PortInitializer::PortInitializer()
#if __FreeBSD__ && __i386__
// 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 };
Port::ldbl_max = *(long double *)&x[0];
Port::ldbl_max = *(longdouble *)&x[0];
// FreeBSD defaults to double precision. Switch to extended precision.
fpsetprec(FP_PE);
#endif
@@ -388,7 +388,7 @@ int Port::isNan(double r)
#endif
}
int Port::isNan(long double r)
int Port::isNan(longdouble r)
{
#if __APPLE__
return __inline_isnan(r);
@@ -408,7 +408,7 @@ int Port::isSignallingNan(double r)
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
* its significand, which is bit 62 of 0..79 for 80 bit reals.
@@ -454,7 +454,7 @@ double Port::pow(double x, double 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__
return ::fmod(x, y); // hack for now, fix later
@@ -532,7 +532,7 @@ 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;
longdouble Port::ldbl_max = LDBL_MAX;
struct PortInitializer
{
@@ -546,7 +546,7 @@ PortInitializer::PortInitializer()
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile long double foo;
volatile longdouble foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
@@ -558,7 +558,7 @@ int Port::isNan(double r)
return isnan(r);
}
int Port::isNan(long double r)
int Port::isNan(longdouble r)
{
return isnan(r);
}
@@ -571,7 +571,7 @@ int Port::isSignallingNan(double r)
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
* its significand, which is bit 62 of 0..79 for 80 bit reals.
@@ -653,144 +653,3 @@ char *Port::strupr(char *s)
#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
+7 -5
View File
@@ -10,6 +10,8 @@
// Portable wrapper around compiler/system specific things.
// The idea is to minimize #ifdef's in the app code.
#include "longdouble.h"
#ifndef TYPEDEFS
#define TYPEDEFS
@@ -20,7 +22,7 @@ typedef __int64 longlong;
typedef unsigned __int64 ulonglong;
// 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
#else
@@ -38,7 +40,7 @@ struct Port
static double infinity;
static double dbl_max;
static double dbl_min;
static long double ldbl_max;
static longdouble ldbl_max;
#if !defined __HAIKU__ || __OpenBSD__
#elif __GNUC__
@@ -49,10 +51,10 @@ struct Port
#undef signbit
#endif
static int isNan(double);
static int isNan(long double);
static int isNan(longdouble);
static int isSignallingNan(double);
static int isSignallingNan(long double);
static int isSignallingNan(longdouble);
static int isFinite(double);
static int isInfinity(double);
@@ -61,7 +63,7 @@ struct Port
static double floor(double);
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);
+7
View File
@@ -29,6 +29,13 @@
#include <utime.h>
#endif
#if _MSC_VER
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#endif
/*********************************
* #include <stdlib.h>
* int response_expand(int *pargc,char ***pargv);
+3 -3
View File
@@ -1533,7 +1533,7 @@ void File::stat()
void File::checkoffset(size_t offset, size_t nbytes)
{
if (offset > len || offset + nbytes > len)
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset);
}
char *File::toChars()
@@ -1802,7 +1802,7 @@ void OutBuffer::align(unsigned size)
// The compiler shipped with Visual Studio 2005 (and possible
// other versions) does not support C99 printf format specfiers
// such as %z and %j
#if _MSC_VER
#if 0 && _MSC_VER
using std::string;
using std::wstring;
@@ -1821,7 +1821,7 @@ search_and_replace(S& str, const S& what, const S& replacement)
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \
S tmp = f; \
search_and_replace(fmt, S("%z"), S("%l")); \
search_and_replace(fmt, S("%j"), S("%i")); \
search_and_replace(fmt, S("%j"), S("%l")); \
f = tmp.c_str();
#else
#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f)
+2 -4
View File
@@ -23,6 +23,7 @@
typedef size_t hash_t;
#include "longdouble.h"
#include "dchar.h"
char *wchar2ascii(wchar_t *);
@@ -32,9 +33,6 @@ int wcharIsAscii(wchar_t *, unsigned len);
int bstrcmp(unsigned char *s1, unsigned char *s2);
char *bstr2str(unsigned char *b);
void error(const char *format, ...);
void error(const wchar_t *format, ...);
void warning(const char *format, ...);
#ifndef TYPEDEFS
#define TYPEDEFS
@@ -43,7 +41,7 @@ void warning(const char *format, ...);
#include <float.h> // for _isnan
#include <malloc.h> // for alloca
// According to VC 8.0 docs, long double is the same as double
#define strtold strtod
longdouble strtold(const char *p,char **endp);
#define strtof strtod
#define isnan _isnan
+1 -1
View File
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <assert.h>
#if __sun&&__SVR4
#if __sun&&__SVR4 || _MSC_VER
#include <alloca.h>
#endif
+2 -2
View File
@@ -75,11 +75,11 @@ Scope::Scope()
this->noaccesscheck = 0;
this->mustsemantic = 0;
this->intypeof = 0;
this->speculative = 0;
this->parameterSpecialization = 0;
this->ignoreTemplates = 0;
this->callSuper = 0;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = NULL;
@@ -125,11 +125,11 @@ Scope::Scope(Scope *enclosing)
this->noaccesscheck = enclosing->noaccesscheck;
this->mustsemantic = enclosing->mustsemantic;
this->intypeof = enclosing->intypeof;
this->speculative = enclosing->speculative;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->ignoreTemplates = enclosing->ignoreTemplates;
this->callSuper = enclosing->callSuper;
this->flags = 0;
this->anonAgg = NULL;
this->lastdc = NULL;
this->lastoffset = 0;
this->docbuf = enclosing->docbuf;
+9 -2
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2009 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -63,11 +63,16 @@ struct Scope
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it
unsigned offset; // next offset to use in aggregate
// This really shouldn't be a part of Scope, because it requires
// semantic() to be done in the lexical field order. It should be
// set in a pass after semantic() on all fields so they can be
// semantic'd in any order.
int inunion; // we're processing members of a union
int incontract; // we're inside contract code
int nofree; // set if shouldn't free it
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
bool speculative; // in __traits(compiles) or typeof(exp)
int parameterSpecialization; // if in template parameter specialization
int noaccesscheck; // don't do access checks
int mustsemantic; // cannot defer semantic()
@@ -97,7 +102,9 @@ struct Scope
#define SCOPEstaticassert 8 // inside static assert
#define SCOPEdebug 0x10 // inside debug conditional
AnonymousAggregateDeclaration *anonAgg; // for temporary analysis
#if IN_GCC
Expressions *attributes; // GCC decl/type attributes
#endif
DocComment *lastdc; // documentation comment for last symbol at this scope
unsigned lastoffset; // offset in docbuf of where to insert next dec
+168 -25
View File
@@ -1243,6 +1243,7 @@ ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expr
this->condition = condition;
this->increment = increment;
this->body = body;
this->nest = 0;
}
Statement *ForStatement::syntaxCopy()
@@ -1260,17 +1261,145 @@ Statement *ForStatement::syntaxCopy()
return s;
}
/*
* Run semantic on init recursively.
* Rewrite:
* for (auto x=X(), y = Y(); ...; ...) {}
* as:
* try {
* try {
* for (auto x=X(), auto y=Y(); ...; ...) {}
* }
* finally { y.~this(); }
* }
* finally { x.~this(); }
*/
Statement *ForStatement::semanticInit(Scope *sc)
{
assert(init);
++nest;
Loc locinit = init->loc;
Statements *ainit = init->flatten(sc);
if (!ainit)
(ainit = new Statements())->push(init);
init = NULL;
Statement *statement = this;
for (size_t i = 0; i < ainit->dim; i++)
{ Statement *s = (*ainit)[i];
s = s->semantic(sc);
(*ainit)[i] = s;
if (s)
{
Statement *sentry;
Statement *sexception;
Statement *sfinally;
(*ainit)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally);
if (sentry)
{ sentry = sentry->semantic(sc);
if (sentry)
ainit->insert(i++, sentry);
}
if (sexception)
sexception = sexception->semantic(sc);
if (sexception)
{ // Re-initialize this->init
if (i + 1 < ainit->dim)
{
Statements *a = new Statements();
for (size_t j = i + 1; j < ainit->dim; j++)
a->push((*ainit)[j]);
init = new CompoundStatement(0, a);
}
Identifier *id = Lexer::uniqueId("__o");
Statement *handler = sexception;
if (sexception->blockExit(FALSE) & BEfallthru)
{ handler = new ThrowStatement(0, new IdentifierExp(0, id));
handler = new CompoundStatement(0, sexception, handler);
}
Catches *catches = new Catches();
Catch *ctch = new Catch(0, NULL, id, handler);
catches->push(ctch);
s = new TryCatchStatement(0, this, catches);
if (sfinally)
s = new TryFinallyStatement(0, s, sfinally);
//printf("ex {{{\n");
s = s->semantic(sc);
//printf("}}}\n");
statement = s;
if (init)
{ Statements *a = init->flatten(sc);
if (!a)
(a = new Statements())->push(init);
for (size_t j = 0; j < i + 1; j++)
a->insert(j, (*ainit)[j]);
init = new CompoundStatement(locinit, a);
}
break;
}
else if (sfinally)
{ // Re-initialize this->init
if (i + 1 < ainit->dim)
{
Statements *a = new Statements();
for (size_t j = i + 1; j < ainit->dim; j++)
a->push((*ainit)[j]);
init = new CompoundStatement(0, a);
}
s = new TryFinallyStatement(0, this, sfinally);
//printf("fi {{{\n");
s = s->semantic(sc);
//printf("}}} fi\n");
statement = s;
if (init)
{ Statements *a = init->flatten(sc);
if (!a)
(a = new Statements())->push(init);
for (size_t j = 0; j < i + 1; j++)
a->insert(j, (*ainit)[j]);
init = new CompoundStatement(locinit, a);
}
break;
}
}
}
if (!init)
{ // whole init semantic is completely done.
init = new CompoundStatement(locinit, ainit);
}
--nest;
return statement;
}
Statement *ForStatement::semantic(Scope *sc)
{
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc->scopesym;
sc = sc->push(sym);
if (!nest)
{ ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc->scopesym;
sc = sc->push(sym);
}
else if (init)
{ // Process this->init recursively
return semanticInit(sc);
}
Statement *statement = this;
if (init)
init = init->semantic(sc);
statement = semanticInit(sc);
sc->noctor++;
if (condition)
{
condition = condition->semantic(sc);
{ condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
condition = condition->optimize(WANTvalue);
condition = condition->checkToBoolean(sc);
@@ -1287,18 +1416,16 @@ Statement *ForStatement::semantic(Scope *sc)
body = body->semanticNoScope(sc);
sc->noctor--;
sc->pop();
return this;
if (!nest)
sc->pop();
//if (!nest) statement->print();
return statement;
}
Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
{
//printf("ForStatement::scopeCode()\n");
//print();
if (init)
init = init->scopeCode(sc, sentry, sexception, sfinally);
else
Statement::scopeCode(sc, sentry, sexception, sfinally);
Statement::scopeCode(sc, sentry, sexception, sfinally);
return this;
}
@@ -1538,6 +1665,10 @@ Statement *ForeachStatement::semantic(Scope *sc)
if (arg->storageClass & STCref)
error("symbol %s cannot be ref", s->toChars());
}
else if (e->op == TOKtype)
{
var = new AliasDeclaration(loc, arg->ident, e->type);
}
else
{
arg->type = e->type;
@@ -2111,11 +2242,7 @@ Lagain:
default: assert(0);
}
const char *r = (op == TOKforeach_reverse) ? "R" : "";
#ifdef __MINGW32__
int j = sprintf(fdname, "_aApply%s%.*s%lu", r, 2, fntab[flag], dim);
#else
int j = sprintf(fdname, "_aApply%s%.*s%zu", r, 2, fntab[flag], dim);
#endif
int j = sprintf(fdname, "_aApply%s%.*s%llu", r, 2, fntab[flag], (ulonglong)dim);
assert(j < sizeof(fdname));
//LDC: Build arguments.
Parameters* args = new Parameters;
@@ -2844,7 +2971,12 @@ Statement *PragmaStatement::semantic(Scope *sc)
Expression *e = (*args)[i];
e = e->semantic(sc);
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op != TOKerror)
e = e->optimize(WANTvalue | WANTinterpret);
if (e->op == TOKerror)
{ errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
goto Lerror;
}
StringExp *se = e->toString();
if (se)
{
@@ -2916,7 +3048,7 @@ Statement *PragmaStatement::semantic(Scope *sc)
#endif
else
error("unrecognized pragma(%s)", ident->toChars());
Lerror:
if (body)
{
body = body->semantic(sc);
@@ -3021,6 +3153,7 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFi
Statement *SwitchStatement::syntaxCopy()
{
//printf("SwitchStatement::syntaxCopy(%p)\n", this);
SwitchStatement *s = new SwitchStatement(loc,
condition->syntaxCopy(), body->syntaxCopy(), isFinal);
return s;
@@ -3029,7 +3162,8 @@ Statement *SwitchStatement::syntaxCopy()
Statement *SwitchStatement::semantic(Scope *sc)
{
//printf("SwitchStatement::semantic(%p)\n", this);
assert(!cases); // ensure semantic() is only run once
if (cases)
return this; // already run
#if IN_LLVM
enclosingScopeExit = sc->enclosingScopeExit;
@@ -3441,7 +3575,7 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s)
{
this->statement = s;
#if IN_GCC
+ cblock = NULL;
cblock = NULL;
#endif
bodyBB = NULL;
// LDC
@@ -3676,9 +3810,8 @@ Statement *ReturnStatement::semantic(Scope *sc)
{
fd->hasReturnExp |= 1;
if (exp->op == TOKfunction && tbret)
((FuncExp *)exp)->setType(tbret);
if (tret)
exp = exp->inferType(tbret);
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
if (!((TypeFunction *)fd->type)->isref)
@@ -4211,6 +4344,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
{
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
if (exp->op == TOKerror)
goto Lbody;
ClassDeclaration *cd = exp->type->isClassHandle();
if (!cd)
error("can only synchronize on class objects, not '%s'", exp->type->toChars());
@@ -4312,6 +4447,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
return s->semantic(sc);
}
#endif
Lbody:
if (body)
{
Statement* oldScopeExit = sc->enclosingScopeExit;
@@ -4416,6 +4552,13 @@ Statement *WithStatement::semantic(Scope *sc)
}
else if (t->ty == Tstruct)
{
if (!exp->isLvalue())
{
init = new ExpInitializer(loc, exp);
wthis = new VarDeclaration(loc, exp->type, Lexer::uniqueId("__withtmp"), init);
exp = new CommaExp(loc, new DeclarationExp(loc, wthis), new VarExp(loc, wthis));
exp = exp->semantic(sc);
}
Expression *e = exp->addressOf(sc);
init = new ExpInitializer(loc, e);
wthis = new VarDeclaration(loc, e->type, Id::withSym, init);
+2
View File
@@ -356,9 +356,11 @@ struct ForStatement : Statement
Expression *condition;
Expression *increment;
Statement *body;
int nest;
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
Statement *syntaxCopy();
Statement *semanticInit(Scope *sc);
Statement *semantic(Scope *sc);
Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
int hasBreak();
+103 -88
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -39,7 +39,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
alignsize = 0; // size of struct for alignment purposes
structalign = 0; // struct member alignment in effect
hasUnions = 0;
sizeok = 0; // size not determined yet
sizeok = SIZEOKnone; // size not determined yet
deferred = NULL;
isdeprecated = false;
inv = NULL;
@@ -129,9 +129,46 @@ unsigned AggregateDeclaration::size(Loc loc)
//printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope);
if (!members)
error(loc, "unknown size");
if (sizeok != 1 && scope)
if (sizeok != SIZEOKdone && scope)
semantic(NULL);
if (sizeok != 1)
StructDeclaration *sd = isStructDeclaration();
if (sizeok != SIZEOKdone && sd && sd->members)
{
/* See if enough is done to determine the size,
* meaning all the fields are done.
*/
struct SV
{
static int func(Dsymbol *s, void *param)
{ SV *psv = (SV *)param;
VarDeclaration *v = s->isVarDeclaration();
if (v)
{
if (v->scope)
v->semantic(NULL);
if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCconst | STCimmutable | STCmanifest | STCctfe | STCtemplateparameter))
return 0;
if (v->storage_class & STCfield && v->sem >= SemanticDone)
return 0;
return 1;
}
return 0;
}
};
SV sv;
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
if (s->apply(&SV::func, &sv))
goto L1;
}
sd->finalizeSize(NULL);
L1: ;
}
if (sizeok != SIZEOKdone)
{ error(loc, "no size yet for forward reference");
//*(char*)0=0;
}
@@ -175,76 +212,38 @@ void AggregateDeclaration::alignmember(
//printf("result = %d\n",offset);
}
void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v)
/****************************************
* Place a member (mem) into an aggregate (agg), which can be a struct, union or class
* Returns:
* offset to place field at
*/
unsigned AggregateDeclaration::placeField(
unsigned *nextoffset, // next location in aggregate
unsigned memsize, // size of member
unsigned memalignsize, // size of member for alignment purposes
unsigned memalign, // alignment in effect for this member
unsigned *paggsize, // size of aggregate (updated)
unsigned *paggalignsize, // size of aggregate for alignment purposes (updated)
bool isunion // the aggregate is a union
)
{
unsigned memsize; // size of member
unsigned memalignsize; // size of member for alignment purposes
unsigned xalign; // alignment boundaries
//printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars());
assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls)));
// Check for forward referenced types which will fail the size() call
Type *t = v->type->toBasetype();
if (v->storage_class & STCref)
{ // References are the size of a pointer
t = Type::tvoidptr;
}
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 = t->size(loc);
memalignsize = t->alignsize();
xalign = t->memalign(sc->structalign);
#if 0
alignmember(xalign, memalignsize, &sc->offset);
v->offset = sc->offset;
sc->offset += memsize;
if (sc->offset > structsize)
structsize = sc->offset;
#else
unsigned ofs = sc->offset;
alignmember(xalign, memalignsize, &ofs);
v->offset = ofs;
unsigned ofs = *nextoffset;
alignmember(memalign, memalignsize, &ofs);
unsigned memoffset = ofs;
ofs += memsize;
if (ofs > structsize)
structsize = ofs;
if (!isUnionDeclaration())
sc->offset = ofs;
#endif
if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16 && isUnionDeclaration())
if (ofs > *paggsize)
*paggsize = ofs;
if (!isunion)
*nextoffset = ofs;
if (global.params.is64bit && memalign == 8 && memalignsize == 16)
/* Not sure how to handle this */
;
else if (sc->structalign < memalignsize)
memalignsize = sc->structalign;
if (alignsize < memalignsize)
alignsize = memalignsize;
//printf("\t%s: alignsize = %d\n", toChars(), alignsize);
else if (memalign < memalignsize)
memalignsize = memalign;
if (*paggalignsize < memalignsize)
*paggalignsize = memalignsize;
v->storage_class |= STCfield;
//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize);
fields.push(v);
return memoffset;
}
@@ -363,7 +362,7 @@ void StructDeclaration::semantic(Scope *sc)
return;
if (symtab)
{ if (sizeok == 1 || !scope)
{ if (sizeok == SIZEOKdone || !scope)
{ //printf("already completed\n");
scope = NULL;
return; // semantic() already completed
@@ -398,16 +397,8 @@ void StructDeclaration::semantic(Scope *sc)
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
#if DMDV2
if (storage_class & STCimmutable)
type = type->addMod(MODimmutable);
if (storage_class & STCconst)
type = type->addMod(MODconst);
if (storage_class & STCshared)
type = type->addMod(MODshared);
#endif
if (sizeok == 0) // if not already done the addMember step
if (sizeok == SIZEOKnone) // if not already done the addMember step
{
int hasfunctions = 0;
for (size_t i = 0; i < members->dim; i++)
@@ -453,7 +444,7 @@ void StructDeclaration::semantic(Scope *sc)
}
}
sizeok = 0;
sizeok = SIZEOKnone;
sc2 = sc->push(this);
sc2->stc &= STCsafe | STCtrusted | STCsystem;
sc2->parent = this;
@@ -472,7 +463,7 @@ void StructDeclaration::semantic(Scope *sc)
/* There are problems doing this in the general case because
* Scope keeps track of things like 'offset'
*/
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
//if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
{
//printf("setScope %s %s\n", s->kind(), s->toChars());
s->setScope(sc2);
@@ -490,15 +481,27 @@ void StructDeclaration::semantic(Scope *sc)
*/
if (i + 1 == members_dim)
{
if (sizeok == 0 && s->isAliasDeclaration())
finalizeSize();
if (sizeok == SIZEOKnone && s->isAliasDeclaration())
finalizeSize(sc2);
}
// Ungag errors when not speculative
unsigned oldgag = global.gag;
if (global.isSpeculativeGagging() && !isSpeculative())
global.gag = 0;
s->semantic(sc2);
global.gag = oldgag;
}
finalizeSize(sc2);
if (sizeok == 2)
if (sizeok == SIZEOKfwd)
{ // semantic() failed because of forward references.
// Unwind what we did, and defer it for later
for (size_t i = 0; i < fields.dim; i++)
{ Dsymbol *s = fields[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd)
vd->offset = 0;
}
fields.setDim(0);
structsize = 0;
alignsize = 0;
@@ -513,7 +516,6 @@ void StructDeclaration::semantic(Scope *sc)
return;
}
finalizeSize();
Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
@@ -522,7 +524,7 @@ void StructDeclaration::semantic(Scope *sc)
zeroInit = 1;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
Dsymbol *s = fields[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd && !vd->isDataseg())
{
@@ -661,8 +663,21 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
return ScopeDsymbol::search(loc, ident, flags);
}
void StructDeclaration::finalizeSize()
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)
{
@@ -675,7 +690,7 @@ void StructDeclaration::finalizeSize()
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
sizeok = SIZEOKdone;
}
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+322 -184
View File
@@ -201,7 +201,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
{
if (sc1->scopesym == ti1)
{
error("recursive template expansion for template argument %s", t1->toChars());
tempdecl->error("recursive template expansion for template argument %s", t1->toChars());
return 1; // fake a match
}
}
@@ -379,7 +379,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
this->members = decldefs;
this->overnext = NULL;
this->overroot = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->onemember = NULL;
this->literal = 0;
this->ismixin = ismixin;
@@ -435,7 +435,7 @@ void TemplateDeclaration::semantic(Scope *sc)
#endif
if (semanticRun)
return; // semantic() already run
semanticRun = 1;
semanticRun = PASSsemantic;
if (sc->module && sc->module->ident == Id::object && ident == Id::AssociativeArray)
{ Type::associativearray = this;
@@ -496,7 +496,7 @@ void TemplateDeclaration::semantic(Scope *sc)
origParameters->setDim(parameters->dim);
for (size_t i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = parameters->tdata()[i];
TemplateParameter *tp = (*parameters)[i];
origParameters->tdata()[i] = tp->syntaxCopy();
}
}
@@ -510,11 +510,13 @@ void TemplateDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = parameters->tdata()[i];
TemplateParameter *tp = (*parameters)[i];
tp->semantic(paramscope);
if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
error("template tuple parameter must be last one");
{ error("template tuple parameter must be last one");
errors = true;
}
}
paramscope->pop();
@@ -688,6 +690,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
#endif
dedtypes->zero();
if (errors)
return MATCHnomatch;
size_t parameters_dim = parameters->dim;
int variadic = isVariadic() != NULL;
@@ -968,6 +973,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
dedtypes.setDim(parameters->dim);
dedtypes.zero();
if (errors)
return MATCHnomatch;
// Set up scope for parameters
ScopeDsymbol *paramsym = new ScopeDsymbol();
paramsym->parent = scope->parent;
@@ -1108,6 +1116,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
t->objects.setDim(tuple_dim);
for (size_t i = 0; i < tuple_dim; i++)
{ Expression *farg = fargs->tdata()[fptupindex + i];
// Check invalid arguments to detect errors early.
if (farg->op == TOKerror || farg->type->ty == Terror)
goto Lnomatch;
if (!(fparam->storageClass & STClazy) && farg->type->ty == Tvoid)
goto Lnomatch;
unsigned mod = farg->type->mod;
Type *tt;
MATCH m;
@@ -1384,6 +1400,11 @@ L2:
else
{
Expression *farg = fargs->tdata()[i];
// Check invalid arguments to detect errors early.
if (farg->op == TOKerror || farg->type->ty == Terror)
goto Lnomatch;
Lretry:
#if 0
printf("\tfarg->type = %s\n", farg->type->toChars());
@@ -1413,22 +1434,16 @@ Lretry:
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = fparam->type;
if (tp->ty == Tdelegate &&
fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved)
{ Type *tdg = new TypeDelegate(fe->type->nextOf());
tdg = tdg->semantic(loc, sc);
farg = fe->inferType(sc, tdg);
}
else if (fe->type == Type::tvoid)
{
farg = fe->inferType(sc, tp);
if (!farg)
goto Lvarargs;
}
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) &&
@@ -1443,12 +1458,11 @@ Lretry:
if (fvarargs == 2 && i + 1 == nfparams && i + 1 < nfargs)
goto Lvarargs;
MATCH m;
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes,
tf->hasWild() ? &wildmatch : NULL);
unsigned wm = 0;
MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, &wm);
//printf("\tdeduceType m = %d\n", m);
//if (tf->hasWild())
// printf("\twildmatch = x%x m = %d\n", wildmatch, m);
//printf("\twildmatch = x%x m = %d\n", wildmatch, m);
wildmatch |= wm;
/* If no match, see if there's a conversion to a delegate
*/
@@ -1483,9 +1497,7 @@ Lretry:
* eg purity(bug 7295), just regard it as not a match.
*/
unsigned olderrors = global.startGagging();
Expression *e = new DotIdExp(farg->loc, farg, ad->aliasthis->ident);
e = e->semantic(sc);
e = resolveProperties(sc, e);
Expression *e = resolveAliasThis(sc, farg);
if (!global.endGagging(olderrors))
{ farg = e;
goto Lretry;
@@ -1542,19 +1554,11 @@ Lretry:
if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
Type *tp = tb->nextOf();
if (tp->ty == Tdelegate &&
fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved)
{ tp = new TypeDelegate(fe->type->nextOf());
tp = tp->semantic(loc, sc);
arg = fe->inferType(sc, tp);
}
else if (arg->type == Type::tvoid)
{
arg = fe->inferType(sc, tp);
if (!arg)
goto Lnomatch;
}
Expression *e = fe->inferType(tp, 1, parameters);
if (!e)
goto Lnomatch;
arg = e;
}
MATCH m;
@@ -1897,11 +1901,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
goto Lerror;
}
MATCH m;
Objects dedargs;
FuncDeclaration *fd = NULL;
m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs);
MATCH m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs);
//printf("deduceFunctionTemplateMatch = %d\n", m);
if (!m) // if no match
continue;
@@ -1930,9 +1933,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
goto Lerror;
}
{
tdargs->setDim(dedargs.dim);
memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
fd = td->doHeaderInstantiation(sc, tdargs, fargs);
fd = td->doHeaderInstantiation(sc, &dedargs, fargs);
if (!fd)
goto Lerror;
}
@@ -1985,13 +1986,14 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
if (!td_best)
{
if (!(flags & 1))
error(loc, "does not match any function template declaration");
::error(loc, "%s %s.%s does not match any function template declaration",
kind(), parent->toPrettyChars(), ident->toChars());
goto Lerror;
}
if (td_ambig)
{
error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
kind(), parent->toPrettyChars(), ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
}
@@ -2005,6 +2007,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
fd_best = ti->toAlias()->isFuncDeclaration();
if (!fd_best || !((TypeFunction*)fd_best->type)->callMatch(ethis, fargs, flags))
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_best->type;
assert(tf->ty == Tfunction);
if (tf->next)
fd_best->type = tf->semantic(loc, sc);
}
return fd_best;
Lerror:
@@ -2028,8 +2040,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
OutBuffer buf;
argExpTypesToCBuffer(&buf, fargs, &hgs);
error(loc, "cannot deduce template function from argument types !(%s)(%s)",
bufa.toChars(), buf.toChars());
if (this->overnext)
::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)",
kind(), parent->toPrettyChars(), ident->toChars(),
bufa.toChars(), buf.toChars());
else
error("cannot deduce template function from argument types !(%s)(%s)",
bufa.toChars(), buf.toChars());
}
return NULL;
}
@@ -2225,7 +2242,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
* Foo!(int*) // template instantiation
* Input:
* this = int*
* tparam = T
* tparam = T*
* parameters = [ T:T* ] // Array of TemplateParameter's
* Output:
* dedtypes = [ int ] // Array of Expression/Type's
@@ -2287,13 +2304,17 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
{
switch (X(tparam->mod, mod))
{
case X(MODwild, MODwild):
case X(MODwild | MODshared, MODwild | MODshared):
case X(MODwild, 0):
case X(MODwild, MODshared):
case X(MODwild, MODconst):
case X(MODwild, MODconst | MODshared):
case X(MODwild, MODimmutable):
case X(MODwild, MODwild):
case X(MODwild, MODwild | MODshared):
case X(MODwild | MODshared, MODshared):
case X(MODwild | MODshared, MODconst | MODshared):
case X(MODwild | MODshared, MODimmutable):
case X(MODwild | MODshared, MODwild | MODshared):
if (!at)
{
@@ -2407,11 +2428,18 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
}
break;
case X(MODconst, MODshared):
// foo(U:const(U)) shared(T) => shared(T)
if (!at)
{ (*dedtypes)[i] = tt;
goto Lconst;
}
break;
case X(MODimmutable, 0):
case X(MODimmutable, MODconst):
case X(MODimmutable, MODshared):
case X(MODimmutable, MODconst | MODshared):
case X(MODconst, MODshared):
case X(MODshared, 0):
case X(MODshared, MODconst):
case X(MODshared, MODimmutable):
@@ -2534,6 +2562,23 @@ Lconst:
#endif
}
#if DMDV2
MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("TypeVector::deduceType()\n");
printf("\tthis = %d, ", ty); print();
printf("\ttparam = %d, ", tparam->ty); tparam->print();
#endif
if (tparam->ty == Tvector)
{ TypeVector *tp = (TypeVector *)tparam;
return basetype->deduceType(sc, tp->basetype, parameters, dedtypes, wildmatch);
}
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
#endif
#if DMDV2
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes, unsigned *wildmatch)
@@ -3825,7 +3870,16 @@ void TemplateValueParameter::declareParameter(Scope *sc)
void TemplateValueParameter::semantic(Scope *sc)
{
bool wasSame = (sparam->type == valType);
sparam->semantic(sc);
if (sparam->type == Type::terror && wasSame)
{ /* If sparam has a type error, avoid duplicate errors
* The simple solution of leaving that function if sparam->type == Type::terror
* doesn't quite work because it causes failures in xtest46 for bug 6295
*/
valType = Type::terror;
return;
}
valType = valType->semantic(loc, sc);
if (!(valType->isintegral() || valType->isfloating() || valType->isString()) &&
valType->ty != Tident)
@@ -3834,6 +3888,7 @@ void TemplateValueParameter::semantic(Scope *sc)
error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars());
}
#if 0 // defer semantic analysis to arg match
if (specValue)
{ Expression *e = specValue;
@@ -3846,7 +3901,6 @@ void TemplateValueParameter::semantic(Scope *sc)
//e->toInteger();
}
#if 0 // defer semantic analysis to arg match
if (defaultValue)
{ Expression *e = defaultValue;
@@ -3883,8 +3937,8 @@ Lnomatch:
}
MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
MATCH TemplateValueParameter::matchArg(Scope *sc,
Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
{
//printf("TemplateValueParameter::matchArg()\n");
@@ -3941,7 +3995,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs,
Expression *e = specValue;
e = e->semantic(sc);
e = e->implicitCastTo(sc, valType);
e = e->implicitCastTo(sc, vt);
e = e->optimize(WANTvalue | WANTinterpret);
ei = ei->syntaxCopy();
@@ -4199,13 +4253,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->semantictiargsdone = 0;
this->withsym = NULL;
this->nest = 0;
this->havetempdecl = 0;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
this->ignore = true;
@@ -4234,13 +4287,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->tinst = NULL;
this->argsym = NULL;
this->aliasdecl = NULL;
this->semanticRun = 0;
this->semanticRun = PASSinit;
this->semantictiargsdone = 1;
this->withsym = NULL;
this->nest = 0;
this->havetempdecl = 1;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
this->ignore = true;
@@ -4289,23 +4341,96 @@ void TemplateInstance::semantic(Scope *sc)
semantic(sc, NULL);
}
void TemplateInstance::expandMembers(Scope *sc2)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setScope(sc2);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
//printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
//printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
// if (isnested)
// s->parent = sc->parent;
//printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
s->semantic(sc2);
//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
sc2->module->runDeferredSemantic();
}
}
void TemplateInstance::tryExpandMembers(Scope *sc2)
{
static int nest;
// extracted to a function to allow windows SEH to work without destructors in the same function
//printf("%d\n", nest);
if (++nest > 500)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
#if WINDOWS_SEH
if(nest == 1)
{
// do not catch at every nesting level, because generating the output error might cause more stack
// errors in the __except block otherwise
__try
{
expandMembers(sc2);
}
__except (__ehfilter(GetExceptionInformation()))
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
}
else
#endif
expandMembers(sc2);
nest--;
}
void TemplateInstance::trySemantic3(Scope *sc2)
{
// extracted to a function to allow windows SEH to work without destructors in the same function
static int nest;
if (++nest > 300)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
#if WINDOWS_SEH
if(nest == 1)
{
// do not catch at every nesting level, because generating the output error might cause more stack
// errors in the __except block otherwise
__try
{
semantic3(sc2);
}
__except (__ehfilter(GetExceptionInformation()))
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
}
else
#endif
semantic3(sc2);
--nest;
}
void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
{
//printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc);
if (global.errors && name != Id::AssociativeArray)
{
//printf("not instantiating %s due to %d errors\n", toChars(), global.errors);
if (!global.gag)
{
/* Trying to soldier on rarely generates useful messages
* at this point.
*/
fatal();
}
// return;
}
if (!sc->ignoreTemplates)
ignore = false;
#if LOG
printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this);
#endif
@@ -4316,11 +4441,15 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
#endif
return;
}
if (!sc->ignoreTemplates)
ignore = false;
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
if (semanticRun != 0)
if (semanticRun != PASSinit)
{
#if LOG
printf("Recursive template expansion\n");
@@ -4329,7 +4458,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// inst = this;
return;
}
semanticRun = 1;
semanticRun = PASSsemantic;
#if IN_LLVM
// get the enclosing template instance from the scope tinst
tinst = sc->tinst;
@@ -4368,11 +4497,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
//printf("error return %p, %d\n", tempdecl, global.errors);
return; // error recovery
}
unsigned errs = global.errors;
tempdecl = findTemplateDeclaration(sc);
if (tempdecl)
tempdecl = findBestMatch(sc, fargs);
if (!tempdecl || global.errors)
if (!tempdecl || (errs != global.errors))
{ inst = this;
//printf("error return %p, %d\n", tempdecl, global.errors);
return; // error recovery
@@ -4403,10 +4532,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
//printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : "");
continue;
}
#if 0
if (isnested && sc->parent != ti->parent)
continue;
#endif
//printf("parent = %s, ti->parent = %s\n", tempdecl->parent->toPrettyChars(), ti->parent->toPrettyChars());
if (!arrayObjectMatch(&tdtypes, &ti->tdtypes, tempdecl, sc))
goto L1;
@@ -4463,7 +4590,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
}
#if LOG
printf("\tit's a match with instance %p\n", inst);
printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun);
#endif
return;
@@ -4480,7 +4607,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
unsigned errorsave = global.errors;
inst = this;
// Mark as speculative if we are instantiated from inside is(typeof())
if (global.gag && sc->intypeof)
if (global.gag && sc->speculative)
speculative = 1;
int tempdecl_instance_idx = tempdecl->instances.dim;
@@ -4651,46 +4778,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
sc2->parent = /*isnested ? sc->parent :*/ this;
sc2->tinst = this;
#if WINDOWS_SEH
__try
{
#endif
static int nest;
//printf("%d\n", nest);
if (++nest > 500)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
tryExpandMembers(sc2);
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setScope(sc2);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
//printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars());
//printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars());
// if (isnested)
// s->parent = sc->parent;
//printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
s->semantic(sc2);
//printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars());
sc2->module->runDeferredSemantic();
}
--nest;
#if WINDOWS_SEH
}
__except (__ehfilter(GetExceptionInformation()))
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
#endif
semanticRun = PASSsemanticdone;
/* If any of the instantiation members didn't get semantic() run
* on them due to forward references, we cannot run semantic2()
@@ -4744,28 +4834,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
if (sc->func || dosemantic3)
{
#if WINDOWS_SEH
__try
{
#endif
static int nest;
if (++nest > 300)
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
semantic3(sc2);
--nest;
#if WINDOWS_SEH
}
__except (__ehfilter(GetExceptionInformation()))
{
global.gag = 0; // ensure error message gets printed
error("recursive expansion");
fatal();
}
#endif
trySemantic3(sc2);
}
Laftersemantic:
@@ -4795,7 +4864,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
target_symbol_list->remove(target_symbol_list_idx);
}
semanticRun = 0;
semanticRun = PASSinit;
inst = NULL;
}
}
@@ -5172,13 +5241,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far
// Only one template, so we can give better error message
error("%s does not match template declaration %s", toChars(), tempdecl->toChars());
else
error("%s does not match any template declaration", toChars());
::error(loc, "%s %s.%s does not match any template declaration",
tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars());
return NULL;
}
if (td_ambig)
{
error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
toChars(),
::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s",
td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(),
td_best->loc.filename, td_best->loc.linnum, td_best->toChars(),
td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars());
}
@@ -5237,6 +5307,11 @@ int TemplateInstance::hasNestedArgs(Objects *args)
sa = ((VarExp *)ea)->var;
goto Lsa;
}
if (ea->op == TOKthis)
{
sa = ((ThisExp *)ea)->var;
goto Lsa;
}
if (ea->op == TOKfunction)
{
sa = ((FuncExp *)ea)->fd;
@@ -5309,7 +5384,7 @@ Identifier *TemplateInstance::genIdent(Objects *args)
//printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
char *id = tempdecl->ident->toChars();
buf.printf("__T%zu%s", strlen(id), id);
buf.printf("__T%llu%s", (ulonglong)strlen(id), id);
for (size_t i = 0; i < args->dim; i++)
{ Object *o = args->tdata()[i];
Type *ta = isType(o);
@@ -5325,7 +5400,8 @@ Identifier *TemplateInstance::genIdent(Objects *args)
else
{
#ifdef DEBUG
printf("ta = %d, %s\n", ta->ty, ta->toChars());
if (!global.errors)
printf("ta = %d, %s\n", ta->ty, ta->toChars());
#endif
assert(global.errors);
}
@@ -5358,8 +5434,9 @@ Identifier *TemplateInstance::genIdent(Objects *args)
continue;
}
// Now that we know it is not an alias, we MUST obtain a value
unsigned olderr = global.errors;
ea = ea->optimize(WANTvalue | WANTinterpret);
if (ea->op == TOKerror)
if (ea->op == TOKerror || olderr != global.errors)
continue;
#if 1
/* Use deco that matches what it would be for a function parameter
@@ -5404,7 +5481,7 @@ Identifier *TemplateInstance::genIdent(Objects *args)
* Unfortunately, fixing this ambiguity will break existing binary
* compatibility and the demanglers, so we'll leave it as is.
*/
buf.printf("%zu%s", strlen(p), p);
buf.printf("%llu%s", (ulonglong)strlen(p), p);
}
else if (va)
{
@@ -5477,12 +5554,33 @@ int TemplateInstance::needsTypeInference(Scope *sc)
/* Determine if the instance arguments, tiargs, are all that is necessary
* to instantiate the template.
*/
TemplateTupleParameter *tp = td->isVariadic();
//printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim);
TypeFunction *fdtype = (TypeFunction *)fd->type;
if (Parameter::dim(fdtype->parameters) &&
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim))
return TRUE;
if (Parameter::dim(fdtype->parameters))
{
TemplateParameter *tp = td->isVariadic();
if (tp && td->parameters->dim > 1)
return TRUE;
if (tiargs->dim < td->parameters->dim)
{ // Can remain tiargs be filled by default arguments?
for (size_t i = tiargs->dim; i < td->parameters->dim; i++)
{ tp = (*td->parameters)[i];
if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter())
{ if (!ttp->defaultType)
return TRUE;
}
else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter())
{ if (!tap->defaultAlias)
return TRUE;
}
else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter())
{ if (!tvp->defaultValue)
return TRUE;
}
}
}
}
/* If there is more than one function template which matches, we may
* need type inference (see Bugzilla 4430)
*/
@@ -5496,9 +5594,9 @@ int TemplateInstance::needsTypeInference(Scope *sc)
void TemplateInstance::semantic2(Scope *sc)
{ int i;
if (semanticRun >= 2)
if (semanticRun >= PASSsemantic2)
return;
semanticRun = 2;
semanticRun = PASSsemantic2;
#if LOG
printf("+TemplateInstance::semantic2('%s')\n", toChars());
#endif
@@ -5531,9 +5629,9 @@ void TemplateInstance::semantic3(Scope *sc)
printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
#endif
//if (toChars()[0] == 'D') *(char*)0=0;
if (semanticRun >= 3)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = 3;
semanticRun = PASSsemantic3;
if (!errors && members)
{
sc = tempdecl->scope;
@@ -5702,7 +5800,7 @@ void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (i)
buf->writeByte(',');
Object *oarg = args->tdata()[i];
Object *oarg = (*args)[i];
ObjectToCBuffer(buf, hgs, oarg);
}
nest--;
@@ -5717,9 +5815,24 @@ Dsymbol *TemplateInstance::toAlias()
printf("TemplateInstance::toAlias()\n");
#endif
if (!inst)
{ error("cannot resolve forward reference");
errors = 1;
return this;
{
// Maybe we can resolve it
if (scope)
{
/* Anything that affects scope->offset must be
* done in lexical order. Fwd ref error if it is affected, otherwise allow.
*/
unsigned offset = scope->offset;
Scope *sc = scope;
semantic(scope);
// if (offset != sc->offset)
// inst = NULL; // trigger fwd ref error
}
if (!inst)
{ error("cannot resolve forward reference");
errors = 1;
return this;
}
}
if (inst != this)
@@ -5851,7 +5964,7 @@ void TemplateMixin::semantic(Scope *sc)
// This for when a class/struct contains mixin members, and
// is done over because of forward references
if (parent && toParent()->isAggregateDeclaration())
semanticRun = 1; // do over
semanticRun = PASSsemantic; // do over
else
{
#if LOG
@@ -5861,12 +5974,12 @@ void TemplateMixin::semantic(Scope *sc)
}
}
if (!semanticRun)
semanticRun = 1;
semanticRun = PASSsemantic;
#if LOG
printf("\tdo semantic\n");
#endif
#if !IN_LLVM
#if !IN_LLVM && !IN_GCC
// dont know what this is
util_progress();
#endif
@@ -5944,10 +6057,10 @@ void TemplateMixin::semantic(Scope *sc)
* runDeferred will re-run mixin's semantic outside of the struct's
* semantic.
*/
semanticRun = 0;
semanticRun = PASSinit;
AggregateDeclaration *ad = toParent()->isAggregateDeclaration();
if (ad)
ad->sizeok = 2;
ad->sizeok = SIZEOKfwd;
else
{
// Forward reference
@@ -5992,11 +6105,11 @@ void TemplateMixin::semantic(Scope *sc)
continue;
for (size_t i = 0; i < tiargs->dim; i++)
{ Object *o = tiargs->tdata()[i];
{ Object *o = (*tiargs)[i];
Type *ta = isType(o);
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
Object *tmo = tm->tiargs->tdata()[i];
Object *tmo = (*tm->tiargs)[i];
if (ta)
{
Type *tmta = isType(tmo);
@@ -6060,10 +6173,8 @@ void TemplateMixin::semantic(Scope *sc)
declareParameters(argscope);
// Add members to enclosing scope, as well as this scope
for (unsigned i = 0; i < members->dim; i++)
{ Dsymbol *s;
s = members->tdata()[i];
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->addMember(argscope, this, i);
//sc->insert(s);
//printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym);
@@ -6089,7 +6200,7 @@ void TemplateMixin::semantic(Scope *sc)
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
s->semantic(sc2);
}
@@ -6131,9 +6242,9 @@ void TemplateMixin::semantic(Scope *sc)
void TemplateMixin::semantic2(Scope *sc)
{
if (semanticRun >= 2)
if (semanticRun >= PASSsemantic2)
return;
semanticRun = 2;
semanticRun = PASSsemantic2;
#if LOG
printf("+TemplateMixin::semantic2('%s')\n", toChars());
#endif
@@ -6144,7 +6255,7 @@ void TemplateMixin::semantic2(Scope *sc)
sc = sc->push(this);
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
Dsymbol *s = (*members)[i];
#if LOG
printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind());
#endif
@@ -6160,9 +6271,9 @@ void TemplateMixin::semantic2(Scope *sc)
void TemplateMixin::semantic3(Scope *sc)
{
if (semanticRun >= 3)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = 3;
semanticRun = PASSsemantic3;
#if LOG
printf("TemplateMixin::semantic3('%s')\n", toChars());
#endif
@@ -6195,6 +6306,22 @@ int TemplateMixin::oneMember(Dsymbol **ps, Identifier *ident)
return Dsymbol::oneMember(ps, ident);
}
int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param)
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
if (s)
{
if (s->apply(fp, param))
return 1;
}
}
}
return 0;
}
int TemplateMixin::hasPointers()
{
//printf("TemplateMixin::hasPointers() %s\n", toChars());
@@ -6212,6 +6339,17 @@ int TemplateMixin::hasPointers()
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);
}
}
}
char *TemplateMixin::toChars()
{
OutBuffer buf;
+9 -6
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -41,6 +41,7 @@ struct AliasDeclaration;
struct FuncDeclaration;
struct HdrGenState;
enum MATCH;
enum PASS;
struct Tuple : Object
{
@@ -61,7 +62,7 @@ struct TemplateDeclaration : ScopeDsymbol
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
TemplateDeclaration *overroot; // first in overnext list
int semanticRun; // 1 semantic() run
enum PASS semanticRun; // 1 semantic() run
Dsymbol *onemember; // if !=NULL then one member of this template
@@ -190,8 +191,6 @@ struct TemplateThisParameter : TemplateTypeParameter
/* Syntax:
* this ident : specType = defaultType
*/
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
@@ -299,12 +298,11 @@ struct TemplateInstance : ScopeDsymbol
AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its
// sole member
WithScopeSymbol *withsym; // if a member of a with statement
int semanticRun; // has semantic() been done?
enum PASS semanticRun; // has semantic() been done?
int semantictiargsdone; // has semanticTiargs() been done?
int nest; // for recursion detection
int havetempdecl; // 1 if used second constructor
Dsymbol *isnested; // if referencing local symbols, this is the context
int errors; // 1 if compiled with errors
int speculative; // 1 if only instantiated with errors gagged
bool ignore; // true if the instance must be ignored when codegen'ing
#ifdef IN_GCC
@@ -344,6 +342,9 @@ struct TemplateInstance : ScopeDsymbol
void declareParameters(Scope *sc);
int hasNestedArgs(Objects *tiargs);
Identifier *genIdent(Objects *args);
void expandMembers(Scope *sc);
void tryExpandMembers(Scope *sc);
void trySemantic3(Scope *sc2);
TemplateInstance *isTemplateInstance() { return this; }
AliasDeclaration *isAliasDeclaration();
@@ -369,7 +370,9 @@ struct TemplateMixin : TemplateInstance
void inlineScan();
const char *kind();
int oneMember(Dsymbol **ps, Identifier *ident);
int apply(Dsymbol_apply_ft_t fp, void *param);
int hasPointers();
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
char *toChars();
char *mangle();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+8 -2
View File
@@ -64,10 +64,10 @@ static int fptraits(void *param, FuncDeclaration *f)
if (p->e1->op == TOKdotvar)
{ DotVarExp *dve = (DotVarExp *)p->e1;
e = new DotVarExp(0, dve->e1, f);
e = new DotVarExp(0, dve->e1, new FuncAliasDeclaration(f, 0));
}
else
e = new DsymbolExp(0, f);
e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0));
p->exps->push(e);
return 0;
}
@@ -451,6 +451,10 @@ Expression *TraitsExp::semantic(Scope *sc)
Expression *e;
unsigned errors = global.startGagging();
unsigned oldspec = global.speculativeGag;
global.speculativeGag = global.gag;
bool scSpec = sc->speculative;
sc->speculative = true;
Type *t = isType(o);
if (t)
@@ -471,6 +475,8 @@ Expression *TraitsExp::semantic(Scope *sc)
}
}
sc->speculative = scSpec;
global.speculativeGag = oldspec;
if (global.endGagging(errors))
{
goto Lfalse;
+1
View File
@@ -0,0 +1 @@
#include <malloc.h>
+13
View File
@@ -0,0 +1,13 @@
@echo off
rem Run this batch file from the src folder like this:
rem vcbuild\builddmd.bat
rem
rem Make sure that you do not have cl.exe from the dmc compiler
rem in your path!
rem
rem "make" should be the Digital Mars make, this can be found
rem if dmd's bin folder is in the path
set DEBUG=/Zi
if "%1" == "release" set DEBUG=/O2
make -f win32.mak CC=vcbuild\dmc_cl INCLUDE=vcbuild DEBUG=%DEBUG% dmd.exe
+44
View File
@@ -0,0 +1,44 @@
@echo off
rem echo called with: %*
set def=/DLITTLE_ENDIAN=1 /D__pascal= /D_M_I86=1
rem copt defaults to linker options
set copt=/nologo /link /LARGEADDRESSAWARE
set cmd=
:next
if "%1" == "" goto done
rem echo %1
set opt=%1
if "%opt:~0,1%" == "-" goto opt
if "%opt:~0,1%" == "/" goto opt
if "%opt:~-2%" == ".c" goto isC
if "%opt:~-4%" == ".obj" goto add
set opt=%opt%.c
:isC
set copt=/TP /Ivcbuild /Iroot /nologo /EHsc /Zp1 %def%
goto add
:opt
if "%opt:~0,2%" == "-o" (
if "%opt:~-4%" == ".exe" set opt=/Fe%opt:~2%
if "%opt:~-4%" == ".obj" set opt=/Fo%opt:~2%
)
if "%opt%" == "-e" goto shift
if "%opt%" == "-Ae" goto shift
if "%opt%" == "-Ar" goto shift
if "%opt%" == "-mn" goto shift
if "%opt%" == "-cpp" goto shift
if "%opt%" == "-wx" goto shift
if "%opt%" == "-m32" goto shift
:add
set cmd=%cmd% %opt%
:shift
shift
goto next
:done
rem echo cl %copt% %cmd%
cl %cmd% %copt%
+5
View File
@@ -0,0 +1,5 @@
#include <float.h>
#define isnan _isnan
+336
View File
@@ -0,0 +1,336 @@
;; 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
;.386
;.model flat, c
; Custom Build Step, including a listing file placed in intermediate directory
; debug:
; ml -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; release:
; ml -c "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; outputs:
; $(IntDir)\$(InputName).obj
.data
twoPow63 dd 0, 80000000h, 03fffh + 63
.code
; double ld_read(longdouble* ld);
; rcx: ld
ld_read PROC
fld tbyte ptr [rcx]
push rax
fstp qword ptr [esp]
movq xmm0,qword ptr [rsp]
pop rax
ret
ld_read ENDP
; long long ld_readll(longdouble* ld);
; rcx: ld
ld_readll PROC
fld tbyte ptr [rcx]
push rax
fistp qword ptr [esp]
pop rax
ret
ld_readll ENDP
; unsigned long long ld_readull(longdouble* ld);
; rcx: ld
ld_readull PROC
fld tbyte ptr [rcx]
push rax
lea rax,twoPow63
fld tbyte ptr [rax]
fsubp ST(1),ST(0) ; move it into signed range
fistp qword ptr [esp]
pop rax
btc rax,63
ret
ld_readull ENDP
; void ld_set(longdouble* ld, double d);
; rcx: ld
; xmm1: d
ld_set PROC
push rax
movq qword ptr [rsp],xmm1
fld qword ptr [rsp]
fstp tbyte ptr [rcx]
pop rax
ret
ld_set ENDP
; void ld_setll(longdouble* ld, long long d);
; rcx: ld
; rdx: d
ld_setll PROC
push rdx
fild qword ptr [esp]
fstp tbyte ptr [rcx]
pop rax
ret
ld_setll ENDP
; void ld_setull(longdouble* ld, long long d);
; rcx: ld
; rax: d
ld_setull PROC
btc rdx,63
push rdx
fild qword ptr [esp]
lea rax,twoPow63
fld tbyte ptr [rax]
faddp ST(1),ST(0)
fstp tbyte ptr [rcx]
pop rax
ret
ld_setull ENDP
; void ld_expl(longdouble* ld, int exp);
; rcx: ld
; edx: exp
ld_expl PROC
push rdx
fild dword ptr [esp]
fld tbyte ptr [rcx]
fscale ; ST(0) = ST(0) * (2**ST(1))
fstp ST(1)
fstp tbyte ptr [rcx]
pop rax
ret
ld_expl ENDP
; long_double ld_add(long_double ld1, long_double ld2);
; rcx: &res
; rdx: &ld1
; r8: &ld2
ld_add PROC
fld tbyte ptr [r8]
fld tbyte ptr [rdx]
fadd
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_add ENDP
; long_double ld_sub(long_double ld1, long_double ld2);
; rcx: &res
; rdx: &ld1
; r8: &ld2
ld_sub PROC
fld tbyte ptr [rdx]
fld tbyte ptr [r8]
fsub
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_sub ENDP
; long_double ld_mul(long_double ld1, long_double ld2);
; rcx: &res
; rdx: &ld1
; r8: &ld2
ld_mul PROC
fld tbyte ptr [r8]
fld tbyte ptr [rdx]
fmul
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_mul ENDP
; long_double ld_div(long_double ld1, long_double ld2);
; rcx: &res
; rdx: &ld1
; r8: &ld2
ld_div PROC
fld tbyte ptr [rdx]
fld tbyte ptr [r8]
fdiv
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_div ENDP
; long_double ld_mod(long_double ld1, long_double ld2);
; rcx: &res
; rdx: &ld1
; r8: &ld2
ld_mod PROC
push rax
fld tbyte ptr [r8]
fld tbyte ptr [rdx] ; 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 [rsp]
fwait
mov AH,byte ptr [rsp+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 [ecx]
pop rax
mov rax,rcx
ret
ld_mod ENDP
; bool ld_cmpb(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpb PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
setb AL
setnp AH
and AL,AH
fstp ST(0)
ret
ld_cmpb ENDP
; bool ld_cmpbe(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpbe PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
setbe AL
setnp AH
and AL,AH
fstp ST(0)
ret
ld_cmpbe ENDP
; bool ld_cmpa(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpa PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
seta AL
setnp AH
and AL,AH
fstp ST(0)
ret
ld_cmpa ENDP
; bool ld_cmpae(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpae PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
setae AL
setnp AH
and AL,AH
fstp ST(0)
ret
ld_cmpae ENDP
; bool ld_cmpe(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpe PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
sete AL
setnp AH
and AL,AH
fstp ST(0)
ret
ld_cmpe ENDP
; bool ld_cmpne(long_double x, long_double y);
; rcx: &x
; rdx: &y
ld_cmpne PROC
fld tbyte ptr [rdx]
fld tbyte ptr [rcx]
fucomip ST(0),ST(1)
setne AL
setp AH
or AL,AH
fstp ST(0)
ret
ld_cmpne ENDP
; long_double ld_sqrt(long_double x);
; rcx: &res
; rdx: &x
ld_sqrt PROC
fld tbyte ptr [rdx]
fsqrt
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_sqrt ENDP
; long_double ld_sin(long_double x);
; rcx: &res
; rdx: &x
ld_sin PROC
fld tbyte ptr [rdx]
fsin
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_sin ENDP
; long_double ld_cos(long_double x);
; rcx: &res
; rdx: &x
ld_cos PROC
fld tbyte ptr [rdx]
fcos
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_cos ENDP
; long_double ld_tan(long_double x);
; rcx: &res
; rdx: &x
ld_tan PROC
fld tbyte ptr [rdx]
fptan
fstp st(0)
fstp tbyte ptr [rcx]
mov rax,rcx
ret
ld_tan ENDP
; int ld_initfpu(int bits, int mask)
; ecx: bits
; edx: mask
ld_initfpu PROC
push rcx
fstcw word ptr [rsp]
movzx EAX,word ptr [rsp] ; also return old CW in EAX
not EDX
and EDX,EAX
or ECX,EDX
mov dword ptr [rsp],ECX
fldcw word ptr [rsp]
pop rcx
ret
ld_initfpu ENDP
end
+206
View File
@@ -0,0 +1,206 @@
/* ISO C9x 7.18 Integer types <stdint.h>
* Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
*
* THIS SOFTWARE IS NOT COPYRIGHTED
*
* Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
*
* This source code is offered for use in the public domain. You may
* use, modify or distribute it freely.
*
* This code is distributed in the hope that it will be useful but
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
* DISCLAIMED. This includes but is not limited to warranties of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Date: 2000-12-02
*/
#ifndef _STDINT_H
#define _STDINT_H
#define __need_wint_t
#define __need_wchar_t
#include <stddef.h>
/* 7.18.1.1 Exact-width integer types */
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
/* 7.18.1.2 Minimum-width integer types */
typedef signed char int_least8_t;
typedef unsigned char uint_least8_t;
typedef short int_least16_t;
typedef unsigned short uint_least16_t;
typedef int int_least32_t;
typedef unsigned uint_least32_t;
typedef long long int_least64_t;
typedef unsigned long long uint_least64_t;
/* 7.18.1.3 Fastest minimum-width integer types
* Not actually guaranteed to be fastest for all purposes
* Here we use the exact-width types for 8 and 16-bit ints.
*/
typedef char int_fast8_t;
typedef unsigned char uint_fast8_t;
typedef short int_fast16_t;
typedef unsigned short uint_fast16_t;
typedef int int_fast32_t;
typedef unsigned int uint_fast32_t;
typedef long long int_fast64_t;
typedef unsigned long long uint_fast64_t;
/* 7.18.1.4 Integer types capable of holding object pointers */
#ifndef _INTPTR_T_DEFINED
#define _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef int intptr_t;
#endif
#endif
#ifndef _UINTPTR_T_DEFINED
#define _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned int uintptr_t;
#endif
#endif
/* 7.18.1.5 Greatest-width integer types */
typedef long long intmax_t;
typedef unsigned long long uintmax_t;
/* 7.18.2 Limits of specified-width integer types */
#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS)
/* 7.18.2.1 Limits of exact-width integer types */
#define INT8_MIN (-128)
#define INT16_MIN (-32768)
#define INT32_MIN (-2147483647 - 1)
#define INT64_MIN (-9223372036854775807LL - 1)
#define INT8_MAX 127
#define INT16_MAX 32767
#define INT32_MAX 2147483647
#define INT64_MAX 9223372036854775807LL
#define UINT8_MAX 0xff /* 255U */
#define UINT16_MAX 0xffff /* 65535U */
#define UINT32_MAX 0xffffffff /* 4294967295U */
#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */
/* 7.18.2.2 Limits of minimum-width integer types */
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
/* 7.18.2.3 Limits of fastest minimum-width integer types */
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
/* 7.18.2.4 Limits of integer types capable of holding
object pointers */
#ifdef _WIN64
#define INTPTR_MIN INT64_MIN
#define INTPTR_MAX INT64_MAX
#define UINTPTR_MAX UINT64_MAX
#else
#define INTPTR_MIN INT32_MIN
#define INTPTR_MAX INT32_MAX
#define UINTPTR_MAX UINT32_MAX
#endif
/* 7.18.2.5 Limits of greatest-width integer types */
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
/* 7.18.3 Limits of other integer types */
#define PTRDIFF_MIN INTPTR_MIN
#define PTRDIFF_MAX INTPTR_MAX
#define SIG_ATOMIC_MIN INTPTR_MIN
#define SIG_ATOMIC_MAX INTPTR_MAX
#define SIZE_MAX UINTPTR_MAX
#ifndef WCHAR_MIN /* also in wchar.h */
#define WCHAR_MIN 0
#define WCHAR_MAX 0xffff /* UINT16_MAX */
#endif
/*
* wint_t is unsigned short for compatibility with MS runtime
*/
#define WINT_MIN 0
#define WINT_MAX 0xffff /* UINT16_MAX */
#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */
/* 7.18.4 Macros for integer constants */
#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS)
/* 7.18.4.1 Macros for minimum-width integer constants
Accoding to Douglas Gwyn <gwyn@arl.mil>:
"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
9899:1999 as initially published, the expansion was required
to be an integer constant of precisely matching type, which
is impossible to accomplish for the shorter types on most
platforms, because C99 provides no standard way to designate
an integer constant with width less than that of type int.
TC1 changed this to require just an integer constant
*expression* with *promoted* type."
*/
#define INT8_C(val) ((int8_t) + (val))
#define UINT8_C(val) ((uint8_t) + (val##U))
#define INT16_C(val) ((int16_t) + (val))
#define UINT16_C(val) ((uint16_t) + (val##U))
#define INT32_C(val) val##L
#define UINT32_C(val) val##UL
#define INT64_C(val) val##LL
#define UINT64_C(val) val##ULL
/* 7.18.4.2 Macros for greatest-width integer constants */
#define INTMAX_C(val) INT64_C(val)
#define UINTMAX_C(val) UINT64_C(val)
#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */
#endif
+30
View File
@@ -0,0 +1,30 @@
#pragma warning(disable:4996) // This function or variable may be unsafe.
#pragma warning(disable:4127) // conditional expression is constant
#pragma warning(disable:4101) // unreferenced local variable
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning(disable:4244) // conversion from 'int' to 'unsigned short', possible loss of data
#pragma warning(disable:4245) // conversion from 'int' to 'unsigned int', signed/unsigned mismatch
#pragma warning(disable:4018) // signed/unsigned mismatch
#pragma warning(disable:4389) // signed/unsigned mismatch
#pragma warning(disable:4505) // unreferenced local function has been removed
#pragma warning(disable:4701) // potentially uninitialized local variable 'm' used
#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
#pragma warning(disable:4189) // local variable is initialized but not referenced
#pragma warning(disable:4102) // unreferenced label
#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable:4390) // ';' : empty controlled statement found; is this the intent?
#pragma warning(disable:4702) // unreachable code
#pragma warning(disable:4703) // potentially uninitialized local pointer variable 'm' used
#ifdef _WIN64
#pragma warning(disable:4366) // The result of the unary '&' operator may be unaligned
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int', possible loss of data
#pragma warning(disable:4310) // cast truncates constant value
#endif
#define LITTLE_ENDIAN 1
#define __pascal
#define MARS 1
#define UNITTEST 1
#define _M_I86 1
+1
View File
@@ -1,5 +1,6 @@
#include "gen/cl_helpers.h"
#include "mars.h"
#include "root.h"
#include "rmem.h"
+1 -1
View File
@@ -12,7 +12,7 @@
#include "llvm/Support/PassNameParser.h"
#include "llvm/Transforms/IPO.h"
#include "root.h" // error()
#include "mars.h" // error()
#include <cstring> // strcmp();
using namespace llvm;
+1 -1
View File
@@ -379,6 +379,6 @@ void DtoCheckPragma(PragmaDeclaration *decl, Dsymbol *s,
break;
default:
warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
warning(Loc(), "the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ DValue* DtoVaArg(Loc& loc, Type* type, Expression* valistArg)
llt = getPtrToType(llt);
// issue a warning for broken va_arg instruction.
if (global.params.cpu != ARCHx86)
warning("%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
warning(Loc(), "%s: va_arg for C variadic functions is probably broken for anything but x86", loc.toChars());
// done
return new DImValue(type, gIR->ir->CreateVAArg(expelem->getLVal(), llt, "tmp"));
}
+8
View File
@@ -306,7 +306,15 @@ std::vector<llvm::Type*> IrTypeClass::buildVtblType(Type* first, Array* vtbl_arr
IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());
if (fd->type->nextOf() == NULL) {
// Return type of the virtual function has not been inferred.
// FIXME: is it a frontend bug?
types.push_back(getVoidPtrType());
continue;
}
types.push_back(DtoType(fd->type->pointerTo()));
}
return types;