Merge v2.056

This commit is contained in:
Alexey Prokhin
2011-11-01 10:47:30 +04:00
parent 423076dd82
commit b52c224d57
62 changed files with 6486 additions and 943 deletions

View File

@@ -186,6 +186,12 @@ list(REMOVE_ITEM FE_SRC
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/id.c
${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/impcnvtab.c
)
# exclude root/win32.c on non-windows systems
if(NOT WIN32)
list(REMOVE_ITEM FE_SRC ${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/root/win32.c)
endif(NOT WIN32)
# disable dmd gc
list(REMOVE_ITEM FE_SRC ${PROJECT_SOURCE_DIR}/${DMDFE_PATH}/root/dmgcmem.c)
set(LDC_SOURCE_FILES
${LDC_GENERATED}
${FE_SRC}

View File

@@ -150,11 +150,13 @@ struct StructDeclaration : AggregateDeclaration
int zeroInit; // !=0 if initialize with 0 fill
#if DMDV2
int hasIdentityAssign; // !=0 if has identity opAssign
int hasIdentityEquals; // !=0 if has identity opEquals
FuncDeclaration *cpctor; // generated copy-constructor, if any
FuncDeclaration *eq; // bool opEquals(ref const T), if any
FuncDeclarations postblits; // Array of postblit functions
FuncDeclaration *postblit; // aggregate postblit
FuncDeclaration *xeq; // TypeInfo_Struct.xopEquals
static FuncDeclaration *xerreq; // object.xopEquals
#endif
StructDeclaration(Loc loc, Identifier *id);
@@ -174,6 +176,8 @@ struct StructDeclaration : AggregateDeclaration
FuncDeclaration *buildOpEquals(Scope *sc);
FuncDeclaration *buildPostBlit(Scope *sc);
FuncDeclaration *buildCpCtor(Scope *sc);
FuncDeclaration *buildXopEquals(Scope *sc);
#endif
void toDocBuffer(OutBuffer *buf);

View File

@@ -52,7 +52,12 @@ void AliasThis::semantic(Scope *sc)
assert(ad->members);
Dsymbol *s = ad->search(loc, ident, 0);
if (!s)
::error(loc, "undefined identifier %s", ident->toChars());
{ s = sc->search(loc, ident, 0);
if (s)
::error(loc, "%s is not a member of %s", s->toChars(), ad->toChars());
else
::error(loc, "undefined identifier %s", ident->toChars());
}
ad->aliasthis = s;
}
else

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -13,7 +13,7 @@
#include "rmem.h"
#include "stringtable.h"
#include "aav.h"
#include "expression.h"
#include "statement.h"
@@ -31,7 +31,7 @@ extern int binary(const char *p , const char **tab, int high);
* Hash table of array op functions already generated or known about.
*/
StringTable arrayfuncs;
AA *arrayfuncs;
#endif
/**********************************************
@@ -126,16 +126,17 @@ Expression *BinExp::arrayOp(Scope *sc)
size_t namelen = buf.offset;
buf.writeByte(0);
char *name = (char *)buf.extractData();
char *name = buf.toChars();
Identifier *ident = Lexer::idPool(name);
/* Look up name in hash table
*/
#if IN_LLVM
StringValue *sv = sc->module->arrayfuncs.update(name, namelen);
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&sc->module->arrayfuncs, ident);
#else
StringValue *sv = arrayfuncs.update(name, namelen);
FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident);
#endif
FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
FuncDeclaration *fd = (FuncDeclaration *)*pfd;
if (!fd)
{
#if IN_DMD
@@ -326,7 +327,7 @@ Expression *BinExp::arrayOp(Scope *sc)
Parameters *fparams = new Parameters();
Expression *loopbody = buildArrayLoop(fparams);
Parameter *p = fparams->tdata()[0 /*fparams->dim - 1*/];
Parameter *p = (*fparams)[0 /*fparams->dim - 1*/];
#if DMDV1
// for (size_t i = 0; i < p.length; i++)
Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
@@ -352,7 +353,7 @@ Expression *BinExp::arrayOp(Scope *sc)
*/
TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
//printf("ftype: %s\n", ftype->toChars());
fd = new FuncDeclaration(loc, 0, Lexer::idPool(name), STCundefined, ftype);
fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype);
fd->fbody = fbody;
fd->protection = PROTpublic;
fd->linkage = LINKd;
@@ -373,10 +374,10 @@ Expression *BinExp::arrayOp(Scope *sc)
else
{ /* In library, refer to it.
*/
fd = FuncDeclaration::genCfunc(type, name);
fd = FuncDeclaration::genCfunc(type, ident);
}
#endif
sv->ptrvalue = fd; // cache symbol in hash table
*pfd = fd; // cache symbol in hash table
}
/* Call the function fd(arguments)
@@ -537,7 +538,7 @@ Expression *AssignExp::buildArrayLoop(Parameters *fparams)
ex2 = new CastExp(0, ex2, e1->type->nextOf());
#endif
Expression *ex1 = e1->buildArrayLoop(fparams);
Parameter *param = fparams->tdata()[0];
Parameter *param = (*fparams)[0];
param->storageClass = 0;
Expression *e = new AssignExp(0, ex1, ex2);
return e;
@@ -550,7 +551,7 @@ Expression *Str##AssignExp::buildArrayLoop(Parameters *fparams) \
*/ \
Expression *ex2 = e2->buildArrayLoop(fparams); \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Parameter *param = fparams->tdata()[0]; \
Parameter *param = (*fparams)[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(0, ex1, ex2); \
return e; \

View File

@@ -384,6 +384,35 @@ Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
return scd;
}
int StorageClassDeclaration::oneMember(Dsymbol **ps)
{
int t = Dsymbol::oneMembers(decl, ps);
if (t && *ps)
{
/* This is to deal with the following case:
* struct Tick {
* template to(T) { const T to() { ... } }
* }
* For eponymous function templates, the 'const' needs to get attached to 'to'
* before the semantic analysis of 'to', so that template overloading based on the
* 'this' pointer can be successful.
*/
FuncDeclaration *fd = (*ps)->isFuncDeclaration();
if (fd)
{
/* Use storage_class2 instead of storage_class otherwise when we do .di generation
* we'll wind up with 'const const' rather than 'const'.
*/
/* Don't think we need to worry about mutually exclusive storage classes here
*/
fd->storage_class2 |= stc;
}
}
return t;
}
void StorageClassDeclaration::setScope(Scope *sc)
{
if (decl)

View File

@@ -73,6 +73,7 @@ struct StorageClassDeclaration: AttribDeclaration
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);

View File

@@ -43,6 +43,12 @@ enum BUILTIN FuncDeclaration::isBuiltin()
{
static const char FeZe [] = "FNaNbNfeZe"; // @safe pure nothrow real function(real)
static const char FeZe2[] = "FNaNbNeeZe"; // @trusted pure nothrow real function(real)
static const char FuintZint[] = "FNaNbkZi"; // pure nothrow int function(uint)
static const char FuintZuint[] = "FNaNbkZk"; // pure nothrow uint function(uint)
static const char FulongZulong[] = "FNaNbkZk"; // pure nothrow int function(ulong)
static const char FulongZint[] = "FNaNbmZi"; // pure nothrow int function(uint)
static const char FrealrealZreal [] = "FNaNbNfeeZe"; // @safe pure nothrow real function(real, real)
static const char FrealZlong [] = "FNaNbNfeZl"; // @safe pure nothrow long function(real)
//printf("FuncDeclaration::isBuiltin() %s, %d\n", toChars(), builtin);
if (builtin == BUILTINunknown)
@@ -68,6 +74,10 @@ enum BUILTIN FuncDeclaration::isBuiltin()
builtin = BUILTINsqrt;
else if (ident == Id::fabs)
builtin = BUILTINfabs;
else if (ident == Id::expm1)
builtin = BUILTINexpm1;
else if (ident == Id::exp2)
builtin = BUILTINexp2;
//printf("builtin = %d\n", builtin);
}
// if float or double versions
@@ -77,19 +87,83 @@ enum BUILTIN FuncDeclaration::isBuiltin()
if (ident == Id::_sqrt)
builtin = BUILTINsqrt;
}
else if (strcmp(type->deco, FrealrealZreal) == 0)
{
if (ident == Id::atan2)
builtin = BUILTINatan2;
else if (ident == Id::yl2x)
builtin = BUILTINyl2x;
else if (ident == Id::yl2xp1)
builtin = BUILTINyl2xp1;
}
else if (strcmp(type->deco, FrealZlong) == 0 && ident == Id::rndtol)
builtin = BUILTINrndtol;
}
if (parent->ident == Id::bitop &&
parent->parent && parent->parent->ident == Id::core &&
!parent->parent->parent)
{
//printf("deco = %s\n", type->deco);
if (strcmp(type->deco, FuintZint) == 0 || strcmp(type->deco, FulongZint) == 0)
{
if (ident == Id::bsf)
builtin = BUILTINbsf;
else if (ident == Id::bsr)
builtin = BUILTINbsr;
}
else if (strcmp(type->deco, FuintZuint) == 0)
{
if (ident == Id::bswap)
builtin = BUILTINbswap;
}
}
}
}
return builtin;
}
int eval_bsf(uinteger_t n)
{
n = (n ^ (n - 1)) >> 1; // convert trailing 0s to 1, and zero rest
int k = 0;
while( n )
{ ++k;
n >>=1;
}
return k;
}
int eval_bsr(uinteger_t n)
{ int k= 0;
while(n>>=1)
{
++k;
}
return k;
}
uinteger_t eval_bswap(Expression *arg0)
{ uinteger_t n = arg0->toInteger();
#define BYTEMASK 0x00FF00FF00FF00FFLL
#define SHORTMASK 0x0000FFFF0000FFFFLL
#define INTMASK 0x0000FFFF0000FFFFLL
// swap adjacent ubytes
n = ((n >> 8 ) & BYTEMASK) | ((n & BYTEMASK) << 8 );
// swap adjacent ushorts
n = ((n >> 16) & SHORTMASK) | ((n & SHORTMASK) << 16);
TY ty = arg0->type->toBasetype()->ty;
// If 64 bits, we need to swap high and low uints
if (ty == Tint64 || ty == Tuns64)
n = ((n >> 32) & INTMASK) | ((n & INTMASK) << 32);
return n;
}
/**************************************
* Evaluate builtin function.
* Return result; NULL if cannot evaluate it.
*/
Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments)
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments)
{
assert(arguments && arguments->dim);
Expression *arg0 = arguments->tdata()[0];
@@ -120,6 +194,39 @@ Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments)
if (arg0->op == TOKfloat64)
e = new RealExp(0, fabsl(arg0->toReal()), arg0->type);
break;
// These math intrinsics are not yet implemented
case BUILTINatan2:
break;
case BUILTINrndtol:
break;
case BUILTINexpm1:
break;
case BUILTINexp2:
break;
case BUILTINyl2x:
break;
case BUILTINyl2xp1:
break;
case BUILTINbsf:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsf(0) is undefined");
else
e = new IntegerExp(loc, eval_bsf(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbsr:
if (arg0->op == TOKint64)
{ if (arg0->toInteger()==0)
error(loc, "bsr(0) is undefined");
else
e = new IntegerExp(loc, eval_bsr(arg0->toInteger()), Type::tint32);
}
break;
case BUILTINbswap:
if (arg0->op == TOKint64)
e = new IntegerExp(loc, eval_bswap(arg0), arg0->type);
break;
}
return e;
}

View File

@@ -143,6 +143,8 @@ MATCH Expression::implicitConvTo(Type *t)
toChars(), type->toChars(), t->toChars());
#endif
//static int nest; if (++nest == 10) halt();
if (t == Type::terror)
return MATCHnomatch;
if (!type)
{ error("%s is not an expression", toChars());
type = Type::terror;
@@ -543,6 +545,10 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t)
if (result == MATCHnomatch)
break; // no need to check for worse
}
if (!result)
result = type->implicitConvTo(t);
return result;
}
else
@@ -590,7 +596,7 @@ MATCH CallExp::implicitConvTo(Type *t)
/* Allow the result of strongly pure functions to
* convert to immutable
*/
if (f && f->isPure() == PUREstrong)
if (f && f->isPure() == PUREstrong && !f->type->hasWild())
return type->invariantOf()->implicitConvTo(t);
return MATCHnomatch;
@@ -1720,7 +1726,8 @@ Lagain:
if (t1 == t2)
{
}
else if (t1->ty == Tpointer && t2->ty == Tpointer)
else if ((t1->ty == Tpointer && t2->ty == Tpointer) ||
(t1->ty == Tdelegate && t2->ty == Tdelegate))
{
// Bring pointers to compatible type
Type *t1n = t1->nextOf();
@@ -1760,7 +1767,14 @@ Lagain:
else
d->trust = TRUSTtrusted;
Type *tx = d->pointerTo();
Type *tx = NULL;
if (t1->ty == Tdelegate)
{
tx = new TypeDelegate(d);
tx = tx->merge();
}
else
tx = d->pointerTo();
if (t1->implicitConvTo(tx) && t2->implicitConvTo(tx))
{

View File

@@ -970,7 +970,10 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
{
FuncDeclaration *fdstart = s->isFuncDeclaration();
//printf("%s fdstart = %p\n", s->kind(), fdstart);
return !overloadApply(fdstart, &isf, fd);
if (overloadApply(fdstart, &isf, fd))
return 0;
return !fd->parent->isTemplateMixin();
}
}
#endif
@@ -983,6 +986,8 @@ int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
{
//printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
FuncDeclaration *fdmatch = NULL;
FuncDeclaration *fdambig = NULL;
ClassDeclaration *cd = this;
Dsymbols *vtbl = &cd->vtbl;
@@ -996,11 +1001,43 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
//printf("\t[%d] = %s\n", i, fd->toChars());
if (ident == fd->ident &&
//tf->equals(fd->type)
fd->type->covariant(tf) == 1
)
{ //printf("\t\tfound\n");
return fd;
fd->type->covariant(tf) == 1)
{ //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration());
if (!fdmatch)
goto Lfd;
{
// Function type matcing: exact > covariant
int m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch;
int m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch;
if (m1 > m2)
goto Lfd;
else if (m1 < m2)
goto Lfdmatch;
}
{
// The way of definition: non-mixin > mixin
int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
int m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
if (m1 > m2)
goto Lfd;
else if (m1 < m2)
goto Lfdmatch;
}
Lambig:
fdambig = fd;
//printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars());
continue;
Lfd:
fdmatch = fd, fdambig = NULL;
//printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars());
continue;
Lfdmatch:
continue;
}
//else printf("\t\t%d\n", fd->type->covariant(tf));
}
@@ -1010,7 +1047,9 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
cd = cd->baseClass;
}
return NULL;
if (fdambig)
error("ambiguous virtual function %s", fdambig->toChars());
return fdmatch;
}
void ClassDeclaration::interfaceSemantic(Scope *sc)
@@ -1302,15 +1341,15 @@ void InterfaceDeclaration::semantic(Scope *sc)
}
sc = sc->push(this);
sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
sc->stc |= storage_class & STC_TYPECTOR;
sc->stc &= STCsafe | STCtrusted | STCsystem;
sc->parent = this;
if (isCOMinterface())
sc->linkage = LINKwindows;
else if (isCPPinterface())
sc->linkage = LINKcpp;
sc->structalign = 8;
sc->protection = PROTpublic;
sc->explicitProtection = 0;
structalign = sc->structalign;
sc->offset = PTRSIZE * 2;
inuse++;

View File

