mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-16 02:17:07 +02:00
Merged dmd 2.059beta
This commit is contained in:
+16
-8
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -261,6 +261,9 @@ void Module::gendocfile()
|
||||
Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4);
|
||||
}
|
||||
|
||||
char *srcfilename = srcfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename));
|
||||
|
||||
char *docfilename = docfile->toChars();
|
||||
Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename));
|
||||
|
||||
|
||||
+61
-9
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+29
-13
@@ -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
@@ -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
@@ -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++;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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());
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2011 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Rainer Schuetze
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
// 80 bit floating point value implementation for Microsoft compiler
|
||||
|
||||
#ifndef __LONG_DOUBLE_H__
|
||||
#define __LONG_DOUBLE_H__
|
||||
|
||||
#if IN_GCC
|
||||
#include "d-gcc-real.h"
|
||||
typedef real_t longdouble;
|
||||
|
||||
template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
inline int ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
if(fmt == 'a' || fmt == 'A')
|
||||
return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max
|
||||
return x.format(buffer, 46);
|
||||
}
|
||||
|
||||
#elif !_MSC_VER // has native 10 byte doubles
|
||||
#include <stdio.h>
|
||||
typedef long double longdouble;
|
||||
typedef volatile long double volatile_longdouble;
|
||||
|
||||
// also used from within C code, so use a #define rather than a template
|
||||
// template<typename T> longdouble ldouble(T x) { return (longdouble) x; }
|
||||
#define ldouble(x) ((longdouble)(x))
|
||||
|
||||
inline int ld_sprint(char* str, int fmt, longdouble x)
|
||||
{
|
||||
char sfmt[4] = "%Lg";
|
||||
sfmt[2] = fmt;
|
||||
return sprintf(str, sfmt, x);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
|
||||
struct longdouble;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// implemented in ldfpu.asm for _WIN64
|
||||
double ld_read(const longdouble* ld);
|
||||
long long ld_readll(const longdouble* ld);
|
||||
unsigned long long ld_readull(const longdouble* ld);
|
||||
void ld_set(longdouble* ld, double d);
|
||||
void ld_setll(longdouble* ld, long long d);
|
||||
void ld_setull(longdouble* ld, unsigned long long d);
|
||||
}
|
||||
|
||||
struct longdouble
|
||||
{
|
||||
unsigned long long mantissa;
|
||||
unsigned short exponent:15; // bias 0x3fff
|
||||
unsigned short sign:1;
|
||||
unsigned short fill:16; // for 12 byte alignment
|
||||
|
||||
// no constructor to be able to use this class in a union
|
||||
// use ldouble() to explicitely create a longdouble value
|
||||
|
||||
template<typename T> longdouble& operator=(T x) { set(x); return *this; }
|
||||
|
||||
void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; }
|
||||
|
||||
// we need to list all basic types to avoid ambiguities
|
||||
void set(float d) { ld_set(this, d); }
|
||||
void set(double d) { ld_set(this, d); }
|
||||
void set(long double d) { ld_set(this, d); }
|
||||
|
||||
void set(signed char d) { ld_set(this, d); }
|
||||
void set(short d) { ld_set(this, d); }
|
||||
void set(int d) { ld_set(this, d); }
|
||||
void set(long d) { ld_set(this, d); }
|
||||
void set(long long d) { ld_setll(this, d); }
|
||||
|
||||
void set(unsigned char d) { ld_set(this, d); }
|
||||
void set(unsigned short d) { ld_set(this, d); }
|
||||
void set(unsigned int d) { ld_set(this, d); }
|
||||
void set(unsigned long d) { ld_set(this, d); }
|
||||
void set(unsigned long long d) { ld_setull(this, d); }
|
||||
void set(bool d) { ld_set(this, d); }
|
||||
|
||||
operator float () { return ld_read(this); }
|
||||
operator double () { return ld_read(this); }
|
||||
|
||||
operator signed char () { return ld_read(this); }
|
||||
operator short () { return ld_read(this); }
|
||||
operator int () { return ld_read(this); }
|
||||
operator long () { return ld_read(this); }
|
||||
operator long long () { return ld_readll(this); }
|
||||
|
||||
operator unsigned char () { return ld_read(this); }
|
||||
operator unsigned short () { return ld_read(this); }
|
||||
operator unsigned int () { return ld_read(this); }
|
||||
operator unsigned long () { return ld_read(this); }
|
||||
operator unsigned long long() { return ld_readull(this); }
|
||||
operator bool () { return mantissa != 0 || exponent != 0; } // correct?
|
||||
};
|
||||
|
||||
// some optimizations are avoided by adding volatile to the longdouble
|
||||
// type, but this introduces bad ambiguities when using the class implementation above
|
||||
// as we are going through asm these optimizations won't kick in anyway, so "volatile"
|
||||
// is not required.
|
||||
typedef longdouble volatile_longdouble;
|
||||
|
||||
inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0)
|
||||
{
|
||||
longdouble d;
|
||||
d.mantissa = mantissa;
|
||||
d.exponent = exp;
|
||||
d.sign = sign;
|
||||
return d;
|
||||
}
|
||||
template<typename T> inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; }
|
||||
//template<typename T> inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; }
|
||||
|
||||
longdouble operator+(longdouble ld1, longdouble ld2);
|
||||
longdouble operator-(longdouble ld1, longdouble ld2);
|
||||
longdouble operator*(longdouble ld1, longdouble ld2);
|
||||
longdouble operator/(longdouble ld1, longdouble ld2);
|
||||
|
||||
bool operator< (longdouble ld1, longdouble ld2);
|
||||
bool operator<=(longdouble ld1, longdouble ld2);
|
||||
bool operator> (longdouble ld1, longdouble ld2);
|
||||
bool operator>=(longdouble ld1, longdouble ld2);
|
||||
bool operator==(longdouble ld1, longdouble ld2);
|
||||
bool operator!=(longdouble ld1, longdouble ld2);
|
||||
|
||||
inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; }
|
||||
inline longdouble operator+(longdouble ld1) { return ld1; }
|
||||
|
||||
template<typename T> inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); }
|
||||
template<typename T> inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); }
|
||||
template<typename T> inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); }
|
||||
template<typename T> inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); }
|
||||
|
||||
template<typename T> inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; }
|
||||
template<typename T> inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; }
|
||||
template<typename T> inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; }
|
||||
template<typename T> inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; }
|
||||
|
||||
template<typename T> inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; }
|
||||
template<typename T> inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; }
|
||||
template<typename T> inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; }
|
||||
template<typename T> inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; }
|
||||
|
||||
template<typename T> inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); }
|
||||
template<typename T> inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); }
|
||||
template<typename T> inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); }
|
||||
template<typename T> inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); }
|
||||
template<typename T> inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); }
|
||||
template<typename T> inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); }
|
||||
|
||||
template<typename T> inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; }
|
||||
template<typename T> inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; }
|
||||
template<typename T> inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; }
|
||||
template<typename T> inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; }
|
||||
template<typename T> inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; }
|
||||
template<typename T> inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; }
|
||||
|
||||
int _isnan(longdouble ld);
|
||||
|
||||
longdouble fabsl(longdouble ld);
|
||||
longdouble sqrtl(longdouble ld);
|
||||
longdouble sinl (longdouble ld);
|
||||
longdouble cosl (longdouble ld);
|
||||
longdouble tanl (longdouble ld);
|
||||
|
||||
longdouble fmodl(longdouble x, longdouble y);
|
||||
longdouble ldexpl(longdouble ldval, int exp); // see strtold
|
||||
|
||||
inline longdouble fabs (longdouble ld) { return fabsl(ld); }
|
||||
inline longdouble sqrt (longdouble ld) { return sqrtl(ld); }
|
||||
|
||||
#undef LDBL_DIG
|
||||
#undef LDBL_MAX
|
||||
#undef LDBL_MIN
|
||||
#undef LDBL_EPSILON
|
||||
#undef LDBL_MANT_DIG
|
||||
#undef LDBL_MAX_EXP
|
||||
#undef LDBL_MIN_EXP
|
||||
#undef LDBL_MAX_10_EXP
|
||||
#undef LDBL_MIN_10_EXP
|
||||
|
||||
#define LDBL_DIG 18
|
||||
#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe)
|
||||
#define LDBL_MIN ldouble(0x8000000000000000ULL, 1)
|
||||
#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal?
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MAX_10_EXP 4932
|
||||
#define LDBL_MIN_10_EXP (-4932)
|
||||
|
||||
extern longdouble ld_zero;
|
||||
extern longdouble ld_one;
|
||||
extern longdouble ld_pi;
|
||||
extern longdouble ld_log2t;
|
||||
extern longdouble ld_log2e;
|
||||
extern longdouble ld_log2;
|
||||
extern longdouble ld_ln2;
|
||||
|
||||
extern longdouble ld_inf;
|
||||
extern longdouble ld_qnan;
|
||||
extern longdouble ld_snan;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// CLASS numeric_limits<longdouble>
|
||||
template<> class _CRTIMP2_PURE std::numeric_limits<longdouble>
|
||||
: public _Num_float_base
|
||||
{ // limits for type long double
|
||||
public:
|
||||
typedef longdouble _Ty;
|
||||
|
||||
static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; }
|
||||
static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; }
|
||||
static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; }
|
||||
static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); }
|
||||
static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); }
|
||||
static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; }
|
||||
static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; }
|
||||
static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; }
|
||||
|
||||
_STCONS(int, digits, LDBL_MANT_DIG);
|
||||
_STCONS(int, digits10, LDBL_DIG);
|
||||
_STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
|
||||
_STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
|
||||
_STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
|
||||
_STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
|
||||
};
|
||||
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, digits10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, max_exponent10)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent)
|
||||
//_STCONSDEF(numeric_limits<longdouble>, int, min_exponent10)
|
||||
|
||||
int ld_sprint(char* str, int fmt, longdouble x);
|
||||
|
||||
#endif // !_MSC_VER
|
||||
|
||||
#endif // __LONG_DOUBLE_H__
|
||||
@@ -19,8 +19,10 @@ struct Lstring
|
||||
{
|
||||
unsigned length;
|
||||
|
||||
#ifndef IN_GCC
|
||||
// Disable warning about nonstandard extension
|
||||
#pragma warning (disable : 4200)
|
||||
#endif
|
||||
dchar string[];
|
||||
|
||||
static Lstring zero; // 0 length string
|
||||
|
||||
+19
-160
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -4,7 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if __sun&&__SVR4
|
||||
#if __sun&&__SVR4 || _MSC_VER
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include <malloc.h>
|
||||
@@ -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
|
||||
@@ -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%
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#define isnan _isnan
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,5 +1,6 @@
|
||||
#include "gen/cl_helpers.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "root.h"
|
||||
#include "rmem.h"
|
||||
|
||||
|
||||
+1
-1
@@ -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
@@ -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
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 5135dcfeca...946b499bd6
+1
-1
Submodule runtime/phobos updated: 2cc90b12a6...d857400952
Reference in New Issue
Block a user