mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Updated to dmdfe 2.051
This commit is contained in:
@@ -253,7 +253,6 @@ void AggregateDeclaration::accessCheck(Loc loc, Scope *sc, Dsymbol *smember)
|
||||
if (!result)
|
||||
{
|
||||
error(loc, "member %s is not accessible", smember->toChars());
|
||||
halt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,9 @@ bool isArrayOpValid(Expression *e)
|
||||
Expression *BinExp::arrayOp(Scope *sc)
|
||||
{
|
||||
|
||||
if (type->toBasetype()->nextOf()->toBasetype()->ty == Tvoid)
|
||||
Type *tb = type->toBasetype();
|
||||
assert(tb->ty == Tarray || tb->ty == Tsarray);
|
||||
if (tb->nextOf()->toBasetype()->ty == Tvoid)
|
||||
{
|
||||
error("Cannot perform array operations on void[] arrays");
|
||||
return new ErrorExp();
|
||||
|
||||
37
dmd2/cast.c
37
dmd2/cast.c
@@ -449,8 +449,6 @@ MATCH StringExp::implicitConvTo(Type *t)
|
||||
printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
|
||||
toChars(), committed, type->toChars(), t->toChars());
|
||||
#endif
|
||||
if (!committed)
|
||||
{
|
||||
if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid)
|
||||
{
|
||||
return MATCHnomatch;
|
||||
@@ -471,7 +469,9 @@ MATCH StringExp::implicitConvTo(Type *t)
|
||||
((TypeSArray *)t)->dim->toInteger())
|
||||
return MATCHnomatch;
|
||||
TY tynto = t->nextOf()->ty;
|
||||
if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
|
||||
if (tynto == tyn)
|
||||
return MATCHexact;
|
||||
if (!committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar))
|
||||
return MATCHexact;
|
||||
}
|
||||
else if (type->ty == Tarray)
|
||||
@@ -480,7 +480,9 @@ MATCH StringExp::implicitConvTo(Type *t)
|
||||
((TypeSArray *)t)->dim->toInteger())
|
||||
return MATCHnomatch;
|
||||
TY tynto = t->nextOf()->ty;
|
||||
if (tynto == Tchar || tynto == Twchar || tynto == Tdchar)
|
||||
if (tynto == tyn)
|
||||
return MATCHexact;
|
||||
if (!committed && (tynto == Tchar || tynto == Twchar || tynto == Tdchar))
|
||||
return MATCHexact;
|
||||
}
|
||||
case Tarray:
|
||||
@@ -497,13 +499,14 @@ MATCH StringExp::implicitConvTo(Type *t)
|
||||
case Tchar:
|
||||
case Twchar:
|
||||
case Tdchar:
|
||||
return m;
|
||||
if (!committed)
|
||||
return m;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Expression::implicitConvTo(t);
|
||||
#if 0
|
||||
m = (MATCH)type->implicitConvTo(t);
|
||||
@@ -2002,6 +2005,28 @@ int arrayTypeCompatible(Loc loc, Type *t1, Type *t2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* See if both types are arrays that can be compared
|
||||
* for equality without any casting. Return !=0 if so.
|
||||
* This is to enable comparing things like an immutable
|
||||
* array with a mutable one.
|
||||
*/
|
||||
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2)
|
||||
{
|
||||
t1 = t1->toBasetype();
|
||||
t2 = t2->toBasetype();
|
||||
|
||||
if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
|
||||
t2->ty == t1->ty)
|
||||
{
|
||||
if (t1->nextOf()->implicitConvTo(t2->nextOf()) >= MATCHconst ||
|
||||
t2->nextOf()->implicitConvTo(t1->nextOf()) >= MATCHconst)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/* Determine the integral ranges of an expression.
|
||||
|
||||
17
dmd2/class.c
17
dmd2/class.c
@@ -573,17 +573,18 @@ void ClassDeclaration::semantic(Scope *sc)
|
||||
isscope = 1;
|
||||
if (storage_class & STCabstract)
|
||||
isabstract = 1;
|
||||
|
||||
if (storage_class & STCimmutable)
|
||||
type = type->invariantOf();
|
||||
else if (storage_class & STCconst)
|
||||
type = type->constOf();
|
||||
else if (storage_class & STCshared)
|
||||
type = type->sharedOf();
|
||||
type = type->addMod(MODimmutable);
|
||||
if (storage_class & STCconst)
|
||||
type = type->addMod(MODconst);
|
||||
if (storage_class & STCshared)
|
||||
type = type->addMod(MODshared);
|
||||
|
||||
sc = sc->push(this);
|
||||
sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
|
||||
STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
|
||||
sc->stc |= storage_class & STC_TYPECTOR;
|
||||
//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;
|
||||
sc->inunion = 0;
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ struct CppMangleState
|
||||
static Array components;
|
||||
|
||||
int substitute(OutBuffer *buf, void *p);
|
||||
int exist(void *p);
|
||||
void store(void *p);
|
||||
};
|
||||
|
||||
Array CppMangleState::components;
|
||||
@@ -82,6 +84,23 @@ int CppMangleState::substitute(OutBuffer *buf, void *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CppMangleState::exist(void *p)
|
||||
{
|
||||
for (size_t i = 0; i < components.dim; i++)
|
||||
{
|
||||
if (p == components.data[i])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CppMangleState::store(void *p)
|
||||
{
|
||||
components.push(p);
|
||||
}
|
||||
|
||||
void source_name(OutBuffer *buf, Dsymbol *s)
|
||||
{
|
||||
char *name = s->ident->toChars();
|
||||
@@ -203,9 +222,6 @@ void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
* u <source-name> # vendor extended type
|
||||
*/
|
||||
|
||||
if (isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
switch (ty)
|
||||
{
|
||||
case Tvoid: c = 'v'; break;
|
||||
@@ -234,12 +250,18 @@ void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
if (p)
|
||||
if (p || isConst())
|
||||
{
|
||||
if (cms->substitute(buf, this))
|
||||
return;
|
||||
buf->writeByte(p);
|
||||
}
|
||||
|
||||
if (isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
if (p)
|
||||
buf->writeByte(p);
|
||||
|
||||
buf->writeByte(c);
|
||||
}
|
||||
|
||||
@@ -266,19 +288,25 @@ void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
|
||||
void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
if (!cms->exist(this))
|
||||
{ buf->writeByte('P');
|
||||
next->toCppMangle(buf, cms);
|
||||
cms->store(this);
|
||||
}
|
||||
else
|
||||
cms->substitute(buf, this);
|
||||
}
|
||||
|
||||
|
||||
void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
if (!cms->exist(this))
|
||||
{ buf->writeByte('R');
|
||||
next->toCppMangle(buf, cms);
|
||||
cms->store(this);
|
||||
}
|
||||
else
|
||||
cms->substitute(buf, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -325,15 +353,37 @@ void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
|
||||
void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
if (!cms->exist(this))
|
||||
{
|
||||
if (isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
|
||||
if (isConst())
|
||||
cms->store(this);
|
||||
}
|
||||
else
|
||||
cms->substitute(buf, this);
|
||||
}
|
||||
|
||||
|
||||
void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
if (!cms->exist(this))
|
||||
{
|
||||
if (isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
|
||||
if (isConst())
|
||||
cms->store(this);
|
||||
}
|
||||
else
|
||||
cms->substitute(buf, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -373,7 +423,14 @@ void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *a
|
||||
{ // Mangle static arrays as pointers
|
||||
t = t->pointerTo();
|
||||
}
|
||||
t->toCppMangle(buf, cms);
|
||||
|
||||
/* If it is a basic, enum or struct type,
|
||||
* then don't mark it const
|
||||
*/
|
||||
if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst())
|
||||
t->mutableOf()->toCppMangle(buf, cms);
|
||||
else
|
||||
t->toCppMangle(buf, cms);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
|
||||
TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
|
||||
: Declaration(id)
|
||||
{
|
||||
this->loc = loc;
|
||||
this->type = NULL;
|
||||
this->objects = objects;
|
||||
this->isexp = 0;
|
||||
@@ -776,6 +777,10 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
if (storage_class & STCextern && init)
|
||||
error("extern symbols cannot have initializers");
|
||||
|
||||
AggregateDeclaration *ad = isThis();
|
||||
if (ad)
|
||||
storage_class |= ad->storage_class & STC_TYPECTOR;
|
||||
|
||||
/* If auto type inference, do the inference
|
||||
*/
|
||||
int inferred = 0;
|
||||
@@ -789,6 +794,11 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
e = ai->toAssocArrayLiteral();
|
||||
else
|
||||
e = init->toExpression();
|
||||
if (!e)
|
||||
{
|
||||
error("cannot infer type from initializer");
|
||||
e = new ErrorExp();
|
||||
}
|
||||
init = new ExpInitializer(e->loc, e);
|
||||
type = init->inferType(sc);
|
||||
if (type->ty == Tsarray)
|
||||
@@ -1446,6 +1456,27 @@ void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
AggregateDeclaration *VarDeclaration::isThis()
|
||||
{
|
||||
AggregateDeclaration *ad = NULL;
|
||||
|
||||
if (!(storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter |
|
||||
STCtls | STCgshared | STCctfe)))
|
||||
{
|
||||
if ((storage_class & (STCconst | STCimmutable | STCwild)) && init)
|
||||
return NULL;
|
||||
|
||||
for (Dsymbol *s = this; s; s = s->parent)
|
||||
{
|
||||
ad = s->isMember();
|
||||
if (ad)
|
||||
break;
|
||||
if (!s->parent || !s->parent->isTemplateMixin()) break;
|
||||
}
|
||||
}
|
||||
return ad;
|
||||
}
|
||||
|
||||
int VarDeclaration::needThis()
|
||||
{
|
||||
//printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
|
||||
|
||||
@@ -304,6 +304,7 @@ struct VarDeclaration : Declaration
|
||||
Type *htype;
|
||||
Initializer *hinit;
|
||||
#endif
|
||||
AggregateDeclaration *isThis();
|
||||
int needThis();
|
||||
int isImportedSymbol();
|
||||
int isDataseg();
|
||||
@@ -757,6 +758,7 @@ struct FuncDeclaration : Declaration
|
||||
void semantic3(Scope *sc);
|
||||
// called from semantic3
|
||||
void varArgs(Scope *sc, TypeFunction*, VarDeclaration *&, VarDeclaration *&);
|
||||
int equals(Object *o);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -899,7 +901,6 @@ struct CtorDeclaration : FuncDeclaration
|
||||
int isVirtual();
|
||||
int addPreInvariant();
|
||||
int addPostInvariant();
|
||||
void toDocBuffer(OutBuffer *buf);
|
||||
|
||||
CtorDeclaration *isCtorDeclaration() { return this; }
|
||||
};
|
||||
|
||||
17
dmd2/doc.c
17
dmd2/doc.c
@@ -131,6 +131,8 @@ SMALL = <small>$0</small>\n\
|
||||
BR = <br>\n\
|
||||
LINK = <a href=\"$0\">$0</a>\n\
|
||||
LINK2 = <a href=\"$1\">$+</a>\n\
|
||||
LPAREN= (\n\
|
||||
RPAREN= )\n\
|
||||
\n\
|
||||
RED = <font color=red>$0</font>\n\
|
||||
BLUE = <font color=blue>$0</font>\n\
|
||||
@@ -833,7 +835,8 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
|
||||
hgs.ddoc = 1;
|
||||
prefix(buf, td);
|
||||
tf->next->toCBuffer(buf, NULL, &hgs);
|
||||
if (tf)
|
||||
tf->next->toCBuffer(buf, NULL, &hgs);
|
||||
buf->writeByte(' ');
|
||||
buf->writestring(ident->toChars());
|
||||
buf->writeByte('(');
|
||||
@@ -845,7 +848,7 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
tp->toCBuffer(buf, &hgs);
|
||||
}
|
||||
buf->writeByte(')');
|
||||
Parameter::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
|
||||
Parameter::argsToCBuffer(buf, &hgs, tf ? tf->parameters : NULL, tf ? tf->varargs : 0);
|
||||
buf->writestring(";\n");
|
||||
|
||||
highlightCode(NULL, this, buf, o);
|
||||
@@ -857,16 +860,6 @@ void FuncDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void CtorDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
{
|
||||
HdrGenState hgs;
|
||||
|
||||
buf->writestring("this");
|
||||
Parameter::argsToCBuffer(buf, &hgs, arguments, varargs);
|
||||
buf->writestring(";\n");
|
||||
}
|
||||
|
||||
|
||||
void AggregateDeclaration::toDocBuffer(OutBuffer *buf)
|
||||
{
|
||||
if (ident)
|
||||
|
||||
@@ -280,13 +280,13 @@ Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc)
|
||||
*/
|
||||
|
||||
#if DMDV2
|
||||
int arrayExpressionCanThrow(Expressions *exps)
|
||||
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow)
|
||||
{
|
||||
if (exps)
|
||||
{
|
||||
for (size_t i = 0; i < exps->dim; i++)
|
||||
{ Expression *e = (Expression *)exps->data[i];
|
||||
if (e && e->canThrow())
|
||||
if (e && e->canThrow(mustNotThrow))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1321,6 +1321,15 @@ Expression *Expression::checkToBoolean(Scope *sc)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
|
||||
// Forward to aliasthis.
|
||||
if (ad->aliasthis)
|
||||
{
|
||||
Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident);
|
||||
e = e->semantic(sc);
|
||||
e = e->checkToBoolean(sc);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type->checkBoolean())
|
||||
@@ -1407,9 +1416,11 @@ int Expression::isBit()
|
||||
/********************************
|
||||
* Can this expression throw an exception?
|
||||
* Valid only after semantic() pass.
|
||||
*
|
||||
* If 'mustNotThrow' is true, generate an error if it throws
|
||||
*/
|
||||
|
||||
int Expression::canThrow()
|
||||
int Expression::canThrow(bool mustNotThrow)
|
||||
{
|
||||
#if DMDV2
|
||||
return FALSE;
|
||||
@@ -2353,7 +2364,7 @@ Lagain:
|
||||
{
|
||||
//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
|
||||
if (!type)
|
||||
{ if (!v->type && v->scope)
|
||||
{ if ((!v->type || !v->type->deco) && v->scope)
|
||||
v->semantic(v->scope);
|
||||
type = v->type;
|
||||
if (!v->type)
|
||||
@@ -2390,6 +2401,11 @@ Lagain:
|
||||
|
||||
if (!f->originalType && f->scope) // semantic not yet run
|
||||
f->semantic(f->scope);
|
||||
if (f->isUnitTestDeclaration())
|
||||
{
|
||||
error("cannot call unittest function %s", toChars());
|
||||
return new ErrorExp();
|
||||
}
|
||||
if (!f->type->deco)
|
||||
{
|
||||
error("forward reference to %s", toChars());
|
||||
@@ -2772,7 +2788,7 @@ Expression *StringExp::syntaxCopy()
|
||||
|
||||
int StringExp::equals(Object *o)
|
||||
{
|
||||
//printf("StringExp::equals('%s')\n", o->toChars());
|
||||
//printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
|
||||
if (o && o->dyncast() == DYNCAST_EXPRESSION)
|
||||
{ Expression *e = (Expression *)o;
|
||||
|
||||
@@ -2941,6 +2957,7 @@ StringExp *StringExp::toUTF8(Scope *sc)
|
||||
|
||||
int StringExp::compare(Object *obj)
|
||||
{
|
||||
//printf("StringExp::compare()\n");
|
||||
// Used to sort case statement expressions so we can do an efficient lookup
|
||||
StringExp *se2 = (StringExp *)(obj);
|
||||
|
||||
@@ -2954,12 +2971,13 @@ int StringExp::compare(Object *obj)
|
||||
int len1 = len;
|
||||
int len2 = se2->len;
|
||||
|
||||
//printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
switch (sz)
|
||||
{
|
||||
case 1:
|
||||
return strcmp((char *)string, (char *)se2->string);
|
||||
return memcmp((char *)string, (char *)se2->string, len1);
|
||||
|
||||
case 2:
|
||||
{ unsigned u;
|
||||
@@ -3184,7 +3202,7 @@ int ArrayLiteralExp::isBool(int result)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int ArrayLiteralExp::canThrow()
|
||||
int ArrayLiteralExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return 1; // because it can fail allocating memory
|
||||
}
|
||||
@@ -3279,7 +3297,7 @@ int AssocArrayLiteralExp::isBool(int result)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int AssocArrayLiteralExp::canThrow()
|
||||
int AssocArrayLiteralExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -3530,9 +3548,9 @@ int StructLiteralExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int StructLiteralExp::canThrow()
|
||||
int StructLiteralExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return arrayExpressionCanThrow(elements);
|
||||
return arrayExpressionCanThrow(elements, mustNotThrow);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4068,9 +4086,9 @@ int NewExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int NewExp::canThrow()
|
||||
int NewExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return 1;
|
||||
return 0; // regard storage allocation failures as not recoverable
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4142,7 +4160,7 @@ int NewAnonClassExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int NewAnonClassExp::canThrow()
|
||||
int NewAnonClassExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -4618,9 +4636,9 @@ int TupleExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int TupleExp::canThrow()
|
||||
int TupleExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return arrayExpressionCanThrow(exps);
|
||||
return arrayExpressionCanThrow(exps, mustNotThrow);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4806,12 +4824,12 @@ int DeclarationExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int DeclarationExp::canThrow()
|
||||
int DeclarationExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
VarDeclaration *v = declaration->isVarDeclaration();
|
||||
if (v && v->init)
|
||||
{ ExpInitializer *ie = v->init->isExpInitializer();
|
||||
return ie && ie->exp->canThrow();
|
||||
return ie && ie->exp->canThrow(mustNotThrow);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -5159,6 +5177,17 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
goto Lno;
|
||||
break;
|
||||
|
||||
case TOKargTypes:
|
||||
/* Generate a type tuple of the equivalent types used to determine if a
|
||||
* function argument of this type can be passed in registers.
|
||||
* The results of this are highly platform dependent, and intended
|
||||
* primarly for use in implementing va_arg().
|
||||
*/
|
||||
tded = targ->toArgTypes();
|
||||
if (!tded)
|
||||
goto Lno; // not valid for a parameter
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -5189,7 +5218,7 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
tded = (Type *)dedtypes.data[0];
|
||||
if (!tded)
|
||||
tded = targ;
|
||||
|
||||
#if DMDV2
|
||||
Objects tiargs;
|
||||
tiargs.setDim(1);
|
||||
tiargs.data[0] = (void *)targ;
|
||||
@@ -5204,16 +5233,16 @@ Expression *IsExp::semantic(Scope *sc)
|
||||
if (m == MATCHnomatch)
|
||||
goto Lno;
|
||||
s->semantic(sc);
|
||||
if (!sc->insert(s))
|
||||
error("declaration %s is already defined", s->toChars());
|
||||
#if 0
|
||||
Object *o = (Object *)dedtypes.data[i];
|
||||
Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
|
||||
#endif
|
||||
if (sc->sd)
|
||||
s->addMember(sc, sc->sd, 1);
|
||||
else if (!sc->insert(s))
|
||||
error("declaration %s is already defined", s->toChars());
|
||||
}
|
||||
|
||||
#endif
|
||||
goto Lyes;
|
||||
}
|
||||
}
|
||||
@@ -5327,9 +5356,9 @@ Expression *UnaExp::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int UnaExp::canThrow()
|
||||
int UnaExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return e1->canThrow();
|
||||
return e1->canThrow(mustNotThrow);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5473,9 +5502,9 @@ int BinExp::isunsigned()
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int BinExp::canThrow()
|
||||
int BinExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return e1->canThrow() || e2->canThrow();
|
||||
return e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5509,7 +5538,9 @@ Expression *BinAssignExp::commonSemanticAssign(Scope *sc)
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{ // T[] op= ...
|
||||
typeCombine(sc);
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
@@ -5552,7 +5583,9 @@ Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc)
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{ // T[] op= ...
|
||||
typeCombine(sc);
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
@@ -5791,7 +5824,7 @@ int AssertExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int AssertExp::canThrow()
|
||||
int AssertExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
/* assert()s are non-recoverable errors, so functions that
|
||||
* use them can be considered "nothrow"
|
||||
@@ -7305,10 +7338,10 @@ int CallExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CallExp::canThrow()
|
||||
int CallExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
//printf("CallExp::canThrow() %s\n", toChars());
|
||||
if (e1->canThrow())
|
||||
if (e1->canThrow(mustNotThrow))
|
||||
return 1;
|
||||
|
||||
/* If any of the arguments can throw, then this expression can throw
|
||||
@@ -7316,7 +7349,7 @@ int CallExp::canThrow()
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Expression *e = (Expression *)arguments->data[i];
|
||||
|
||||
if (e && e->canThrow())
|
||||
if (e && e->canThrow(mustNotThrow))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -7332,7 +7365,8 @@ int CallExp::canThrow()
|
||||
return 0;
|
||||
if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
|
||||
return 0;
|
||||
|
||||
if (mustNotThrow)
|
||||
error("%s is not nothrow", e1->toChars());
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -8681,7 +8715,10 @@ Expression *IndexExp::semantic(Scope *sc)
|
||||
|
||||
case Taarray:
|
||||
{ TypeAArray *taa = (TypeAArray *)t1;
|
||||
if (!arrayTypeCompatible(e2->loc, e2->type, taa->index))
|
||||
/* We can skip the implicit conversion if they differ only by
|
||||
* constness (Bugzilla 2684, see also bug 2954b)
|
||||
*/
|
||||
if (!arrayTypeCompatibleWithoutCasting(e2->loc, e2->type, taa->index))
|
||||
{
|
||||
e2 = e2->implicitCastTo(sc, taa->index); // type checking
|
||||
}
|
||||
@@ -8761,8 +8798,14 @@ Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
|
||||
error("string literals are immutable");
|
||||
if (type && !type->isMutable())
|
||||
error("%s isn't mutable", e->toChars());
|
||||
if (e1->type->toBasetype()->ty == Taarray)
|
||||
Type *t1 = e1->type->toBasetype();
|
||||
if (t1->ty == Taarray)
|
||||
{ TypeAArray *taa = (TypeAArray *)t1;
|
||||
Type *t2b = e2->type->toBasetype();
|
||||
if (t2b->ty == Tarray && t2b->nextOf()->isMutable())
|
||||
error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars());
|
||||
e1 = e1->modifiableLvalue(sc, e1);
|
||||
}
|
||||
return toLvalue(sc, e);
|
||||
}
|
||||
|
||||
@@ -9079,9 +9122,10 @@ Expression *AssignExp::semantic(Scope *sc)
|
||||
{
|
||||
// Deal with AAs (Bugzilla 2451)
|
||||
// Rewrite as:
|
||||
// e1 = (typeof(e2) tmp = void, tmp = e2, tmp);
|
||||
// e1 = (typeof(aa.value) tmp = void, tmp = e2, tmp);
|
||||
Type * aaValueType = ((TypeAArray *)((IndexExp*)e1)->e1->type->toBasetype())->next;
|
||||
Identifier *id = Lexer::uniqueId("__aatmp");
|
||||
VarDeclaration *v = new VarDeclaration(loc, e2->type,
|
||||
VarDeclaration *v = new VarDeclaration(loc, aaValueType,
|
||||
id, new VoidInitializer(NULL));
|
||||
v->storage_class |= STCctfe;
|
||||
|
||||
@@ -9264,7 +9308,9 @@ Expression *AddAssignExp::semantic(Scope *sc)
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{
|
||||
typeCombine(sc);
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
@@ -9375,7 +9421,9 @@ Expression *MinAssignExp::semantic(Scope *sc)
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{ // T[] -= ...
|
||||
typeCombine(sc);
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
@@ -9505,9 +9553,10 @@ Expression *MulAssignExp::semantic(Scope *sc)
|
||||
#endif
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{ // T[] -= ...
|
||||
typeCombine(sc);
|
||||
type = e1->type;
|
||||
{ // T[] *= ...
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
|
||||
@@ -9578,8 +9627,10 @@ Expression *DivAssignExp::semantic(Scope *sc)
|
||||
#endif
|
||||
|
||||
if (e1->op == TOKslice)
|
||||
{ // T[] -= ...
|
||||
typeCombine(sc);
|
||||
{ // T[] /= ...
|
||||
e = typeCombine(sc);
|
||||
if (e->op == TOKerror)
|
||||
return e;
|
||||
type = e1->type;
|
||||
return arrayOp(sc);
|
||||
}
|
||||
@@ -11238,9 +11289,9 @@ int CondExp::checkSideEffect(int flag)
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int CondExp::canThrow()
|
||||
int CondExp::canThrow(bool mustNotThrow)
|
||||
{
|
||||
return econd->canThrow() || e1->canThrow() || e2->canThrow();
|
||||
return econd->canThrow(mustNotThrow) || e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
||||
void expandTuples(Expressions *exps);
|
||||
FuncDeclaration *hasThis(Scope *sc);
|
||||
Expression *fromConstInitializer(int result, Expression *e);
|
||||
int arrayExpressionCanThrow(Expressions *exps);
|
||||
int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow);
|
||||
|
||||
struct IntRange
|
||||
{ uinteger_t imin;
|
||||
@@ -163,7 +163,7 @@ struct Expression : Object
|
||||
virtual int isBool(int result);
|
||||
virtual int isBit();
|
||||
virtual int checkSideEffect(int flag);
|
||||
virtual int canThrow();
|
||||
virtual int canThrow(bool mustNotThrow);
|
||||
|
||||
virtual int inlineCost(InlineCostState *ics);
|
||||
virtual Expression *doInline(InlineDoState *ids);
|
||||
@@ -448,7 +448,7 @@ struct TupleExp : Expression
|
||||
#if IN_DMD
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -477,7 +477,7 @@ struct ArrayLiteralExp : Expression
|
||||
Expression *interpret(InterState *istate);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -513,7 +513,7 @@ struct AssocArrayLiteralExp : Expression
|
||||
Expression *interpret(InterState *istate);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -552,7 +552,7 @@ struct StructLiteralExp : Expression
|
||||
Expression *interpret(InterState *istate);
|
||||
int isLvalue();
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
MATCH implicitConvTo(Type *t);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -644,7 +644,7 @@ struct NewExp : Expression
|
||||
int checkSideEffect(int flag);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
//int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -670,7 +670,7 @@ struct NewAnonClassExp : Expression
|
||||
Expression *semantic(Scope *sc);
|
||||
int checkSideEffect(int flag);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
};
|
||||
|
||||
#if DMDV2
|
||||
@@ -808,7 +808,7 @@ struct DeclarationExp : Expression
|
||||
elem *toElem(IRState *irs);
|
||||
#endif
|
||||
void scanForNestedRef(Scope *sc);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -891,7 +891,7 @@ struct UnaExp : Expression
|
||||
void dump(int indent);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *));
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
Expression *resolveLoc(Loc loc, Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -924,7 +924,7 @@ struct BinExp : Expression
|
||||
Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *));
|
||||
Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *));
|
||||
Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
Expression *arrayOp(Scope *sc);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -981,7 +981,7 @@ struct AssertExp : UnaExp
|
||||
Expression *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int checkSideEffect(int flag);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -1114,7 +1114,7 @@ struct CallExp : UnaExp
|
||||
void scanForNestedRef(Scope *sc);
|
||||
int isLvalue();
|
||||
Expression *toLvalue(Scope *sc, Expression *e);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
@@ -1985,7 +1985,7 @@ struct CondExp : BinExp
|
||||
MATCH implicitConvTo(Type *t);
|
||||
Expression *castTo(Scope *sc, Type *t);
|
||||
void scanForNestedRef(Scope *sc);
|
||||
int canThrow();
|
||||
int canThrow(bool mustNotThrow);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
Expression *doInline(InlineDoState *ids);
|
||||
|
||||
74
dmd2/func.c
74
dmd2/func.c
@@ -142,6 +142,7 @@ Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
void FuncDeclaration::semantic(Scope *sc)
|
||||
{ TypeFunction *f;
|
||||
AggregateDeclaration *ad;
|
||||
StructDeclaration *sd;
|
||||
ClassDeclaration *cd;
|
||||
InterfaceDeclaration *id;
|
||||
@@ -187,6 +188,10 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
foverrides.setDim(0); // reset in case semantic() is being retried for this function
|
||||
|
||||
storage_class |= sc->stc & ~STCref;
|
||||
ad = isThis();
|
||||
if (ad)
|
||||
storage_class |= ad->storage_class & (STC_TYPECTOR | STCsynchronized);
|
||||
|
||||
//printf("function storage_class = x%llx, sc->stc = x%llx, %x\n", storage_class, sc->stc, Declaration::isFinal());
|
||||
|
||||
if (!originalType)
|
||||
@@ -194,7 +199,9 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
if (!type->deco)
|
||||
{
|
||||
sc = sc->push();
|
||||
sc->stc |= storage_class & STCref; // forward to function type
|
||||
sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCdisable
|
||||
| STCsafe | STCtrusted | STCsystem); // forward to function type
|
||||
|
||||
if (isCtorDeclaration())
|
||||
sc->flags |= SCOPEctor;
|
||||
type = type->semantic(loc, sc);
|
||||
@@ -302,11 +309,11 @@ void FuncDeclaration::semantic(Scope *sc)
|
||||
#endif
|
||||
|
||||
#ifdef IN_GCC
|
||||
AggregateDeclaration *ad;
|
||||
|
||||
ad = parent->isAggregateDeclaration();
|
||||
if (ad)
|
||||
ad->methods.push(this);
|
||||
{
|
||||
AggregateDeclaration *ad = parent->isAggregateDeclaration();
|
||||
if (ad)
|
||||
ad->methods.push(this);
|
||||
}
|
||||
#endif
|
||||
sd = parent->isStructDeclaration();
|
||||
if (sd)
|
||||
@@ -1381,8 +1388,10 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
else if (!inlineAsm)
|
||||
{
|
||||
#if DMDV2
|
||||
int blockexit = fbody ? fbody->blockExit() : BEfallthru;
|
||||
if (f->isnothrow && blockexit & BEthrow)
|
||||
// Check for errors related to 'nothrow'.
|
||||
int nothrowErrors = global.errors;
|
||||
int blockexit = fbody ? fbody->blockExit(f->isnothrow) : BEfallthru;
|
||||
if (f->isnothrow && (global.errors != nothrowErrors) )
|
||||
error("'%s' is nothrow yet may throw", toChars());
|
||||
|
||||
int offend = blockexit & BEfallthru;
|
||||
@@ -1680,7 +1689,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
if (e)
|
||||
{ Statement *s = new ExpStatement(0, e);
|
||||
s = s->semantic(sc2);
|
||||
if (fbody->blockExit() == BEfallthru)
|
||||
if (fbody->blockExit(f->isnothrow) == BEfallthru)
|
||||
fbody = new CompoundStatement(0, fbody, s);
|
||||
else
|
||||
fbody = new TryFinallyStatement(0, fbody, s);
|
||||
@@ -1737,6 +1746,8 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
semanticRun = PASSsemanticdone; // Ensure errors get reported again
|
||||
else
|
||||
semanticRun = PASSsemantic3done;
|
||||
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
|
||||
//fflush(stdout);
|
||||
}
|
||||
|
||||
void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -1748,6 +1759,23 @@ void FuncDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
bodyToCBuffer(buf, hgs);
|
||||
}
|
||||
|
||||
int FuncDeclaration::equals(Object *o)
|
||||
{
|
||||
if (this == o)
|
||||
return TRUE;
|
||||
|
||||
Dsymbol *s = isDsymbol(o);
|
||||
if (s)
|
||||
{
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{
|
||||
return toParent()->equals(fd->toParent()) &&
|
||||
ident->equals(fd->ident) && type->equals(fd->type);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
@@ -1825,7 +1853,10 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf)
|
||||
if (fdv->fdrequire && fdv->fdrequire->semanticRun != PASSsemantic3done)
|
||||
{
|
||||
assert(fdv->scope);
|
||||
fdv->semantic3(fdv->scope);
|
||||
Scope *sc = fdv->scope->push();
|
||||
sc->stc &= ~STCoverride;
|
||||
fdv->semantic3(sc);
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
sf = fdv->mergeFrequire(sf);
|
||||
@@ -1872,6 +1903,19 @@ Statement *FuncDeclaration::mergeFensure(Statement *sf)
|
||||
for (int i = 0; i < foverrides.dim; i++)
|
||||
{
|
||||
FuncDeclaration *fdv = (FuncDeclaration *)foverrides.data[i];
|
||||
|
||||
/* The semantic pass on the contracts of the overridden functions must
|
||||
* be completed before code generation occurs (bug 3602 and 5230).
|
||||
*/
|
||||
if (fdv->fdensure && fdv->fdensure->semanticRun != PASSsemantic3done)
|
||||
{
|
||||
assert(fdv->scope);
|
||||
Scope *sc = fdv->scope->push();
|
||||
sc->stc &= ~STCoverride;
|
||||
fdv->semantic3(sc);
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
sf = fdv->mergeFensure(sf);
|
||||
if (fdv->fdensure)
|
||||
{
|
||||
@@ -3046,7 +3090,11 @@ void CtorDeclaration::semantic(Scope *sc)
|
||||
|
||||
#if STRUCTTHISREF
|
||||
if (ad && ad->isStructDeclaration())
|
||||
((TypeFunction *)type)->isref = 1;
|
||||
{ ((TypeFunction *)type)->isref = 1;
|
||||
if (!originalType)
|
||||
// Leave off the "ref"
|
||||
originalType = new TypeFunction(arguments, tret, varargs, LINKd, storage_class | sc->stc);
|
||||
}
|
||||
#endif
|
||||
if (!originalType)
|
||||
originalType = type;
|
||||
@@ -3104,6 +3152,8 @@ int CtorDeclaration::addPostInvariant()
|
||||
|
||||
void CtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
if (originalType && originalType->ty == Tfunction)
|
||||
((TypeFunction *)originalType)->attributesToCBuffer(buf, 0);
|
||||
buf->writestring("this");
|
||||
Parameter::argsToCBuffer(buf, hgs, arguments, varargs);
|
||||
bodyToCBuffer(buf, hgs);
|
||||
@@ -3628,6 +3678,8 @@ void UnitTestDeclaration::semantic(Scope *sc)
|
||||
if (!type)
|
||||
type = new TypeFunction(NULL, Type::tvoid, FALSE, LINKd);
|
||||
Scope *sc2 = sc->push();
|
||||
// It makes no sense for unit tests to be pure or nothrow.
|
||||
sc2->stc &= ~(STCnothrow | STCpure);
|
||||
sc2->linkage = LINKd;
|
||||
FuncDeclaration::semantic(sc2);
|
||||
sc2->pop();
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
/******************************************
|
||||
* Looks for undefined identifier s to see
|
||||
* if it might be undefined because an import
|
||||
@@ -30,24 +32,28 @@ const char *importHint(const char *s)
|
||||
{ "std.c.stdio",
|
||||
"std.stdio",
|
||||
"std.math",
|
||||
"std.c.stdarg",
|
||||
};
|
||||
static const char *names[] =
|
||||
{
|
||||
"printf", NULL,
|
||||
"writefln", NULL,
|
||||
"sin", "cos", "sqrt", "fabs", NULL,
|
||||
"__va_argsave_t", NULL,
|
||||
};
|
||||
#else
|
||||
static const char *modules[] =
|
||||
{ "core.stdc.stdio",
|
||||
"std.stdio",
|
||||
"std.math",
|
||||
"std.c.stdarg",
|
||||
};
|
||||
static const char *names[] =
|
||||
{
|
||||
"printf", NULL,
|
||||
"writeln", NULL,
|
||||
"sin", "cos", "sqrt", "fabs", NULL,
|
||||
"__va_argsave_t", NULL,
|
||||
};
|
||||
#endif
|
||||
int m = 0;
|
||||
|
||||
@@ -55,6 +55,7 @@ Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclarati
|
||||
ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, Expression *elem, size_t dim);
|
||||
Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL);
|
||||
Expression *getVarExp(Loc loc, InterState *istate, Declaration *d);
|
||||
VarDeclaration *findParentVar(Expression *e, Expression *thisval);
|
||||
|
||||
/*************************************
|
||||
* Attempt to interpret a function given the arguments.
|
||||
@@ -220,9 +221,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
||||
}
|
||||
}
|
||||
// Don't restore the value of 'this' upon function return
|
||||
if (needThis() && thisarg->op == TOKvar && istate)
|
||||
if (needThis() && istate)
|
||||
{
|
||||
VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration();
|
||||
VarDeclaration *thisvar = findParentVar(thisarg, istate->localThis);
|
||||
if (!thisvar) // it's a reference. Find which variable it refers to.
|
||||
thisvar = findParentVar(thisarg->interpret(istate), istate->localThis);
|
||||
for (size_t i = 0; i < istate->vars.dim; i++)
|
||||
{ VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
|
||||
if (v == thisvar)
|
||||
@@ -1354,6 +1357,11 @@ Expression *DeclarationExp::interpret(InterState *istate)
|
||||
e = ie->exp->interpret(istate);
|
||||
else if (v->init->isVoidInitializer())
|
||||
e = NULL;
|
||||
else
|
||||
{
|
||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
}
|
||||
#if DMDV2
|
||||
else if (s == v && (v->isConst() || v->isImmutable()) && v->init)
|
||||
@@ -1366,13 +1374,19 @@ Expression *DeclarationExp::interpret(InterState *istate)
|
||||
else if (!e->type)
|
||||
e->type = v->type;
|
||||
}
|
||||
else if (s->isTupleDeclaration() && !v->init)
|
||||
e = NULL;
|
||||
else
|
||||
{
|
||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
}
|
||||
else if (declaration->isAttribDeclaration() ||
|
||||
declaration->isTemplateMixin() ||
|
||||
declaration->isTupleDeclaration())
|
||||
{ // These can be made to work, too lazy now
|
||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||
|
||||
error("Declaration %s is not yet implemented in CTFE", toChars());
|
||||
e = EXP_CANT_INTERPRET;
|
||||
}
|
||||
else
|
||||
@@ -2731,8 +2745,12 @@ Expression *CallExp::interpret(InterState *istate)
|
||||
VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
|
||||
if (vd && vd->value && vd->value->op == TOKsymoff)
|
||||
fd = ((SymOffExp *)vd->value)->var->isFuncDeclaration();
|
||||
else {
|
||||
ecall = vd->value->interpret(istate);
|
||||
else
|
||||
{
|
||||
ecall = getVarExp(loc, istate, vd);
|
||||
if (ecall == EXP_CANT_INTERPRET)
|
||||
return ecall;
|
||||
|
||||
#if IN_LLVM
|
||||
if (ecall->op == TOKaddress) {
|
||||
AddrExp *e = (AddrExp*)ecall;
|
||||
@@ -2741,7 +2759,7 @@ Expression *CallExp::interpret(InterState *istate)
|
||||
}
|
||||
#else
|
||||
if (ecall->op == TOKsymoff)
|
||||
fd = ((SymOffExp *)ecall)->var->isFuncDeclaration();
|
||||
fd = ((SymOffExp *)ecall)->var->isFuncDeclaration();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3002,6 +3002,7 @@ static Keyword keywords[] =
|
||||
//{ "manifest", TOKmanifest },
|
||||
|
||||
// Added after 1.0
|
||||
{ "__argTypes", TOKargTypes },
|
||||
{ "ref", TOKref },
|
||||
{ "macro", TOKmacro },
|
||||
#if DMDV2
|
||||
|
||||
@@ -152,6 +152,7 @@ enum TOK
|
||||
TOKunittest,
|
||||
|
||||
// Added after 1.0
|
||||
TOKargTypes,
|
||||
TOKref,
|
||||
TOKmacro,
|
||||
#if DMDV2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2009 by Digital Mars
|
||||
// Copyright (c) 1999-2010 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
@@ -218,23 +218,26 @@ char *ClassDeclaration::mangle()
|
||||
char *TemplateInstance::mangle()
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *id;
|
||||
|
||||
#if 0
|
||||
printf("TemplateInstance::mangle() %s", toChars());
|
||||
printf("TemplateInstance::mangle() %p %s", this, toChars());
|
||||
if (parent)
|
||||
printf(" parent = %s %s", parent->kind(), parent->toChars());
|
||||
printf("\n");
|
||||
#endif
|
||||
id = ident ? ident->toChars() : toChars();
|
||||
char *id = ident ? ident->toChars() : toChars();
|
||||
if (!tempdecl)
|
||||
error("is not defined");
|
||||
else if (tempdecl->parent)
|
||||
else
|
||||
{
|
||||
char *p = tempdecl->parent->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
Dsymbol *par = isnested || isTemplateMixin() ? parent : tempdecl->parent;
|
||||
if (par)
|
||||
{
|
||||
char *p = par->mangle();
|
||||
if (p[0] == '_' && p[1] == 'D')
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
|
||||
@@ -100,7 +100,7 @@ Global::Global()
|
||||
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
|
||||
#endif
|
||||
;
|
||||
version = "v2.050";
|
||||
version = "v2.051";
|
||||
#if IN_LLVM
|
||||
ldc_version = "LDC trunk";
|
||||
llvm_version = "LLVM 2.8";
|
||||
|
||||
146
dmd2/mtype.c
146
dmd2/mtype.c
@@ -1223,10 +1223,10 @@ Type *Type::addStorageClass(StorageClass stc)
|
||||
else
|
||||
{ if (stc & (STCconst | STCin))
|
||||
mod = MODconst;
|
||||
else if (stc & STCwild) // const takes precedence over wild
|
||||
mod |= MODwild;
|
||||
if (stc & STCshared)
|
||||
mod |= MODshared;
|
||||
if (stc & STCwild)
|
||||
mod |= MODwild;
|
||||
}
|
||||
return addMod(mod);
|
||||
}
|
||||
@@ -2198,7 +2198,7 @@ Type *TypeNext::makeConst()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeConst();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable() && !next->isConst())
|
||||
{ if (next->isShared())
|
||||
t->next = next->sharedConstOf();
|
||||
@@ -2222,7 +2222,7 @@ Type *TypeNext::makeInvariant()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeInvariant();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable())
|
||||
{ t->next = next->invariantOf();
|
||||
}
|
||||
@@ -2242,7 +2242,7 @@ Type *TypeNext::makeShared()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeShared();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable() && !next->isShared())
|
||||
{
|
||||
if (next->isConst() || next->isWild())
|
||||
@@ -2267,7 +2267,7 @@ Type *TypeNext::makeSharedConst()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeSharedConst();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable() && !next->isSharedConst())
|
||||
{
|
||||
t->next = next->sharedConstOf();
|
||||
@@ -2289,7 +2289,7 @@ Type *TypeNext::makeWild()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeWild();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable() && !next->isConst() && !next->isWild())
|
||||
{
|
||||
if (next->isShared())
|
||||
@@ -2314,7 +2314,7 @@ Type *TypeNext::makeSharedWild()
|
||||
}
|
||||
TypeNext *t = (TypeNext *)Type::makeSharedWild();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
!next->isImmutable() && !next->isSharedConst())
|
||||
{
|
||||
t->next = next->sharedWildOf();
|
||||
@@ -2331,9 +2331,9 @@ Type *TypeNext::makeMutable()
|
||||
{
|
||||
//printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
|
||||
TypeNext *t = (TypeNext *)Type::makeMutable();
|
||||
if (ty != Tfunction && ty != Tdelegate &&
|
||||
(next->deco || next->ty == Tfunction) &&
|
||||
next->isWild())
|
||||
if ((ty != Tfunction && ty != Tdelegate &&
|
||||
//(next->deco || next->ty == Tfunction) &&
|
||||
next->isWild()) || ty == Tsarray)
|
||||
{
|
||||
t->next = next->mutableOf();
|
||||
}
|
||||
@@ -3509,7 +3509,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
{
|
||||
Loverflow:
|
||||
error(loc, "index %jd overflow for static array", d1);
|
||||
dim = new IntegerExp(0, 1, tsize_t);
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3523,7 +3523,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
|
||||
if (d >= tt->arguments->dim)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
|
||||
return Type::terror;
|
||||
goto Lerror;
|
||||
}
|
||||
Parameter *arg = (Parameter *)tt->arguments->data[(size_t)d];
|
||||
return arg->type;
|
||||
@@ -3531,18 +3531,30 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
case Tstruct:
|
||||
{ TypeStruct *ts = (TypeStruct *)tbn;
|
||||
if (ts->sym->isnested)
|
||||
error(loc, "cannot have array of inner structs %s", ts->toChars());
|
||||
{ error(loc, "cannot have array of inner structs %s", ts->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Tfunction:
|
||||
case Tnone:
|
||||
error(loc, "can't have array of %s", tbn->toChars());
|
||||
tbn = next = tint32;
|
||||
break;
|
||||
goto Lerror;
|
||||
}
|
||||
if (tbn->isscope())
|
||||
error(loc, "cannot have array of scope %s", tbn->toChars());
|
||||
return merge();
|
||||
{ error(loc, "cannot have array of scope %s", tbn->toChars());
|
||||
goto Lerror;
|
||||
}
|
||||
|
||||
/* Ensure things like const(immutable(T)[3]) become immutable(T[3])
|
||||
* and const(T)[3] become const(T[3])
|
||||
*/
|
||||
t = addMod(next->mod);
|
||||
|
||||
return t->merge();
|
||||
|
||||
Lerror:
|
||||
return Type::terror;
|
||||
}
|
||||
|
||||
void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag, bool mangle)
|
||||
@@ -4096,6 +4108,7 @@ printf("index->ito->ito = x%x\n", index->ito->ito);
|
||||
switch (next->toBasetype()->ty)
|
||||
{
|
||||
case Tfunction:
|
||||
case Tvoid:
|
||||
case Tnone:
|
||||
error(loc, "can't have associative array of %s", next->toChars());
|
||||
return Type::terror;
|
||||
@@ -5882,7 +5895,19 @@ L1:
|
||||
}
|
||||
if (!s)
|
||||
{
|
||||
error(loc, "identifier '%s' is not defined", toChars());
|
||||
const char *p = toChars();
|
||||
const char *n = importHint(p);
|
||||
if (n)
|
||||
error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n);
|
||||
else
|
||||
{
|
||||
Identifier *id = new Identifier(p, TOKidentifier);
|
||||
s = sc->search_correct(id);
|
||||
if (s)
|
||||
error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars());
|
||||
else
|
||||
error(loc, "undefined identifier %s", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6197,7 +6222,7 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
|
||||
{ Expression *e;
|
||||
Type *t;
|
||||
|
||||
//printf("TypeTypeof::semantic() %p\n", this);
|
||||
//printf("TypeTypeof::semantic() %s\n", toChars());
|
||||
|
||||
//static int nest; if (++nest == 50) *(char*)0=0;
|
||||
|
||||
@@ -6248,14 +6273,15 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sc->intypeof++;
|
||||
exp = exp->semantic(sc);
|
||||
Scope *sc2 = sc->push();
|
||||
sc2->intypeof++;
|
||||
exp = exp->semantic(sc2);
|
||||
#if DMDV2
|
||||
if (exp->type && exp->type->ty == Tfunction &&
|
||||
((TypeFunction *)exp->type)->isproperty)
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = resolveProperties(sc2, exp);
|
||||
#endif
|
||||
sc->intypeof--;
|
||||
sc2->pop();
|
||||
if (exp->op == TOKtype)
|
||||
{
|
||||
error(loc, "argument %s to typeof is not an expression", exp->toChars());
|
||||
@@ -6304,7 +6330,7 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc)
|
||||
return t;
|
||||
|
||||
Lerr:
|
||||
return tvoid;
|
||||
return terror;
|
||||
}
|
||||
|
||||
d_uns64 TypeTypeof::size(Loc loc)
|
||||
@@ -7290,6 +7316,30 @@ int TypeStruct::hasPointers()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MATCH aliasthisConvTo(AggregateDeclaration *ad, Type *from, Type *to)
|
||||
{
|
||||
assert(ad->aliasthis);
|
||||
Declaration *d = ad->aliasthis->isDeclaration();
|
||||
if (d)
|
||||
{ assert(d->type);
|
||||
Type *t = d->type;
|
||||
if (d->isVarDeclaration() && d->needThis())
|
||||
{
|
||||
t = t->addMod(from->mod);
|
||||
}
|
||||
else if (d->isFuncDeclaration())
|
||||
{
|
||||
FuncDeclaration *fd = (FuncDeclaration *)d;
|
||||
Expression *ethis = from->defaultInit(0);
|
||||
fd = fd->overloadResolve(0, ethis, NULL);
|
||||
if (fd)
|
||||
t = ((TypeFunction *)fd->type)->next;
|
||||
}
|
||||
return t->implicitConvTo(to);
|
||||
}
|
||||
return MATCHnomatch;
|
||||
}
|
||||
|
||||
MATCH TypeStruct::implicitConvTo(Type *to)
|
||||
{ MATCH m;
|
||||
|
||||
@@ -7304,7 +7354,8 @@ MATCH TypeStruct::implicitConvTo(Type *to)
|
||||
to = ((TypeAArray*)to)->getImpl()->type;
|
||||
--global.gag;
|
||||
if (errs != global.errors)
|
||||
{ global.errors = errs;
|
||||
{
|
||||
global.errors = errs;
|
||||
return MATCHnomatch;
|
||||
}
|
||||
}
|
||||
@@ -7339,15 +7390,7 @@ MATCH TypeStruct::implicitConvTo(Type *to)
|
||||
}
|
||||
}
|
||||
else if (sym->aliasthis)
|
||||
{
|
||||
m = MATCHnomatch;
|
||||
Declaration *d = sym->aliasthis->isDeclaration();
|
||||
if (d)
|
||||
{ assert(d->type);
|
||||
Type *t = d->type->addMod(mod);
|
||||
m = t->implicitConvTo(to);
|
||||
}
|
||||
}
|
||||
m = aliasthisConvTo(sym, this, to);
|
||||
else
|
||||
m = MATCHnomatch; // no match
|
||||
return m;
|
||||
@@ -7812,14 +7855,7 @@ MATCH TypeClass::implicitConvTo(Type *to)
|
||||
|
||||
m = MATCHnomatch;
|
||||
if (sym->aliasthis)
|
||||
{
|
||||
Declaration *d = sym->aliasthis->isDeclaration();
|
||||
if (d)
|
||||
{ assert(d->type);
|
||||
Type *t = d->type->addMod(mod);
|
||||
m = t->implicitConvTo(to);
|
||||
}
|
||||
}
|
||||
m = aliasthisConvTo(sym, this, to);
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -7906,6 +7942,30 @@ TypeTuple::TypeTuple(Expressions *exps)
|
||||
//printf("TypeTuple() %p, %s\n", this, toChars());
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Type tuple with 0, 1 or 2 types in it.
|
||||
*/
|
||||
TypeTuple::TypeTuple()
|
||||
: Type(Ttuple)
|
||||
{
|
||||
arguments = new Parameters();
|
||||
}
|
||||
|
||||
TypeTuple::TypeTuple(Type *t1)
|
||||
: Type(Ttuple)
|
||||
{
|
||||
arguments = new Parameters();
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL));
|
||||
}
|
||||
|
||||
TypeTuple::TypeTuple(Type *t1, Type *t2)
|
||||
: Type(Ttuple)
|
||||
{
|
||||
arguments = new Parameters();
|
||||
arguments->push(new Parameter(0, t1, NULL, NULL));
|
||||
arguments->push(new Parameter(0, t2, NULL, NULL));
|
||||
}
|
||||
|
||||
Type *TypeTuple::syntaxCopy()
|
||||
{
|
||||
Parameters *args = Parameter::arraySyntaxCopy(arguments);
|
||||
|
||||
21
dmd2/mtype.h
21
dmd2/mtype.h
@@ -54,10 +54,10 @@ typedef TYPE type;
|
||||
#endif
|
||||
|
||||
#if IN_DMD
|
||||
typedef struct TYPE type;
|
||||
struct Symbol;
|
||||
#endif
|
||||
|
||||
struct TypeTuple;
|
||||
|
||||
enum ENUMTY
|
||||
{
|
||||
@@ -185,7 +185,7 @@ struct Type : Object
|
||||
#define tshiftcnt tint32 // right side of shift expression
|
||||
// #define tboolean tint32 // result of boolean expression
|
||||
#define tboolean tbool // result of boolean expression
|
||||
#define tindex tint32 // array/ptr index
|
||||
#define tindex tsize_t // array/ptr index
|
||||
static Type *tvoidptr; // void*
|
||||
static Type *tstring; // immutable(char)[]
|
||||
#define terror basic[Terror] // for error recovery
|
||||
@@ -331,7 +331,7 @@ struct Type : Object
|
||||
virtual unsigned wildMatch(Type *targ);
|
||||
virtual Expression *toExpression();
|
||||
virtual int hasPointers();
|
||||
//Type *next;
|
||||
virtual TypeTuple *toArgTypes();
|
||||
virtual Type *nextOf();
|
||||
uinteger_t sizemask();
|
||||
|
||||
@@ -419,6 +419,7 @@ struct TypeBasic : Type
|
||||
Expression *defaultInit(Loc loc);
|
||||
int isZeroInit(Loc loc);
|
||||
int builtinTypeInfo();
|
||||
TypeTuple *toArgTypes();
|
||||
|
||||
// For eliminating dynamic_cast
|
||||
TypeBasic *isTypeBasic();
|
||||
@@ -459,6 +460,7 @@ struct TypeSArray : TypeArray
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *toExpression();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -489,6 +491,7 @@ struct TypeDArray : TypeArray
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -521,6 +524,7 @@ struct TypeAArray : TypeArray
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
#if CPP_MANGLE
|
||||
@@ -550,7 +554,7 @@ struct TypePointer : TypeNext
|
||||
int isZeroInit(Loc loc);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -665,6 +669,7 @@ struct TypeDelegate : TypeNext
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -769,6 +774,7 @@ struct TypeStruct : Type
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
MATCH implicitConvTo(Type *to);
|
||||
MATCH constConv(Type *to);
|
||||
Type *toHeadMutable();
|
||||
@@ -818,6 +824,7 @@ struct TypeEnum : Type
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
#if CPP_MANGLE
|
||||
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
|
||||
#endif
|
||||
@@ -864,6 +871,7 @@ struct TypeTypedef : Type
|
||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
int hasWild();
|
||||
Type *toHeadMutable();
|
||||
#if CPP_MANGLE
|
||||
@@ -899,6 +907,7 @@ struct TypeClass : Type
|
||||
int checkBoolean();
|
||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||
int hasPointers();
|
||||
TypeTuple *toArgTypes();
|
||||
int builtinTypeInfo();
|
||||
#if DMDV2
|
||||
Type *toHeadMutable();
|
||||
@@ -921,6 +930,9 @@ struct TypeTuple : Type
|
||||
|
||||
TypeTuple(Parameters *arguments);
|
||||
TypeTuple(Expressions *exps);
|
||||
TypeTuple();
|
||||
TypeTuple(Type *t1);
|
||||
TypeTuple(Type *t1, Type *t2);
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
int equals(Object *o);
|
||||
@@ -982,6 +994,7 @@ extern int Tsize_t;
|
||||
extern int Tptrdiff_t;
|
||||
|
||||
int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
|
||||
int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2);
|
||||
void MODtoBuffer(OutBuffer *buf, unsigned char mod);
|
||||
int MODimplicitConv(unsigned char modfrom, unsigned char modto);
|
||||
int MODmerge(unsigned char mod1, unsigned char mod2);
|
||||
|
||||
@@ -3785,7 +3785,10 @@ Statement *Parser::parseStatement(int flags)
|
||||
}
|
||||
else
|
||||
elsebody = NULL;
|
||||
s = new IfStatement(loc, arg, condition, ifbody, elsebody);
|
||||
if (condition && ifbody)
|
||||
s = new IfStatement(loc, arg, condition, ifbody, elsebody);
|
||||
else
|
||||
s = NULL; // don't propagate parsing errors
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5175,6 +5178,7 @@ Expression *Parser::parsePrimaryExp()
|
||||
token.value == TOKsuper ||
|
||||
token.value == TOKenum ||
|
||||
token.value == TOKinterface ||
|
||||
token.value == TOKargTypes ||
|
||||
#if DMDV2
|
||||
token.value == TOKconst && peek(&token)->value == TOKrparen ||
|
||||
token.value == TOKinvariant && peek(&token)->value == TOKrparen ||
|
||||
|
||||
@@ -161,7 +161,7 @@ void _aaRehash(AA** paa)
|
||||
}
|
||||
}
|
||||
if (aa->b != aa->binit)
|
||||
delete aa->b;
|
||||
delete[] aa->b;
|
||||
|
||||
newb.nodes = aa->nodes;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,8 @@ void Array::append(Array *a)
|
||||
|
||||
void Array::remove(unsigned i)
|
||||
{
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
if (dim - i - 1)
|
||||
memmove(data + i, data + i + 1, (dim - i - 1) * sizeof(data[0]));
|
||||
dim--;
|
||||
}
|
||||
|
||||
|
||||
228
dmd2/statement.c
228
dmd2/statement.c
@@ -149,8 +149,9 @@ int Statement::usesEH()
|
||||
}
|
||||
|
||||
/* Only valid after semantic analysis
|
||||
* If 'mustNotThrow' is true, generate an error if it throws
|
||||
*/
|
||||
int Statement::blockExit()
|
||||
int Statement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
printf("Statement::blockExit(%p)\n", this);
|
||||
printf("%s\n", toChars());
|
||||
@@ -278,7 +279,7 @@ Statement *ExpStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int ExpStatement::blockExit()
|
||||
int ExpStatement::blockExit(bool mustNotThrow)
|
||||
{ int result = BEfallthru;
|
||||
|
||||
if (exp)
|
||||
@@ -291,7 +292,7 @@ int ExpStatement::blockExit()
|
||||
if (a->e1->isBool(FALSE)) // if it's an assert(0)
|
||||
return BEhalt;
|
||||
}
|
||||
if (exp->canThrow())
|
||||
if (exp->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
}
|
||||
return result;
|
||||
@@ -347,7 +348,8 @@ Statements *CompileStatement::flatten(Scope *sc)
|
||||
while (p.token.value != TOKeof)
|
||||
{
|
||||
Statement *s = p.parseStatement(PSsemi | PScurlyscope);
|
||||
a->push(s);
|
||||
if (s) // if no parsing errors
|
||||
a->push(s);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
@@ -640,7 +642,7 @@ int CompoundStatement::usesEH()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CompoundStatement::blockExit()
|
||||
int CompoundStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
|
||||
int result = BEfallthru;
|
||||
@@ -652,13 +654,13 @@ int CompoundStatement::blockExit()
|
||||
//printf("%s\n", s->toChars());
|
||||
if (!(result & BEfallthru) && !s->comeFrom())
|
||||
{
|
||||
if (s->blockExit() != BEhalt && !s->isEmpty())
|
||||
if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty())
|
||||
s->warning("statement is not reachable");
|
||||
}
|
||||
else
|
||||
{
|
||||
result &= ~BEfallthru;
|
||||
result |= s->blockExit();
|
||||
result |= s->blockExit(mustNotThrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -852,14 +854,14 @@ int UnrolledLoopStatement::usesEH()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int UnrolledLoopStatement::blockExit()
|
||||
int UnrolledLoopStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
int result = BEfallthru;
|
||||
for (size_t i = 0; i < statements->dim; i++)
|
||||
{ Statement *s = (Statement *) statements->data[i];
|
||||
if (s)
|
||||
{
|
||||
int r = s->blockExit();
|
||||
int r = s->blockExit(mustNotThrow);
|
||||
result |= r & ~(BEbreak | BEcontinue);
|
||||
}
|
||||
}
|
||||
@@ -955,10 +957,10 @@ int ScopeStatement::usesEH()
|
||||
return statement ? statement->usesEH() : FALSE;
|
||||
}
|
||||
|
||||
int ScopeStatement::blockExit()
|
||||
int ScopeStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("ScopeStatement::blockExit(%p)\n", statement);
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
|
||||
}
|
||||
|
||||
|
||||
@@ -1028,18 +1030,18 @@ int WhileStatement::usesEH()
|
||||
return body ? body->usesEH() : 0;
|
||||
}
|
||||
|
||||
int WhileStatement::blockExit()
|
||||
int WhileStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
assert(0);
|
||||
//printf("WhileStatement::blockExit(%p)\n", this);
|
||||
|
||||
int result = BEnone;
|
||||
if (condition->canThrow())
|
||||
if (condition->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
if (condition->isBool(TRUE))
|
||||
{
|
||||
if (body)
|
||||
{ result |= body->blockExit();
|
||||
{ result |= body->blockExit(mustNotThrow);
|
||||
if (result & BEbreak)
|
||||
result |= BEfallthru;
|
||||
}
|
||||
@@ -1051,7 +1053,7 @@ int WhileStatement::blockExit()
|
||||
else
|
||||
{
|
||||
if (body)
|
||||
result |= body->blockExit();
|
||||
result |= body->blockExit(mustNotThrow);
|
||||
result |= BEfallthru;
|
||||
}
|
||||
result &= ~(BEbreak | BEcontinue);
|
||||
@@ -1123,11 +1125,11 @@ int DoStatement::usesEH()
|
||||
return body ? body->usesEH() : 0;
|
||||
}
|
||||
|
||||
int DoStatement::blockExit()
|
||||
int DoStatement::blockExit(bool mustNotThrow)
|
||||
{ int result;
|
||||
|
||||
if (body)
|
||||
{ result = body->blockExit();
|
||||
{ result = body->blockExit(mustNotThrow);
|
||||
if (result == BEbreak)
|
||||
return BEfallthru;
|
||||
if (result & BEcontinue)
|
||||
@@ -1137,7 +1139,7 @@ int DoStatement::blockExit()
|
||||
result = BEfallthru;
|
||||
if (result & BEfallthru)
|
||||
{
|
||||
if (condition->canThrow())
|
||||
if (condition->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
if (!(result & BEbreak) && condition->isBool(TRUE))
|
||||
result &= ~BEfallthru;
|
||||
@@ -1248,16 +1250,16 @@ int ForStatement::usesEH()
|
||||
return (init && init->usesEH()) || body->usesEH();
|
||||
}
|
||||
|
||||
int ForStatement::blockExit()
|
||||
int ForStatement::blockExit(bool mustNotThrow)
|
||||
{ int result = BEfallthru;
|
||||
|
||||
if (init)
|
||||
{ result = init->blockExit();
|
||||
{ result = init->blockExit(mustNotThrow);
|
||||
if (!(result & BEfallthru))
|
||||
return result;
|
||||
}
|
||||
if (condition)
|
||||
{ if (condition->canThrow())
|
||||
{ if (condition->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
if (condition->isBool(TRUE))
|
||||
result &= ~BEfallthru;
|
||||
@@ -1267,12 +1269,12 @@ int ForStatement::blockExit()
|
||||
else
|
||||
result &= ~BEfallthru; // the body must do the exiting
|
||||
if (body)
|
||||
{ int r = body->blockExit();
|
||||
{ int r = body->blockExit(mustNotThrow);
|
||||
if (r & (BEbreak | BEgoto))
|
||||
result |= BEfallthru;
|
||||
result |= r & ~(BEfallthru | BEbreak | BEcontinue);
|
||||
}
|
||||
if (increment && increment->canThrow())
|
||||
if (increment && increment->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
return result;
|
||||
}
|
||||
@@ -2086,15 +2088,15 @@ int ForeachStatement::usesEH()
|
||||
return body->usesEH();
|
||||
}
|
||||
|
||||
int ForeachStatement::blockExit()
|
||||
int ForeachStatement::blockExit(bool mustNotThrow)
|
||||
{ int result = BEfallthru;
|
||||
|
||||
if (aggr->canThrow())
|
||||
if (aggr->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
|
||||
if (body)
|
||||
{
|
||||
result |= body->blockExit() & ~(BEbreak | BEcontinue);
|
||||
result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2316,19 +2318,19 @@ int ForeachRangeStatement::usesEH()
|
||||
return body->usesEH();
|
||||
}
|
||||
|
||||
int ForeachRangeStatement::blockExit()
|
||||
int ForeachRangeStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
assert(0);
|
||||
int result = BEfallthru;
|
||||
|
||||
if (lwr && lwr->canThrow())
|
||||
if (lwr && lwr->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
else if (upr && upr->canThrow())
|
||||
else if (upr && upr->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
|
||||
if (body)
|
||||
{
|
||||
result |= body->blockExit() & ~(BEbreak | BEcontinue);
|
||||
result |= body->blockExit(mustNotThrow) & ~(BEbreak | BEcontinue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2454,35 +2456,35 @@ int IfStatement::usesEH()
|
||||
return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
|
||||
}
|
||||
|
||||
int IfStatement::blockExit()
|
||||
int IfStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("IfStatement::blockExit(%p)\n", this);
|
||||
|
||||
int result = BEnone;
|
||||
if (condition->canThrow())
|
||||
if (condition->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
if (condition->isBool(TRUE))
|
||||
{
|
||||
if (ifbody)
|
||||
result |= ifbody->blockExit();
|
||||
result |= ifbody->blockExit(mustNotThrow);
|
||||
else
|
||||
result |= BEfallthru;
|
||||
}
|
||||
else if (condition->isBool(FALSE))
|
||||
{
|
||||
if (elsebody)
|
||||
result |= elsebody->blockExit();
|
||||
result |= elsebody->blockExit(mustNotThrow);
|
||||
else
|
||||
result |= BEfallthru;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifbody)
|
||||
result |= ifbody->blockExit();
|
||||
result |= ifbody->blockExit(mustNotThrow);
|
||||
else
|
||||
result |= BEfallthru;
|
||||
if (elsebody)
|
||||
result |= elsebody->blockExit();
|
||||
result |= elsebody->blockExit(mustNotThrow);
|
||||
else
|
||||
result |= BEfallthru;
|
||||
}
|
||||
@@ -2574,11 +2576,11 @@ int ConditionalStatement::usesEH()
|
||||
return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH());
|
||||
}
|
||||
|
||||
int ConditionalStatement::blockExit()
|
||||
int ConditionalStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
int result = ifbody->blockExit();
|
||||
int result = ifbody->blockExit(mustNotThrow);
|
||||
if (elsebody)
|
||||
result |= elsebody->blockExit();
|
||||
result |= elsebody->blockExit(mustNotThrow);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2724,14 +2726,14 @@ int PragmaStatement::usesEH()
|
||||
return body && body->usesEH();
|
||||
}
|
||||
|
||||
int PragmaStatement::blockExit()
|
||||
int PragmaStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
int result = BEfallthru;
|
||||
#if 0 // currently, no code is generated for Pragma's, so it's just fallthru
|
||||
if (arrayExpressionCanThrow(args))
|
||||
result |= BEthrow;
|
||||
if (body)
|
||||
result |= body->blockExit();
|
||||
result |= body->blockExit(mustNotThrow);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@@ -2786,7 +2788,7 @@ Statement *StaticAssertStatement::semantic(Scope *sc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int StaticAssertStatement::blockExit()
|
||||
int StaticAssertStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return BEfallthru;
|
||||
}
|
||||
@@ -2964,13 +2966,13 @@ int SwitchStatement::usesEH()
|
||||
return body ? body->usesEH() : 0;
|
||||
}
|
||||
|
||||
int SwitchStatement::blockExit()
|
||||
int SwitchStatement::blockExit(bool mustNotThrow)
|
||||
{ int result = BEnone;
|
||||
if (condition->canThrow())
|
||||
if (condition->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
|
||||
if (body)
|
||||
{ result |= body->blockExit();
|
||||
{ result |= body->blockExit(mustNotThrow);
|
||||
if (result & BEbreak)
|
||||
{ result |= BEfallthru;
|
||||
result &= ~BEbreak;
|
||||
@@ -3115,9 +3117,9 @@ int CaseStatement::usesEH()
|
||||
return statement->usesEH();
|
||||
}
|
||||
|
||||
int CaseStatement::blockExit()
|
||||
int CaseStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return statement->blockExit();
|
||||
return statement->blockExit(mustNotThrow);
|
||||
}
|
||||
|
||||
|
||||
@@ -3278,9 +3280,9 @@ int DefaultStatement::usesEH()
|
||||
return statement->usesEH();
|
||||
}
|
||||
|
||||
int DefaultStatement::blockExit()
|
||||
int DefaultStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return statement->blockExit();
|
||||
return statement->blockExit(mustNotThrow);
|
||||
}
|
||||
|
||||
|
||||
@@ -3317,7 +3319,7 @@ Statement *GotoDefaultStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int GotoDefaultStatement::blockExit()
|
||||
int GotoDefaultStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return BEgoto;
|
||||
}
|
||||
@@ -3365,7 +3367,7 @@ Statement *GotoCaseStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int GotoCaseStatement::blockExit()
|
||||
int GotoCaseStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return BEgoto;
|
||||
}
|
||||
@@ -3389,9 +3391,10 @@ SwitchErrorStatement::SwitchErrorStatement(Loc loc)
|
||||
{
|
||||
}
|
||||
|
||||
int SwitchErrorStatement::blockExit()
|
||||
int SwitchErrorStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return BEthrow;
|
||||
// Switch errors are non-recoverable
|
||||
return BEhalt;
|
||||
}
|
||||
|
||||
|
||||
@@ -3713,10 +3716,10 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int ReturnStatement::blockExit()
|
||||
int ReturnStatement::blockExit(bool mustNotThrow)
|
||||
{ int result = BEreturn;
|
||||
|
||||
if (exp && exp->canThrow())
|
||||
if (exp && exp->canThrow(mustNotThrow))
|
||||
result |= BEthrow;
|
||||
return result;
|
||||
}
|
||||
@@ -3808,7 +3811,7 @@ Statement *BreakStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int BreakStatement::blockExit()
|
||||
int BreakStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
|
||||
return ident ? BEgoto : BEbreak;
|
||||
@@ -3911,7 +3914,7 @@ Statement *ContinueStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int ContinueStatement::blockExit()
|
||||
int ContinueStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return ident ? BEgoto : BEcontinue;
|
||||
}
|
||||
@@ -4089,9 +4092,9 @@ int SynchronizedStatement::usesEH()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int SynchronizedStatement::blockExit()
|
||||
int SynchronizedStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return body ? body->blockExit() : BEfallthru;
|
||||
return body ? body->blockExit(mustNotThrow) : BEfallthru;
|
||||
}
|
||||
|
||||
|
||||
@@ -4202,13 +4205,13 @@ int WithStatement::usesEH()
|
||||
return body ? body->usesEH() : 0;
|
||||
}
|
||||
|
||||
int WithStatement::blockExit()
|
||||
int WithStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
int result = BEnone;
|
||||
if (exp->canThrow())
|
||||
if (exp->canThrow(mustNotThrow))
|
||||
result = BEthrow;
|
||||
if (body)
|
||||
result |= body->blockExit();
|
||||
result |= body->blockExit(mustNotThrow);
|
||||
else
|
||||
result |= BEfallthru;
|
||||
return result;
|
||||
@@ -4277,10 +4280,10 @@ int TryCatchStatement::usesEH()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TryCatchStatement::blockExit()
|
||||
int TryCatchStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
assert(body);
|
||||
int result = body->blockExit();
|
||||
int result = body->blockExit(false);
|
||||
|
||||
int catchresult = 0;
|
||||
for (size_t i = 0; i < catches->dim; i++)
|
||||
@@ -4289,7 +4292,7 @@ int TryCatchStatement::blockExit()
|
||||
if (c->type == Type::terror)
|
||||
continue;
|
||||
|
||||
catchresult |= c->blockExit();
|
||||
catchresult |= c->blockExit(mustNotThrow);
|
||||
|
||||
/* If we're catching Object, then there is no throwing
|
||||
*/
|
||||
@@ -4300,6 +4303,10 @@ int TryCatchStatement::blockExit()
|
||||
result &= ~BEthrow;
|
||||
}
|
||||
}
|
||||
if (mustNotThrow && (result & BEthrow))
|
||||
{
|
||||
body->blockExit(mustNotThrow); // now explain why this is nothrow
|
||||
}
|
||||
return result | catchresult;
|
||||
}
|
||||
|
||||
@@ -4381,9 +4388,9 @@ void Catch::semantic(Scope *sc)
|
||||
sc->pop();
|
||||
}
|
||||
|
||||
int Catch::blockExit()
|
||||
int Catch::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return handler ? handler->blockExit() : BEfallthru;
|
||||
return handler ? handler->blockExit(mustNotThrow) : BEfallthru;
|
||||
}
|
||||
|
||||
void Catch::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
@@ -4438,7 +4445,7 @@ Statement *TryFinallyStatement::semantic(Scope *sc)
|
||||
return finalbody;
|
||||
if (!finalbody)
|
||||
return body;
|
||||
if (body->blockExit() == BEfallthru)
|
||||
if (body->blockExit(false) == BEfallthru)
|
||||
{ Statement *s = new CompoundStatement(loc, body, finalbody);
|
||||
return s;
|
||||
}
|
||||
@@ -4470,10 +4477,10 @@ int TryFinallyStatement::usesEH()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TryFinallyStatement::blockExit()
|
||||
int TryFinallyStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
if (body)
|
||||
return body->blockExit();
|
||||
return body->blockExit(mustNotThrow);
|
||||
return BEfallthru;
|
||||
}
|
||||
|
||||
@@ -4500,7 +4507,7 @@ Statement *OnScopeStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int OnScopeStatement::blockExit()
|
||||
int OnScopeStatement::blockExit(bool mustNotThrow)
|
||||
{ // At this point, this statement is just an empty placeholder
|
||||
return BEfallthru;
|
||||
}
|
||||
@@ -4596,8 +4603,10 @@ Statement *ThrowStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int ThrowStatement::blockExit()
|
||||
int ThrowStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
if (mustNotThrow)
|
||||
error("%s is thrown but not caught", exp->type->toChars());
|
||||
return BEthrow; // obviously
|
||||
}
|
||||
|
||||
@@ -4654,9 +4663,9 @@ Statements *VolatileStatement::flatten(Scope *sc)
|
||||
return a;
|
||||
}
|
||||
|
||||
int VolatileStatement::blockExit()
|
||||
int VolatileStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
|
||||
}
|
||||
|
||||
|
||||
@@ -4719,7 +4728,7 @@ Statement *GotoStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
int GotoStatement::blockExit()
|
||||
int GotoStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("GotoStatement::blockExit(%p)\n", this);
|
||||
return BEgoto;
|
||||
@@ -4811,10 +4820,10 @@ int LabelStatement::usesEH()
|
||||
return statement ? statement->usesEH() : FALSE;
|
||||
}
|
||||
|
||||
int LabelStatement::blockExit()
|
||||
int LabelStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
//printf("LabelStatement::blockExit(%p)\n", this);
|
||||
return statement ? statement->blockExit() : BEfallthru;
|
||||
return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
|
||||
}
|
||||
|
||||
|
||||
@@ -4849,3 +4858,68 @@ LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
#if !IN_LLVM
|
||||
|
||||
/************************ AsmStatement ***************************************/
|
||||
|
||||
AsmStatement::AsmStatement(Loc loc, Token *tokens)
|
||||
: Statement(loc)
|
||||
{
|
||||
this->tokens = tokens;
|
||||
asmcode = NULL;
|
||||
asmalign = 0;
|
||||
refparam = FALSE;
|
||||
naked = FALSE;
|
||||
regs = 0;
|
||||
}
|
||||
|
||||
Statement *AsmStatement::syntaxCopy()
|
||||
{
|
||||
return new AsmStatement(loc, tokens);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AsmStatement::comeFrom()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int AsmStatement::blockExit(bool mustNotThrow)
|
||||
{
|
||||
if (mustNotThrow)
|
||||
error("asm statements are assumed to throw", toChars());
|
||||
// Assume the worst
|
||||
return BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt;
|
||||
}
|
||||
|
||||
void AsmStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
{
|
||||
buf->writestring("asm { ");
|
||||
Token *t = tokens;
|
||||
while (t)
|
||||
{
|
||||
buf->writestring(t->toChars());
|
||||
if (t->next &&
|
||||
t->value != TOKmin &&
|
||||
t->value != TOKcomma &&
|
||||
t->next->value != TOKcomma &&
|
||||
t->value != TOKlbracket &&
|
||||
t->next->value != TOKlbracket &&
|
||||
t->next->value != TOKrbracket &&
|
||||
t->value != TOKlparen &&
|
||||
t->next->value != TOKlparen &&
|
||||
t->next->value != TOKrparen &&
|
||||
t->value != TOKdot &&
|
||||
t->next->value != TOKdot)
|
||||
{
|
||||
buf->writebyte(' ');
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
buf->writestring("; }");
|
||||
buf->writenl();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -130,7 +130,7 @@ struct Statement : Object
|
||||
virtual int hasBreak();
|
||||
virtual int hasContinue();
|
||||
virtual int usesEH();
|
||||
virtual int blockExit();
|
||||
virtual int blockExit(bool mustNotThrow);
|
||||
virtual int comeFrom();
|
||||
virtual int isEmpty();
|
||||
virtual void scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
|
||||
@@ -174,7 +174,7 @@ struct ExpStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int isEmpty();
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -224,7 +224,7 @@ struct CompoundStatement : Statement
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
virtual Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
int isEmpty();
|
||||
virtual Statements *flatten(Scope *sc);
|
||||
@@ -265,7 +265,7 @@ struct UnrolledLoopStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -289,7 +289,7 @@ struct ScopeStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
int isEmpty();
|
||||
Expression *interpret(InterState *istate);
|
||||
@@ -310,7 +310,7 @@ struct WhileStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -331,7 +331,7 @@ struct DoStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -355,7 +355,7 @@ struct ForStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -387,7 +387,7 @@ struct ForeachStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -415,7 +415,7 @@ struct ForeachRangeStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -441,7 +441,7 @@ struct IfStatement : Statement
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
IfStatement *isIfStatement() { return this; }
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -462,7 +462,7 @@ struct ConditionalStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
@@ -477,7 +477,7 @@ struct PragmaStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -491,7 +491,7 @@ struct StaticAssertStatement : Statement
|
||||
StaticAssertStatement(StaticAssert *sa);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
@@ -518,7 +518,7 @@ struct SwitchStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
@@ -544,7 +544,7 @@ struct CaseStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int compare(Object *obj);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -592,7 +592,7 @@ struct DefaultStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -614,7 +614,7 @@ struct GotoDefaultStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -630,7 +630,7 @@ struct GotoCaseStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -639,7 +639,7 @@ struct GotoCaseStatement : Statement
|
||||
struct SwitchErrorStatement : Statement
|
||||
{
|
||||
SwitchErrorStatement(Loc loc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -653,7 +653,7 @@ struct ReturnStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
int inlineCost(InlineCostState *ics);
|
||||
@@ -673,7 +673,7 @@ struct BreakStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -692,7 +692,7 @@ struct ContinueStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Expression *interpret(InterState *istate);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -714,7 +714,7 @@ struct SynchronizedStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -739,7 +739,7 @@ struct WithStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -757,7 +757,7 @@ struct TryCatchStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
int hasBreak();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -778,7 +778,7 @@ struct Catch : Object
|
||||
Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
|
||||
Catch *syntaxCopy();
|
||||
void semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
};
|
||||
|
||||
@@ -794,7 +794,7 @@ struct TryFinallyStatement : Statement
|
||||
int hasBreak();
|
||||
int hasContinue();
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -809,7 +809,7 @@ struct OnScopeStatement : Statement
|
||||
|
||||
OnScopeStatement(Loc loc, TOK tok, Statement *statement);
|
||||
Statement *syntaxCopy();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
Statement *semantic(Scope *sc);
|
||||
int usesEH();
|
||||
@@ -827,7 +827,7 @@ struct ThrowStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -843,7 +843,7 @@ struct VolatileStatement : Statement
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
@@ -861,7 +861,7 @@ struct GotoStatement : Statement
|
||||
GotoStatement(Loc loc, Identifier *ident);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
@@ -884,7 +884,7 @@ struct LabelStatement : Statement
|
||||
Statement *semantic(Scope *sc);
|
||||
Statements *flatten(Scope *sc);
|
||||
int usesEH();
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||
@@ -923,7 +923,7 @@ struct AsmStatement : Statement
|
||||
AsmStatement(Loc loc, Token *tokens);
|
||||
Statement *syntaxCopy();
|
||||
Statement *semantic(Scope *sc);
|
||||
int blockExit();
|
||||
int blockExit(bool mustNotThrow);
|
||||
int comeFrom();
|
||||
Expression *interpret(InterState *istate);
|
||||
|
||||
|
||||
@@ -338,11 +338,11 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
error("structs, unions cannot be abstract");
|
||||
#if DMDV2
|
||||
if (storage_class & STCimmutable)
|
||||
type = type->invariantOf();
|
||||
else if (storage_class & STCconst)
|
||||
type = type->constOf();
|
||||
else if (storage_class & STCshared)
|
||||
type = type->sharedOf();
|
||||
type = type->addMod(MODimmutable);
|
||||
if (storage_class & STCconst)
|
||||
type = type->addMod(MODconst);
|
||||
if (storage_class & STCshared)
|
||||
type = type->addMod(MODshared);
|
||||
#endif
|
||||
|
||||
if (sizeok == 0) // if not already done the addMember step
|
||||
@@ -393,7 +393,7 @@ void StructDeclaration::semantic(Scope *sc)
|
||||
|
||||
sizeok = 0;
|
||||
sc2 = sc->push(this);
|
||||
sc2->stc &= storage_class & STC_TYPECTOR;
|
||||
sc2->stc &= STCsafe | STCtrusted | STCsystem;
|
||||
sc2->parent = this;
|
||||
if (isUnionDeclaration())
|
||||
sc2->inunion = 1;
|
||||
|
||||
@@ -212,9 +212,19 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
}
|
||||
else if (s1)
|
||||
{
|
||||
//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
|
||||
if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
|
||||
{
|
||||
if (s2)
|
||||
{
|
||||
VarDeclaration *v1 = s1->isVarDeclaration();
|
||||
VarDeclaration *v2 = s2->isVarDeclaration();
|
||||
if (v1 && v2 && v1->storage_class & v2->storage_class & STCmanifest)
|
||||
{ ExpInitializer *ei1 = v1->init->isExpInitializer();
|
||||
ExpInitializer *ei2 = v2->init->isExpInitializer();
|
||||
if (ei1 && ei2 && ei1->exp->equals(ei2->exp))
|
||||
goto Lmatch;
|
||||
}
|
||||
}
|
||||
goto Lnomatch;
|
||||
}
|
||||
#if DMDV2
|
||||
@@ -242,6 +252,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc)
|
||||
goto Lnomatch;
|
||||
}
|
||||
}
|
||||
Lmatch:
|
||||
//printf("match\n");
|
||||
return 1; // match
|
||||
Lnomatch:
|
||||
@@ -716,8 +727,10 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
|
||||
*/
|
||||
makeParamNamesVisibleInConstraint(paramscope);
|
||||
Expression *e = constraint->syntaxCopy();
|
||||
paramscope->flags |= SCOPEstaticif;
|
||||
e = e->semantic(paramscope);
|
||||
Scope *sc = paramscope->push();
|
||||
sc->flags |= SCOPEstaticif;
|
||||
e = e->semantic(sc);
|
||||
sc->pop();
|
||||
e = e->optimize(WANTvalue | WANTinterpret);
|
||||
if (e->isBool(TRUE))
|
||||
;
|
||||
@@ -1304,17 +1317,31 @@ Lmatch:
|
||||
paramscope->flags |= SCOPEstaticif;
|
||||
|
||||
/* Detect recursive attempts to instantiate this template declaration,
|
||||
* Bugzilla 4072
|
||||
* void foo(T)(T x) if (is(typeof(foo(x)))) { }
|
||||
* static assert(!is(typeof(bug4072(7))));
|
||||
* static assert(!is(typeof(foo(7))));
|
||||
* Recursive attempts are regarded as a constraint failure.
|
||||
*/
|
||||
int nmatches = 0;
|
||||
for (Previous *p = previous; p; p = p->prev)
|
||||
{
|
||||
if (arrayObjectMatch(p->dedargs, dedargs, this, sc))
|
||||
goto Lnomatch;
|
||||
{
|
||||
//printf("recursive, no match %p %s\n", this, this->toChars());
|
||||
nmatches++;
|
||||
}
|
||||
/* BUG: should also check for ref param differences
|
||||
*/
|
||||
}
|
||||
/* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to
|
||||
* be recursion but isn't.
|
||||
* Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint.
|
||||
* Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk
|
||||
* with that is what if semantic3() fails, but our constraint "succeeded"?
|
||||
*/
|
||||
if (nmatches >= 2)
|
||||
goto Lnomatch;
|
||||
|
||||
Previous pr;
|
||||
pr.prev = previous;
|
||||
pr.dedargs = dedargs;
|
||||
@@ -3523,7 +3550,11 @@ MATCH TemplateTupleParameter::matchArg(Scope *sc,
|
||||
*/
|
||||
assert(i + 1 == dedtypes->dim); // must be the last one
|
||||
Tuple *ovar;
|
||||
if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i]))
|
||||
|
||||
if (dedtypes->data[i] && isTuple((Object *)dedtypes->data[i]))
|
||||
// It was already been deduced
|
||||
ovar = isTuple((Object *)dedtypes->data[i]);
|
||||
else if (i + 1 == tiargs->dim && isTuple((Object *)tiargs->data[i]))
|
||||
ovar = isTuple((Object *)tiargs->data[i]);
|
||||
else
|
||||
{
|
||||
@@ -3865,7 +3896,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
||||
/* So, we need to implement 'this' instance.
|
||||
*/
|
||||
#if LOG
|
||||
printf("\timplement template instance '%s'\n", toChars());
|
||||
printf("\timplement template instance %s '%s'\n", tempdecl->parent->toChars(), toChars());
|
||||
printf("\ttempdecl %s\n", tempdecl->toChars());
|
||||
#endif
|
||||
unsigned errorsave = global.errors;
|
||||
inst = this;
|
||||
@@ -3874,7 +3906,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
||||
parent = tempdecl->parent;
|
||||
//printf("parent = '%s'\n", parent->kind());
|
||||
|
||||
ident = genIdent(); // need an identifier for name mangling purposes.
|
||||
ident = genIdent(tiargs); // need an identifier for name mangling purposes.
|
||||
|
||||
#if 1
|
||||
if (isnested)
|
||||
@@ -3917,7 +3949,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
||||
//printf("\t2: adding to module %s instead of module %s\n", m->toChars(), sc->module->toChars());
|
||||
a = m->members;
|
||||
if (m->semanticRun >= 3)
|
||||
{
|
||||
dosemantic3 = 1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; 1; i++)
|
||||
{
|
||||
@@ -4122,13 +4156,14 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
|
||||
// Give additional context info if error occurred during instantiation
|
||||
if (global.errors != errorsave)
|
||||
{
|
||||
error("error instantiating");
|
||||
error(loc, "error instantiating");
|
||||
if (tinst)
|
||||
{ tinst->printInstantiationTrace();
|
||||
}
|
||||
errors = 1;
|
||||
if (global.gag)
|
||||
{ // Try to reset things so we can try again later to instantiate it
|
||||
//printf("remove %s\n", toChars());
|
||||
tempdecl->instances.remove(tempdecl_instance_idx);
|
||||
if (!(sc->flags & SCOPEstaticif))
|
||||
{ // Bugzilla 4302 for discussion
|
||||
@@ -4345,11 +4380,7 @@ TemplateDeclaration *TemplateInstance::findTemplateDeclaration(Scope *sc)
|
||||
if (s->parent &&
|
||||
(ti = s->parent->isTemplateInstance()) != NULL)
|
||||
{
|
||||
if (
|
||||
(ti->name == id ||
|
||||
ti->toAlias()->ident == id)
|
||||
&&
|
||||
ti->tempdecl)
|
||||
if (ti->tempdecl && ti->tempdecl->ident == id)
|
||||
{
|
||||
/* This is so that one can refer to the enclosing
|
||||
* template, even if it has the same name as a member
|
||||
@@ -4637,13 +4668,12 @@ int TemplateInstance::hasNestedArgs(Objects *args)
|
||||
* the type signature for it.
|
||||
*/
|
||||
|
||||
Identifier *TemplateInstance::genIdent()
|
||||
Identifier *TemplateInstance::genIdent(Objects *args)
|
||||
{ OutBuffer buf;
|
||||
|
||||
//printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
|
||||
char *id = tempdecl->ident->toChars();
|
||||
buf.printf("__T%zu%s", strlen(id), id);
|
||||
Objects *args = tiargs;
|
||||
for (int i = 0; i < args->dim; i++)
|
||||
{ Object *o = (Object *)args->data[i];
|
||||
Type *ta = isType(o);
|
||||
@@ -4723,6 +4753,14 @@ Identifier *TemplateInstance::genIdent()
|
||||
}
|
||||
#endif
|
||||
const char *p = sa->mangle();
|
||||
|
||||
/* Bugzilla 3043: if the first character of p is a digit this
|
||||
* causes ambiguity issues because the digits of the two numbers are adjacent.
|
||||
* Current demanglers resolve this by trying various places to separate the
|
||||
* numbers until one gets a successful demangle.
|
||||
* Unfortunately, fixing this ambiguity will break existing binary
|
||||
* compatibility and the demanglers, so we'll leave it as is.
|
||||
*/
|
||||
buf.printf("%zu%s", strlen(p), p);
|
||||
}
|
||||
else if (va)
|
||||
@@ -4736,9 +4774,9 @@ Identifier *TemplateInstance::genIdent()
|
||||
}
|
||||
buf.writeByte('Z');
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//buf.data = NULL; // we can free the string after call to idPool()
|
||||
//printf("\tgenIdent = %s\n", id);
|
||||
return new Identifier(id, TOKidentifier);
|
||||
return Lexer::idPool(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -5269,7 +5307,7 @@ void TemplateMixin::semantic(Scope *sc)
|
||||
}
|
||||
|
||||
if (!ident)
|
||||
ident = genIdent();
|
||||
ident = genIdent(tiargs);
|
||||
|
||||
inst = this;
|
||||
parent = sc->parent;
|
||||
|
||||
@@ -336,7 +336,7 @@ struct TemplateInstance : ScopeDsymbol
|
||||
TemplateDeclaration *findBestMatch(Scope *sc);
|
||||
void declareParameters(Scope *sc);
|
||||
int hasNestedArgs(Objects *tiargs);
|
||||
Identifier *genIdent();
|
||||
Identifier *genIdent(Objects *args);
|
||||
|
||||
TemplateInstance *isTemplateInstance() { return this; }
|
||||
AliasDeclaration *isAliasDeclaration();
|
||||
|
||||
1259
druntime.patch
1259
druntime.patch
File diff suppressed because it is too large
Load Diff
30
gen/aa.cpp
30
gen/aa.cpp
@@ -37,13 +37,25 @@ static LLValue* to_keyti(DValue* key)
|
||||
|
||||
DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
|
||||
{
|
||||
// D1:
|
||||
// call:
|
||||
// extern(C) void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
// or
|
||||
// extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey)
|
||||
|
||||
// D2:
|
||||
// call:
|
||||
// extern(C) void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
// or
|
||||
// extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey)
|
||||
|
||||
// first get the runtime function
|
||||
#if DMDV2
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGetX":"_aaInX");
|
||||
#else
|
||||
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, lvalue?"_aaGet":"_aaIn");
|
||||
#endif
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
// aa param
|
||||
@@ -127,11 +139,20 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
|
||||
|
||||
DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key)
|
||||
{
|
||||
// D1:
|
||||
// call:
|
||||
// extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey)
|
||||
|
||||
// D2:
|
||||
// call:
|
||||
// extern(C) void* _aaInX(AA aa*, TypeInfo keyti, void* pkey)
|
||||
|
||||
// first get the runtime function
|
||||
#if DMDV2
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaInX");
|
||||
#else
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaIn");
|
||||
#endif
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
if (Logger::enabled())
|
||||
@@ -173,11 +194,20 @@ DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key)
|
||||
|
||||
void DtoAARemove(Loc& loc, DValue* aa, DValue* key)
|
||||
{
|
||||
// D1:
|
||||
// call:
|
||||
// extern(C) void _aaDel(AA aa, TypeInfo keyti, void* pkey)
|
||||
|
||||
// D2:
|
||||
// call:
|
||||
// extern(C) void _aaDelX(AA aa, TypeInfo keyti, void* pkey)
|
||||
|
||||
// first get the runtime function
|
||||
#if DMDV2
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDelX");
|
||||
#else
|
||||
llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaDel");
|
||||
#endif
|
||||
const llvm::FunctionType* funcTy = func->getFunctionType();
|
||||
|
||||
if (Logger::enabled())
|
||||
|
||||
@@ -627,9 +627,27 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size
|
||||
|
||||
#if DMDV2
|
||||
const char* fnname = zeroInit ? "_d_newarraymT" : "_d_newarraymiT";
|
||||
|
||||
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname);
|
||||
|
||||
std::vector<LLValue*> args;
|
||||
args.push_back(arrayTypeInfo);
|
||||
args.push_back(DtoConstSize_t(ndims));
|
||||
|
||||
// build dims
|
||||
for (size_t i=0; i<ndims; ++i)
|
||||
args.push_back(dims[i]->getRVal());
|
||||
|
||||
// call allocator
|
||||
LLValue* newptr = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".gc_mem").getInstruction();
|
||||
|
||||
if (Logger::enabled())
|
||||
Logger::cout() << "final ptr = " << *newptr << '\n';
|
||||
|
||||
return getSlice(arrayType, newptr);
|
||||
#else
|
||||
|
||||
const char* fnname = defaultInit ? (zeroInit ? "_d_newarraymT" : "_d_newarraymiT") : "_d_newarraymvT";
|
||||
#endif
|
||||
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname);
|
||||
|
||||
// build dims
|
||||
@@ -645,9 +663,6 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size
|
||||
// call allocator
|
||||
LLValue* newptr = gIR->CreateCallOrInvoke3(fn, arrayTypeInfo, DtoConstSize_t(ndims), dimsArg, ".gc_mem").getInstruction();
|
||||
|
||||
#if DMDV2
|
||||
return getSlice(arrayType, newptr);
|
||||
#else
|
||||
// cast to wanted type
|
||||
const LLType* dstType = DtoType(arrayType)->getContainedType(1);
|
||||
if (newptr->getType() != dstType)
|
||||
|
||||
@@ -182,9 +182,17 @@ Statement *AsmStatement::semantic(Scope *sc)
|
||||
return this;
|
||||
}
|
||||
|
||||
#if DMDV2
|
||||
int AsmStatement::blockExit(bool mustNotThrow)
|
||||
#else
|
||||
int AsmStatement::blockExit()
|
||||
#endif
|
||||
{
|
||||
//printf("AsmStatement::blockExit(%p)\n", this);
|
||||
#if DMDV2
|
||||
if (mustNotThrow)
|
||||
error("asm statements are assumed to throw", toChars());
|
||||
#endif
|
||||
return BEfallthru | BEreturn | BEgoto | BEhalt;
|
||||
}
|
||||
|
||||
|
||||
@@ -915,10 +915,8 @@ DValue* DtoArgument(Parameter* fnarg, Expression* argexp)
|
||||
// ref/out arg
|
||||
if (fnarg && (fnarg->storageClass & (STCref | STCout)))
|
||||
{
|
||||
if (arg->isVar())
|
||||
arg = new DImValue(argexp->type, arg->getLVal());
|
||||
else
|
||||
arg = new DImValue(argexp->type, arg->getRVal());
|
||||
Loc loc;
|
||||
arg = new DImValue(argexp->type, makeLValue(loc, arg));
|
||||
}
|
||||
// lazy arg
|
||||
else if (fnarg && (fnarg->storageClass & STClazy))
|
||||
|
||||
@@ -1279,7 +1279,7 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
|
||||
|
||||
LLConstant* val = exp->toConstElem(gIR);
|
||||
|
||||
Type* expbase = exp->type->toBasetype();
|
||||
Type* expbase = stripModifiers(exp->type->toBasetype());
|
||||
Logger::println("expbase: %s", expbase->toChars());
|
||||
Type* t = base->toBasetype();
|
||||
|
||||
|
||||
@@ -360,8 +360,7 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(typeInfoTy);
|
||||
types.push_back(sizeTy);
|
||||
types.push_back(rt_ptr(sizeTy));
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, true);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||||
}
|
||||
@@ -833,9 +832,16 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
->setAttributes(Attr_ReadOnly_NoUnwind_1_NoCapture);
|
||||
}
|
||||
|
||||
// D1:
|
||||
// void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
// D2:
|
||||
// void* _aaGetX(AA* aa, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
{
|
||||
#if DMDV2
|
||||
llvm::StringRef fname("_aaGetX");
|
||||
#else
|
||||
llvm::StringRef fname("_aaGet");
|
||||
#endif
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(aaTy);
|
||||
types.push_back(typeInfoTy);
|
||||
@@ -846,9 +852,16 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
->setAttributes(Attr_1_4_NoCapture);
|
||||
}
|
||||
|
||||
// D1:
|
||||
// void* _aaIn(AA aa, TypeInfo keyti, void* pkey)
|
||||
// D2:
|
||||
// void* _aaInX(AA aa, TypeInfo keyti, void* pkey)
|
||||
{
|
||||
#if DMDV2
|
||||
llvm::StringRef fname("_aaInX");
|
||||
#else
|
||||
llvm::StringRef fname("_aaIn");
|
||||
#endif
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(aaTy);
|
||||
types.push_back(typeInfoTy);
|
||||
@@ -858,9 +871,16 @@ static void LLVM_D_BuildRuntimeModule()
|
||||
->setAttributes(Attr_ReadOnly_1_3_NoCapture);
|
||||
}
|
||||
|
||||
// D1:
|
||||
// void _aaDel(AA aa, TypeInfo keyti, void* pkey)
|
||||
// D2:
|
||||
// void _aaDelX(AA aa, TypeInfo keyti, void* pkey)
|
||||
{
|
||||
#if DMDV2
|
||||
llvm::StringRef fname("_aaDelX");
|
||||
#else
|
||||
llvm::StringRef fname("_aaDel");
|
||||
#endif
|
||||
std::vector<const LLType*> types;
|
||||
types.push_back(aaTy);
|
||||
types.push_back(typeInfoTy);
|
||||
|
||||
@@ -1568,12 +1568,16 @@ void VolatileStatement::toIR(IRState* p)
|
||||
DtoMemoryBarrier(false, true, false, false);
|
||||
|
||||
// do statement
|
||||
p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL));
|
||||
p->func()->gen->targetScopes.push_back(IRTargetScope(this,new EnclosingVolatile(this),NULL,NULL));
|
||||
statement->toIR(p);
|
||||
p->func()->gen->targetScopes.pop_back();
|
||||
p->func()->gen->targetScopes.pop_back();
|
||||
|
||||
// no point in a unreachable barrier, terminating statements must insert this themselves.
|
||||
#if DMDV2
|
||||
if (statement->blockExit(false) & BEfallthru)
|
||||
#else
|
||||
if (statement->blockExit() & BEfallthru)
|
||||
#endif
|
||||
{
|
||||
// store-load
|
||||
DtoMemoryBarrier(false, false, true, false);
|
||||
|
||||
@@ -52,6 +52,14 @@ llvm::cl::opt<bool> checkPrintf("check-printf-calls",
|
||||
|
||||
void Expression::cacheLvalue(IRState* irs)
|
||||
{
|
||||
#if DMDV2
|
||||
if (isLvalue()) {
|
||||
Logger::println("Caching l-value of %s", toChars());
|
||||
LOG_SCOPE;
|
||||
cachedLvalue = toElem(irs)->getLVal();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
error("expression %s does not mask any l-value", toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
133
phobos.patch
133
phobos.patch
@@ -1,6 +1,6 @@
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/concurrency.d phobos/std/concurrency.d
|
||||
--- phobos-orig/std/concurrency.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/concurrency.d 2010-11-07 19:26:52.000000000 +0300
|
||||
--- phobos-orig/std/concurrency.d 2010-12-20 23:02:36.000000000 +0300
|
||||
+++ phobos/std/concurrency.d 2011-01-05 15:15:31.000000000 +0300
|
||||
@@ -359,9 +359,10 @@
|
||||
owner = ownerTid;
|
||||
fn( args );
|
||||
@@ -14,9 +14,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
return spawnTid;
|
||||
}
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/conv.d phobos/std/conv.d
|
||||
--- phobos-orig/std/conv.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/conv.d 2010-11-08 15:54:33.109464001 +0300
|
||||
@@ -1405,7 +1405,7 @@
|
||||
--- phobos-orig/std/conv.d 2010-12-20 23:02:36.000000000 +0300
|
||||
+++ phobos/std/conv.d 2011-01-05 15:15:31.000000000 +0300
|
||||
@@ -1425,7 +1425,7 @@
|
||||
else // not hex
|
||||
{
|
||||
if (toupper(p.front) == 'N' && !startsWithZero)
|
||||
@@ -25,7 +25,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
// nan
|
||||
enforce((p.popFront(), !p.empty && toupper(p.front) == 'A')
|
||||
&& (p.popFront(), !p.empty && toupper(p.front) == 'N'),
|
||||
@@ -3243,6 +3243,11 @@
|
||||
@@ -3263,6 +3263,11 @@
|
||||
T toImpl(T, S)(S d) if (is(Unqual!S == double) && isSomeString!(T))
|
||||
{
|
||||
//alias Unqual!(ElementType!T) Char;
|
||||
@@ -38,9 +38,9 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
int len = sprintf(buffer.ptr, "%g", d);
|
||||
return to!T(buffer[0 .. len].dup);
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/functional.d phobos/std/functional.d
|
||||
--- phobos-orig/std/functional.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/functional.d 2010-12-30 13:56:03.206104002 +0300
|
||||
@@ -713,6 +713,13 @@
|
||||
--- phobos-orig/std/functional.d 2010-12-20 23:02:36.000000000 +0300
|
||||
+++ phobos/std/functional.d 2011-01-05 15:15:31.000000000 +0300
|
||||
@@ -714,6 +714,13 @@
|
||||
assert(dg_pure_nothrow() == 7);
|
||||
//assert(dg_pure_nothrow_safe() == 8);
|
||||
}
|
||||
@@ -54,7 +54,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
/* test for linkage */
|
||||
{
|
||||
struct S
|
||||
@@ -724,4 +731,6 @@
|
||||
@@ -725,4 +732,6 @@
|
||||
auto dg_xtrnD = toDelegate(&S.xtrnD);
|
||||
static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD)));
|
||||
}
|
||||
@@ -62,8 +62,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
+ }
|
||||
}
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/internal/math/biguintx86.d phobos/std/internal/math/biguintx86.d
|
||||
--- phobos-orig/std/internal/math/biguintx86.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/internal/math/biguintx86.d 2010-11-07 19:26:52.000000000 +0300
|
||||
--- phobos-orig/std/internal/math/biguintx86.d 2010-12-20 23:02:36.000000000 +0300
|
||||
+++ phobos/std/internal/math/biguintx86.d 2011-01-05 15:15:30.000000000 +0300
|
||||
@@ -734,7 +734,10 @@
|
||||
// EDI = dest
|
||||
// ESI = src
|
||||
@@ -98,56 +98,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
mixin(asmMulAdd_enter_odd(OP, "ESP+LASTPARAM"));
|
||||
}
|
||||
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/intrinsic.d phobos/std/intrinsic.d
|
||||
--- phobos-orig/std/intrinsic.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/intrinsic.d 2010-12-16 14:56:59.311832002 +0300
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
module std.intrinsic;
|
||||
|
||||
-nothrow:
|
||||
+//nothrow:
|
||||
|
||||
/**
|
||||
* Scans the bits in v starting with bit 0, looking
|
||||
@@ -72,12 +72,12 @@
|
||||
/**
|
||||
* Tests and complements the bit.
|
||||
*/
|
||||
-int btc(uint *p, uint bitnum);
|
||||
+nothrow int btc(uint *p, uint bitnum);
|
||||
|
||||
/**
|
||||
* Tests and resets (sets to 0) the bit.
|
||||
*/
|
||||
-int btr(uint *p, size_t bitnum);
|
||||
+nothrow int btr(uint *p, size_t bitnum);
|
||||
|
||||
/**
|
||||
* Tests and sets the bit.
|
||||
@@ -136,7 +136,7 @@
|
||||
array = [0]:x2, [1]:x100
|
||||
</pre>
|
||||
*/
|
||||
-int bts(uint *p, size_t bitnum);
|
||||
+nothrow int bts(uint *p, size_t bitnum);
|
||||
|
||||
|
||||
/**
|
||||
@@ -144,7 +144,8 @@
|
||||
byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3
|
||||
becomes byte 0.
|
||||
*/
|
||||
-pure uint bswap(uint v);
|
||||
+pure nothrow pragma(intrinsic, "llvm.bswap.i32")
|
||||
+ uint bswap(uint val);
|
||||
|
||||
|
||||
/**
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/math.d phobos/std/math.d
|
||||
--- phobos-orig/std/math.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/math.d 2010-12-28 21:51:24.775335002 +0300
|
||||
@@ -276,7 +276,7 @@
|
||||
--- phobos-orig/std/math.d 2011-01-05 16:04:59.087062853 +0300
|
||||
+++ phobos/std/math.d 2011-01-05 18:17:40.283062853 +0300
|
||||
@@ -266,7 +266,7 @@
|
||||
assert(abs(71.6Li) == 71.6L);
|
||||
assert(abs(-56) == 56);
|
||||
assert(abs(2321312L) == 2321312L);
|
||||
@@ -156,55 +110,57 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
}
|
||||
|
||||
/***********************************
|
||||
@@ -318,7 +318,10 @@
|
||||
@@ -308,7 +308,10 @@
|
||||
* Results are undefined if |x| >= $(POWER 2,64).
|
||||
*/
|
||||
|
||||
-@safe pure nothrow real cos(real x); /* intrinsic */
|
||||
-real cos(real x) @safe pure nothrow; /* intrinsic */
|
||||
+version(LDC)
|
||||
+ @safe pure nothrow real cos(real x) { return llvm_cos(x); }
|
||||
+else
|
||||
+ @safe pure nothrow real cos(real x); /* intrinsic */
|
||||
+ real cos(real x) @safe pure nothrow; /* intrinsic */
|
||||
|
||||
/***********************************
|
||||
* Returns sine of x. x is in radians.
|
||||
@@ -333,7 +336,10 @@
|
||||
@@ -323,7 +326,10 @@
|
||||
* Results are undefined if |x| >= $(POWER 2,64).
|
||||
*/
|
||||
|
||||
-@safe pure nothrow real sin(real x); /* intrinsic */
|
||||
-real sin(real x) @safe pure nothrow; /* intrinsic */
|
||||
+version(LDC)
|
||||
+ @safe pure nothrow real sin(real x) { return llvm_sin(x); }
|
||||
+else
|
||||
+ @safe pure nothrow real sin(real x); /* intrinsic */
|
||||
+ real sin(real x) @safe pure nothrow; /* intrinsic */
|
||||
|
||||
|
||||
/***********************************
|
||||
@@ -400,7 +406,9 @@
|
||||
@@ -390,7 +396,9 @@
|
||||
|
||||
@trusted pure nothrow real tan(real x)
|
||||
real tan(real x) @trusted pure nothrow
|
||||
{
|
||||
- version(Naked_D_InlineAsm_X86) {
|
||||
- version(D_InlineAsm_X86) {
|
||||
+ version(LDC) {
|
||||
+ return core.stdc.math.tanl(x);
|
||||
+ } else version(Naked_D_InlineAsm_X86) {
|
||||
+ } else version(D_InlineAsm_X86) {
|
||||
asm
|
||||
{
|
||||
fld x[EBP] ; // load theta
|
||||
@@ -809,6 +817,12 @@
|
||||
@@ -806,7 +814,13 @@
|
||||
* greater than long.max, the result is
|
||||
* indeterminate.
|
||||
*/
|
||||
-long rndtol(real x) @safe pure nothrow; /* intrinsic */
|
||||
+version(LDC)
|
||||
+pure nothrow long rndtol(real x)
|
||||
+{
|
||||
+ return core.stdc.math.llroundl(x);
|
||||
+}
|
||||
+else
|
||||
@safe pure nothrow long rndtol(real x); /* intrinsic */
|
||||
+ long rndtol(real x) @safe pure nothrow; /* intrinsic */
|
||||
|
||||
|
||||
@@ -831,6 +845,20 @@
|
||||
/*****************************************
|
||||
@@ -828,6 +842,20 @@
|
||||
* )
|
||||
*/
|
||||
|
||||
@@ -225,7 +181,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
@safe pure nothrow
|
||||
{
|
||||
float sqrt(float x); /* intrinsic */
|
||||
@@ -838,6 +866,8 @@
|
||||
@@ -835,6 +863,8 @@
|
||||
real sqrt(real x); /* intrinsic */ /// ditto
|
||||
}
|
||||
|
||||
@@ -234,7 +190,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
@trusted pure nothrow { // Should be @safe. See bugs 4628, 4630.
|
||||
// Create explicit overloads for integer sqrts. No ddoc for these because
|
||||
// hopefully a more elegant solution will eventually be found, so we don't
|
||||
@@ -1413,9 +1443,22 @@
|
||||
@@ -1421,9 +1451,22 @@
|
||||
* Compute n * 2$(SUP exp)
|
||||
* References: frexp
|
||||
*/
|
||||
@@ -250,27 +206,20 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
+else
|
||||
+{
|
||||
|
||||
@safe pure nothrow real ldexp(real n, int exp); /* intrinsic */
|
||||
real ldexp(real n, int exp) @safe pure nothrow; /* intrinsic */
|
||||
|
||||
+}
|
||||
+
|
||||
unittest {
|
||||
assert(ldexp(1, -16384) == 0x1p-16384L);
|
||||
assert(ldexp(1, -16382) == 0x1p-16382L);
|
||||
@@ -1608,7 +1651,31 @@
|
||||
@@ -1617,7 +1660,24 @@
|
||||
* $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) )
|
||||
* )
|
||||
*/
|
||||
-@safe pure nothrow real fabs(real x); /* intrinsic */
|
||||
-real fabs(real x) @safe pure nothrow; /* intrinsic */
|
||||
+version(LDC) {
|
||||
+ version( FreeBSD )
|
||||
+ version (all) // < 8-CURRENT
|
||||
+ private extern(C) real fabsl(real x) { return fabs(x); }
|
||||
+ else
|
||||
+ private extern(C) real fabsl(real x);
|
||||
+ else
|
||||
+ private extern(C) real fabsl(real x);
|
||||
+ pure nothrow real fabs(real x)
|
||||
+ @trusted pure nothrow real fabs(real x)
|
||||
+ {
|
||||
+ version(D_InlineAsm_X86)
|
||||
+ {
|
||||
@@ -285,12 +234,12 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
+ }
|
||||
+ }
|
||||
+} else {
|
||||
+ @safe pure nothrow real fabs(real x); /* intrinsic */
|
||||
+ real fabs(real x) @safe pure nothrow; /* intrinsic */
|
||||
+}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
@@ -2993,9 +3060,15 @@
|
||||
@@ -3017,9 +3077,15 @@
|
||||
assert(pow(x,eight) == (x * x) * (x * x) * (x * x) * (x * x));
|
||||
|
||||
assert(pow(x, neg1) == 1 / x);
|
||||
@@ -310,7 +259,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
/** Compute the value of an integer x, raised to the power of a positive
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/openrj.d phobos/std/openrj.d
|
||||
--- phobos-orig/std/openrj.d 2009-09-03 12:01:40.000000000 +0400
|
||||
+++ phobos/std/openrj.d 2010-10-26 13:17:37.000000000 +0400
|
||||
+++ phobos/std/openrj.d 2011-01-05 15:15:30.000000000 +0300
|
||||
@@ -620,11 +620,11 @@
|
||||
/**
|
||||
*
|
||||
@@ -354,8 +303,8 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.
|
||||
result = dg(field);
|
||||
|
||||
diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- phobos-orig/std/outbuffer.d phobos/std/outbuffer.d
|
||||
--- phobos-orig/std/outbuffer.d 2010-10-29 05:54:44.000000000 +0400
|
||||
+++ phobos/std/outbuffer.d 2010-11-05 13:59:42.000000000 +0300
|
||||
--- phobos-orig/std/outbuffer.d 2010-12-20 23:02:36.000000000 +0300
|
||||
+++ phobos/std/outbuffer.d 2011-01-05 15:15:31.000000000 +0300
|
||||
@@ -308,8 +308,15 @@
|
||||
void printf(string format, ...)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user