@@ -21,6 +21,7 @@
#include "expression.h"
#include "statement.h"
#include "init.h"
#include "template.h"
/*******************************************
@@ -71,48 +72,6 @@ Lneed:
#undef X
}
/*******************************************
* We need an opEquals for the struct if
* any fields has an opEquals.
* Generate one if a user-specified one does not exist.
*/
int StructDeclaration::needOpEquals()
{
#define X 0
if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars());
/* If any of the fields has an opEquals, then we
* need it too.
*/
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->eq)
goto Lneed;
}
}
if (X) printf("\tdontneed\n");
return 0;
Lneed:
if (X) printf("\tneed\n");
return 1;
#undef X
}
/******************************************
* Build opAssign for struct.
* S* opAssign(S s) { ... }
@@ -232,33 +191,99 @@ FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc)
return fop;
}
/*******************************************
* We need an opEquals for the struct if
* any fields has an opEquals.
* Generate one if a user-specified one does not exist.
*/
int StructDeclaration::needOpEquals()
{
#define X 0
if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars());
if (hasIdentityEquals)
goto Lneed;
/* If any of the fields has an opEquals, then we
* need it too.
*/
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *v = s->isVarDeclaration();
assert(v && v->storage_class & STCfield);
if (v->storage_class & STCref)
continue;
Type *tv = v->type->toBasetype();
while (tv->ty == Tsarray)
{ TypeSArray *ta = (TypeSArray *)tv;
tv = tv->nextOf()->toBasetype();
}
if (tv->ty == Tstruct)
{ TypeStruct *ts = (TypeStruct *)tv;
StructDeclaration *sd = ts->sym;
if (sd->needOpEquals())
goto Lneed;
}
}
if (X) printf("\tdontneed\n");
return 0;
Lneed:
if (X) printf("\tneed\n");
return 1;
#undef X
}
/******************************************
* Build opEquals for struct.
* const bool opEquals(const ref S s) { ... }
* const bool opEquals(const S s) { ... }
*/
FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
{
Dsymbol *eq = search_function(this, Id::eq);
if (eq)
{
for (size_t i = 0; i <= 1; i++)
{
Expression *e =
i == 0 ? new NullExp(loc, type->constOf()) // dummy rvalue
: type->constOf()->defaultInit(); // dummy lvalue
Expressions *arguments = new Expressions();
arguments->push(e);
// check identity opEquals exists
FuncDeclaration *fd = eq->isFuncDeclaration();
if (fd)
{ fd = fd->overloadResolve(loc, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
}
TemplateDeclaration *td = eq->isTemplateDeclaration();
if (td)
{ fd = td->deduceFunctionTemplate(sc, loc, NULL, e, arguments, 1);
if (fd && !(fd->storage_class & STCdisable))
return fd;
}
}
return NULL;
}
if (!needOpEquals())
return NULL;
//printf("StructDeclaration::buildOpEquals() %s\n", toChars());
Loc loc = this->loc;
Parameters *parameters = new Parameters;
#if STRUCTTHISREF
// bool opEquals(ref const T) const;
Parameter *param = new Parameter(STCref, type->constOf(), Id::p, NULL);
#else
// bool opEquals(const T*) const;
Parameter *param = new Parameter(STCin, type->pointerTo(), Id::p, NULL);
#endif
parameters->push(new Parameter(STCin, type, Id::p, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf->mod = MODconst;
tf = (TypeFunction *)tf->semantic(loc, sc);
parameters->push(param);
TypeFunction *ftype = new TypeFunction(parameters, Type::tbool, 0, LINKd);
ftype->mod = MODconst;
ftype = (TypeFunction *)ftype->semantic(loc, sc);
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, ftype);
FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::eq, STCundefined, tf);
Expression *e = NULL;
/* Do memberwise compare
@@ -300,16 +325,90 @@ FuncDeclaration *StructDeclaration::buildOpEquals(Scope *sc)
return fop;
}
/******************************************
* Build __xopEquals for TypeInfo_Struct
* bool __xopEquals(in void* p, in void* q) { ... }
*/
FuncDeclaration *StructDeclaration::buildXopEquals(Scope *sc)
{
if (!search_function(this, Id::eq))
return NULL;
/* static bool__xopEquals(in void* p, in void* q) {
* return ( *cast(const S*)(p) ).opEquals( *cast(const S*)(q) );
* }
*/
Parameters *parameters = new Parameters;
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::p, NULL));
parameters->push(new Parameter(STCin, Type::tvoidptr, Id::q, NULL));
TypeFunction *tf = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tf = (TypeFunction *)tf->semantic(loc, sc);
Identifier *id = Lexer::idPool("__xopEquals");
FuncDeclaration *fop = new FuncDeclaration(loc, 0, id, STCstatic, tf);
Expression *e = new CallExp(0,
new DotIdExp(0,
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::p), type->pointerTo()->constOf())),
Id::eq),
new PtrExp(0, new CastExp(0,
new IdentifierExp(0, Id::q), type->pointerTo()->constOf())));
fop->fbody = new ReturnStatement(loc, e);
size_t index = members->dim;
members->push(fop);
sc = sc->push();
sc->stc = 0;
sc->linkage = LINKd;
unsigned errors = global.startGagging();
fop->semantic(sc);
if (errors == global.gaggedErrors)
{ fop->semantic2(sc);
if (errors == global.gaggedErrors)
{ fop->semantic3(sc);
if (errors == global.gaggedErrors)
fop->addMember(sc, this, 1);
}
}
if (global.endGagging(errors)) // if errors happened
{
members->remove(index);
if (!xerreq)
{
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Lexer::idPool("_xopEquals"));
e = e->semantic(sc);
Dsymbol *s = getDsymbol(e);
FuncDeclaration *fd = s->isFuncDeclaration();
xerreq = fd;
}
fop = xerreq;
}
sc->pop();
return fop;
}
/*******************************************
* Build copy constructor for struct.
* Copy constructors are compiler generated only, and are only
* callable from the compiler. They are not user accessible.
* A copy constructor is:
* void cpctpr(ref S s)
* void cpctpr(ref const S s) const
* {
* *this = s;
* this.postBlit();
* (*cast(S*)&this) = *cast(S*)s;
* (*cast(S*)&this).postBlit();
* }
* This is done so:
* - postBlit() never sees uninitialized data
@@ -329,10 +428,11 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
{
//printf("generating cpctor\n");
Parameter *param = new Parameter(STCref, type, Id::p, NULL);
Parameter *param = new Parameter(STCref, type->constOf(), Id::p, NULL);
Parameters *fparams = new Parameters;
fparams->push(param);
Type *ftype = new TypeFunction(fparams, Type::tvoid, FALSE, LINKd);
ftype->mod = MODconst;
fcp = new FuncDeclaration(loc, 0, Id::cpctor, STCundefined, ftype);
fcp->storage_class |= postblit->storage_class & STCdisable;
@@ -344,12 +444,20 @@ FuncDeclaration *StructDeclaration::buildCpCtor(Scope *sc)
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
AssignExp *ea = new AssignExp(0, e, new IdentifierExp(0, Id::p));
AssignExp *ea = new AssignExp(0,
new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo())),
new PtrExp(0, new CastExp(0, new AddrExp(0, new IdentifierExp(0, Id::p)), type->mutableOf()->pointerTo()))
);
ea->op = TOKblit;
Statement *s = new ExpStatement(0, ea);
// Build postBlit();
e = new VarExp(0, postblit, 0);
e = new ThisExp(0);
#if !STRUCTTHISREF
e = new PtrExp(0, e);
#endif
e = new PtrExp(0, new CastExp(0, new AddrExp(0, e), type->mutableOf()->pointerTo()));
e = new DotVarExp(0, e, postblit, 0);
e = new CallExp(0, e);
s = new CompoundStatement(0, s, new ExpStatement(0, e));

View File

@@ -558,6 +558,83 @@ Expression *Mod(Type *type, Expression *e1, Expression *e2)
return e;
}
Expression *Pow(Type *type, Expression *e1, Expression *e2)
{ Expression *e;
Loc loc = e1->loc;
// Handle integer power operations.
if (e2->type->isintegral())
{
Expression * r;
Expression * v;
dinteger_t n = e2->toInteger();
bool neg;
if (!e2->type->isunsigned() && (sinteger_t)n < 0)
{
if (e1->type->isintegral())
return EXP_CANT_INTERPRET;
// Don't worry about overflow, from now on n is unsigned.
neg = true;
n = -n;
}
else
neg = false;
if (e1->type->isfloating())
{
r = new RealExp(loc, e1->toReal(), e1->type);
v = new RealExp(loc, 1.0, e1->type);
}
else
{
r = new RealExp(loc, e1->toReal(), Type::tfloat64);
v = new RealExp(loc, 1.0, Type::tfloat64);
}
while (n != 0)
{
if (n & 1)
v = Mul(v->type, v, r);
n >>= 1;
r = Mul(r->type, r, r);
}
if (neg)
v = Div(v->type, new RealExp(loc, 1.0, v->type), v);
if (type->isintegral())
e = new IntegerExp(loc, v->toInteger(), type);
else
e = new RealExp(loc, v->toReal(), type);
}
else if (e2->type->isfloating())
{
// 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);
}
else if (e2->toReal() == 0.5)
{
// Special case: call sqrt directly.
Expressions args;
args.setDim(1);
args.tdata()[0] = e1;
e = eval_builtin(loc, BUILTINsqrt, &args);
if (!e)
e = EXP_CANT_INTERPRET;
}
else
e = EXP_CANT_INTERPRET;
}
else
e = EXP_CANT_INTERPRET;
return e;
}
Expression *Shl(Type *type, Expression *e1, Expression *e2)
{ Expression *e;
Loc loc = e1->loc;
@@ -581,6 +658,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2)
break;
case Tuns8:
case Tchar:
value = (d_uns8)(value) >> count;
break;
@@ -589,6 +667,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2)
break;
case Tuns16:
case Twchar:
value = (d_uns16)(value) >> count;
break;
@@ -597,6 +676,7 @@ Expression *Shr(Type *type, Expression *e1, Expression *e2)
break;
case Tuns32:
case Tdchar:
value = (d_uns32)(value) >> count;
break;
@@ -630,18 +710,21 @@ Expression *Ushr(Type *type, Expression *e1, Expression *e2)
{
case Tint8:
case Tuns8:
case Tchar:
// Possible only with >>>=. >>> always gets promoted to int.
value = (value & 0xFF) >> count;
break;
case Tint16:
case Tuns16:
case Twchar:
// Possible only with >>>=. >>> always gets promoted to int.
value = (value & 0xFFFF) >> count;
break;
case Tint32:
case Tuns32:
case Tdchar:
value = (value & 0xFFFFFFFF) >> count;
break;
@@ -1270,7 +1353,10 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
uinteger_t i = e2->toInteger();
if (i >= es1->len)
{
e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len);
e = new ErrorExp();
}
else
{
e = new IntegerExp(loc, es1->charAt(i), type);
@@ -1282,7 +1368,9 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
uinteger_t i = e2->toInteger();
if (i >= length)
{ e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
{
e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
e = new ErrorExp();
}
else if (e1->op == TOKarrayliteral)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
@@ -1299,7 +1387,9 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (e1->op == TOKarrayliteral)
{ 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 %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
e = new ErrorExp();
}
else
{ e = ale->elements->tdata()[i];
@@ -1353,7 +1443,10 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
uinteger_t iupr = upr->toInteger();
if (iupr > es1->len || ilwr > iupr)
{
e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
e = new ErrorExp();
}
else
{
void *s;
@@ -1380,7 +1473,10 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
uinteger_t iupr = upr->toInteger();
if (iupr > es1->elements->dim || ilwr > iupr)
{
e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
e = new ErrorExp();
}
else
{
Expressions *elements = new Expressions();

View File

@@ -107,6 +107,8 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
p = "const";
else if (isImmutable())
p = "immutable";
else if (isWild())
p = "inout";
else if (storage_class & STCmanifest)
p = "enum";
else if (!t->isAssignable())
@@ -291,14 +293,31 @@ void TypedefDeclaration::semantic(Scope *sc)
//printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
if (sem == SemanticStart)
{ sem = SemanticIn;
parent = sc->parent;
int errors = global.errors;
Type *savedbasetype = basetype;
basetype = basetype->semantic(loc, sc);
if (errors != global.errors)
{
basetype = savedbasetype;
sem = SemanticStart;
return;
}
sem = SemanticDone;
#if DMDV2
type = type->addStorageClass(storage_class);
#endif
Type *savedtype = type;
type = type->semantic(loc, sc);
if (sc->parent->isFuncDeclaration() && init)
semantic2(sc);
if (errors != global.errors)
{
basetype = savedbasetype;
type = savedtype;
sem = SemanticStart;
return;
}
storage_class |= sc->stc & STCdeprecated;
}
else if (sem == SemanticIn)
@@ -314,7 +333,14 @@ void TypedefDeclaration::semantic2(Scope *sc)
{ sem = Semantic2Done;
if (init)
{
Initializer *savedinit = init;
int errors = global.errors;
init = init->semantic(sc, basetype, WANTinterpret);
if (errors != global.errors)
{
init = savedinit;
return;
}
ExpInitializer *ie = init->isExpInitializer();
if (ie)
@@ -440,6 +466,9 @@ void AliasDeclaration::semantic(Scope *sc)
// type. If it is a symbol, then aliassym is set and type is NULL -
// toAlias() will return aliasssym.
int errors = global.errors;
Type *savedtype = type;
Dsymbol *s;
Type *t;
Expression *e;
@@ -486,12 +515,15 @@ void AliasDeclaration::semantic(Scope *sc)
}
else if (t)
{
type = t;
type = t->semantic(loc, sc);
//printf("\talias resolved to type %s\n", type->toChars());
}
if (overnext)
ScopeDsymbol::multiplyDefined(0, this, overnext);
this->inSemantic = 0;
if (errors != global.errors)
type = savedtype;
return;
L2:
@@ -505,6 +537,7 @@ void AliasDeclaration::semantic(Scope *sc)
}
else
{
Dsymbol *savedovernext = overnext;
FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
if (f)
{
@@ -528,6 +561,14 @@ void AliasDeclaration::semantic(Scope *sc)
assert(global.errors);
s = NULL;
}
if (errors != global.errors)
{
type = savedtype;
overnext = savedovernext;
aliassym = NULL;
inSemantic = 0;
return;
}
}
//printf("setting aliassym %s to %s %s\n", toChars(), s->kind(), s->toChars());
aliassym = s;
@@ -585,7 +626,7 @@ Dsymbol *AliasDeclaration::toAlias()
//static int count; if (++count == 10) *(char*)0=0;
if (inSemantic)
{ error("recursive alias declaration");
aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL);
aliassym = new AliasDeclaration(loc, ident, Type::terror);
type = Type::terror;
}
else if (!aliassym && scope)
@@ -988,6 +1029,8 @@ Lnomatch:
}
VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
if (arg->storageClass & STCparameter)
v->storage_class |= arg->storageClass;
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
v->semantic(sc);
@@ -1110,11 +1153,19 @@ Lnomatch:
error("only parameters or foreach declarations can be ref");
}
if ((storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest) ||
isDataseg()) &&
type->hasWild())
if (type->hasWild() &&
!(type->ty == Tpointer && type->nextOf()->ty == Tfunction || type->ty == Tdelegate))
{
error("only fields, parameters or stack based variables can be inout");
if (storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCfield) ||
isDataseg()
)
{
error("only parameters or stack based variables can be inout");
}
if (sc->func && !sc->func->type->hasWild())
{
error("inout variables can only be declared inside inout functions");
}
}
if (!(storage_class & (STCctfe | STCref)) && tb->ty == Tstruct &&
@@ -1401,9 +1452,7 @@ Lnomatch:
if (!global.errors && !inferred)
{
unsigned errors = global.errors;
global.gag++;
//printf("+gag\n");
unsigned errors = global.startGagging();
Expression *e;
Initializer *i2 = init;
inuse++;
@@ -1462,12 +1511,8 @@ Lnomatch:
i2 = i2->semantic(sc, type, WANTinterpret);
}
inuse--;
global.gag--;
//printf("-gag\n");
if (errors != global.errors) // if errors happened
if (global.endGagging(errors)) // if errors happened
{
if (global.gag == 0)
global.errors = errors; // act as if nothing happened
#if DMDV2
/* Save scope for later use, to try again
*/

View File

@@ -87,6 +87,7 @@ enum PURE;
// but not typed as "shared"
#define STCwild 0x80000000LL // for "wild" type constructor
#define STC_TYPECTOR (STCconst | STCimmutable | STCshared | STCwild)
#define STC_FUNCATTR (STCref | STCnothrow | STCpure | STCproperty | STCsafe | STCtrusted | STCsystem)
#define STCproperty 0x100000000LL
#define STCsafe 0x200000000LL
@@ -154,6 +155,7 @@ struct Declaration : Dsymbol
int isAbstract() { return storage_class & STCabstract; }
int isConst() { return storage_class & STCconst; }
int isImmutable() { return storage_class & STCimmutable; }
int isWild() { return storage_class & STCwild; }
int isAuto() { return storage_class & STCauto; }
int isScope() { return storage_class & STCscope; }
int isSynchronized() { return storage_class & STCsynchronized; }
@@ -680,9 +682,18 @@ enum BUILTIN
BUILTINtan, // std.math.tan
BUILTINsqrt, // std.math.sqrt
BUILTINfabs, // std.math.fabs
BUILTINatan2, // std.math.atan2
BUILTINrndtol, // std.math.rndtol
BUILTINexpm1, // std.math.expm1
BUILTINexp2, // std.math.exp2
BUILTINyl2x, // std.math.yl2x
BUILTINyl2xp1, // std.math.yl2xp1
BUILTINbsr, // core.bitop.bsr
BUILTINbsf, // core.bitop.bsf
BUILTINbswap, // core.bitop.bswap
};
Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments);
#else
enum BUILTIN { };
@@ -729,6 +740,7 @@ struct FuncDeclaration : Declaration
// of the 'introducing' function
// this one is overriding
int inferRetType; // !=0 if return type is to be inferred
StorageClass storage_class2; // storage class for template onemember's
// Things that should really go into Scope
int hasReturnExp; // 1 if there's a return exp; statement
@@ -907,7 +919,6 @@ struct CtorDeclaration : FuncDeclaration
CtorDeclaration(Loc loc, Loc endloc, StorageClass stc, Type *type);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
char *toChars();
int isVirtual();

View File

@@ -44,7 +44,11 @@ Expression *Expression::toDelegate(Scope *sc, Type *t)
#else
e = this->syntaxCopy();
#endif
Statement *s = new ReturnStatement(loc, e);
Statement *s;
if (t->ty == Tvoid)
s = new ExpStatement(loc, e);
else
s = new ReturnStatement(loc, e);
fld->fbody = s;
e = new FuncExp(loc, fld);
e = e->semantic(sc);

View File

