Updated to dmdfe 2.051

This commit is contained in:
Alexey Prokhin
2011-01-05 18:21:40 +03:00
parent 8a4ee0ede5
commit c5e9784863
37 changed files with 1405 additions and 1157 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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++;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3002,6 +3002,7 @@ static Keyword keywords[] =
//{ "manifest", TOKmanifest },
// Added after 1.0
{ "__argTypes", TOKargTypes },
{ "ref", TOKref },
{ "macro", TOKmacro },
#if DMDV2

View File

@@ -152,6 +152,7 @@ enum TOK
TOKunittest,
// Added after 1.0
TOKargTypes,
TOKref,
TOKmacro,
#if DMDV2

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -161,7 +161,7 @@ void _aaRehash(AA** paa)
}
}
if (aa->b != aa->binit)
delete aa->b;
delete[] aa->b;
newb.nodes = aa->nodes;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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, ...)
{