@@ -553,35 +553,28 @@ int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
void Dsymbol::error(const char *format, ...)
{
//printf("Dsymbol::error()\n");
if (!global.gag)
if (!loc.filename) // avoid bug 5861.
{
char *p = locToChars();
Module *m = getModule();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
fprintf(stdmsg, "Error: ");
if (isAnonymous())
fprintf(stdmsg, "%s ", kind());
else
fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
//halt();
if (m && m->srcfile)
loc.filename = m->srcfile->toChars();
}
global.errors++;
//fatal();
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end(ap);
}
void Dsymbol::error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end(ap);
}
void Dsymbol::verror(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
@@ -596,15 +589,16 @@ void Dsymbol::error(Loc loc, const char *format, ...)
fprintf(stdmsg, "Error: ");
fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
halt();
}
else
{
global.gaggedErrors++;
}
global.errors++;
@@ -721,7 +715,7 @@ Dsymbols *Dsymbol::arraySyntaxCopy(Dsymbols *a)
Dsymbols *b = NULL;
if (a)
{
b = (Dsymbols *)a->copy();
b = a->copy();
for (size_t i = 0; i < b->dim; i++)
{
Dsymbol *s = (*b)[i];
@@ -1032,11 +1026,19 @@ size_t ScopeDsymbol::dim(Dsymbols *members)
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
AttribDeclaration *a = s->isAttribDeclaration();
TemplateMixin *tm = s->isTemplateMixin();
TemplateInstance *ti = s->isTemplateInstance();
if (a)
{
n += dim(a->decl);
}
else if (tm)
{
n += dim(tm->members);
}
else if (ti)
;
else
n++;
}
@@ -1262,7 +1264,9 @@ Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
* or a variable (in which case an expression is created in
* toir.c).
*/
v->init = new VoidInitializer(0);
VoidInitializer *e = new VoidInitializer(0);
e->type = Type::tsize_t;
v->init = e;
}
*pvar = v;
}
@@ -1279,6 +1283,7 @@ DsymbolTable::DsymbolTable()
{
#if STRINGTABLE
tab = new StringTable;
tab->init();
#else
tab = NULL;
#endif

View File

@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2010 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -151,6 +151,7 @@ struct Dsymbol : Object
int isAnonymous();
void error(Loc loc, const char *format, ...) IS_PRINTF(3);
void error(const char *format, ...) IS_PRINTF(2);
void verror(Loc loc, const char *format, va_list ap);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getCompilationModule(); // possibly different for templates
@@ -360,11 +361,7 @@ struct OverloadSet : Dsymbol
struct DsymbolTable : Object
{
#if STRINGTABLE
StringTable *tab;
#else
AA *tab;
#endif
DsymbolTable();
~DsymbolTable();

View File

@@ -649,6 +649,23 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope)
}
#endif
// Check if this function is a member of a template which has only been
// instantiated speculatively, eg from inside is(typeof()).
// Return the speculative template instance it is part of,
// or NULL if not speculative.
TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd)
{
Dsymbol * par = fd->parent;
while (par)
{
TemplateInstance *ti = par->isTemplateInstance();
if (ti && ti->speculative)
return ti;
par = par->toParent();
}
return NULL;
}
/****************************************
* Now that we know the exact type of the function we're calling,
* the arguments[] need to be adjusted:
@@ -662,7 +679,7 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope)
*/
Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
Expressions *arguments, FuncDeclaration *fd)
Expression *ethis, Expressions *arguments, FuncDeclaration *fd)
{
//printf("functionParameters()\n");
assert(arguments);
@@ -675,7 +692,15 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
// If inferring return type, and semantic3() needs to be run if not already run
if (!tf->next && fd->inferRetType)
{
TemplateInstance *spec = isSpeculativeFunction(fd);
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;
}
unsigned n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
@@ -718,7 +743,9 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
//printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
if (arg->implicitConvTo(p->type))
{
if (nargs != nparams)
if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()))
goto L2;
else if (nargs != nparams)
{ error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
return tf->next;
}
@@ -801,7 +828,16 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
L1:
if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
{
if (p->type != arg->type)
if (p->type->hasWild())
{ unsigned mod = p->type->wildMatch(arg->type);
if (mod)
{
wildmatch |= mod;
arg = arg->implicitCastTo(sc, p->type->substWildTo(mod));
arg = arg->optimize(WANTvalue);
}
}
else if (p->type != arg->type)
{
//printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
if (arg->op == TOKtype)
@@ -809,20 +845,6 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
arg = new ErrorExp();
goto L3;
}
if (p->type->isWild() && tf->next->isWild())
{ Type *t = p->type;
MATCH m = arg->implicitConvTo(t);
if (m == MATCHnomatch)
{ t = t->constOf();
m = arg->implicitConvTo(t);
if (m == MATCHnomatch)
{ t = t->sharedConstOf();
m = arg->implicitConvTo(t);
}
wildmatch |= p->type->wildMatch(arg->type);
}
arg = arg->implicitCastTo(sc, t);
}
else
arg = arg->implicitCastTo(sc, p->type);
arg = arg->optimize(WANTvalue);
@@ -989,6 +1011,19 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
break;
}
if (ethis && tf->isWild())
{
Type *tthis = ethis->type;
if (tthis->isWild())
wildmatch |= MODwild;
else if (tthis->isConst())
wildmatch |= MODconst;
else if (tthis->isImmutable())
wildmatch |= MODimmutable;
else
wildmatch |= MODmutable;
}
#if !IN_LLVM
// If D linkage and variadic, add _arguments[] as first argument
if (tf->linkage == LINKd && tf->varargs == 1)
@@ -1003,15 +1038,16 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
if (wildmatch)
{ /* Adjust function return type based on wildmatch
*/
//printf("wildmatch = x%x\n", wildmatch);
assert(tret->isWild());
//printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
if (wildmatch & MODconst || wildmatch & (wildmatch - 1))
tret = tret->constOf();
tret = tret->substWildTo(MODconst);
else if (wildmatch & MODimmutable)
tret = tret->invariantOf();
tret = tret->substWildTo(MODimmutable);
else if (wildmatch & MODwild)
;
else
{ assert(wildmatch & MODmutable);
tret = tret->mutableOf();
tret = tret->substWildTo(MODmutable);
}
}
return tret;
@@ -1159,13 +1195,10 @@ Expression *Expression::semantic(Scope *sc)
Expression *Expression::trySemantic(Scope *sc)
{
//printf("+trySemantic(%s)\n", toChars());
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
Expression *e = semantic(sc);
global.gag--;
if (errors != global.errors)
if (global.endGagging(errors))
{
global.errors = errors;
e = NULL;
}
//printf("-trySemantic(%s)\n", toChars());
@@ -2542,7 +2575,7 @@ Expression *IdentifierExp::semantic(Scope *sc)
if (hasThis(sc))
{
AggregateDeclaration *ad = sc->getStructClassScope();
if (ad->aliasthis)
if (ad && ad->aliasthis)
{
Expression *e;
e = new IdentifierExp(loc, Id::This);
@@ -2648,9 +2681,10 @@ Lagain:
return this;
if (!s->isFuncDeclaration()) // functions are checked after overloading
checkDeprecated(sc, s);
Dsymbol *olds = s;
s = s->toAlias();
//printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
if (!s->isFuncDeclaration())
if (s != olds && !s->isFuncDeclaration())
checkDeprecated(sc, s);
if (sc->func)
@@ -2727,7 +2761,15 @@ Lagain:
// if inferring return type, sematic3 needs to be run
if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
{
TemplateInstance *spec = isSpeculativeFunction(f);
int olderrs = global.errors;
f->semantic3(f->scope);
// Update the template instantiation with the number
// of errors which occured.
if (spec && global.errors != olderrs)
spec->errors = global.errors - olderrs;
}
if (f->isUnitTestDeclaration())
{
@@ -2785,7 +2827,8 @@ Lagain:
t = s->getType();
if (t)
{
return new TypeExp(loc, t);
TypeExp *te = new TypeExp(loc, t);
return te->semantic(sc);
}
TupleDeclaration *tup = s->isTupleDeclaration();
@@ -2859,10 +2902,7 @@ ThisExp::ThisExp(Loc loc)
}
Expression *ThisExp::semantic(Scope *sc)
{ FuncDeclaration *fd;
FuncDeclaration *fdthis;
int nested = 0;
{
#if LOGSEMANTIC
printf("ThisExp::semantic()\n");
#endif
@@ -2874,13 +2914,15 @@ Expression *ThisExp::semantic(Scope *sc)
return this;
}
FuncDeclaration *fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
/* Special case for typeof(this) and typeof(super) since both
* should work even if they are not inside a non-static member function
*/
if (sc->intypeof)
if (!fd && sc->intypeof)
{
// Find enclosing struct or class
for (Dsymbol *s = sc->parent; 1; s = s->parent)
for (Dsymbol *s = sc->getStructClassScope(); 1; s = s->parent)
{
if (!s)
{
@@ -2905,9 +2947,6 @@ Expression *ThisExp::semantic(Scope *sc)
}
}
}
fdthis = sc->parent->isFuncDeclaration();
fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
if (!fd)
goto Lerr;
@@ -3823,7 +3862,10 @@ Expression *StructLiteralExp::semantic(Scope *sc)
Initializer *i2 = v->init->syntaxCopy();
i2 = i2->semantic(v->scope, v->type, WANTinterpret);
e = i2->toExpression();
v->scope = NULL;
// remove v->scope (see bug 3426)
// but not if gagged, for we might be called again.
if (!global.gag)
v->scope = NULL;
}
}
}
@@ -4358,7 +4400,7 @@ Lagain:
if (!arguments)
arguments = new Expressions();
functionParameters(loc, sc, tf, arguments, f);
functionParameters(loc, sc, tf, NULL, arguments, f);
type = type->addMod(tf->nextOf()->mod);
}
@@ -4383,7 +4425,7 @@ Lagain:
assert(allocator);
TypeFunction *tf = (TypeFunction *)f->type;
functionParameters(loc, sc, tf, newargs, f);
functionParameters(loc, sc, tf, NULL, newargs, f);
}
else
{
@@ -4418,7 +4460,7 @@ Lagain:
if (!arguments)
arguments = new Expressions();
functionParameters(loc, sc, tf, arguments, f);
functionParameters(loc, sc, tf, NULL, arguments, f);
}
else
{
@@ -4442,7 +4484,7 @@ Lagain:
assert(allocator);
tf = (TypeFunction *)f->type;
functionParameters(loc, sc, tf, newargs, f);
functionParameters(loc, sc, tf, NULL, newargs, f);
#if 0
e = new VarExp(loc, f);
e = new CallExp(loc, e, newargs);
@@ -4962,10 +5004,6 @@ Expression *TupleExp::semantic(Scope *sc)
}
expandTuples(exps);
if (0 && exps->dim == 1)
{
return (*exps)[0];
}
type = new TypeTuple(exps);
type = type->semantic(loc, sc);
//printf("-TupleExp::semantic(%s)\n", toChars());
@@ -5027,27 +5065,28 @@ Expression *FuncExp::semantic(Scope *sc)
#endif
if (!type)
{
unsigned olderrors = global.errors;
fd->semantic(sc);
//fd->parent = sc->parent;
if (global.errors)
if (olderrors != global.errors)
{
}
else
{
fd->semantic2(sc);
if (!global.errors ||
if ( (olderrors == global.errors) ||
// need to infer return type
(fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()))
{
fd->semantic3(sc);
if (!global.errors && global.params.useInline)
if ( (olderrors == global.errors) && global.params.useInline)
fd->inlineScan();
}
}
// need to infer return type
if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
if ((olderrors != global.errors) && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
((TypeFunction *)fd->type)->next = Type::terror;
// Type is a "delegate to" or "pointer to" the function literal
@@ -5099,6 +5138,8 @@ Expression *DeclarationExp::semantic(Scope *sc)
printf("DeclarationExp::semantic() %s\n", toChars());
#endif
unsigned olderrors = global.errors;
/* This is here to support extern(linkage) declaration,
* where the extern(linkage) winds up being an AttribDeclaration
* wrapper.
@@ -5164,14 +5205,14 @@ Expression *DeclarationExp::semantic(Scope *sc)
sc2->pop();
s->parent = sc->parent;
}
if (!global.errors)
if (global.errors == olderrors)
{
declaration->semantic2(sc);
if (!global.errors)
if (global.errors == olderrors)
{
declaration->semantic3(sc);
if (!global.errors && global.params.useInline)
if ((global.errors == olderrors) && global.params.useInline)
declaration->inlineScan();
}
}
@@ -6578,22 +6619,20 @@ Expression *DotIdExp::semantic(Scope *sc, int flag)
return e->type->dotExp(sc, e, ident);
}
#if DMDV2
else if (t1b->ty == Tarray ||
t1b->ty == Tsarray ||
t1b->ty == Taarray)
else if ((t1b->ty == Tarray || t1b->ty == Tsarray ||
t1b->ty == Taarray) &&
ident != Id::sort && ident != Id::reverse &&
ident != Id::dup && ident != Id::idup)
{ /* If ident is not a valid property, rewrite:
* e1.ident
* as:
* .ident(e1)
*/
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
Type *t1 = e1->type;
e = e1->type->dotExp(sc, e1, ident);
global.gag--;
if (errors != global.errors) // if failed to find the property
if (global.endGagging(errors)) // if failed to find the property
{
global.errors = errors;
e1->type = t1; // kludge to restore type
e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
e = new CallExp(loc, e, e1);
@@ -6773,7 +6812,7 @@ void modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
if (fd &&
((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
(fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
fd->toParent2() == var->toParent() &&
fd->toParent2() == var->toParent2() &&
(!e1 || e1->op == TOKthis)
)
{
@@ -6901,7 +6940,13 @@ L1:
TemplateDeclaration *td = dte->td;
eleft = dte->e1;
ti->tempdecl = td;
ti->semantic(sc);
if (ti->needsTypeInference(sc))
{
e = new CallExp(loc, this);
return e->semantic(sc);
}
else
ti->semantic(sc);
if (!ti->inst) // if template failed to expand
return new ErrorExp();
Dsymbol *s = ti->inst->toAlias();
@@ -7291,7 +7336,8 @@ Lagain:
if (ve->var->storage_class & STClazy)
{
TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
// lazy paramaters can be called without violating purity and safety
TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd, STCsafe | STCpure);
TypeDelegate *t = new TypeDelegate(tf);
ve->type = t->semantic(loc, sc);
}
@@ -7462,6 +7508,7 @@ Lagain:
if (f->needThis())
{
ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
ethis = ue->e1;
}
/* Cannot call public functions from inside invariant
@@ -7700,10 +7747,7 @@ Lagain:
tf = (TypeFunction *)(td->next);
if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
{
if (e1->op == TOKvar && ((VarExp *)e1)->var->storage_class & STClazy)
{ // lazy paramaters can be called without violating purity
// since they are checked explicitly
} else if (sc->func->setImpure())
if (sc->func->setImpure())
error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
}
if (sc->func && tf->trust <= TRUSTsystem)
@@ -7783,6 +7827,8 @@ Lagain:
accessCheck(loc, sc, NULL, f);
ethis = NULL;
ve->var = f;
// ve->hasOverloads = 0;
ve->type = f->type;
@@ -7796,7 +7842,7 @@ Lcheckargs:
if (!arguments)
arguments = new Expressions();
type = functionParameters(loc, sc, tf, arguments, f);
type = functionParameters(loc, sc, tf, ethis, arguments, f);
if (!type)
{
@@ -8328,7 +8374,7 @@ Expression *DeleteExp::semantic(Scope *sc)
UnaExp::semantic(sc);
e1 = resolveProperties(sc, e1);
e1 = e1->toLvalue(sc, NULL);
e1 = e1->modifiableLvalue(sc, NULL);
if (e1->op == TOKerror)
return e1;
type = Type::tvoid;
@@ -8539,7 +8585,9 @@ Expression *CastExp::semantic(Scope *sc)
}
// Struct casts are possible only when the sizes match
if (tob->ty == Tstruct || t1b->ty == Tstruct)
// Same with static array -> static array
if (tob->ty == Tstruct || t1b->ty == Tstruct ||
(tob->ty == Tsarray && t1b->ty == Tsarray))
{
size_t fromsize = t1b->size(loc);
size_t tosize = tob->size(loc);
@@ -8870,12 +8918,11 @@ Lagain:
return e;
}
if (t->ty == Tarray)
{
type = t->nextOf()->arrayOf();
// Allow typedef[] -> typedef[]
if (type->equals(t))
type = e1->type;
}
else
type = t->nextOf()->arrayOf();
return e;
Lerror:
@@ -9277,7 +9324,7 @@ Expression *IndexExp::semantic(Scope *sc)
goto Lerr;
}
if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix
e2 = (Expression *)((TupleExp *)e2)->exps->data[0];
e2 = ((TupleExp *)e2)->exps->tdata()[0];
e2 = resolveProperties(sc, e2);
if (e2->type == Type::terror)
goto Lerr;
@@ -9897,6 +9944,9 @@ Ltupleassign:
{ /* Write as:
* e1.cpctor(e2);
*/
if (!e2->type->implicitConvTo(e1->type))
error("conversion error from %s to %s", e2->type->toChars(), e1->type->toChars());
Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
e = new CallExp(loc, e, e2);
if (ec)
@@ -9915,7 +9965,7 @@ Ltupleassign:
}
else if (t1->ty == Tclass)
{ // Disallow assignment operator overloads for same type
if (!e2->type->implicitConvTo(e1->type))
if (!e2->implicitConvTo(e1->type))
{
Expression *e = op_overload(sc);
if (e)
@@ -11160,6 +11210,8 @@ Expression *PowExp::semantic(Scope *sc)
return e;
assert(e1->type && e2->type);
typeCombine(sc);
if (e1->op == TOKslice)
{
// Check element types are arithmetic
@@ -11183,64 +11235,14 @@ Expression *PowExp::semantic(Scope *sc)
// TODO: backend support, especially for e1 ^^ 2.
bool wantSqrt = false;
e1 = e1->optimize(0);
e2 = e2->optimize(0);
// Replace 1 ^^ x or 1.0^^x by (x, 1)
if ((e1->op == TOKint64 && e1->toInteger() == 1) ||
(e1->op == TOKfloat64 && e1->toReal() == 1.0))
// First, attempt to fold the expression.
e = optimize(WANTvalue);
if (e->op != TOKpow)
{
typeCombine(sc);
e = new CommaExp(loc, e2, e1);
e = e->semantic(sc);
return e;
}
// Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
if (e2->type->isintegral() && e1->op == TOKint64 && (sinteger_t)e1->toInteger() == -1L)
{
typeCombine(sc);
Type* resultType = type;
e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2->type));
e = new CondExp(loc, e, new IntegerExp(loc, -1L, resultType), new IntegerExp(loc, 1L, resultType));
e = e->semantic(sc);
return e;
}
// Replace x ^^ 0 or x^^0.0 by (x, 1)
if ((e2->op == TOKint64 && e2->toInteger() == 0) ||
(e2->op == TOKfloat64 && e2->toReal() == 0.0))
{
if (e1->type->isintegral())
e = new IntegerExp(loc, 1, e1->type);
else
e = new RealExp(loc, 1.0, e1->type);
typeCombine(sc);
e = new CommaExp(loc, e1, e);
e = e->semantic(sc);
return e;
}
// Replace x ^^ 1 or x^^1.0 by (x)
if ((e2->op == TOKint64 && e2->toInteger() == 1) ||
(e2->op == TOKfloat64 && e2->toReal() == 1.0))
{
typeCombine(sc);
return e1;
}
// Replace x ^^ -1.0 by (1.0 / x)
if ((e2->op == TOKfloat64 && e2->toReal() == -1.0))
{
typeCombine(sc);
e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1);
e = e->semantic(sc);
return e;
}
// All other negative integral powers are illegal
if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
{
error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
e1->type->toBasetype()->toChars(), e1->toChars(), e2->toChars());
return new ErrorExp();
}
// Determine if we're raising to an integer power.
sinteger_t intpow = 0;
@@ -11252,7 +11254,6 @@ Expression *PowExp::semantic(Scope *sc)
// Deal with x^^2, x^^3 immediately, since they are of practical importance.
if (intpow == 2 || intpow == 3)
{
typeCombine(sc);
// Replace x^^2 with (tmp = x, tmp*tmp)
// Replace x^^3 with (tmp = x, tmp*tmp*tmp)
Identifier *idtmp = Lexer::uniqueId("__powtmp");
@@ -11293,27 +11294,14 @@ Expression *PowExp::semantic(Scope *sc)
e = new DotIdExp(loc, e, Id::math);
if (e2->op == TOKfloat64 && e2->toReal() == 0.5)
{ // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
typeCombine(sc);
e = new CallExp(loc, new DotIdExp(loc, e, Id::_sqrt), e1);
}
else
{
// Replace e1 ^^ e2 with .std.math.pow(e1, e2)
// We don't combine the types if raising to an integer power (because
// integer powers are treated specially by std.math.pow).
if (!e2->type->isintegral())
typeCombine(sc);
// In fact, if it *could* have been an integer, make it one.
if (e2->op == TOKfloat64 && intpow != 0)
e2 = new IntegerExp(loc, intpow, Type::tint64);
e = new CallExp(loc, new DotIdExp(loc, e, Id::_pow), e1, e2);
}
e = e->semantic(sc);
// Always constant fold integer powers of literals. This will run the interpreter
// on .std.math.pow
if ((e1->op == TOKfloat64 || e1->op == TOKint64) && (e2->op == TOKint64))
e = e->optimize(WANTvalue | WANTinterpret);
return e;
}
incompatibleTypes();
@@ -11825,6 +11813,33 @@ EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
assert(op == TOKequal || op == TOKnotequal);
}
int needDirectEq(Type *t1, Type *t2)
{
assert(t1->ty == Tarray || t1->ty == Tsarray);
assert(t2->ty == Tarray || t2->ty == Tsarray);
Type *t1n = t1->nextOf()->toBasetype();
Type *t2n = t2->nextOf()->toBasetype();
if (((t1n->ty == Tchar || t1n->ty == Twchar || t1n->ty == Tdchar) &&
(t2n->ty == Tchar || t2n->ty == Twchar || t2n->ty == Tdchar)) ||
(t1n->ty == Tvoid || t2n->ty == Tvoid))
{
return FALSE;
}
if (t1n->constOf() != t2n->constOf())
return TRUE;
Type *t = t1n;
while (t->toBasetype()->nextOf())
t = t->nextOf()->toBasetype();
if (t->ty != Tstruct)
return FALSE;
return ((TypeStruct *)t)->sym->xeq == StructDeclaration::xerreq;
}
Expression *EqualExp::semantic(Scope *sc)
{ Expression *e;
@@ -11868,13 +11883,8 @@ Expression *EqualExp::semantic(Scope *sc)
if ((t1->ty == Tarray || t1->ty == Tsarray) &&
(t2->ty == Tarray || t2->ty == Tsarray))
{ Type *t1n = t1->nextOf()->toBasetype();
Type *t2n = t2->nextOf()->toBasetype();
if (t1n->constOf() != t2n->constOf() &&
!((t1n->ty == Tchar || t1n->ty == Twchar || t1n->ty == Tdchar) &&
(t2n->ty == Tchar || t2n->ty == Twchar || t2n->ty == Tdchar)) &&
!(t1n->ty == Tvoid || t2n->ty == Tvoid)
)
{
if (needDirectEq(t1, t2))
{ /* Rewrite as:
* _ArrayEq(e1, e2)
*/
@@ -11885,7 +11895,11 @@ Expression *EqualExp::semantic(Scope *sc)
e = new CallExp(loc, eq, args);
if (op == TOKnotequal)
e = new NotExp(loc, e);
e = e->semantic(sc);
e = e->trySemantic(sc); // for better error message
if (!e)
{ error("cannot compare %s and %s", t1->toChars(), t2->toChars());
return new ErrorExp();
}
return e;
}
}

View File

@@ -1562,6 +1562,9 @@ ASSIGNEXP(Mod)
ASSIGNEXP(And)
ASSIGNEXP(Or)
ASSIGNEXP(Xor)
#if DMDV2
ASSIGNEXP(Pow)
#endif
#undef X
#define X(a)
@@ -1575,18 +1578,6 @@ ASSIGNEXP(Cat)
#undef ASSIGNEXP
#undef ASSIGNEXP_TOELEM
// Only a reduced subset of operations for now.
struct PowAssignExp : BinAssignExp
{
PowAssignExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
// For operator overloading
Identifier *opId();
};
struct AddExp : BinExp
{
AddExp(Loc loc, Expression *e1, Expression *e2);
@@ -1731,12 +1722,22 @@ struct PowExp : BinExp
{
PowExp(Loc loc, Expression *e1, Expression *e2);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
// For operator overloading
Identifier *opId();
Identifier *opId_r();
#if IN_DMD
elem *toElem(IRState *irs);
#endif
#if IN_LLVM
DValue* toElem(IRState* irs);
#endif
};
#endif
@@ -1958,6 +1959,7 @@ struct InExp : BinExp
struct RemoveExp : BinExp
{
RemoveExp(Loc loc, Expression *e1, Expression *e2);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -2119,6 +2121,7 @@ Expression *Min(Type *type, Expression *e1, Expression *e2);
Expression *Mul(Type *type, Expression *e1, Expression *e2);
Expression *Div(Type *type, Expression *e1, Expression *e2);
Expression *Mod(Type *type, Expression *e1, Expression *e2);
Expression *Pow(Type *type, Expression *e1, Expression *e2);
Expression *Shl(Type *type, Expression *e1, Expression *e2);
Expression *Shr(Type *type, Expression *e1, Expression *e2);
Expression *Ushr(Type *type, Expression *e1, Expression *e2);

View File

@@ -38,6 +38,8 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
//printf("storage_class = x%x\n", storage_class);
this->storage_class = storage_class;
this->type = type;
if (type)
this->storage_class &= ~(STC_TYPECTOR | STC_FUNCATTR);
this->loc = loc;
this->endloc = endloc;
fthrows = NULL;
@@ -77,6 +79,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
* NULL for the return type.
*/
inferRetType = (type && type->nextOf() == NULL);
storage_class2 = 0;
hasReturnExp = 0;
nrvo_can = 1;
nrvo_var = NULL;
@@ -199,8 +202,15 @@ void FuncDeclaration::semantic(Scope *sc)
if (!type->deco)
{
sc = sc->push();
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
| STCsafe | STCtrusted | STCsystem | STCproperty); // forward to function type
sc->stc |= storage_class & STCdisable; // forward to function type
TypeFunction *tf = (TypeFunction *)type;
if (tf->isref) sc->stc |= STCref;
if (tf->isnothrow) sc->stc |= STCnothrow;
if (tf->isproperty) sc->stc |= STCproperty;
if (tf->purity == PUREfwdref) sc->stc |= STCpure;
if (tf->trust == TRUSTsafe) sc->stc |= STCsafe;
if (tf->trust == TRUSTsystem) sc->stc |= STCsystem;
if (tf->trust == TRUSTtrusted) sc->stc |= STCtrusted;
if (isCtorDeclaration())
sc->flags |= SCOPEctor;
@@ -287,12 +297,9 @@ void FuncDeclaration::semantic(Scope *sc)
if (fbody &&
(isFuncLiteralDeclaration() || parent->isTemplateInstance()))
{
if (f->purity == PUREimpure && // purity not specified
!f->hasLazyParameters()
)
{
if (f->purity == PUREimpure) // purity not specified
flags |= FUNCFLAGpurityInprocess;
}
if (f->trust == TRUSTdefault)
flags |= FUNCFLAGsafetyInprocess;
@@ -517,12 +524,13 @@ void FuncDeclaration::semantic(Scope *sc)
warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
#endif
if (fdv->toParent() == parent)
FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration();
if (fdc->toParent() == parent)
{
// If both are mixins, then error.
// If either is not, the one that is not overrides
// the other.
if (fdv->parent->isClassDeclaration())
if (fdc->parent->isClassDeclaration())
break;
if (!this->parent->isClassDeclaration()
#if !BREAKABI
@@ -2951,7 +2959,7 @@ int FuncDeclaration::addPreInvariant()
return (ad &&
//ad->isClassDeclaration() &&
global.params.useInvariants &&
(protection == PROTpublic || protection == PROTexport) &&
(protection == PROTprotected || protection == PROTpublic || protection == PROTexport) &&
!naked &&
ident != Id::cpctor);
}
@@ -2963,7 +2971,7 @@ int FuncDeclaration::addPostInvariant()
ad->inv &&
//ad->isClassDeclaration() &&
global.params.useInvariants &&
(protection == PROTpublic || protection == PROTexport) &&
(protection == PROTprotected || protection == PROTpublic || protection == PROTexport) &&
!naked &&
ident != Id::cpctor);
}
@@ -3224,10 +3232,10 @@ void CtorDeclaration::semantic(Scope *sc)
//printf("CtorDeclaration::semantic() %s\n", toChars());
TypeFunction *tf = (TypeFunction *)type;
assert(tf && tf->ty == Tfunction);
Expressions *fargs = ((TypeFunction *)type)->fargs; // for auto ref
sc = sc->push();
sc->stc &= ~STCstatic; // not a static constructor
sc->flags |= SCOPEctor;
parent = sc->parent;
Dsymbol *parent = toParent2();
@@ -3243,17 +3251,16 @@ void CtorDeclaration::semantic(Scope *sc)
{ tret = ad->handle;
assert(tret);
tret = tret->addStorageClass(storage_class | sc->stc);
tret = tret->addMod(type->mod);
}
tf = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
tf->fargs = fargs;
type = tf;
tf->next = tret;
type = type->semantic(loc, sc);
#if STRUCTTHISREF
if (ad && ad->isStructDeclaration())
{ ((TypeFunction *)type)->isref = 1;
if (!originalType)
// Leave off the "ref"
originalType = new TypeFunction(tf->parameters, tret, tf->varargs, LINKd, storage_class | sc->stc);
{ if (!originalType)
originalType = type->syntaxCopy();
((TypeFunction *)type)->isref = 1;
}
#endif
if (!originalType)
@@ -3319,18 +3326,6 @@ int CtorDeclaration::addPostInvariant()
}
void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
TypeFunction *tf = (TypeFunction *)type;
assert(tf && tf->ty == Tfunction);
if (originalType && originalType->ty == Tfunction)
((TypeFunction *)originalType)->attributesToCBuffer(buf, 0);
buf->writestring("this");
Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
bodyToCBuffer(buf, hgs);
}
/********************************* PostBlitDeclaration ****************************/
#if DMDV2

View File

@@ -73,6 +73,7 @@ Msgtable msgtable[] =
{ "line" },
{ "empty", "" },
{ "p" },
{ "q" },
{ "coverage", "__coverage" },
{ "__vptr" },
{ "__monitor" },
@@ -310,7 +311,17 @@ Msgtable msgtable[] =
{ "tan" },
{ "_sqrt", "sqrt" },
{ "_pow", "pow" },
{ "atan2" },
{ "rndtol" },
{ "expm1" },
{ "exp2" },
{ "yl2x" },
{ "yl2xp1" },
{ "fabs" },
{ "bitop" },
{ "bsf" },
{ "bsr" },
{ "bswap" },
// Traits
{ "isAbstractClass" },

View File

@@ -810,6 +810,9 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret)
if (!global.gag && olderrors != global.errors)
return this; // Failed, suppress duplicate error messages
if (exp->op == TOKtype)
error("initializer must be an expression, not '%s'", exp->toChars());
// Make sure all pointers are constants
if (needInterpret && hasNonConstPointers(exp))
{

View File

@@ -54,7 +54,7 @@ int CompoundStatement::inlineCost(InlineCostState *ics)
{ int cost = 0;
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
{
cost += s->inlineCost(ics);
@@ -69,7 +69,7 @@ int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
{ int cost = 0;
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
{
cost += s->inlineCost(ics);
@@ -147,7 +147,7 @@ int arrayInlineCost(InlineCostState *ics, Expressions *arguments)
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *e = arguments->tdata()[i];
{ Expression *e = (*arguments)[i];
if (e)
cost += e->inlineCost(ics);
@@ -211,6 +211,8 @@ int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
int StructLiteralExp::inlineCost(InlineCostState *ics)
{
if (sd->isnested)
return COST_MAX;
return 1 + arrayInlineCost(ics, elements);
}
@@ -246,7 +248,7 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
return COST_MAX; // finish DeclarationExp::doInline
#else
for (size_t i = 0; i < td->objects->dim; i++)
{ Object *o = td->objects->tdata()[i];
{ Object *o = (*td->objects)[i];
if (o->dyncast() != DYNCAST_EXPRESSION)
return COST_MAX;
Expression *eo = (Expression *)o;
@@ -379,7 +381,7 @@ Expression *CompoundStatement::doInline(InlineDoState *ids)
//printf("CompoundStatement::doInline() %d\n", statements->dim);
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
{
Expression *e2 = s->doInline(ids);
@@ -411,7 +413,7 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
//printf("UnrolledLoopStatement::doInline() %d\n", statements->dim);
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
{
Expression *e2 = s->doInline(ids);
@@ -843,9 +845,9 @@ Statement *ExpStatement::inlineScan(InlineScanState *iss)
Statement *CompoundStatement::inlineScan(InlineScanState *iss)
{
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
statements->tdata()[i] = s->inlineScan(iss);
(*statements)[i] = s->inlineScan(iss);
}
return this;
}
@@ -853,9 +855,9 @@ Statement *CompoundStatement::inlineScan(InlineScanState *iss)
Statement *UnrolledLoopStatement::inlineScan(InlineScanState *iss)
{
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = statements->tdata()[i];
{ Statement *s = (*statements)[i];
if (s)
statements->tdata()[i] = s->inlineScan(iss);
(*statements)[i] = s->inlineScan(iss);
}
return this;
}

File diff suppressed because it is too large Load Diff

View File

@@ -102,7 +102,7 @@ void Token::print()
const char *Token::toChars()
{ const char *p;
static char buffer[3 + 3 * sizeof(value) + 1];
static char buffer[3 + 3 * sizeof(float80value) + 1];
p = buffer;
switch (value)
@@ -298,28 +298,21 @@ Lexer::Lexer(Module *mod,
void Lexer::error(const char *format, ...)
{
if (mod && !global.gag)
{
char *p = loc.toChars();
if (*p)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
if (global.errors >= 20) // moderate blizzard of cascading messages
fatal();
}
global.errors++;
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end(ap);
}
void Lexer::error(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verror(loc, format, ap);
va_end(ap);
}
void Lexer::verror(Loc loc, const char *format, va_list ap)
{
if (mod && !global.gag)
{
@@ -328,10 +321,7 @@ void Lexer::error(Loc loc, const char *format, ...)
fprintf(stdmsg, "%s: ", p);
mem.free(p);
va_list ap;
va_start(ap, format);
vfprintf(stdmsg, format, ap);
va_end(ap);
fprintf(stdmsg, "\n");
fflush(stdmsg);
@@ -339,6 +329,10 @@ void Lexer::error(Loc loc, const char *format, ...)
if (global.errors >= 20) // moderate blizzard of cascading messages
fatal();
}
else
{
global.gaggedErrors++;
}
global.errors++;
}
@@ -2286,9 +2280,11 @@ done:
break;
}
#if DMDV2
if (state == STATE_octal && n >= 8 && !global.params.useDeprecated)
error("octal literals 0%llo%.*s are deprecated, use std.conv.octal!%llo%.*s instead",
n, p - psuffix, psuffix, n, p - psuffix, psuffix);
#endif
switch (flags)
{
@@ -3041,6 +3037,8 @@ void Lexer::initKeywords()
enum TOK v;
unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
stringtable.init();
if (global.params.Dversion == 1)
nkeywords -= 2;

View File

@@ -307,6 +307,7 @@ struct Lexer
TOK inreal(Token *t);
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();
unsigned decodeUTF();
void getDocComment(Token *t, unsigned lineComment);

File diff suppressed because it is too large Load Diff

View File

@@ -189,6 +189,7 @@ struct Param
#endif
ARCH cpu; // target CPU
OS os;
bool alwaysframe; // always emit standard stack frame
char map; // generate linker .map file
bool isLE; // generate little endian code
bool is64bit; // generate 64 bit code
@@ -307,9 +308,18 @@ struct Global
#endif
Param params;
unsigned errors; // number of errors reported so far
unsigned warnings; // number of warnings reported so far
unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned errors; // number of errors reported so far
unsigned warnings; // number of warnings reported so far
unsigned gag; // !=0 means gag reporting of errors & warnings
unsigned gaggedErrors; // number of errors reported while gagged
// Start gagging. Return the current number of gagged errors
unsigned startGagging();
/* End gagging, restoring the old gagged state.
* Return true if errors occured while gagged.
*/
bool endGagging(unsigned oldGagged);
Global();
};

View File

@@ -133,6 +133,10 @@ void Mem::mark(void *pointer)
(void) pointer; // necessary for VC /W4
}
void Mem::setStackBottom(void */*bottom*/)
{
}
/* =================================================== */
void * operator new(size_t m_size)
@@ -262,4 +266,8 @@ void Mem::mark(void *pointer)
{
}
void Mem::setStackBottom(void */*stackbottom*/)
{
}
#endif // USE_BOEHM_GC

View File

@@ -475,7 +475,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident)
{
for (size_t i = 0; i < global.path->dim; i++)
{
char *p = global.path->tdata()[i];
char *p = (*global.path)[i];
char *n = FileName::combine(p, sdi);
if (FileName::exists(n))
{ result = n;
@@ -795,6 +795,11 @@ void Module::parse()
#endif
p.nextToken();
members = p.parseModule();
::free(srcfile->buffer);
srcfile->buffer = NULL;
srcfile->len = 0;
md = p.md;
numlines = p.loc.linnum;
@@ -855,7 +860,7 @@ void Module::importAll(Scope *prevsc)
// Add import of "object" if this module isn't "object"
if (ident != Id::object)
{
if (members->dim == 0 || members->tdata()[0]->ident != Id::object)
if (members->dim == 0 || ((*members)[0])->ident != Id::object)
{
Import *im = new Import(0, NULL, Id::object, NULL, 0);
members->shift(im);

View File

@@ -211,7 +211,7 @@ struct Module : Package
llvm::PATypeHolder* moduleInfoType;
// array ops emitted in this module already
StringTable arrayfuncs;
AA *arrayfuncs;
bool isRoot;
#endif

View File

@@ -198,6 +198,10 @@ void Type::init(Ir* _sir)
void Type::init()
#endif
{
stringtable.init();
#if IN_LLVM
deco_stringtable.init();
#endif
Lexer::initKeywords();
for (size_t i = 0; i < TMAX; i++)
@@ -362,13 +366,10 @@ Type *Type::semantic(Loc loc, Scope *sc)
Type *Type::trySemantic(Loc loc, Scope *sc)
{
//printf("+trySemantic(%s) %d\n", toChars(), global.errors);
unsigned errors = global.errors;
global.gag++; // suppress printing of error messages
unsigned errors = global.startGagging();
Type *t = semantic(loc, sc);
global.gag--;
if (errors != global.errors) // if any errors happened
if (global.endGagging(errors)) // if any errors happened
{
global.errors = errors;
t = NULL;
}
//printf("-trySemantic(%s) %d\n", toChars(), global.errors);
@@ -1098,6 +1099,37 @@ Type *Type::makeMutable()
return t;
}
/*************************************
* Apply STCxxxx bits to existing type.
* Use *before* semantic analysis is run.
*/
Type *Type::addSTC(StorageClass stc)
{ Type *t = this;
if (stc & STCconst)
{ if (t->isShared())
t = t->makeSharedConst();
else
t = t->makeConst();
}
if (stc & STCimmutable)
t = t->makeInvariant();
if (stc & STCshared)
{ if (t->isConst())
t = t->makeSharedConst();
else
t = t->makeShared();
}
if (stc & STCwild)
{ if (t->isShared())
t = t->makeSharedWild();
else
t = t->makeWild();
}
return t;
}
/************************************
* Apply MODxxxx bits to existing type.
*/
@@ -1531,6 +1563,7 @@ void Type::modToBuffer(OutBuffer *buf)
Type *Type::merge()
{ Type *t;
if (ty == Terror) return this;
//printf("merge(%s)\n", toChars());
t = this;
assert(t);
@@ -2056,11 +2089,96 @@ int Type::hasWild()
* Return MOD bits matching argument type (targ) to wild parameter type (this).
*/
unsigned getWildModConv(Type *twild, Type *targ)
{
assert(twild);
assert(targ);
unsigned mod = 0;
if (twild->nextOf())
mod = getWildModConv(twild->nextOf(), targ->nextOf());
if (!mod)
{
if (twild->isWild())
{
if (targ->isWild())
mod = MODwild;
else if (targ->isConst())
mod = MODconst;
else if (targ->isImmutable())
mod = MODimmutable;
else if (targ->isMutable())
mod = MODmutable;
else
assert(0);
}
}
return mod;
}
unsigned Type::wildMatch(Type *targ)
{
//printf("Type::wildMatch this = '%s', targ = '%s'\n", toChars(), targ->toChars());
assert(hasWild());
Type *tc = substWildTo(MODconst);
if (targ->implicitConvTo(tc))
return getWildModConv(this, targ);
return 0;
}
Type *Type::substWildTo(unsigned mod)
{
//printf("+Type::substWildTo this = %s, mod = x%x\n", toChars(), mod);
Type *t;
if (nextOf())
{
t = nextOf()->substWildTo(mod);
if (t == nextOf())
t = this;
else
{
if (ty == Tpointer)
t = t->pointerTo();
else if (ty == Tarray)
t = t->arrayOf();
else if (ty == Tsarray)
t = new TypeSArray(t, ((TypeSArray *)this)->dim->syntaxCopy());
else if (ty == Taarray)
{
t = new TypeAArray(t, ((TypeAArray *)this)->index->syntaxCopy());
t = t->merge();
}
else
assert(0);
t = t->addMod(this->mod);
}
}
else
t = this;
if (isWild())
{
if (mod & MODconst)
t = t->constOf();
else if (mod & MODimmutable)
t = t->invariantOf();
else if (mod & MODwild)
t = t->wildOf();
else
t = t->mutableOf();
}
//printf("-Type::substWildTo t = %s\n", t->toChars());
return t;
}
/********************************
* We've mistakenly parsed this as a type.
* Redo it as an Expression.
@@ -2168,30 +2286,7 @@ Type *TypeNext::reliesOnTident()
int TypeNext::hasWild()
{
return mod == MODwild || next->hasWild();
}
/***************************************
* Return MOD bits matching argument type (targ) to wild parameter type (this).
*/
unsigned TypeNext::wildMatch(Type *targ)
{ unsigned mod;
Type *tb = targ->nextOf();
if (!tb)
return 0;
tb = tb->toBasetype();
if (tb->isMutable())
mod = MODmutable;
else if (tb->isConst() || tb->isWild())
return MODconst;
else if (tb->isImmutable())
mod = MODimmutable;
else
assert(0);
mod |= next->wildMatch(tb);
return mod;
return mod & MODwild || (next && next->hasWild());
}
@@ -3152,6 +3247,11 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
#if LOGDOTEXP
printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
#endif
if (!n->isMutable())
if (ident == Id::sort || ident == Id::reverse)
error(e->loc, "can only %s a mutable array\n", ident->toChars());
if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
{
Expression *ec;
@@ -3221,6 +3321,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
int size = next->size(e->loc);
int dup;
Expression *olde = e;
assert(size);
dup = (ident == Id::dup || ident == Id::idup);
//LDC: Build arguments.
@@ -3263,9 +3364,18 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
if (ident == Id::idup)
{ Type *einv = next->invariantOf();
if (next->implicitConvTo(einv) < MATCHconst)
error(e->loc, "cannot implicitly convert element type %s to immutable", next->toChars());
error(e->loc, "cannot implicitly convert element type %s to immutable in %s.idup",
next->toChars(), olde->toChars());
e->type = einv->arrayOf();
}
else if (ident == Id::dup)
{
Type *emut = next->mutableOf();
if (next->implicitConvTo(emut) < MATCHconst)
error(e->loc, "cannot implicitly convert element type %s to mutable in %s.dup",
next->toChars(), olde->toChars());
e->type = emut->arrayOf();
}
else
e->type = next->mutableOf()->arrayOf();
}
@@ -3479,10 +3589,11 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
return t;
}
next = next->semantic(loc,sc);
transitive();
Type *tn = next->semantic(loc,sc);
if (tn->ty == Terror)
return terror;
Type *tbn = next->toBasetype();
Type *tbn = tn->toBasetype();
if (dim)
{ dinteger_t n, n2;
@@ -3571,7 +3682,9 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
/* Ensure things like const(immutable(T)[3]) become immutable(T[3])
* and const(T)[3] become const(T[3])
*/
t = addMod(next->mod);
next = tn;
transitive();
t = addMod(tn->mod);
return t->merge();
@@ -3860,6 +3973,8 @@ Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
return new IntegerExp(se->loc, se->len, Type::tindex);
}
if (e->op == TOKnull)
return new IntegerExp(e->loc, 0, Type::tindex);
e = new ArrayLengthExp(e->loc, e);
e->type = Type::tsize_t;
return e;
@@ -4002,6 +4117,9 @@ d_uns64 TypeAArray::size(Loc loc)
Type *TypeAArray::semantic(Loc loc, Scope *sc)
{
//printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
if (deco)
return this;
this->loc = loc;
this->sc = sc;
if (sc)
@@ -4614,6 +4732,9 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e
if (stc & STCproperty)
this->isproperty = true;
if (stc & STCref)
this->isref = true;
this->trust = TRUSTdefault;
if (stc & STCsafe)
this->trust = TRUSTsafe;
@@ -4703,7 +4824,12 @@ int Type::covariant(Type *t)
}
}
else if (t1->parameters != t2->parameters)
goto Ldistinct;
{
size_t dim1 = !t1->parameters ? 0 : t1->parameters->dim;
size_t dim2 = !t2->parameters ? 0 : t2->parameters->dim;
if (dim1 || dim2)
goto Ldistinct;
}
// The argument lists match
if (inoutmismatch)
@@ -4879,8 +5005,6 @@ void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs
void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td)
{
//printf("TypeFunction::toCBuffer() this = %p\n", this);
const char *p = NULL;
if (inuse)
{ inuse = 2; // flag error to caller
return;
@@ -4919,19 +5043,16 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
break;
}
if (next && (!ident || ident->toHChars2() == ident->toChars()))
next->toCBuffer2(buf, hgs, 0);
else if (hgs->ddoc && !next)
buf->writestring("auto");
if (hgs->ddoc != 1)
{
const char *p = NULL;
switch (attrs->linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = "C "; break;
case LINKwindows: p = "Windows "; break;
case LINKpascal: p = "Pascal "; break;
case LINKcpp: p = "C++ "; break;
case LINKc: p = "C"; break;
case LINKwindows: p = "Windows"; break;
case LINKpascal: p = "Pascal"; break;
case LINKcpp: p = "C++"; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
@@ -4939,14 +5060,28 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
default:
assert(0);
}
if (!hgs->hdrgen && p)
{
buf->writestring("extern (");
buf->writestring(p);
buf->writestring(") ");
}
}
if (!ident || ident->toHChars2() == ident->toChars())
{ if (next)
next->toCBuffer2(buf, hgs, 0);
else if (hgs->ddoc)
buf->writestring("auto");
}
if (!hgs->hdrgen && p)
buf->writestring(p);
if (ident)
{ buf->writeByte(' ');
{
if (next || hgs->ddoc)
buf->writeByte(' ');
buf->writestring(ident->toHChars2());
}
if (td)
{ buf->writeByte('(');
for (size_t i = 0; i < td->origParameters->dim; i++)
@@ -4965,24 +5100,21 @@ void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, Hd
void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
//printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref);
const char *p = NULL;
if (inuse)
{ inuse = 2; // flag error to caller
return;
}
inuse++;
if (next)
next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1)
{
const char *p = NULL;
switch (linkage)
{
case LINKd: p = NULL; break;
case LINKc: p = " C"; break;
case LINKwindows: p = " Windows"; break;
case LINKpascal: p = " Pascal"; break;
case LINKcpp: p = " C++"; break;
case LINKc: p = "C"; break;
case LINKwindows: p = "Windows"; break;
case LINKpascal: p = "Pascal"; break;
case LINKcpp: p = "C++"; break;
// LDC
case LINKintrinsic: p = "Intrinsic"; break;
@@ -4990,11 +5122,19 @@ void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
default:
assert(0);
}
if (!hgs->hdrgen && p)
{
buf->writestring("extern (");
buf->writestring(p);
buf->writestring(") ");
}
}
if (!hgs->hdrgen && p)
buf->writestring(p);
buf->writestring(" function");
if (next)
{
next->toCBuffer2(buf, hgs, 0);
buf->writeByte(' ');
}
buf->writestring("function");
Parameter::argsToCBuffer(buf, hgs, parameters, varargs);
attributesToCBuffer(buf, mod);
inuse--;
@@ -5091,7 +5231,10 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
bool wildreturn = FALSE;
if (tf->next)
{
sc = sc->push();
sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
tf->next = tf->next->semantic(loc,sc);
sc = sc->pop();
#if !SARRAYVALUE
if (tf->next->toBasetype()->ty == Tsarray)
{ error(loc, "functions cannot return static array %s", tf->next->toChars());
@@ -5110,7 +5253,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
error(loc, "functions cannot return scope %s", tf->next->toChars());
if (tf->next->toBasetype()->ty == Tvoid)
tf->isref = FALSE; // rewrite "ref void" as just "void"
if (tf->next->isWild())
if (tf->next->hasWild() &&
!(tf->next->ty == Tpointer && tf->next->nextOf()->ty == Tfunction || tf->next->ty == Tdelegate))
wildreturn = TRUE;
}
@@ -5152,7 +5296,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
if (!(fparam->storageClass & STClazy) && t->ty == Tvoid)
error(loc, "cannot have parameter of type %s", fparam->type->toChars());
if (t->isWild())
if (t->hasWild() &&
!(t->ty == Tpointer && t->nextOf()->ty == Tfunction || t->ty == Tdelegate))
{
wildparams = TRUE;
if (tf->next && !wildreturn)
@@ -5211,6 +5356,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
argsc->pop();
}
if (tf->isWild())
wildparams = TRUE;
if (wildreturn && !wildparams)
error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
if (wildsubparams && wildparams)
@@ -5338,6 +5486,11 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
{
if (MODimplicitConv(t->mod, mod))
match = MATCHconst;
else if ((mod & MODwild)
&& MODimplicitConv(t->mod, (mod & ~MODwild) | MODconst))
{
match = MATCHconst;
}
else
return MATCHnomatch;
}
@@ -5406,15 +5559,15 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
else
m = arg->implicitConvTo(p->type);
//printf("match %d\n", m);
if (p->type->isWild())
if (p->type->hasWild())
{
if (m == MATCHnomatch)
{
m = arg->implicitConvTo(p->type->constOf());
if (m == MATCHnomatch)
m = arg->implicitConvTo(p->type->sharedConstOf());
if (m != MATCHnomatch)
if (p->type->wildMatch(arg->type))
{
wildmatch = TRUE; // mod matched to wild
m = MATCHconst;
}
}
else
exactwildmatch = TRUE; // wild matched to wild
@@ -5422,11 +5575,17 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
/* If both are allowed, then there could be more than one
* binding of mod to wild, leaving a gaping type hole.
*/
if (wildmatch && exactwildmatch)
m = MATCHnomatch;
//if (wildmatch && exactwildmatch)
// m = MATCHnomatch;
}
}
/* prefer matching the element type rather than the array
* type when more arguments are present with T[]...
*/
if (varargs == 2 && u + 1 == nparams && nargs > nparams)
goto L1;
//printf("\tm = %d\n", m);
if (m == MATCHnomatch) // if no match
{
@@ -5823,7 +5982,14 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
t = s->getType();
if (!t && s->isDeclaration())
t = s->isDeclaration()->type;
{ t = s->isDeclaration()->type;
if (!t && s->isTupleDeclaration())
{
e = new TupleExp(loc, s->isTupleDeclaration());
e = e->semantic(sc);
t = e->type;
}
}
if (t)
{
sm = t->toDsymbol(sc);
@@ -6192,15 +6358,12 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc)
if (sc->parameterSpecialization)
{
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
resolve(loc, sc, &e, &t, &s);
global.gag--;
if (errors != global.errors)
{ if (global.gag == 0)
global.errors = errors;
if (global.endGagging(errors))
{
return this;
}
}
@@ -6225,17 +6388,12 @@ Dsymbol *TypeInstance::toDsymbol(Scope *sc)
if (sc->parameterSpecialization)
{
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
resolve(loc, sc, &e, &t, &s);
global.gag--;
if (errors != global.errors)
{ if (global.gag == 0)
global.errors = errors;
if (global.endGagging(errors))
return NULL;
}
}
else
resolve(loc, sc, &e, &t, &s);
@@ -6790,7 +6948,10 @@ char *TypeTypedef::toChars()
Type *TypeTypedef::semantic(Loc loc, Scope *sc)
{
//printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
int errors = global.errors;
sym->semantic(sc);
if (errors != global.errors)
return terror;
return merge();
}
@@ -7024,6 +7185,7 @@ int TypeTypedef::hasPointers()
int TypeTypedef::hasWild()
{
assert(toBasetype());
return mod & MODwild || toBasetype()->hasWild();
}
@@ -7459,13 +7621,10 @@ MATCH TypeStruct::implicitConvTo(Type *to)
/* If there is an error instantiating AssociativeArray!(), it shouldn't
* be reported -- it just means implicit conversion is impossible.
*/
++global.gag;
int errs = global.errors;
int errs = global.startGagging();
to = ((TypeAArray*)to)->getImpl()->type;
--global.gag;
if (errs != global.errors)
if (global.endGagging(errs))
{
global.errors = errs;
return MATCHnomatch;
}
}

View File

@@ -286,6 +286,7 @@ struct Type : Object
Type *sharedWildOf();
void fixTo(Type *t);
void check();
Type *addSTC(StorageClass stc);
Type *castMod(unsigned mod);
Type *addMod(unsigned mod);
Type *addStorageClass(StorageClass stc);
@@ -317,7 +318,7 @@ struct Type : Object
virtual dt_t **toDt(dt_t **pdt);
#endif
Identifier *getTypeInfoIdent(int internal);
virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
virtual MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
virtual void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Expression *getInternalTypeInfo(Scope *sc);
Expression *getTypeInfo(Scope *sc);
@@ -325,7 +326,8 @@ struct Type : Object
virtual int builtinTypeInfo();
virtual Type *reliesOnTident();
virtual int hasWild();
virtual unsigned wildMatch(Type *targ);
unsigned wildMatch(Type *targ);
Type *substWildTo(unsigned mod);
virtual Expression *toExpression();
virtual int hasPointers();
virtual TypeTuple *toArgTypes();
@@ -376,7 +378,6 @@ struct TypeNext : Type
void checkDeprecated(Loc loc, Scope *sc);
Type *reliesOnTident();
int hasWild();
unsigned wildMatch(Type *targ);
Type *nextOf();
Type *makeConst();
Type *makeInvariant();
@@ -456,7 +457,7 @@ struct TypeSArray : TypeArray
dt_t **toDt(dt_t **pdt);
dt_t **toDtElem(dt_t **pdt, Expression *e);
#endif
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
Expression *toExpression();
int hasPointers();
@@ -489,7 +490,7 @@ struct TypeDArray : TypeArray
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
int builtinTypeInfo();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
TypeTuple *toArgTypes();
@@ -520,7 +521,7 @@ struct TypeAArray : TypeArray
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
int isZeroInit(Loc loc);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -630,7 +631,7 @@ struct TypeFunction : TypeNext
void toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td);
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void attributesToCBuffer(OutBuffer *buf, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident();
bool hasLazyParameters();
@@ -713,7 +714,7 @@ struct TypeIdentifier : TypeQualified
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
Type *reliesOnTident();
Expression *toExpression();
};
@@ -732,7 +733,7 @@ struct TypeInstance : TypeQualified
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
};
struct TypeTypeof : TypeQualified
@@ -781,7 +782,7 @@ struct TypeStruct : Type
#if IN_DMD
dt_t **toDt(dt_t **pdt);
#endif
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
TypeTuple *toArgTypes();
@@ -832,7 +833,7 @@ struct TypeEnum : Type
Type *toBasetype();
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
TypeTuple *toArgTypes();
@@ -879,7 +880,7 @@ struct TypeTypedef : Type
#if IN_DMD
dt_t **toDt(dt_t **pdt);
#endif
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
TypeTuple *toArgTypes();
@@ -913,7 +914,7 @@ struct TypeClass : Type
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
int isZeroInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL);
int isscope();
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();

View File

@@ -1275,7 +1275,10 @@ void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Mo
break;
goto Lapply;
}
// Resolve inout qualifier of front type
arg->type = fd->type->nextOf();
if (arg->type)
arg->type = arg->type->substWildTo(tab->mod);
}
break;
}

View File

@@ -874,6 +874,71 @@ Expression *XorExp::optimize(int result)
return e;
}
Expression *PowExp::optimize(int result)
{ Expression *e;
e1 = e1->optimize(result);
e2 = e2->optimize(result);
// Replace 1 ^^ x or 1.0^^x by (x, 1)
if ((e1->op == TOKint64 && e1->toInteger() == 1) ||
(e1->op == TOKfloat64 && e1->toReal() == 1.0))
{
e = new CommaExp(loc, e2, e1);
}
// Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
else if (e2->type->isintegral() && e1->op == TOKint64 && (sinteger_t)e1->toInteger() == -1L)
{
Type* resultType = type;
e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2->type));
e = new CondExp(loc, e, new IntegerExp(loc, -1L, resultType), new IntegerExp(loc, 1L, resultType));
}
// Replace x ^^ 0 or x^^0.0 by (x, 1)
else if ((e2->op == TOKint64 && e2->toInteger() == 0) ||
(e2->op == TOKfloat64 && e2->toReal() == 0.0))
{
if (e1->type->isintegral())
e = new IntegerExp(loc, 1, e1->type);
else
e = new RealExp(loc, 1.0, e1->type);
e = new CommaExp(loc, e1, e);
}
// Replace x ^^ 1 or x^^1.0 by (x)
else if ((e2->op == TOKint64 && e2->toInteger() == 1) ||
(e2->op == TOKfloat64 && e2->toReal() == 1.0))
{
e = e1;
}
// 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);
}
// All other negative integral powers are illegal
else if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
{
error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
e1->type->toBasetype()->toChars(), e1->toChars(), e2->toChars());
e = new ErrorExp();
}
else
{
// If e2 *could* have been an integer, make it one.
if (e2->op == TOKfloat64 && (e2->toReal() == (sinteger_t)(e2->toReal())))
e2 = new IntegerExp(loc, e2->toInteger(), Type::tint64);
if (e1->isConst() == 1 && e2->isConst() == 1)
{
e = Pow(type, e1, e2);
if (e != EXP_CANT_INTERPRET)
return e;
}
e = this;
}
return e;
}
Expression *CommaExp::optimize(int result)
{ Expression *e;

View File

@@ -386,10 +386,16 @@ Dsymbols *Parser::parseDeclDefs(int once)
storageClass |= stc;
switch (token.value)
{
case TOKshared:
// Look for "shared static this" or "shared static ~this"
if (peekNext() == TOKstatic)
{ TOK next2 = peekNext2();
if (next2 == TOKthis || next2 == TOKtilde)
break;
}
case TOKconst:
case TOKinvariant:
case TOKimmutable:
case TOKshared:
case TOKwild:
// If followed by a (, it is not a storage class
if (peek(&token)->value == TOKlparen)
@@ -547,7 +553,7 @@ Dsymbols *Parser::parseDeclDefs(int once)
nextToken();
if (token.value == TOKidentifier)
s = new DebugSymbol(loc, token.ident);
else if (token.value == TOKint32v)
else if (token.value == TOKint32v || token.value == TOKint64v)
s = new DebugSymbol(loc, (unsigned)token.uns64value);
else
{ error("identifier or integer expected, not %s", token.toChars());
@@ -570,7 +576,7 @@ Dsymbols *Parser::parseDeclDefs(int once)
nextToken();
if (token.value == TOKidentifier)
s = new VersionSymbol(loc, token.ident);
else if (token.value == TOKint32v)
else if (token.value == TOKint32v || token.value == TOKint64v)
s = new VersionSymbol(loc, (unsigned)token.uns64value);
else
{ error("identifier or integer expected, not %s", token.toChars());
@@ -699,10 +705,9 @@ StorageClass Parser::parsePostfix()
case TOKpure: stc |= STCpure; break;
case TOKat: stc |= parseAttribute(); break;
default:
composeStorageClass(stc);
return stc;
default: return stc;
}
composeStorageClass(stc);
nextToken();
}
}
@@ -876,7 +881,7 @@ Condition *Parser::parseDebugCondition()
if (token.value == TOKidentifier)
id = token.ident;
else if (token.value == TOKint32v)
else if (token.value == TOKint32v || token.value == TOKint64v)
level = (unsigned)token.uns64value;
else
error("identifier or integer expected, not %s", token.toChars());
@@ -905,7 +910,7 @@ Condition *Parser::parseVersionCondition()
nextToken();
if (token.value == TOKidentifier)
id = token.ident;
else if (token.value == TOKint32v)
else if (token.value == TOKint32v || token.value == TOKint64v)
level = (unsigned)token.uns64value;
#if DMDV2
/* Allow:
@@ -995,7 +1000,9 @@ Dsymbol *Parser::parseCtor()
Expression *constraint = tpl ? parseConstraint() : NULL;
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
tf = tf->addSTC(stc);
CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf);
parseContracts(f);
@@ -1012,7 +1019,9 @@ Dsymbol *Parser::parseCtor()
int varargs;
Parameters *parameters = parseParameters(&varargs);
StorageClass stc = parsePostfix();
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
Type *tf = new TypeFunction(parameters, NULL, varargs, linkage, stc); // RetrunType -> auto
tf = tf->addSTC(stc);
CtorDeclaration *f = new CtorDeclaration(loc, 0, stc, tf);
parseContracts(f);
return f;
@@ -2633,27 +2642,7 @@ Type *Parser::parseDeclarator(Type *t, Identifier **pident, TemplateParameters *
StorageClass stc = parsePostfix();
stc |= storage_class; // merge prefix storage classes
Type *tf = new TypeFunction(arguments, t, varargs, linkage, stc);
if (stc & STCconst)
{ if (tf->isShared())
tf = tf->makeSharedConst();
else
tf = tf->makeConst();
}
if (stc & STCimmutable)
tf = tf->makeInvariant();
if (stc & STCshared)
{ if (tf->isConst())
tf = tf->makeSharedConst();
else
tf = tf->makeShared();
}
if (stc & STCwild)
{ if (tf->isShared())
tf = tf->makeSharedWild();
else
tf = tf->makeWild();
}
tf = tf->addSTC(stc);
/* Insert tf into
* ts -> ... -> t
@@ -3681,6 +3670,10 @@ Statement *Parser::parseStatement(int flags)
check(TOKlparen);
condition = parseExpression();
check(TOKrparen);
if (token.value == TOKsemicolon)
nextToken();
else if (!global.params.useDeprecated)
error("do-while statement requires terminating ;");
s = new DoStatement(loc, body, condition);
break;
}
@@ -5764,9 +5757,12 @@ Expression *Parser::parseUnaryExp()
case TOKimmutable: // immutable(type)(arguments)
{
Type *t = parseBasicType();
if (token.value != TOKlparen)
error("(arguments) expected following type");
e = new TypeExp(loc, t);
if (token.value != TOKlparen)
{
error("(arguments) expected following %s", t->toChars());
return e;
}
e = new CallExp(loc, e, parseArguments());
break;
}

View File

@@ -1,16 +0,0 @@
#ifndef __RMEM_H__
#define __RMEM_H__
// jam memory stuff here
#include "mem.h"
#if (defined (__SVR4) && defined (__sun))
#include <alloca.h>
#endif
#ifdef __MINGW32__
#include <malloc.h>
#endif
#endif // __RMEM_H__

View File

@@ -12,7 +12,6 @@
#include <process.h>
#include "root.h"
#include "rmem.h"
static unsigned __stdcall startthread(void *p);
@@ -41,7 +40,7 @@ struct AsyncRead
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
@@ -92,7 +91,7 @@ int AsyncRead::read(size_t i)
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
free(aw);
}
@@ -119,7 +118,6 @@ unsigned __stdcall startthread(void *p)
#include <time.h>
#include "root.h"
#include "rmem.h"
void *startthread(void *arg);
@@ -155,7 +153,7 @@ struct AsyncRead
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
@@ -228,7 +226,7 @@ void AsyncRead::dispose(AsyncRead *aw)
if (status != 0)
err_abort(status, "mutex destroy");
}
delete aw;
free(aw);
}
@@ -265,7 +263,6 @@ void *startthread(void *p)
#include <errno.h>
#include "root.h"
#include "rmem.h"
struct FileData
{
@@ -292,7 +289,7 @@ struct AsyncRead
AsyncRead *AsyncRead::create(size_t nfiles)
{
AsyncRead *aw = (AsyncRead *)mem.calloc(1, sizeof(AsyncRead) +
AsyncRead *aw = (AsyncRead *)calloc(1, sizeof(AsyncRead) +
(nfiles - 1) * sizeof(FileData));
aw->filesmax = nfiles;
return aw;
@@ -322,7 +319,7 @@ int AsyncRead::read(size_t i)
void AsyncRead::dispose(AsyncRead *aw)
{
delete aw;
free(aw);
}
#endif

43
dmd2/root/bits.c Normal file
View File

@@ -0,0 +1,43 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <assert.h>
#include <stdlib.h>
#include "bits.h"
GCBits::GCBits()
{
data = NULL;
nwords = 0;
nbits = 0;
}
GCBits::~GCBits()
{
if (data)
::free(data);
data = NULL;
}
void GCBits::invariant()
{
if (data)
{
assert(nwords * sizeof(*data) * 8 >= nbits);
}
}
void GCBits::alloc(unsigned nbits)
{
this->nbits = nbits;
nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT;
data = (unsigned *)::calloc(nwords + 2, sizeof(unsigned));
assert(data);
}

83
dmd2/root/bits.h Normal file
View File

@@ -0,0 +1,83 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <string.h>
#if __DMC__
// Inline bit operations
#include <bitops.h>
#endif
#ifdef linux
#include "gccbitops.h"
#endif
#if _MSC_VER
// Disable useless warnings about unreferenced functions
#pragma warning (disable : 4514)
#endif // _MSC_VER
#define BITS_PER_WORD 32
#define BITS_SHIFT 5
#define BITS_MASK 31
struct Mem;
struct GCBits
{
unsigned *data;
unsigned nwords; // allocated words in data[] excluding sentinals
unsigned nbits; // number of bits in data[] excluding sentinals
GCBits();
~GCBits();
void invariant();
void alloc(unsigned nbits);
#if __DMC__
unsigned test(unsigned i) { return _inline_bt(data + 1, i); }
void set(unsigned i) { _inline_bts(data + 1, i); }
void clear(unsigned i) { _inline_btr(data + 1, i); }
unsigned testClear(unsigned i) { return _inline_btr(data + 1, i); }
unsigned testSet(unsigned i) { return _inline_bts(data + 1, i); }
#elif 0 //defined linux
// for unknown reasons, GCC does badly with this
unsigned test(unsigned i) { return _inline_bt(data + 1, i); }
void set(unsigned i) { _inline_bts(data + 1, i); }
void clear(unsigned i) { _inline_btr(data + 1, i); }
unsigned testClear(unsigned i) { return _inline_btr(data + 1, i); }
unsigned testSet(unsigned i) { return _inline_bts(data + 1, i); }
#else
unsigned test(unsigned i) { return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK)); }
void set(unsigned i) { data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK)); }
void clear(unsigned i) { data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK)); }
unsigned testClear(unsigned i)
{
unsigned *p = &data[1 + (i >> BITS_SHIFT)];
unsigned mask = (1 << (i & BITS_MASK));
unsigned result = *p & mask;
*p &= ~mask;
return result;
}
unsigned testSet(unsigned i)
{
unsigned *p = &data[1 + (i >> BITS_SHIFT)];
unsigned mask = (1 << (i & BITS_MASK));
unsigned result = *p & mask;
*p |= mask;
return result;
}
#endif
void zero() { memset(data + 1, 0, nwords * sizeof(unsigned)); }
void copy(GCBits *f) { memcpy(data + 1, f->data + 1, nwords * sizeof(unsigned)); }
unsigned *base() { return data + 1; }
};

499
dmd2/root/dmgcmem.c Normal file
View File

@@ -0,0 +1,499 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#include <unistd.h>
#include <pthread.h>
#endif
#include "rmem.h"
#include "gc/gc.h"
//#include "printf.h"
/* This implementation of the storage allocator uses the Digital Mars gc.
*/
Mem mem;
//static int nuncollectable;
extern "C"
{
void gc_init();
GC *gc_get();
}
void Mem::init()
{
gc_init();
}
char *Mem::strdup(const char *s)
{
return gc_get()->strdup(s);
}
void *Mem::malloc(size_t size)
{
if (gc) // if cached allocator
{
// PRINTF("Using cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return ((GC *)gc)->malloc(size);
}
if (this == &mem) // don't cache global mem
{
// PRINTF("Using global gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
// GC::file = NULL;
// GC::line = 0;
return gc_get()->malloc(size);
}
// PRINTF("Generating cached gc for size %d, file = '%s', line = %d\n", size, GC::file, GC::line);
gc = gc_get();
return gc->malloc(size);
}
void *Mem::malloc_uncollectable(size_t size)
{ void *p;
p = ::malloc(size);
if (!p)
error();
addroots((char *)p, (char *)p + size);
#if 0
++nuncollectable;
WPRINTF(L"malloc_uncollectable(%u) = %x, n=%d\n", size, p, nuncollectable);
#endif
return p;
}
void *Mem::calloc(size_t size, size_t n)
{
return gc_get()->calloc(size, n);
}
void *Mem::realloc(void *p, size_t size)
{
return gc_get()->realloc(p, size);
}
void Mem::free(void *p)
{
gc_get()->free(p);
}
void Mem::free_uncollectable(void *p)
{
if (p)
{ removeroots((char *)p);
::free(p);
#if 0
--nuncollectable;
WPRINTF(L"free_uncollectable(%x) n=%d\n", p, nuncollectable);
#endif
#if 0
gc_get()->fullcollect();
GCStats stats;
getStats(&stats);
WPRINTF(L"poolsize = %x, usedsize = %x, freelistsize = %x\n",
stats.poolsize, stats.usedsize, stats.freelistsize);
#endif
}
}
void *Mem::mallocdup(void *o, size_t size)
{
return gc_get()->mallocdup(o, size);
}
void Mem::check(void *p)
{
if (gc)
gc->check(p);
else
gc_get()->check(p);
}
void Mem::error()
{
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
assert(0);
#endif
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
gc_get()->fullcollect();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::fullcollectNoStack()
{
gc_get()->fullcollectNoStack();
#if 0
{
GCStats stats;
gc_get()->getStats(&stats);
WPRINTF(L"Thread %x ", Thread::getId());
WPRINTF(L"poolsize=x%x, usedsize=x%x, freelistsize=x%x, freeblocks=%d, pageblocks=%d\n",
stats.poolsize, stats.usedsize, stats.freelistsize, stats.freeblocks, stats.pageblocks);
}
#endif
}
void Mem::mark(void *pointer)
{
(void) pointer; // for VC /W4 compatibility
}
void Mem::addroots(char* pStart, char* pEnd)
{
gc_get()->addRange(pStart, pEnd);
}
void Mem::removeroots(char* pStart)
{
gc_get()->removeRange(pStart);
}
void Mem::setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData)
{
(void)pClientData;
gc_get()->setFinalizer(pObj, pFn);
}
void Mem::setStackBottom(void *stackbottom)
{
gc_get()->setStackBottom(stackbottom);
}
GC *Mem::getThreadGC()
{
return gc_get();
}
/* =================================================== */
#if 1
void * operator new(size_t m_size)
{
//PRINTF("Call to global operator new(%d), file = '%s', line = %d\n", m_size, GC::file ? GC::file : "(null)", GC::line);
GC::file = NULL;
GC::line = 0;
return mem.malloc(m_size);
}
void operator delete(void *p)
{
//WPRINTF(L"Call to global operator delete\n");
mem.free(p);
}
void* operator new[](size_t size)
{
return operator new(size);
}
void operator delete[](void *pv)
{
operator delete(pv);
}
#endif
void * Mem::operator new(size_t m_size)
{ void *p;
p = gc_get()->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
mem.error();
return p;
}
void * Mem::operator new(size_t m_size, Mem *mem)
{ void *p;
p = mem->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void * Mem::operator new(size_t m_size, GC *gc)
{ void *p;
// if (!gc)
// WPRINTF(L"gc is NULL\n");
p = gc->malloc(m_size);
//printf("Mem::operator new(%d) = %p\n", m_size, p);
if (!p)
::mem.error();
return p;
}
void Mem::operator delete(void *p)
{
// printf("Mem::operator delete(%p)\n", p);
gc_get()->free(p);
}
/* ============================================================ */
/* The following section of code exists to find the right
* garbage collector for this thread. There is one independent instance
* of the collector per thread.
*/
/* ===================== linux ================================ */
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
#include <pthread.h>
#define LOG 0 // log thread creation / destruction
extern "C"
{
// Key identifying the thread-specific data
static pthread_key_t gc_key;
/* "Once" variable ensuring that the key for gc_alloc will be allocated
* exactly once.
*/
static pthread_once_t gc_alloc_key_once = PTHREAD_ONCE_INIT;
/* Forward functions */
static void gc_alloc_key();
static void gc_alloc_destroy_gc(void * accu);
void gc_init()
{
#if LOG
WPRINTF(L"Thread %lx: gc_init()\n", pthread_self());
#endif
pthread_once(&gc_alloc_key_once, gc_alloc_key);
#if LOG
WPRINTF(L"Thread %lx: gc_init() return\n", pthread_self());
#endif
}
GC *gc_get()
{
GC *gc;
// Get the thread-specific data associated with the key
gc = (GC *) pthread_getspecific(gc_key);
// It's initially NULL, meaning that we must allocate the buffer first.
if (gc == NULL)
{
GC_LOG();
gc = new GC();
gc->init();
// Store the buffer pointer in the thread-specific data.
pthread_setspecific(gc_key, (void *) gc);
#if LOG
WPRINTF(L"Thread %lx: allocating gc at %x\n", pthread_self(), gc);
#endif
}
return gc;
}
// Function to allocate the key for gc_alloc thread-specific data.
static void gc_alloc_key()
{
pthread_key_create(&gc_key, gc_alloc_destroy_gc);
#if LOG
WPRINTF(L"Thread %lx: allocated gc key %d\n", pthread_self(), gc_key);
#endif
}
// Function to free the buffer when the thread exits.
// Called only when the thread-specific data is not NULL.
static void gc_alloc_destroy_gc(void *gc)
{
#if LOG
WPRINTF(L"Thread %x: freeing gc at %x\n", pthread_self(), gc);
#endif
delete (GC *)gc;
}
}
#endif
/* ===================== win32 ================================ */
#if !defined(linux) && defined(_WIN32)
#if 1 // single threaded version
extern "C"
{
static GC *gc;
void gc_init()
{
if (!gc)
{ gc = (GC *)::malloc(sizeof(GC));
gc->init();
}
}
GC *gc_get()
{
return gc;
}
}
#else // multi threaded version
#include "mutex.h"
#include "thread.h"
/* This is the win32 version. It suffers from the bug that
* when the thread exits the data structure is not cleared,
* but the memory pool it points to is free'd.
* Thus, if a new thread comes along with the same thread id,
* the data will look initialized, but will point to garbage.
*
* What needs to happen is when a thread exits, the associated
* GC_context data struct is cleared.
*/
struct GC_context
{
ThreadId threadid; // identifier of current thread
GC *gc;
};
Mutex gc_mutex;
static GC_context array[64];
// Array of pointers to GC_context objects, one per threadid
GC_context *gccontext = array;
unsigned gccontext_allocdim = 64;
unsigned gccontext_dim;
ThreadId gc_cache_ti;
GC_context *gc_cache_cc;
extern "C" void gc_init()
{
}
extern "C" GC *gc_get()
{
/* This works by creating an array of GC_context's, one
* for each thread. We match up by thread id.
*/
ThreadId ti;
GC_context *cc;
//PRINTF("gc_get()\n");
ti = Thread::getId();
gc_mutex.acquire();
// Used cached version if we can
if (ti == gc_cache_ti)
{
cc = gc_cache_cc;
//exception(L"getGC_context(): cache x%x", ti);
}
else
{
// This does a linear search through gccontext[].
// A hash table might be faster if there are more
// than a dozen threads.
GC_context *ccp;
GC_context *ccptop = &gccontext[gccontext_dim];
for (ccp = gccontext; ccp < ccptop; ccp++)
{
cc = ccp;
if (cc->threadid == ti)
{
WPRINTF(L"getGC_context(): existing x%x", ti);
goto Lret;
}
}
// Do not allocate with garbage collector, as this must reside
// global to all threads.
assert(gccontext_dim < gccontext_allocdim);
cc = ccp;
memset(cc, 0, sizeof(*cc));
cc->threadid = ti;
cc->gc = new GC();
cc->gc->init();
gccontext_dim++;
WPRINTF(L"getGC_context(): new x%x\n", ti);
Lret:
// Cache for next time
gc_cache_ti = ti;
gc_cache_cc = cc;
}
gc_mutex.release();
return cc->gc;
}
#endif
#endif

2223
dmd2/root/gc.c Normal file

File diff suppressed because it is too large Load Diff

68
dmd2/root/gc.h Normal file
View File

@@ -0,0 +1,68 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#ifndef GC_H
#define GC_H
struct Gcx; // private data
typedef void (*GC_FINALIZER)(void *p, void *dummy);
struct GCStats
{
unsigned poolsize; // total size of pool
unsigned usedsize; // bytes allocated
unsigned freeblocks; // number of blocks marked FREE
unsigned freelistsize; // total of memory on free lists
unsigned pageblocks; // number of blocks marked PAGE
};
struct GC
{
// For passing to debug code
static unsigned line;
static char *file;
// #define GC_LOG() ((GC::line = __LINE__), (GC::file = __FILE__))
#define GC_LOG() ((void)0)
Gcx *gcx; // implementation
~GC();
void init();
char *strdup(const char *s);
void *malloc(size_t size);
void *malloc_atomic(size_t size);
void *calloc(size_t size, size_t n);
void *realloc(void *p, size_t size);
void free(void *p);
void *mallocdup(void *o, size_t size);
void check(void *p);
void error();
void setStackBottom(void *p);
void addRoot(void *p); // add p to list of roots
void removeRoot(void *p); // remove p from list of roots
void addRange(void *pbot, void *ptop); // add range to scan for roots
void removeRange(void *pbot); // remove range
void fullcollect(); // do full garbage collection
void fullcollectNoStack(); // do full garbage collection; no scan stack
void gencollect(); // do generational garbage collection
void minimize(); // minimize physical memory usage
void setFinalizer(void *p, GC_FINALIZER pFn);
void getStats(GCStats *stats);
};
#endif

69
dmd2/root/gccbitops.h Normal file
View File

@@ -0,0 +1,69 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
// Bit operations for GCC and I386
#ifndef GCCBITOPS_H
#define GCCBITOPS_H 1
inline int _inline_bsf(int w)
{ int index;
__asm__ __volatile__
(
"bsfl %1, %0 \n\t"
: "=r" (index)
: "r" (w)
);
return index;
}
inline int _inline_bt(unsigned *p, int i)
{
char result;
__asm__ __volatile__
(
"btl %2,%1 \n\t"
"setc %0 \n\t"
:"=r" (result)
:"m" (*p), "r" (i)
);
return result;
}
inline int _inline_bts(unsigned *p, int i)
{
char result;
__asm__ __volatile__
(
"btsl %2,%1 \n\t"
"setc %0 \n\t"
:"=r" (result)
:"m" (*p), "r" (i)
);
return result;
}
inline int _inline_btr(unsigned *p, int i)
{
char result;
__asm__ __volatile__
(
"btrl %2,%1 \n\t"
"setc %0 \n\t"
:"=r" (result)
:"m" (*p), "r" (i)
);
return result;
}
#endif

96
dmd2/root/linux.c Normal file
View File

@@ -0,0 +1,96 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
/*************************************
* This is all necessary to get fd initialized at startup.
*/
#define FDMAP 0
#if FDMAP
#include <fcntl.h>
struct OS_INIT
{
static int fd;
OS_INIT();
};
OS_INIT os_init;
int OS_INIT::fd = 0;
OS_INIT::OS_INIT()
{
fd = open("/dev/zero", O_RDONLY);
}
#endif
/***********************************
* Map memory.
*/
void *os_mem_map(unsigned nbytes)
{ void *p;
errno = 0;
#if FDMAP
p = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, OS_INIT::fd, 0);
#else
p = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#endif
return (p == MAP_FAILED) ? NULL : p;
}
/***********************************
* Commit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_commit(void *base, unsigned offset, unsigned nbytes)
{
return 0;
}
/***********************************
* Decommit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_decommit(void *base, unsigned offset, unsigned nbytes)
{
return 0;
}
/***********************************
* Unmap memory allocated with os_mem_map().
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_unmap(void *base, unsigned nbytes)
{
return munmap(base, nbytes);
}

25
dmd2/root/mscbitops.h Normal file
View File

@@ -0,0 +1,25 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
// Bit operations for MSC and I386
#ifndef MSCBITOPS_H
#define MSCBITOPS_H 1
inline int _inline_bsf(int w)
{ int index;
index = 0;
while (!(w & 1))
{ index++;
w >>= 1;
}
return index;
}
#endif

25
dmd2/root/os.h Normal file
View File

@@ -0,0 +1,25 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
// OS specific routines
void *os_mem_map(unsigned nbytes);
int os_mem_commit(void *base, unsigned offset, unsigned nbytes);
int os_mem_decommit(void *base, unsigned offset, unsigned nbytes);
int os_mem_unmap(void *base, unsigned nbytes);
// Threading
#if defined linux
#include <pthread.h>
#else
typedef long pthread_t;
pthread_t pthread_self();
#endif

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2000-2001 by Chromium Communications
// Copyright (C) 2000-2011 by Digital Mars
// All Rights Reserved
#ifndef ROOT_MEM_H

View File

@@ -1087,7 +1087,7 @@ int File::read()
}
if (!ref)
mem.free(buffer);
::free(buffer);
ref = 0; // we own the buffer now
//printf("\tfile opened\n");
@@ -1097,7 +1097,7 @@ int File::read()
goto err2;
}
size = buf.st_size;
buffer = (unsigned char *) mem.malloc(size + 2);
buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer)
{
printf("\tmalloc error, errno = %d\n",errno);
@@ -1130,7 +1130,7 @@ int File::read()
err2:
close(fd);
err:
mem.free(buffer);
::free(buffer);
buffer = NULL;
len = 0;
@@ -1151,11 +1151,11 @@ err1:
goto err1;
if (!ref)
mem.free(buffer);
::free(buffer);
ref = 0;
size = GetFileSize(h,NULL);
buffer = (unsigned char *) mem.malloc(size + 2);
buffer = (unsigned char *) ::malloc(size + 2);
if (!buffer)
goto err2;
@@ -1184,7 +1184,7 @@ err1:
err2:
CloseHandle(h);
err:
mem.free(buffer);
::free(buffer);
buffer = NULL;
len = 0;

View File

@@ -1,5 +1,5 @@
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -18,7 +18,7 @@
#include "lstring.h"
#include "stringtable.h"
StringTable::StringTable(unsigned size)
void StringTable::init(unsigned size)
{
table = (void **)mem.calloc(size, sizeof(void *));
tabledim = size;

View File

@@ -1,4 +1,4 @@
// Copyright (c) 1999-2008 by Digital Mars
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,13 +28,13 @@ struct StringValue
Lstring lstring;
};
struct StringTable : Object
struct StringTable
{
void **table;
unsigned count;
unsigned tabledim;
StringTable(unsigned size = 37);
void init(unsigned size = 37);
~StringTable();
StringValue *lookup(const dchar *s, unsigned len);

72
dmd2/root/win32.c Normal file
View File

@@ -0,0 +1,72 @@
// Copyright (c) 2000-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// 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.
#include <windows.h>
#include "os.h"
/***********************************
* Map memory.
*/
void *os_mem_map(unsigned nbytes)
{
return VirtualAlloc(NULL, nbytes, MEM_RESERVE, PAGE_READWRITE);
}
/***********************************
* Commit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_commit(void *base, unsigned offset, unsigned nbytes)
{
void *p;
p = VirtualAlloc((char *)base + offset, nbytes, MEM_COMMIT, PAGE_READWRITE);
return (p == NULL);
}
/***********************************
* Decommit memory.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_decommit(void *base, unsigned offset, unsigned nbytes)
{
return VirtualFree((char *)base + offset, nbytes, MEM_DECOMMIT) == 0;
}
/***********************************
* Unmap memory allocated with os_mem_map().
* Memory must have already been decommitted.
* Returns:
* 0 success
* !=0 failure
*/
int os_mem_unmap(void *base, unsigned nbytes)
{
(void)nbytes;
return VirtualFree(base, 0, MEM_RELEASE) == 0;
}
/********************************************
*/
pthread_t pthread_self()
{
return (pthread_t) GetCurrentThreadId();
}

View File

@@ -679,7 +679,8 @@ int CompoundStatement::blockExit(bool mustNotThrow)
if (global.params.warnings && result & BEfallthru && slast)
{
slast = slast->last();
if (slast && (s->isCaseStatement() || s->isDefaultStatement()))
if (slast && (slast->isCaseStatement() || slast->isDefaultStatement()) &&
(s->isCaseStatement() || s->isDefaultStatement()))
{
// Allow if last case/default was empty
CaseStatement *sc = slast->isCaseStatement();
@@ -1210,7 +1211,7 @@ void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
body->toCBuffer(buf, hgs);
buf->writestring("while (");
condition->toCBuffer(buf, hgs);
buf->writebyte(')');
buf->writestring(");");
}
/******************************** ForStatement ***************************/
@@ -1516,18 +1517,22 @@ Lretry:
Dsymbol *var;
if (te)
{ Type *tb = e->type->toBasetype();
Dsymbol *s = NULL;
if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
{ VarExp *ve = (VarExp *)e;
var = new AliasDeclaration(loc, arg->ident, ve->var);
}
s = ((VarExp *)e)->var;
else if (e->op == TOKtemplate)
s =((TemplateExp *)e)->td;
else if (e->op == TOKimport)
s =((ScopeExp *)e)->sds;
if (s)
var = new AliasDeclaration(loc, arg->ident, s);
else
{
arg->type = e->type;
Initializer *ie = new ExpInitializer(0, e);
VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
if (e->isConst())
v->storage_class |= STCconst;
if (e->op == TOKstring)
if (e->isConst() || e->op == TOKstring)
v->storage_class |= STCmanifest;
var = v;
}
@@ -1849,6 +1854,9 @@ Lagain:
if (!ve->type || ve->type->ty == Terror)
goto Lrangeerr;
// Resolve inout qualifier of front type
ve->type = ve->type->substWildTo(tab->mod);
Expressions *exps = new Expressions();
exps->push(ve);
int pos = 0;
@@ -1858,7 +1866,7 @@ Lagain:
if (pos == -1)
break;
}
if (exps->dim > dim)
if (exps->dim != dim)
goto Lrangeerr;
for (size_t i = 0; i < dim; i++)
@@ -1893,6 +1901,9 @@ Lagain:
printf("increment: %s\n", increment->toChars());
printf("body: %s\n", forbody->toChars());
#endif
if (prelude)
s = new CompoundStatement(loc,
new ExpStatement(prelude->loc, prelude), s);
s = s->semantic(sc);
break;
@@ -3718,13 +3729,10 @@ Statement *ReturnStatement::semantic(Scope *sc)
* (but first ensure it doesn't fail the "check for
* escaping reference" test)
*/
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
exp->checkEscapeRef();
global.gag--;
if (errors != global.errors)
if (global.endGagging(errors))
{ tf->isref = FALSE; // return by value
global.errors = errors;
}
}
else
@@ -3832,7 +3840,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
{
if (((TypeFunction *)fd->type)->isref && !fd->isCtorDeclaration())
{ // Function returns a reference
if (tbret->isMutable())
if (tret->isMutable())
exp = exp->modifiableLvalue(sc, exp);
else
exp = exp->toLvalue(sc, exp);
@@ -3893,8 +3901,14 @@ Statement *ReturnStatement::semantic(Scope *sc)
* exp; return;
*/
Statement *s = new ExpStatement(loc, exp);
exp = NULL;
s = s->semantic(sc);
if (exp->type->ty != Tvoid)
{
error("cannot return non-void from void function");
}
exp = NULL;
return new CompoundStatement(loc, s, this);
}

View File

@@ -21,6 +21,8 @@
#include "statement.h"
#include "template.h"
FuncDeclaration *StructDeclaration::xerreq; // object.xopEquals
/********************************* AggregateDeclaration ****************************/
AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
@@ -314,9 +316,11 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)
zeroInit = 0; // assume false until we do semantic processing
#if DMDV2
hasIdentityAssign = 0;
hasIdentityEquals = 0;
cpctor = NULL;
postblit = NULL;
eq = NULL;
xeq = NULL;
#endif
// For forward references
@@ -497,6 +501,65 @@ void StructDeclaration::semantic(Scope *sc)
#endif
}
if (sizeok == 2)
{ // semantic() failed because of forward references.
// Unwind what we did, and defer it for later
fields.setDim(0);
structsize = 0;
alignsize = 0;
structalign = 0;
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
return;
}
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
// Determine if struct is all zeros or not
zeroInit = 1;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd && !vd->isDataseg())
{
if (vd->init)
{
// Should examine init to see if it is really all 0's
zeroInit = 0;
break;
}
else
{
if (!vd->type->isZeroInit(loc))
{
zeroInit = 0;
break;
}
}
}
}
#if DMDV1
/* This doesn't work for DMDV2 because (ref S) and (S) parameter
* lists will overload the same.
@@ -560,107 +623,18 @@ void StructDeclaration::semantic(Scope *sc)
}
#endif
#if DMDV2
/* Try to find the opEquals function. Build it if necessary.
*/
TypeFunction *tfeqptr;
{ // bool opEquals(const T*) const;
Parameters *parameters = new Parameters;
#if STRUCTTHISREF
// bool opEquals(ref const T) const;
Parameter *param = new Parameter(STCref, type->constOf(), NULL, NULL);
#else
// bool opEquals(const T*) const;
Parameter *param = new Parameter(STCin, type->pointerTo(), NULL, NULL);
#endif
parameters->push(param);
tfeqptr = new TypeFunction(parameters, Type::tbool, 0, LINKd);
tfeqptr->mod = MODconst;
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, sc2);
Dsymbol *s = search_function(this, Id::eq);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
eq = fdx->overloadExactMatch(tfeqptr, getModule());
if (!eq)
fdx->error("type signature should be %s not %s", tfeqptr->toChars(), fdx->type->toChars());
}
TemplateDeclaration *td = s ? s->isTemplateDeclaration() : NULL;
// BUG: should also check that td is a function template, not just a template
if (!eq && !td)
eq = buildOpEquals(sc2);
}
dtor = buildDtor(sc2);
postblit = buildPostBlit(sc2);
cpctor = buildCpCtor(sc2);
buildOpAssign(sc2);
hasIdentityEquals = (buildOpEquals(sc2) != NULL);
xeq = buildXopEquals(sc2);
#endif
sc2->pop();
if (sizeok == 2)
{ // semantic() failed because of forward references.
// Unwind what we did, and defer it for later
fields.setDim(0);
structsize = 0;
alignsize = 0;
structalign = 0;
scope = scx ? scx : new Scope(*sc);
scope->setNoFree();
scope->module->addDeferredSemantic(this);
Module::dprogress = dprogress_save;
//printf("\tdeferring %s\n", toChars());
return;
}
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
// Determine if struct is all zeros or not
zeroInit = 1;
for (size_t i = 0; i < fields.dim; i++)
{
Dsymbol *s = fields.tdata()[i];
VarDeclaration *vd = s->isVarDeclaration();
if (vd && !vd->isDataseg())
{
if (vd->init)
{
// Should examine init to see if it is really all 0's
zeroInit = 0;
break;
}
else
{
if (!vd->type->isZeroInit(loc))
{
zeroInit = 0;
break;
}
}
}
}
/* Look for special member functions.
*/
#if DMDV2

View File

@@ -603,39 +603,45 @@ void TemplateDeclaration::makeParamNamesVisibleInConstraint(Scope *paramscope, E
onemember->toAlias()->isFuncDeclaration() : NULL;
if (fd)
{
/*
Making parameters is similar to FuncDeclaration::semantic3
*/
paramscope->parent = fd;
int fvarargs; // function varargs
Parameters *fparameters = fd->getParameters(&fvarargs);
TypeFunction *tf = (TypeFunction *)fd->type->syntaxCopy();
// Shouldn't run semantic on default arguments and return type.
for (int i = 0; i<tf->parameters->dim; i++)
tf->parameters->tdata()[i]->defaultArg = NULL;
tf->next = NULL;
// Resolve parameter types and 'auto ref's.
tf->fargs = fargs;
tf = (TypeFunction *)tf->semantic(loc, paramscope);
Parameters *fparameters = tf->parameters;
int fvarargs = tf->varargs;
size_t nfparams = Parameter::dim(fparameters); // Num function parameters
for (size_t i = 0; i < nfparams; i++)
{
Parameter *fparam = Parameter::getNth(fparameters, i)->syntaxCopy();
Parameter *fparam = Parameter::getNth(fparameters, i);
// Remove addMod same as func.d L1065 of FuncDeclaration::semantic3
//Type *vtype = fparam->type;
//if (fd->type && fd->isPure())
// vtype = vtype->addMod(MODconst);
fparam->storageClass &= (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
fparam->storageClass |= STCparameter;
if (fvarargs == 2 && i + 1 == nfparams)
fparam->storageClass |= STCvariadic;
}
for (size_t i = 0; i < fparameters->dim; i++)
{
Parameter *fparam = fparameters->tdata()[i];
if (!fparam->ident)
continue; // don't add it, if it has no name
Type *vtype = fparam->type->syntaxCopy();
// isPure will segfault if called on a ctor, because fd->type is null.
if (fd->type && fd->isPure())
vtype = vtype->addMod(MODconst);
VarDeclaration *v = new VarDeclaration(loc, vtype, fparam->ident, NULL);
v->storage_class |= STCparameter;
// Not sure if this condition is correct/necessary.
// It's from func.c
if (//fd->type && fd->type->ty == Tfunction &&
fvarargs == 2 && i + 1 == nfparams)
v->storage_class |= STCvariadic;
v->storage_class |= fparam->storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor);
if (fparam->storageClass & STCauto)
{
if (fargs && i < fargs->dim)
{ Expression *farg = fargs->tdata()[i];
if (farg->isLvalue())
; // ref parameter
else
v->storage_class &= ~STCref; // value parameter
}
}
VarDeclaration *v = new VarDeclaration(loc, fparam->type, fparam->ident, NULL);
v->storage_class = fparam->storageClass;
v->semantic(paramscope);
if (!paramscope->insert(v))
error("parameter %s.%s is already defined", toChars(), v->toChars());
@@ -912,6 +918,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec
Parameters *fparameters; // function parameter list
int fvarargs; // function varargs
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
unsigned wildmatch = 0;
TypeFunction *tf = (TypeFunction *)fd->type;
#if 0
printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
@@ -1114,7 +1123,7 @@ L2:
{
Type *tthis = ethis->type;
unsigned mod = fd->type->mod;
StorageClass stc = scope->stc;
StorageClass stc = scope->stc | fd->storage_class2;
// Propagate parent storage class (see bug 5504)
Dsymbol *p = parent;
while (p->isTemplateDeclaration() || p->isTemplateInstance())
@@ -1202,8 +1211,11 @@ L2:
#endif
MATCH m;
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes);
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes,
tf->hasWild() ? &wildmatch : NULL);
//printf("\tdeduceType m = %d\n", m);
//if (tf->hasWild())
// printf("\twildmatch = x%x m = %d\n", wildmatch, m);
/* If no match, see if there's a conversion to a delegate
*/
@@ -1791,7 +1803,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
*/
MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes)
Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("Type::deduceType()\n");
@@ -1827,7 +1839,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
*/
tparam = tparam->semantic(loc, sc);
assert(tparam->ty != Tident);
return deduceType(sc, tparam, parameters, dedtypes);
return deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
TemplateParameter *tp = parameters->tdata()[i];
@@ -1841,6 +1853,59 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
// 7*7 == 49 cases
#define X(U,T) ((U) << 4) | (T)
if (wildmatch && (tparam->mod & MODwild))
{
switch (X(tparam->mod, mod))
{
case X(MODwild, MODwild):
case X(MODwild | MODshared, MODwild | MODshared):
case X(MODwild, 0):
case X(MODwild, MODconst):
case X(MODwild, MODimmutable):
case X(MODwild | MODshared, MODshared):
case X(MODwild | MODshared, MODconst | MODshared):
if (!at)
{
if (mod & MODwild)
*wildmatch |= MODwild;
else if (mod == 0)
*wildmatch |= MODmutable;
else
*wildmatch |= (mod & ~MODshared);
tt = mutableOf();
dedtypes->tdata()[i] = tt;
goto Lconst;
}
//printf("\t> tt = %s, at = %s\n", tt->toChars(), at->toChars());
//printf("\t> tt->implicitConvTo(at->constOf()) = %d\n", tt->implicitConvTo(at->constOf()));
//printf("\t> at->implicitConvTo(tt->constOf()) = %d\n", at->implicitConvTo(tt->constOf()));
if (tt->equals(at))
{
goto Lconst;
}
else if (tt->implicitConvTo(at->constOf()))
{
dedtypes->tdata()[i] = at->constOf()->mutableOf();
*wildmatch |= MODconst;
goto Lconst;
}
else if (at->implicitConvTo(tt->constOf()))
{
dedtypes->tdata()[i] = tt->constOf()->mutableOf();
*wildmatch |= MODconst;
goto Lconst;
}
goto Lnomatch;
default:
break;
}
}
switch (X(tparam->mod, mod))
{
case X(0, 0):
@@ -2003,7 +2068,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
}
if (nextOf())
return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes, wildmatch);
Lexact:
return MATCHexact;
@@ -2019,19 +2084,19 @@ Lconst:
#if DMDV2
MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes)
Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("TypeDArray::deduceType()\n");
printf("\tthis = %d, ", ty); print();
printf("\ttparam = %d, ", tparam->ty); tparam->print();
#endif
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
#endif
MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
Objects *dedtypes)
Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("TypeSArray::deduceType()\n");
@@ -2100,7 +2165,7 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
else
{ dedtypes->tdata()[i] = dim;
}
return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes, wildmatch);
}
}
}
@@ -2109,19 +2174,19 @@ MATCH TypeSArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
else if (tparam->ty == Tarray)
{ MATCH m;
m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes);
m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes, wildmatch);
if (m == MATCHexact)
m = MATCHconvert;
return m;
}
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
Lnomatch:
return MATCHnomatch;
}
MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("TypeAArray::deduceType()\n");
@@ -2133,15 +2198,15 @@ MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
if (tparam && tparam->ty == Taarray)
{
TypeAArray *tp = (TypeAArray *)tparam;
if (!index->deduceType(sc, tp->index, parameters, dedtypes))
if (!index->deduceType(sc, tp->index, parameters, dedtypes, wildmatch))
{
return MATCHnomatch;
}
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
//printf("TypeFunction::deduceType()\n");
//printf("\tthis = %d, ", ty); print();
@@ -2237,14 +2302,14 @@ MATCH TypeFunction::deduceType(Scope *sc, Type *tparam, TemplateParameters *para
Parameter *a = Parameter::getNth(this->parameters, i);
Parameter *ap = Parameter::getNth(tp->parameters, i);
if (a->storageClass != ap->storageClass ||
!a->type->deduceType(sc, ap->type, parameters, dedtypes))
!a->type->deduceType(sc, ap->type, parameters, dedtypes, wildmatch))
return MATCHnomatch;
}
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
// Extra check
if (tparam && tparam->ty == Tident)
@@ -2260,12 +2325,12 @@ MATCH TypeIdentifier::deduceType(Scope *sc, Type *tparam, TemplateParameters *pa
return MATCHnomatch;
}
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
MATCH TypeInstance::deduceType(Scope *sc,
Type *tparam, TemplateParameters *parameters,
Objects *dedtypes)
Objects *dedtypes, unsigned *wildmatch)
{
#if 0
printf("TypeInstance::deduceType()\n");
@@ -2406,7 +2471,7 @@ MATCH TypeInstance::deduceType(Scope *sc,
if (t1 && t2)
{
if (!t1->deduceType(sc, t2, parameters, dedtypes))
if (!t1->deduceType(sc, t2, parameters, dedtypes, wildmatch))
goto Lnomatch;
}
else if (e1 && e2)
@@ -2479,14 +2544,14 @@ MATCH TypeInstance::deduceType(Scope *sc,
goto Lnomatch;
}
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
Lnomatch:
//printf("no match\n");
return MATCHnomatch;
}
MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
//printf("TypeStruct::deduceType()\n");
//printf("\tthis->parent = %s, ", sym->parent->toChars()); print();
@@ -2503,7 +2568,7 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
if (ti && ti->toAlias() == sym)
{
TypeInstance *t = new TypeInstance(0, ti);
return t->deduceType(sc, tparam, parameters, dedtypes);
return t->deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
/* Match things like:
@@ -2520,7 +2585,7 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
/* Slice off the .foo in S!(T).foo
*/
tpi->idents.dim--;
MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes, wildmatch);
tpi->idents.dim++;
return m;
}
@@ -2536,10 +2601,10 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
if (sym != tp->sym)
return MATCHnomatch;
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
// Extra check
if (tparam && tparam->ty == Tenum)
@@ -2549,10 +2614,10 @@ MATCH TypeEnum::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramete
if (sym != tp->sym)
return MATCHnomatch;
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
// Extra check
if (tparam && tparam->ty == Ttypedef)
@@ -2562,7 +2627,7 @@ MATCH TypeTypedef::deduceType(Scope *sc, Type *tparam, TemplateParameters *param
if (sym != tp->sym)
return MATCHnomatch;
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
/* Helper for TypeClass::deduceType().
@@ -2622,7 +2687,7 @@ void deduceBaseClassParameters(BaseClass *b,
}
MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch)
{
//printf("TypeClass::deduceType(this = %s)\n", toChars());
@@ -2637,7 +2702,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
if (ti && ti->toAlias() == sym)
{
TypeInstance *t = new TypeInstance(0, ti);
MATCH m = t->deduceType(sc, tparam, parameters, dedtypes);
MATCH m = t->deduceType(sc, tparam, parameters, dedtypes, wildmatch);
// Even if the match fails, there is still a chance it could match
// a base class.
if (m != MATCHnomatch)
@@ -2658,7 +2723,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
/* Slice off the .foo in S!(T).foo
*/
tpi->idents.dim--;
MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes);
MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes, wildmatch);
tpi->idents.dim++;
return m;
}
@@ -2666,7 +2731,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
}
// If it matches exactly or via implicit conversion, we're done
MATCH m = Type::deduceType(sc, tparam, parameters, dedtypes);
MATCH m = Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
if (m != MATCHnomatch)
return m;
@@ -2715,7 +2780,7 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *paramet
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
return implicitConvTo(tp);
}
return Type::deduceType(sc, tparam, parameters, dedtypes);
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
/* ======================== TemplateParameter =============================== */
@@ -3703,6 +3768,7 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident)
this->havetempdecl = 0;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
#if IN_LLVM
// LDC
@@ -3737,6 +3803,7 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti
this->havetempdecl = 1;
this->isnested = NULL;
this->errors = 0;
this->speculative = 0;
#if IN_LLVM
// LDC
@@ -3934,6 +4001,27 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// It's a match
inst = ti;
parent = ti->parent;
// If both this and the previous instantiation were speculative,
// use the number of errors that happened last time.
if (inst->speculative && global.gag)
{
global.errors += inst->errors;
global.gaggedErrors += inst->errors;
}
// If the first instantiation was speculative, but this is not:
if (inst->speculative && !global.gag)
{
// If the first instantiation had failed, re-run semantic,
// so that error messages are shown.
if (inst->errors)
goto L1;
// It had succeeded, mark it is a non-speculative instantiation,
// and reuse it.
inst->speculative = 0;
}
#if LOG
printf("\tit's a match with instance %p\n", inst);
#endif
@@ -3951,6 +4039,10 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
#endif
unsigned errorsave = global.errors;
inst = this;
// Mark as speculative if we are instantiated from inside is(typeof())
if (global.gag && sc->intypeof)
speculative = 1;
int tempdecl_instance_idx = tempdecl->instances.dim;
tempdecl->instances.push(this);
parent = tempdecl->parent;
@@ -4233,7 +4325,12 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
// (see bugzilla 4302 and 6602).
tempdecl->instances.remove(tempdecl_instance_idx);
if (target_symbol_list)
{
// Because we added 'this' in the last position above, we
// should be able to remove it without messing other indices up.
assert(target_symbol_list->tdata()[target_symbol_list_idx] == this);
target_symbol_list->remove(target_symbol_list_idx);
}
semanticRun = 0;
inst = NULL;
}
@@ -4293,7 +4390,9 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
tiargs->tdata()[j] = ea;
}
else if (sa)
{ tiargs->tdata()[j] = sa;
{
Ldsym:
tiargs->tdata()[j] = sa;
TupleDeclaration *d = sa->toAlias()->isTupleDeclaration();
if (d)
{
@@ -4339,13 +4438,17 @@ void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int f
ea = ea->semantic(sc);
if (flags & 1) // only used by __traits, must not interpret the args
ea = ea->optimize(WANTvalue);
else if (ea->op != TOKvar)
else if (ea->op != TOKvar && ea->op != TOKtuple)
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->tdata()[j] = ea;
if (ea->op == TOKtype)
{ ta = ea->type;
goto Ltype;
}
if (ea->op == TOKimport)
{ sa = ((ScopeExp *)ea)->sds;
goto Ldsym;
}
if (ea->op == TOKtuple)
{ // Expand tuple
TupleExp *te = (TupleExp *)ea;
@@ -4901,6 +5004,10 @@ int TemplateInstance::needsTypeInference(Scope *sc)
return FALSE;
}
for (size_t i = 0; i < td->parameters->dim; i++)
if (td->parameters->tdata()[i]->isTemplateThisParameter())
return TRUE;
/* Determine if the instance arguments, tiargs, are all that is necessary
* to instantiate the template.
*/
@@ -4908,7 +5015,7 @@ int TemplateInstance::needsTypeInference(Scope *sc)
//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 || tiargs->dim < td->parameters->dim))
((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim))
return TRUE;
/* If there is more than one function template which matches, we may
* need type inference (see Bugzilla 4430)
@@ -4967,10 +5074,26 @@ void TemplateInstance::semantic3(Scope *sc)
sc = sc->push(argsym);
sc = sc->push(this);
sc->tinst = this;
int oldgag = global.gag;
int olderrors = global.errors;
/* If this is a speculative instantiation, gag errors.
* Future optimisation: If the results are actually needed, errors
* would already be gagged, so we don't really need to run semantic
* on the members.
*/
if (speculative && !oldgag)
olderrors = global.startGagging();
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
s->semantic3(sc);
if (speculative && global.errors != olderrors)
break;
}
if (speculative && !oldgag)
{ // If errors occurred, this instantiation failed
errors += global.errors - olderrors;
global.endGagging(olderrors);
}
sc = sc->pop();
sc->pop();

View File

@@ -301,6 +301,7 @@ struct TemplateInstance : ScopeDsymbol
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
#ifdef IN_GCC
/* On some targets, it is necessary to know whether a symbol
will be emitted in the output or not before the symbol

View File

@@ -263,7 +263,10 @@ Expression *TraitsExp::semantic(Scope *sc)
e = e->trySemantic(sc);
if (!e)
{ if (global.gag)
{
global.errors++;
global.gaggedErrors++;
}
goto Lfalse;
}
else
@@ -400,8 +403,7 @@ Expression *TraitsExp::semantic(Scope *sc)
{ Object *o = args->tdata()[i];
Expression *e;
unsigned errors = global.errors;
global.gag++;
unsigned errors = global.startGagging();
Type *t = isType(o);
if (t)
@@ -422,10 +424,8 @@ Expression *TraitsExp::semantic(Scope *sc)
}
}
global.gag--;
if (errors != global.errors)
if (global.endGagging(errors))
{
global.errors = errors;
goto Lfalse;
}
}

View File

@@ -4,7 +4,7 @@
#include "declaration.h"
#include "enum.h"
#include "id.h"
#include "mem.h"
#include "rmem.h"
#include "template.h"
#include "gen/irstate.h"

View File

@@ -127,8 +127,22 @@ static void initFromString(char*& dest, const cl::opt<std::string>& src) {
}
}
#if _WIN32
extern "C"
{
extern int _xi_a;
extern int _end;
}
#endif
int main(int argc, char** argv)
{
mem.init(); // initialize storage allocator
mem.setStackBottom(&argv);
#if _WIN32
mem.addroots((char *)&_xi_a, (char *)&_end);
#endif
// stack trace on signals
llvm::sys::PrintStackTraceOnErrorSignal();

View File

@@ -3016,6 +3016,8 @@ STUB(ScopeExp);
#if DMDV2
STUB(SymbolExp);
STUB(PowExp);
STUB(PowAssignExp);
#endif
#define CONSTSTUB(x) LLConstant* x::toConstElem(IRState * p) { \

View File

@@ -666,7 +666,7 @@ void TypeInfoStructDeclaration::llvmDefine()
// opEquals
#if DMDV2
fd = sd->eq;
fd = sd->xeq;
#else
fd = find_method_overload(sd, Id::eq, tfcmpptr, gm);
#endif

2
phobos

Submodule phobos updated: a8106d9d48...2bebc8f8ba