Merge 2.058beta

This commit is contained in:
Alexey Prokhin
2012-02-15 13:23:16 +04:00
parent f2ed2e96b0
commit e74e55df89
64 changed files with 5260 additions and 2973 deletions
+15 -22
View File
@@ -1,5 +1,5 @@
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -91,7 +91,7 @@ enum PROT ClassDeclaration::getAccess(Dsymbol *smember)
break;
case PROTprivate:
access = PROTnone; // private members of base class not accessible
access_ret = PROTnone; // private members of base class not accessible
break;
case PROTpackage:
@@ -265,7 +265,7 @@ int AggregateDeclaration::isFriendOf(AggregateDeclaration *cd)
// Friends if both are in the same module
//if (toParent() == cd->toParent())
if (cd && getModule() == cd->getModule())
if (cd && getAccessModule() == cd->getAccessModule())
{
#if LOG
printf("\tin same module\n");
@@ -354,7 +354,7 @@ int AggregateDeclaration::hasPrivateAccess(Dsymbol *smember)
#endif
return 1;
}
if (!cd && getModule() == smember->getModule())
if (!cd && getAccessModule() == smember->getAccessModule())
{
#if LOG
printf("\tyes 3\n");
@@ -381,39 +381,32 @@ void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d)
}
else
{
//printf("accessCheck(%s)\n", d->toChars());
printf("accessCheck(%s)\n", d->toPrettyChars());
}
#endif
if (!e)
{
if (d->getModule() != sc->module)
if (d->prot() == PROTprivate ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
error(loc, "%s %s.%s is not accessible from %s",
d->kind(), d->getModule()->toChars(), d->toChars(), sc->module->toChars());
if (d->prot() == PROTprivate && d->getAccessModule() != sc->module ||
d->prot() == PROTpackage && !hasPackageAccess(sc, d))
{
error(loc, "%s %s is not accessible from module %s",
d->kind(), d->toPrettyChars(), sc->module->toChars());
}
}
else if (e->type->ty == Tclass)
{ // Do access check
ClassDeclaration *cd;
cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
#if 1
ClassDeclaration *cd = (ClassDeclaration *)(((TypeClass *)e->type)->sym);
if (e->op == TOKsuper)
{ ClassDeclaration *cd2;
cd2 = sc->func->toParent()->isClassDeclaration();
{
ClassDeclaration *cd2 = sc->func->toParent()->isClassDeclaration();
if (cd2)
cd = cd2;
}
#endif
cd->accessCheck(loc, sc, d);
}
else if (e->type->ty == Tstruct)
{ // Do access check
StructDeclaration *cd;
cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
StructDeclaration *cd = (StructDeclaration *)(((TypeStruct *)e->type)->sym);
cd->accessCheck(loc, sc, d);
}
}
+4 -1
View File
@@ -68,7 +68,7 @@ struct AggregateDeclaration : ScopeDsymbol
// 1: size is correct
// 2: cannot determine size; fwd referenced
Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol
int isdeprecated; // !=0 if deprecated
bool isdeprecated; // !=0 if deprecated
#if DMDV2
int isnested; // !=0 if is nested
@@ -107,6 +107,7 @@ struct AggregateDeclaration : ScopeDsymbol
int isDeprecated(); // is aggregate deprecated?
FuncDeclaration *buildDtor(Scope *sc);
int isNested();
int isExport();
void emitComment(Scope *sc);
void toJsonBuffer(OutBuffer *buf);
@@ -166,6 +167,7 @@ struct StructDeclaration : AggregateDeclaration
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
const char *kind();
void finalizeSize();
#if DMDV1
Expression *cloneMembers();
#endif
@@ -284,6 +286,7 @@ struct ClassDeclaration : AggregateDeclaration
virtual int isBaseInfoComplete();
Dsymbol *search(Loc, Identifier *ident, int flags);
Dsymbol *searchBase(Loc, Identifier *ident);
#if DMDV2
int isFuncHidden(FuncDeclaration *fd);
#endif
+165
View File
@@ -0,0 +1,165 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "expression.h"
/**************************************
* An Expression tree walker that will visit each Expression e in the tree,
* in depth-first evaluation order, and call fp(e,param) on it.
* fp() signals whether the walking continues with its return value:
* Returns:
* 0 continue
* 1 done
* It's a bit slower than using virtual functions, but more encapsulated and less brittle.
* Creating an iterator for this would be much more complex.
*/
typedef int (*fp_t)(Expression *, void *);
int Expression::apply(fp_t fp, void *param)
{
return (*fp)(this, param);
}
/******************************
* Perform apply() on an array of Expressions.
*/
int arrayExpressionApply(Expressions *a, fp_t fp, void *param)
{
//printf("arrayExpressionApply(%p)\n", a);
if (a)
{
for (size_t i = 0; i < a->dim; i++)
{ Expression *e = (*a)[i];
if (e)
{
if (e->apply(fp, param))
return 1;
}
}
}
return 0;
}
int NewExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int NewAnonClassExp::apply(int (*fp)(Expression *, void *), void *param)
{
//printf("NewAnonClassExp::apply(): %s\n", toChars());
return ((thisexp ? thisexp->apply(fp, param) : 0) ||
arrayExpressionApply(newargs, fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param));
}
int UnaExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(*fp)(this, param);
}
int BinExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}
int AssertExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
(msg ? msg->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int CallExp::apply(fp_t fp, void *param)
{
//printf("CallExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int ArrayExp::apply(fp_t fp, void *param)
{
//printf("ArrayExp::apply(fp_t fp, void *param): %s\n", toChars());
return e1->apply(fp, param) ||
arrayExpressionApply(arguments, fp, param) ||
(*fp)(this, param);
}
int SliceExp::apply(fp_t fp, void *param)
{
return e1->apply(fp, param) ||
(lwr ? lwr->apply(fp, param) : 0) ||
(upr ? upr->apply(fp, param) : 0) ||
(*fp)(this, param);
}
int ArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int AssocArrayLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(keys, fp, param) ||
arrayExpressionApply(values, fp, param) ||
(*fp)(this, param);
}
int StructLiteralExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(elements, fp, param) ||
(*fp)(this, param);
}
int TupleExp::apply(fp_t fp, void *param)
{
return arrayExpressionApply(exps, fp, param) ||
(*fp)(this, param);
}
int CondExp::apply(fp_t fp, void *param)
{
return econd->apply(fp, param) ||
e1->apply(fp, param) ||
e2->apply(fp, param) ||
(*fp)(this, param);
}
+5
View File
@@ -124,6 +124,11 @@ TypeTuple *TypeBasic::toArgTypes()
return t;
}
TypeTuple *TypeVector::toArgTypes()
{
return new TypeTuple(Type::tfloat64);
}
TypeTuple *TypeSArray::toArgTypes()
{
#if DMDV2
+1 -1
View File
@@ -578,7 +578,7 @@ Expression *Str##AssignExp::buildArrayLoop(Parameters *fparams) \
Expression *ex1 = e1->buildArrayLoop(fparams); \
Parameter *param = (*fparams)[0]; \
param->storageClass = 0; \
Expression *e = new Str##AssignExp(0, ex1, ex2); \
Expression *e = new Str##AssignExp(loc, ex1, ex2); \
return e; \
}
+11 -7
View File
@@ -310,11 +310,11 @@ const char *AttribDeclaration::kind()
return "attribute";
}
int AttribDeclaration::oneMember(Dsymbol **ps)
int AttribDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
Dsymbols *d = include(NULL, NULL);
return Dsymbol::oneMembers(d, ps);
return Dsymbol::oneMembers(d, ps, ident);
}
void AttribDeclaration::checkCtorConstInit()
@@ -392,10 +392,10 @@ Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
return scd;
}
int StorageClassDeclaration::oneMember(Dsymbol **ps)
int StorageClassDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
int t = Dsymbol::oneMembers(decl, ps);
int t = Dsymbol::oneMembers(decl, ps, ident);
if (t && *ps)
{
/* This is to deal with the following case:
@@ -1150,6 +1150,7 @@ void PragmaDeclaration::semantic(Scope *sc)
else
error("unrecognized pragma(%s)", ident->toChars());
Ldecl:
if (decl)
{
for (unsigned i = 0; i < decl->dim; i++)
@@ -1167,10 +1168,13 @@ void PragmaDeclaration::semantic(Scope *sc)
Lnodecl:
if (decl)
{
error("pragma is missing closing ';'");
goto Ldecl; // do them anyway, to avoid segfaults.
}
}
int PragmaDeclaration::oneMember(Dsymbol **ps)
int PragmaDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
*ps = NULL;
return TRUE;
@@ -1263,13 +1267,13 @@ Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
}
int ConditionalDeclaration::oneMember(Dsymbol **ps)
int ConditionalDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
//printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
if (condition->inc)
{
Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl;
return Dsymbol::oneMembers(d, ps);
return Dsymbol::oneMembers(d, ps, ident);
}
*ps = NULL;
return TRUE;
+4 -4
View File
@@ -47,7 +47,7 @@ struct AttribDeclaration : Dsymbol
void addComment(unsigned char *comment);
void emitComment(Scope *sc);
const char *kind();
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
int hasPointers();
bool hasStaticCtorOrDtor();
void checkCtorConstInit();
@@ -74,7 +74,7 @@ struct StorageClassDeclaration: AttribDeclaration
Dsymbol *syntaxCopy(Dsymbol *s);
void setScope(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
static void stcToCBuffer(OutBuffer *buf, StorageClass stc);
@@ -138,7 +138,7 @@ struct PragmaDeclaration : AttribDeclaration
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
void setScope(Scope *sc);
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
@@ -158,7 +158,7 @@ struct ConditionalDeclaration : AttribDeclaration
ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl);
Dsymbol *syntaxCopy(Dsymbol *s);
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
void emitComment(Scope *sc);
Dsymbols *include(Scope *sc, ScopeDsymbol *s);
void addComment(unsigned char *comment);
+190
View File
@@ -0,0 +1,190 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "init.h"
#include "expression.h"
#include "template.h"
#include "statement.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "attrib.h"
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow);
int lambdaCanThrow(Expression *e, void *param);
/********************************************
* Convert from expression to delegate that returns the expression,
* i.e. convert:
* expr
* to:
* t delegate() { return expr; }
*/
struct CanThrow
{
bool can;
bool mustnot;
};
int Expression::canThrow(bool mustNotThrow)
{
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
CanThrow ct;
ct.can = FALSE;
ct.mustnot = mustNotThrow;
apply(&lambdaCanThrow, &ct);
return ct.can;
}
int lambdaCanThrow(Expression *e, void *param)
{
CanThrow *pct = (CanThrow *)param;
switch (e->op)
{
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
pct->can = Dsymbol_canThrow(de->declaration, pct->mustnot);
break;
}
case TOKcall:
{ CallExp *ce = (CallExp *)e;
if (global.errors && !ce->e1->type)
break; // error recovery
/* If calling a function or delegate that is typed as nothrow,
* then this expression cannot throw.
* Note that pure functions can throw.
*/
Type *t = ce->e1->type->toBasetype();
if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow)
;
else if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
;
else
{
if (pct->mustnot)
e->error("%s is not nothrow", ce->e1->toChars());
pct->can = TRUE;
}
break;
}
case TOKnew:
{ NewExp *ne = (NewExp *)e;
if (ne->member)
{
// See if constructor call can throw
Type *t = ne->member->type->toBasetype();
if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow)
{
if (pct->mustnot)
e->error("constructor %s is not nothrow", ne->member->toChars());
pct->can = TRUE;
}
}
// regard storage allocation failures as not recoverable
break;
}
case TOKnewanonclass:
assert(0); // should have been lowered by semantic()
break;
default:
break;
}
return pct->can; // stop walking if we determine this expression can throw
}
/**************************************
* Does symbol, when initialized, throw?
* Mirrors logic in Dsymbol_toElem().
*/
int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
{
AttribDeclaration *ad;
VarDeclaration *vd;
TemplateMixin *tm;
TupleDeclaration *td;
//printf("Dsymbol_toElem() %s\n", s->toChars());
ad = s->isAttribDeclaration();
if (ad)
{
Dsymbols *decl = ad->include(NULL, NULL);
if (decl && decl->dim)
{
for (size_t i = 0; i < decl->dim; i++)
{
s = decl->tdata()[i];
if (Dsymbol_canThrow(s, mustNotThrow))
return 1;
}
}
}
else if ((vd = s->isVarDeclaration()) != NULL)
{
s = s->toAlias();
if (s != vd)
return Dsymbol_canThrow(s, mustNotThrow);
if (vd->storage_class & STCmanifest)
;
else if (vd->isStatic() || vd->storage_class & (STCextern | STCtls | STCgshared))
;
else
{
if (vd->init)
{ ExpInitializer *ie = vd->init->isExpInitializer();
if (ie && ie->exp->canThrow(mustNotThrow))
return 1;
}
if (vd->edtor && !vd->noscope)
return vd->edtor->canThrow(mustNotThrow);
}
}
else if ((tm = s->isTemplateMixin()) != NULL)
{
//printf("%s\n", tm->toChars());
if (tm->members)
{
for (size_t i = 0; i < tm->members->dim; i++)
{
Dsymbol *sm = tm->members->tdata()[i];
if (Dsymbol_canThrow(sm, mustNotThrow))
return 1;
}
}
}
else if ((td = s->isTupleDeclaration()) != NULL)
{
for (size_t i = 0; i < td->objects->dim; i++)
{ Object *o = td->objects->tdata()[i];
if (o->dyncast() == DYNCAST_EXPRESSION)
{ Expression *eo = (Expression *)o;
if (eo->op == TOKdsymbol)
{ DsymbolExp *se = (DsymbolExp *)eo;
if (Dsymbol_canThrow(se->s, mustNotThrow))
return 1;
}
}
}
}
return 0;
}
+119 -24
View File
@@ -209,6 +209,12 @@ MATCH IntegerExp::implicitConvTo(Type *t)
if (m == MATCHnomatch && t->ty == Tenum)
goto Lno;
if (t->ty == Tvector)
{ TypeVector *tv = (TypeVector *)t;
TypeBasic *tb = tv->elementType();
toty = tb->ty;
}
switch (ty)
{
case Tbool:
@@ -713,6 +719,18 @@ MATCH DelegateExp::implicitConvTo(Type *t)
return result;
}
MATCH FuncExp::implicitConvTo(Type *t)
{
//printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars());
if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer
&& (t->ty == Tpointer || t->ty == Tdelegate))
{ // Allow implicit function to delegate conversion
if (type->nextOf()->covariant(t->nextOf()) == 1)
return t->ty == Tpointer ? MATCHconst : MATCHconvert;
}
return Expression::implicitConvTo(t);
}
MATCH OrExp::implicitConvTo(Type *t)
{
MATCH result = Expression::implicitConvTo(t);
@@ -860,6 +878,12 @@ Expression *Expression::castTo(Scope *sc, Type *t)
}
L1: ;
}
else if (tb->ty == Tvector && typeb->ty != Tvector)
{
e = new VectorExp(loc, e, tb);
e = e->semantic(sc);
return e;
}
e = new CastExp(loc, e, tb);
}
}
@@ -1522,6 +1546,22 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t)
return e;
}
Expression *FuncExp::castTo(Scope *sc, Type *t)
{
//printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars());
if (tok == TOKreserved)
{ assert(type && type != Type::tvoid);
if (type->ty == Tpointer && t->ty == Tdelegate)
{
Expression *e = copy();
e->type = new TypeDelegate(fd->type);
e->type = e->type->semantic(loc, sc);
return e;
}
}
return Expression::castTo(sc, t);
}
Expression *CondExp::castTo(Scope *sc, Type *t)
{
Expression *e = this;
@@ -1738,13 +1778,16 @@ Lagain:
t = t2;
else if (t2n->ty == Tvoid)
;
else if (t1->implicitConvTo(t2))
{
goto Lt2;
}
else if (t2->implicitConvTo(t1))
{
goto Lt1;
}
else if (t1n->ty == Tfunction && t2n->ty == Tfunction)
{
if (t1->implicitConvTo(t2))
goto Lt2;
if (t2->implicitConvTo(t1))
goto Lt1;
TypeFunction *tf1 = (TypeFunction *)t1n;
TypeFunction *tf2 = (TypeFunction *)t2n;
TypeFunction *d = (TypeFunction *)tf1->syntaxCopy();
@@ -1782,8 +1825,11 @@ Lagain:
}
else if (t1n->mod != t2n->mod)
{
t1 = t1n->mutableOf()->constOf()->pointerTo();
t2 = t2n->mutableOf()->constOf()->pointerTo();
if (!t1n->isImmutable() && !t2n->isImmutable() && t1n->isShared() != t2n->isShared())
goto Lincompatible;
unsigned char mod = MODmerge(t1n->mod, t2n->mod);
t1 = t1n->castMod(mod)->pointerTo();
t2 = t2n->castMod(mod)->pointerTo();
t = t1;
goto Lagain;
}
@@ -1807,7 +1853,19 @@ Lagain:
goto Lincompatible;
}
else
{
t1 = t1n->constOf()->pointerTo();
t2 = t2n->constOf()->pointerTo();
if (t1->implicitConvTo(t2))
{
goto Lt2;
}
else if (t2->implicitConvTo(t1))
{
goto Lt1;
}
goto Lincompatible;
}
}
else if ((t1->ty == Tsarray || t1->ty == Tarray) &&
(e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid ||
@@ -1840,10 +1898,14 @@ Lagain:
}
else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2))
{
if (t1->ty == Tsarray && e2->op == TOKarrayliteral)
goto Lt1;
goto Lt2;
}
else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1))
{
if (t2->ty == Tsarray && e1->op == TOKarrayliteral)
goto Lt2;
goto Lt1;
}
/* If one is mutable and the other invariant, then retry
@@ -1853,30 +1915,54 @@ Lagain:
(t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) &&
t1->nextOf()->mod != t2->nextOf()->mod
)
{ unsigned char mod = MODmerge(t1->nextOf()->mod, t2->nextOf()->mod);
{
Type *t1n = t1->nextOf();
Type *t2n = t2->nextOf();
unsigned char mod;
if (e1->op == TOKnull && e2->op != TOKnull)
mod = t2n->mod;
else if (e1->op != TOKnull && e2->op == TOKnull)
mod = t1n->mod;
else if (!t1n->isImmutable() && !t2n->isImmutable() && t1n->isShared() != t2n->isShared())
goto Lincompatible;
else
mod = MODmerge(t1n->mod, t2n->mod);
if (t1->ty == Tpointer)
t1 = t1->nextOf()->castMod(mod)->pointerTo();
t1 = t1n->castMod(mod)->pointerTo();
else
t1 = t1->nextOf()->castMod(mod)->arrayOf();
t1 = t1n->castMod(mod)->arrayOf();
if (t2->ty == Tpointer)
t2 = t2->nextOf()->castMod(mod)->pointerTo();
t2 = t2n->castMod(mod)->pointerTo();
else
t2 = t2->nextOf()->castMod(mod)->arrayOf();
t2 = t2n->castMod(mod)->arrayOf();
t = t1;
goto Lagain;
}
else if (t1->ty == Tclass || t2->ty == Tclass)
else if (t1->ty == Tclass && t2->ty == Tclass)
{
if (t1->mod != t2->mod)
{ unsigned char mod = MODmerge(t1->mod, t2->mod);
{
unsigned char mod;
if (e1->op == TOKnull && e2->op != TOKnull)
mod = t2->mod;
else if (e1->op != TOKnull && e2->op == TOKnull)
mod = t1->mod;
else if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
goto Lincompatible;
else
mod = MODmerge(t1->mod, t2->mod);
t1 = t1->castMod(mod);
t2 = t2->castMod(mod);
t = t1;
goto Lagain;
}
goto Lcc;
}
else if (t1->ty == Tclass || t2->ty == Tclass)
{
Lcc:
while (1)
{
int i1 = e2->implicitConvTo(t1);
@@ -1943,6 +2029,8 @@ Lagain:
{
if (t1->mod != t2->mod)
{
if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
goto Lincompatible;
unsigned char mod = MODmerge(t1->mod, t2->mod);
t1 = t1->castMod(mod);
t2 = t2->castMod(mod);
@@ -1998,15 +2086,6 @@ Lagain:
}
else if (t1->ty == Tstruct || t2->ty == Tstruct)
{
if (t1->mod != t2->mod)
{
unsigned char mod = MODmerge(t1->mod, t2->mod);
t1 = t1->castMod(mod);
t2 = t2->castMod(mod);
t = t1;
goto Lagain;
}
if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis)
{
e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident);
@@ -2051,9 +2130,25 @@ Lagain:
e1 = e1->castTo(sc, t);
e2 = e2->castTo(sc, t);
}
else if (t1->ty == Tvector && t2->ty != Tvector &&
e2->implicitConvTo(t1))
{
e2 = e2->castTo(sc, t1);
t2 = t1;
goto Lagain;
}
else if (t2->ty == Tvector && t1->ty != Tvector &&
e1->implicitConvTo(t2))
{
e1 = e1->castTo(sc, t2);
t1 = t2;
goto Lagain;
}
else if (t1->isintegral() && t2->isintegral())
{
assert(t1->ty == t2->ty);
if (!t1->isImmutable() && !t2->isImmutable() && t1->isShared() != t2->isShared())
goto Lincompatible;
unsigned char mod = MODmerge(t1->mod, t2->mod);
t1 = t1->castMod(mod);
+56 -9
View File
@@ -296,9 +296,11 @@ void ClassDeclaration::semantic(Scope *sc)
methods.setDim(0);
#endif
int errors = global.gaggedErrors;
if (sc->stc & STCdeprecated)
{
isdeprecated = 1;
isdeprecated = true;
}
if (sc->linkage == LINKcpp)
@@ -307,9 +309,7 @@ void ClassDeclaration::semantic(Scope *sc)
// Expand any tuples in baseclasses[]
for (size_t i = 0; i < baseclasses->dim; )
{ BaseClass *b = baseclasses->tdata()[i];
//printf("test1 %s %s\n", toChars(), b->type->toChars());
b->type = b->type->semantic(loc, sc);
//printf("test2\n");
Type *tb = b->type->toBasetype();
if (tb->ty == Ttuple)
@@ -349,7 +349,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!isDeprecated())
{
// Deriving from deprecated class makes this one deprecated too
isdeprecated = 1;
isdeprecated = true;
tc->checkDeprecated(loc, sc);
}
@@ -422,7 +422,7 @@ void ClassDeclaration::semantic(Scope *sc)
if (!isDeprecated())
{
// Deriving from deprecated class makes this one deprecated too
isdeprecated = 1;
isdeprecated = true;
tc->checkDeprecated(loc, sc);
}
@@ -657,9 +657,15 @@ void ClassDeclaration::semantic(Scope *sc)
s->semantic(sc);
}
if (sizeok == 2)
{ // semantic() failed because of forward references.
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
type = Type::terror;
}
if (sizeok == 2) // failed due to forward references
{ // semantic() failed due to forward references
// Unwind what we did, and defer it for later
fields.setDim(0);
structsize = 0;
alignsize = 0;
@@ -772,7 +778,7 @@ void ClassDeclaration::semantic(Scope *sc)
#endif
//printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
if (deferred)
if (deferred && !global.gag)
{
deferred->semantic2(sc);
deferred->semantic3(sc);
@@ -938,6 +944,23 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
return s;
}
Dsymbol *ClassDeclaration::searchBase(Loc loc, Identifier *ident)
{
// Search bases classes in depth-first, left to right order
for (size_t i = 0; i < baseclasses->dim; i++)
{
BaseClass *b = (*baseclasses)[i];
Dsymbol *cdb = b->type->isClassHandle();
if (cdb->ident->equals(ident))
return cdb;
cdb = ((ClassDeclaration *)cdb)->searchBase(loc, ident);
if (cdb)
return cdb;
}
return NULL;
}
/**********************************************************
* fd is in the vtbl[] for this class.
* Return 1 if function is hidden (not findable through search).
@@ -1212,9 +1235,11 @@ void InterfaceDeclaration::semantic(Scope *sc)
scope = NULL;
}
int errors = global.gaggedErrors;
if (sc->stc & STCdeprecated)
{
isdeprecated = 1;
isdeprecated = true;
}
// Expand any tuples in baseclasses[]
@@ -1360,11 +1385,33 @@ void InterfaceDeclaration::semantic(Scope *sc)
structalign = sc->structalign;
sc->offset = PTRSIZE * 2;
inuse++;
/* Set scope so if there are forward references, we still might be able to
* resolve individual members like enums.
*/
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because
* Scope keeps track of things like 'offset'
*/
if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
{
//printf("setScope %s %s\n", s->kind(), s->toChars());
s->setScope(sc);
}
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
s->semantic(sc);
}
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
type = Type::terror;
}
inuse--;
//members->print();
sc->pop();
+89 -51
View File
@@ -1376,7 +1376,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
e = ale->elements->tdata()[i];
e->type = type;
if (e->checkSideEffect(2))
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
}
}
@@ -1394,7 +1394,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
else
{ e = ale->elements->tdata()[i];
e->type = type;
if (e->checkSideEffect(2))
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
}
}
@@ -1414,7 +1414,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
if (ex->isBool(TRUE))
{ e = ae->values->tdata()[i];
e->type = type;
if (e->checkSideEffect(2))
if (e->hasSideEffect())
e = EXP_CANT_INTERPRET;
break;
}
@@ -1467,7 +1467,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
}
else if (e1->op == TOKarrayliteral &&
lwr->op == TOKint64 && upr->op == TOKint64 &&
!e1->checkSideEffect(2))
!e1->hasSideEffect())
{ ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
uinteger_t ilwr = lwr->toInteger();
uinteger_t iupr = upr->toInteger();
@@ -1491,6 +1491,64 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
return e;
}
/* Set a slice of char array literal 'existingAE' from a string 'newval'.
* existingAE[firstIndex..firstIndex+newval.length] = newval.
*/
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex)
{
size_t newlen = newval->len;
size_t sz = newval->sz;
unsigned char *s = (unsigned char *)newval->string;
Type *elemType = existingAE->type->nextOf();
for (size_t j = 0; j < newlen; j++)
{
dinteger_t val;
switch (sz)
{
case 1: val = s[j]; break;
case 2: val = ((unsigned short *)s)[j]; break;
case 4: val = ((unsigned *)s)[j]; break;
default:
assert(0);
break;
}
existingAE->elements->tdata()[j+firstIndex]
= new IntegerExp(newval->loc, val, elemType);
}
}
/* Set a slice of string 'existingSE' from a char array literal 'newae'.
* existingSE[firstIndex..firstIndex+newae.length] = newae.
*/
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex)
{
unsigned char *s = (unsigned char *)existingSE->string;
for (size_t j = 0; j < newae->elements->dim; j++)
{
unsigned value = (unsigned)(newae->elements->tdata()[j]->toInteger());
switch (existingSE->sz)
{
case 1: s[j+firstIndex] = value; break;
case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
case 4: ((unsigned *)s)[j+firstIndex] = value; break;
default:
assert(0);
break;
}
}
}
/* Set a slice of string 'existingSE' from a string 'newstr'.
* existingSE[firstIndex..firstIndex+newstr.length] = newstr.
*/
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex)
{
unsigned char *s = (unsigned char *)existingSE->string;
size_t sz = existingSE->sz;
assert(sz == newstr->sz);
memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len);
}
/* Also return EXP_CANT_INTERPRET if this fails
*/
Expression *Cat(Type *type, Expression *e1, Expression *e2)
@@ -1600,62 +1658,42 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
else if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
t1->nextOf()->isintegral())
{
// Concatenate the strings
StringExp *es1 = (StringExp *)e2;
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
size_t len = es1->len + es2->elements->dim;
int sz = es1->sz;
void *s = mem.malloc((len + 1) * sz);
memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
for (size_t i = 0; i < es2->elements->dim; i++)
{ Expression *es2e = es2->elements->tdata()[i];
if (es2e->op != TOKint64)
return EXP_CANT_INTERPRET;
dinteger_t v = es2e->toInteger();
memcpy((unsigned char *)s + i * sz, &v, sz);
// [chars] ~ string --> [chars]
StringExp *es = (StringExp *)e2;
ArrayLiteralExp *ea = (ArrayLiteralExp *)e1;
size_t len = es->len + ea->elements->dim;
Expressions * elems = new Expressions;
elems->setDim(len);
for (size_t i= 0; i < ea->elements->dim; ++i)
{
elems->tdata()[i] = ea->elements->tdata()[i];
}
// Add terminating 0
memset((unsigned char *)s + len * sz, 0, sz);
StringExp *es = new StringExp(loc, s, len);
es->sz = sz;
es->committed = 0;
es->type = type;
e = es;
ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems);
dest->type = type;
sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim);
return dest;
}
else if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
t2->nextOf()->isintegral())
{
// Concatenate the strings
StringExp *es1 = (StringExp *)e1;
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
size_t len = es1->len + es2->elements->dim;
int sz = es1->sz;
void *s = mem.malloc((len + 1) * sz);
memcpy(s, es1->string, es1->len * sz);
for (size_t i = 0; i < es2->elements->dim; i++)
{ Expression *es2e = es2->elements->tdata()[i];
if (es2e->op != TOKint64)
return EXP_CANT_INTERPRET;
dinteger_t v = es2e->toInteger();
memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz);
// string ~ [chars] --> [chars]
StringExp *es = (StringExp *)e1;
ArrayLiteralExp *ea = (ArrayLiteralExp *)e2;
size_t len = es->len + ea->elements->dim;
Expressions * elems = new Expressions;
elems->setDim(len);
for (size_t i= 0; i < ea->elements->dim; ++i)
{
elems->tdata()[es->len + i] = ea->elements->tdata()[i];
}
// Add terminating 0
memset((unsigned char *)s + len * sz, 0, sz);
StringExp *es = new StringExp(loc, s, len);
es->sz = sz;
es->committed = 0; //es1->committed;
es->type = type;
e = es;
ArrayLiteralExp *dest = new ArrayLiteralExp(e1->loc, elems);
dest->type = type;
sliceAssignArrayLiteralFromString(dest, es, 0);
return dest;
}
else if (e1->op == TOKstring && e2->op == TOKint64)
{
// Concatenate the strings
// string ~ char --> string
void *s;
StringExp *es1 = (StringExp *)e1;
StringExp *es;
+8
View File
@@ -266,6 +266,14 @@ void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
}
void TypeVector::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
{ buf->writestring("U8__vector");
basetype->toCppMangle(buf, cms);
}
}
void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
{
if (!cms->substitute(buf, this))
+72 -21
View File
@@ -457,6 +457,7 @@ void AliasDeclaration::semantic(Scope *sc)
#endif
storage_class |= sc->stc & STCdeprecated;
protection = sc->protection;
// Given:
// alias foo.bar.abc def;
@@ -1274,14 +1275,25 @@ Lnomatch:
StructInitializer *si = init->isStructInitializer();
ExpInitializer *ei = init->isExpInitializer();
// See if initializer is a NewExp that can be allocated on the stack
if (ei && isScope() && ei->exp->op == TOKnew)
{ NewExp *ne = (NewExp *)ei->exp;
if (!(ne->newargs && ne->newargs->dim))
{ ne->onstack = 1;
onstack = 1;
if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
onstack = 2;
if (ei && ei->exp->op == TOKfunction && !inferred)
((FuncExp *)ei->exp)->setType(type);
if (ei && isScope())
{
// See if initializer is a NewExp that can be allocated on the stack
if (ei->exp->op == TOKnew)
{ NewExp *ne = (NewExp *)ei->exp;
if (!(ne->newargs && ne->newargs->dim))
{ ne->onstack = 1;
onstack = 1;
if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL))
onstack = 2;
}
}
// or a delegate that doesn't escape a reference to the function
else if (ei->exp->op == TOKfunction)
{ FuncDeclaration *f = ((FuncExp *)ei->exp)->fd;
f->tookAddressOf--;
}
}
@@ -1368,6 +1380,13 @@ Lnomatch:
* variable with a bit copy of the default
* initializer
*/
/* Remove ref if this declaration is ref binding.
* ref Type __self = (__ctmp = 0, __ctmp).this(...);
* -> Type __self = (__self = 0, __self.this(...));
*/
storage_class &= ~(STCref | STCforeach | STCparameter);
Expression *e;
if (sd->zeroInit == 1)
{
@@ -1714,25 +1733,45 @@ void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
* so it never becomes closure.
*/
//printf("\tfdv = %s\n", fdv->toChars());
//printf("\tfdthis = %s\n", fdthis->toChars());
if (loc.filename)
fdthis->getLevel(loc, fdv);
fdthis->getLevel(loc, sc, fdv);
for (size_t i = 0; i < nestedrefs.dim; i++)
{ FuncDeclaration *f = nestedrefs.tdata()[i];
if (f == fdthis)
goto L1;
// Function literals from fdthis to fdv must be delegates
for (Dsymbol *s = fdthis; s && s != fdv; s = s->toParent2())
{
// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
{
fld->tok = TOKdelegate;
}
}
nestedrefs.push(fdthis);
L1: ;
// Add fdthis to nestedrefs[] if not already there
for (size_t i = 0; 1; i++)
{
if (i == nestedrefs.dim)
{
nestedrefs.push(fdthis);
break;
}
if (nestedrefs[i] == fdthis)
break;
}
for (size_t i = 0; i < fdv->closureVars.dim; i++)
{ Dsymbol *s = fdv->closureVars.tdata()[i];
if (s == this)
goto L2;
// Add this to fdv->closureVars[] if not already there
for (size_t i = 0; 1; i++)
{
if (i == fdv->closureVars.dim)
{
fdv->closureVars.push(this);
break;
}
if (fdv->closureVars[i] == this)
break;
}
fdv->closureVars.push(this);
L2: ;
//printf("fdthis is %s\n", fdthis->toChars());
//printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars());
@@ -2205,6 +2244,18 @@ TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *t
type = Type::typeinfoassociativearray->type;
}
/***************************** TypeInfoVectorDeclaration ***********************/
TypeInfoVectorDeclaration::TypeInfoVectorDeclaration(Type *tinfo)
: TypeInfoDeclaration(tinfo, 0)
{
if (!Type::typeinfoarray)
{
ObjectNotFound(Id::TypeInfo_Vector);
}
type = Type::typeinfovector->type;
}
/***************************** TypeInfoEnumDeclaration ***********************/
TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo)
+19 -9
View File
@@ -294,10 +294,7 @@ struct VarDeclaration : Declaration
bool hasValue();
void setValueNull();
void setValueWithoutChecking(Expression *newval);
void createRefValue(Expression *newval);
void setRefValue(Expression *newval);
void setStackValue(Expression *newval);
void createStackValue(Expression *newval);
void setValue(Expression *newval);
#if DMDV2
VarDeclaration *rundtor; // if !NULL, rundtor is tested at runtime to see
@@ -655,6 +652,15 @@ struct TypeInfoWildDeclaration : TypeInfoDeclaration
void llvmDefine();
#endif
};
struct TypeInfoVectorDeclaration : TypeInfoDeclaration
{
TypeInfoVectorDeclaration(Type *tinfo);
#if IN_DMD
void toDt(dt_t **pdt);
#endif
};
#endif
/**************************************************************/
@@ -734,11 +740,12 @@ struct FuncDeclaration : Declaration
Loc endloc; // location of closing curly bracket
int vtblIndex; // for member functions, index into vtbl[]
int naked; // !=0 if naked
ILS inlineStatus;
ILS inlineStatusStmt;
ILS inlineStatusExp;
int inlineNest; // !=0 if nested inline
int cantInterpret; // !=0 if cannot interpret function
int isArrayOp; // !=0 if array operation
enum PASS semanticRun;
int semantic3Errors; // !=0 if errors in semantic3
// this function's frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach
int introducing; // !=0 if 'introducing' function
@@ -801,7 +808,7 @@ struct FuncDeclaration : Declaration
LabelDsymbol *searchLabel(Identifier *ident);
AggregateDeclaration *isThis();
AggregateDeclaration *isMember2();
int getLevel(Loc loc, FuncDeclaration *fd); // lexical nesting level difference
int getLevel(Loc loc, Scope *sc, FuncDeclaration *fd); // lexical nesting level difference
void appendExp(Expression *e);
void appendState(Statement *s);
char *mangle();
@@ -823,18 +830,21 @@ struct FuncDeclaration : Declaration
bool setUnsafe();
virtual int isNested();
int needThis();
int isVirtualMethod();
virtual int isVirtual();
virtual int isFinal();
virtual int addPreInvariant();
virtual int addPostInvariant();
Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL);
void inlineScan();
int canInline(int hasthis, int hdrscan = 0);
Expression *doInline(InlineScanState *iss, Expression *ethis, Expressions *arguments);
int canInline(int hasthis, int hdrscan = false, int statementsToo = true);
Expression *expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps);
const char *kind();
void toDocBuffer(OutBuffer *buf);
FuncDeclaration *isUnique();
void checkNestedReference(Scope *sc, Loc loc);
int needsClosure();
int hasNestedFrameRefs();
Statement *mergeFrequire(Statement *, Expressions *params = 0);
Statement *mergeFensure(Statement *, Expressions *params = 0);
Parameters *getParameters(int *pvarargs);
+74 -152
View File
@@ -28,6 +28,9 @@
* t delegate() { return expr; }
*/
int lambdaSetParent(Expression *e, void *param);
int lambdaCheckForNestedRef(Expression *e, void *param);
Expression *Expression::toDelegate(Scope *sc, Type *t)
{
//printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars());
@@ -35,15 +38,12 @@ Expression *Expression::toDelegate(Scope *sc, Type *t)
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
Expression *e;
#if 1
sc = sc->push();
sc->parent = fld; // set current function to be the delegate
e = this;
e->scanForNestedRef(sc);
e->apply(&lambdaSetParent, sc);
e->apply(&lambdaCheckForNestedRef, sc);
sc = sc->pop();
#else
e = this->syntaxCopy();
#endif
Statement *s;
if (t->ty == Tvoid)
s = new ExpStatement(loc, e);
@@ -55,164 +55,86 @@ Expression *Expression::toDelegate(Scope *sc, Type *t)
return e;
}
/******************************
* Perform scanForNestedRef() on an array of Expressions.
/******************************************
* Patch the parent of declarations to be the new function literal.
*/
void arrayExpressionScanForNestedRef(Scope *sc, Expressions *a)
int lambdaSetParent(Expression *e, void *param)
{
//printf("arrayExpressionScanForNestedRef(%p)\n", a);
if (a)
Scope *sc = (Scope *)param;
/* We could use virtual functions instead of a switch,
* but it doesn't seem worth the bother.
*/
switch (e->op)
{
for (size_t i = 0; i < a->dim; i++)
{ Expression *e = (*a)[i];
if (e)
{
e->scanForNestedRef(sc);
}
case TOKdeclaration:
{ DeclarationExp *de = (DeclarationExp *)e;
de->declaration->parent = sc->parent;
break;
}
case TOKindex:
{ IndexExp *de = (IndexExp *)e;
if (de->lengthVar)
{ //printf("lengthVar\n");
de->lengthVar->parent = sc->parent;
}
break;
}
case TOKslice:
{ SliceExp *se = (SliceExp *)e;
if (se->lengthVar)
{ //printf("lengthVar\n");
se->lengthVar->parent = sc->parent;
}
break;
}
default:
break;
}
return 0;
}
void Expression::scanForNestedRef(Scope *sc)
/*******************************************
* Look for references to variables in a scope enclosing the new function literal.
*/
int lambdaCheckForNestedRef(Expression *e, void *param)
{
//printf("Expression::scanForNestedRef(%s)\n", toChars());
}
Scope *sc = (Scope *)param;
/* We could use virtual functions instead of a switch,
* but it doesn't seem worth the bother.
*/
switch (e->op)
{
case TOKsymoff:
{ SymOffExp *se = (SymOffExp *)e;
VarDeclaration *v = se->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
void SymOffExp::scanForNestedRef(Scope *sc)
{
//printf("SymOffExp::scanForNestedRef(%s)\n", toChars());
VarDeclaration *v = var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
}
case TOKvar:
{ VarExp *ve = (VarExp *)e;
VarDeclaration *v = ve->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
void VarExp::scanForNestedRef(Scope *sc)
{
//printf("VarExp::scanForNestedRef(%s)\n", toChars());
VarDeclaration *v = var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
}
case TOKthis:
case TOKsuper:
{ ThisExp *te = (ThisExp *)e;
VarDeclaration *v = te->var->isVarDeclaration();
if (v)
v->checkNestedReference(sc, 0);
break;
}
void ThisExp::scanForNestedRef(Scope *sc)
{
assert(var);
var->isVarDeclaration()->checkNestedReference(sc, 0);
}
void SuperExp::scanForNestedRef(Scope *sc)
{
ThisExp::scanForNestedRef(sc);
}
void FuncExp::scanForNestedRef(Scope *sc)
{
//printf("FuncExp::scanForNestedRef(%s)\n", toChars());
//fd->parent = sc->parent;
}
void DeclarationExp::scanForNestedRef(Scope *sc)
{
//printf("DeclarationExp::scanForNestedRef() %s\n", toChars());
declaration->parent = sc->parent;
}
void NewExp::scanForNestedRef(Scope *sc)
{
//printf("NewExp::scanForNestedRef(Scope *sc): %s\n", toChars());
if (thisexp)
thisexp->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, newargs);
arrayExpressionScanForNestedRef(sc, arguments);
}
void UnaExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
}
void BinExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
e2->scanForNestedRef(sc);
}
void CallExp::scanForNestedRef(Scope *sc)
{
//printf("CallExp::scanForNestedRef(Scope *sc): %s\n", toChars());
e1->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, arguments);
}
void IndexExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
if (lengthVar)
{ //printf("lengthVar\n");
lengthVar->parent = sc->parent;
default:
break;
}
e2->scanForNestedRef(sc);
return 0;
}
void SliceExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
if (lengthVar)
{ //printf("lengthVar\n");
lengthVar->parent = sc->parent;
}
if (lwr)
lwr->scanForNestedRef(sc);
if (upr)
upr->scanForNestedRef(sc);
}
void ArrayLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, elements);
}
void AssocArrayLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, keys);
arrayExpressionScanForNestedRef(sc, values);
}
void StructLiteralExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, elements);
}
void TupleExp::scanForNestedRef(Scope *sc)
{
arrayExpressionScanForNestedRef(sc, exps);
}
void ArrayExp::scanForNestedRef(Scope *sc)
{
e1->scanForNestedRef(sc);
arrayExpressionScanForNestedRef(sc, arguments);
}
void CondExp::scanForNestedRef(Scope *sc)
{
econd->scanForNestedRef(sc);
e1->scanForNestedRef(sc);
e2->scanForNestedRef(sc);
}
+2 -2
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -1116,7 +1116,7 @@ void DocComment::parseSections(unsigned char *comment)
goto L1;
if (*p == '\n')
{ p++;
if (*p == '\n' && !summary && !namelen)
if (*p == '\n' && !summary && !namelen && !inCode)
{
pend = p;
p++;
+40 -35
View File
@@ -111,7 +111,7 @@ Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
* TRUE, *ps = symbol: The one and only one symbol
*/
int Dsymbol::oneMember(Dsymbol **ps)
int Dsymbol::oneMember(Dsymbol **ps, Identifier *ident)
{
//printf("Dsymbol::oneMember()\n");
*ps = this;
@@ -122,7 +122,7 @@ int Dsymbol::oneMember(Dsymbol **ps)
* Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
*/
int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps)
int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident)
{
//printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
Dsymbol *s = NULL;
@@ -132,7 +132,7 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps)
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *sx = (*members)[i];
int x = sx->oneMember(ps);
int x = sx->oneMember(ps, ident);
//printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
if (!x)
{
@@ -142,6 +142,11 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps)
}
if (*ps)
{
if (ident)
{
if (!(*ps)->ident || !(*ps)->ident->equals(ident))
continue;
}
if (s) // more than one symbol
{ *ps = NULL;
//printf("\tfalse 2\n");
@@ -653,19 +658,16 @@ void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
Module *Dsymbol::getModule()
{
Module *m;
Dsymbol *s;
//printf("Dsymbol::getModule()\n");
TemplateDeclaration *td = getFuncTemplateDecl(this);
if (td)
return td->getModule();
s = this;
Dsymbol *s = this;
while (s)
{
//printf("\ts = '%s'\n", s->toChars());
m = s->isModule();
//printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
Module *m = s->isModule();
if (m)
return m;
s = s->parent;
@@ -673,30 +675,32 @@ Module *Dsymbol::getModule()
return NULL;
}
/**********************************
* Determine which Module a Dsymbol will be compiled in.
* This may be different from getModule for templates.
* Determine which Module a Dsymbol is in, as far as access rights go.
*/
Module *Dsymbol::getCompilationModule()
Module *Dsymbol::getAccessModule()
{
Module *m;
TemplateInstance *ti;
Dsymbol *s;
//printf("Dsymbol::getAccessModule()\n");
TemplateDeclaration *td = getFuncTemplateDecl(this);
if (td)
return td->getAccessModule();
//printf("Dsymbol::getModule()\n");
s = this;
Dsymbol *s = this;
while (s)
{
//printf("\ts = '%s'\n", s->toChars());
m = s->isModule();
if (m)
return m;
ti = s->isTemplateInstance();
if (ti && ti->tmodule)
return ti->tmodule;
s = s->parent;
//printf("\ts = %s '%s'\n", s->kind(), s->toPrettyChars());
Module *m = s->isModule();
if (m)
return m;
TemplateInstance *ti = s->isTemplateInstance();
if (ti && ti->isnested)
/* Because of local template instantiation, the parent isn't where the access
* rights come from - it's the template declaration
*/
s = ti->tempdecl;
else
s = s->parent;
}
return NULL;
}
@@ -832,7 +836,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
// Look in imported modules
for (size_t i = 0; i < imports->dim; i++)
{ ScopeDsymbol *ss = (*imports)[i];
{ Dsymbol *ss = (*imports)[i];
Dsymbol *s2;
// If private import, don't search it
@@ -842,7 +846,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
//printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
/* Don't find private members if ss is a module
*/
s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
s2 = ss->search(loc, ident, ss->isImport() ? 1 : 0);
if (!s)
s = s2;
else if (s2 && s != s2)
@@ -895,7 +899,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
if (flags & 4) // if return NULL on ambiguity
return NULL;
if (!(flags & 2))
ss->multiplyDefined(loc, s, s2);
ScopeDsymbol::multiplyDefined(loc, s, s2);
break;
}
}
@@ -922,7 +926,7 @@ Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
return s;
}
void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
void ScopeDsymbol::importScope(Dsymbol *s, enum PROT protection)
{
//printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
@@ -930,11 +934,11 @@ void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
if (s != this)
{
if (!imports)
imports = new ScopeDsymbols();
imports = new Dsymbols();
else
{
for (size_t i = 0; i < imports->dim; i++)
{ ScopeDsymbol *ss = (*imports)[i];
{ Dsymbol *ss = (*imports)[i];
if (ss == s) // if already imported
{
if (protection > prots[i])
@@ -1051,8 +1055,7 @@ static int dimDg(void *ctx, size_t n, Dsymbol *)
size_t ScopeDsymbol::dim(Dsymbols *members)
{
size_t n = 0;
if (members)
foreach(members, &dimDg, &n);
foreach(members, &dimDg, &n);
return n;
}
#endif
@@ -1102,7 +1105,9 @@ Dsymbol *ScopeDsymbol::getNth(Dsymbols *members, size_t nth, size_t *pn)
#if DMDV2
int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *ctx, size_t *pn)
{
assert(members);
assert(dg);
if (!members)
return 0;
size_t n = pn ? *pn : 0; // take over index
int result = 0;
+5 -5
View File
@@ -154,7 +154,7 @@ struct Dsymbol : Object
void verror(Loc loc, const char *format, va_list ap);
void checkDeprecated(Loc loc, Scope *sc);
Module *getModule(); // module where declared
Module *getCompilationModule(); // possibly different for templates
Module *getAccessModule();
Dsymbol *pastMixin();
Dsymbol *toParent();
Dsymbol *toParent2();
@@ -203,8 +203,8 @@ struct Dsymbol : Object
virtual int needThis(); // need a 'this' pointer?
virtual enum PROT prot();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual int oneMember(Dsymbol **ps);
static int oneMembers(Dsymbols *members, Dsymbol **ps);
virtual int oneMember(Dsymbol **ps, Identifier *ident);
static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL);
virtual int hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addLocalClass(ClassDeclarations *) { }
@@ -291,14 +291,14 @@ struct ScopeDsymbol : Dsymbol
Dsymbols *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
ScopeDsymbols *imports; // imported ScopeDsymbol's
Dsymbols *imports; // imported Dsymbol's
unsigned char *prots; // array of PROT, one for each import
ScopeDsymbol();
ScopeDsymbol(Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *s);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
void importScope(ScopeDsymbol *s, enum PROT protection);
void importScope(Dsymbol *s, enum PROT protection);
int isforwardRef();
void defineRef(Dsymbol *s);
static void multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2);
+3 -3
View File
@@ -300,11 +300,11 @@ void EnumDeclaration::semantic(Scope *sc)
//members->print();
}
int EnumDeclaration::oneMember(Dsymbol **ps)
int EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
if (isAnonymous())
return Dsymbol::oneMembers(members, ps);
return Dsymbol::oneMember(ps);
return Dsymbol::oneMembers(members, ps, ident);
return Dsymbol::oneMember(ps, ident);
}
void EnumDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
+1 -1
View File
@@ -47,7 +47,7 @@ struct EnumDeclaration : ScopeDsymbol
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic0(Scope *sc);
void semantic(Scope *sc);
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident = NULL);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Type *getType();
const char *kind();
+834 -691
View File
File diff suppressed because it is too large Load Diff
+69 -76
View File
@@ -80,11 +80,12 @@ namespace llvm {
void initPrecedence();
typedef int (*apply_fp_t)(Expression *, void *);
Expression *resolveProperties(Scope *sc, Expression *e);
void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d);
Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Dsymbol *d);
Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid);
void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Module *from);
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
void expandTuples(Expressions *exps);
@@ -119,6 +120,7 @@ struct Expression : Object
Expression(Loc loc, enum TOK op, int size);
Expression *copy();
virtual Expression *syntaxCopy();
virtual int apply(apply_fp_t fp, void *param);
virtual Expression *semantic(Scope *sc);
Expression *trySemantic(Scope *sc);
@@ -129,7 +131,7 @@ struct Expression : Object
virtual void dump(int indent);
void error(const char *format, ...) IS_PRINTF(2);
void warning(const char *format, ...) IS_PRINTF(2);
virtual void rvalue();
virtual int rvalue();
static Expression *combine(Expression *e1, Expression *e2);
static Expressions *arraySyntaxCopy(Expressions *exps);
@@ -169,7 +171,6 @@ struct Expression : Object
Expression *isTemp();
Expression *toDelegate(Scope *sc, Type *t);
virtual void scanForNestedRef(Scope *sc);
virtual Expression *optimize(int result);
#define WANTflags 1
@@ -184,10 +185,12 @@ struct Expression : Object
virtual int isConst();
virtual int isBool(int result);
virtual int isBit();
virtual int checkSideEffect(int flag);
virtual int canThrow(bool mustNotThrow);
bool hasSideEffect();
void discardValue();
void useValue();
int canThrow(bool mustNotThrow);
virtual int inlineCost(InlineCostState *ics);
virtual int inlineCost3(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
virtual Expression *inlineScan(InlineScanState *iss);
Expression *inlineCopy(Scope *sc);
@@ -364,9 +367,8 @@ struct ThisExp : Expression
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void scanForNestedRef(Scope *sc);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
@@ -384,9 +386,7 @@ struct SuperExp : ThisExp
SuperExp(Loc loc);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void scanForNestedRef(Scope *sc);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
};
@@ -396,6 +396,7 @@ struct NullExp : Expression
unsigned char committed; // !=0 if type is committed
NullExp(Loc loc, Type *t = NULL);
int equals(Object *o);
Expression *semantic(Scope *sc);
int isBool(int result);
int isConst();
@@ -421,6 +422,7 @@ struct StringExp : Expression
unsigned char sz; // 1: char, 2: wchar, 4: dchar
unsigned char committed; // !=0 if type is committed
unsigned char postfix; // 'c', 'w', 'd'
bool ownedByCtfe; // true = created in CTFE
StringExp(Loc loc, char *s);
StringExp(Loc loc, void *s, size_t len);
@@ -440,6 +442,7 @@ struct StringExp : Expression
int isBool(int result);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
unsigned charAt(size_t i);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
@@ -461,21 +464,18 @@ struct TupleExp : Expression
TupleExp(Loc loc, Expressions *exps);
TupleExp(Loc loc, TupleDeclaration *tup);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
int equals(Object *o);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void scanForNestedRef(Scope *sc);
void checkEscape();
int checkSideEffect(int flag);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *castTo(Scope *sc, Type *t);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -487,25 +487,23 @@ struct TupleExp : Expression
struct ArrayLiteralExp : Expression
{
Expressions *elements;
bool ownedByCtfe; // true = created in CTFE
ArrayLiteralExp(Loc loc, Expressions *elements);
ArrayLiteralExp(Loc loc, Expression *e);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isBool(int result);
int checkSideEffect(int flag);
StringExp *toString();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
void scanForNestedRef(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -522,26 +520,24 @@ struct AssocArrayLiteralExp : Expression
{
Expressions *keys;
Expressions *values;
bool ownedByCtfe; // true = created in CTFE
AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isBool(int result);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
void scanForNestedRef(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -563,25 +559,24 @@ struct StructLiteralExp : Expression
#endif
size_t soffset; // offset from start of s
int fillHoles; // fill alignment 'holes' with zero
bool ownedByCtfe; // true = created in CTFE
StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype = NULL);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *getField(Type *type, unsigned offset);
int getFieldIndex(Type *type, unsigned offset);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void toMangleBuffer(OutBuffer *buf);
void scanForNestedRef(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
int canThrow(bool mustNotThrow);
MATCH implicitConvTo(Type *t);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -608,7 +603,7 @@ struct TypeExp : Expression
TypeExp(Loc loc, Type *type);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void rvalue();
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
#if IN_DMD
@@ -642,7 +637,7 @@ struct TemplateExp : Expression
TemplateDeclaration *td;
TemplateExp(Loc loc, TemplateDeclaration *td);
void rvalue();
int rvalue();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
};
@@ -662,18 +657,16 @@ struct NewExp : Expression
NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
Type *newtype, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *optimize(int result);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void scanForNestedRef(Scope *sc);
int canThrow(bool mustNotThrow);
//int inlineCost(InlineCostState *ics);
//int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
@@ -694,10 +687,9 @@ struct NewAnonClassExp : Expression
NewAnonClassExp(Loc loc, Expression *thisexp, Expressions *newargs,
ClassDeclaration *cd, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int canThrow(bool mustNotThrow);
};
#if DMDV2
@@ -735,7 +727,6 @@ struct SymOffExp : SymbolExp
Expression *doInline(InlineDoState *ids);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
void scanForNestedRef(Scope *sc);
#if IN_DMD
dt_t **toDt(dt_t **pdt);
@@ -766,9 +757,8 @@ struct VarExp : SymbolExp
#if IN_DMD
dt_t **toDt(dt_t **pdt);
#endif
void scanForNestedRef(Scope *sc);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
@@ -797,12 +787,20 @@ struct OverExp : Expression
struct FuncExp : Expression
{
FuncLiteralDeclaration *fd;
TemplateDeclaration *td;
enum TOK tok;
Type *tded;
Scope *scope;
FuncExp(Loc loc, FuncLiteralDeclaration *fd);
FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *semantic(Scope *sc, Expressions *arguments);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
void scanForNestedRef(Scope *sc);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
Expression *inferType(Scope *sc, Type *t);
void setType(Type *t);
char *toChars();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
@@ -810,7 +808,7 @@ struct FuncExp : Expression
dt_t **toDt(dt_t **pdt);
#endif
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
//Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
@@ -830,15 +828,12 @@ struct DeclarationExp : Expression
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
void scanForNestedRef(Scope *sc);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -875,7 +870,6 @@ struct HaltExp : Expression
HaltExp(Loc loc);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int checkSideEffect(int flag);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -913,17 +907,15 @@ struct UnaExp : Expression
UnaExp(Loc loc, enum TOK op, int size, Expression *e1);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Expression *optimize(int result);
void dump(int indent);
void scanForNestedRef(Scope *sc);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *));
int canThrow(bool mustNotThrow);
Expression *resolveLoc(Loc loc, Scope *sc);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -937,9 +929,9 @@ struct BinExp : Expression
BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *semanticp(Scope *sc);
int checkSideEffect(int flag);
void checkComplexMulAssign();
void checkComplexAddAssign();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -947,19 +939,16 @@ struct BinExp : Expression
Expression *typeCombine(Scope *sc);
Expression *optimize(int result);
int isunsigned();
void incompatibleTypes();
Expression *incompatibleTypes();
void dump(int indent);
void scanForNestedRef(Scope *sc);
Expression *interpretCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *));
Expression *interpretCommon2(InterState *istate, CtfeGoal goal,
Expression *(*fp)(TOK, Type *, Expression *, Expression *));
Expression *interpretAssignCommon(InterState *istate, CtfeGoal goal,
Expression *(*fp)(Type *, Expression *, Expression *), int post = 0);
int canThrow(bool mustNotThrow);
Expression *arrayOp(Scope *sc);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -1010,13 +999,11 @@ struct AssertExp : UnaExp
AssertExp(Loc loc, Expression *e, Expression *msg = NULL);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
int canThrow(bool mustNotThrow);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -1098,7 +1085,7 @@ struct DelegateExp : UnaExp
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -1135,24 +1122,22 @@ struct CallExp : UnaExp
CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *resolveUFCS(Scope *sc);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void dump(int indent);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
void scanForNestedRef(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
int canThrow(bool mustNotThrow);
Expression *addDtorHook(Scope *sc);
MATCH implicitConvTo(Type *t);
int inlineCost(InlineCostState *ics);
int inlineCost3(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -1297,7 +1282,6 @@ struct DeleteExp : UnaExp
DeleteExp(Loc loc, Expression *e);
Expression *semantic(Scope *sc);
Expression *checkToBoolean(Scope *sc);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1322,7 +1306,6 @@ struct CastExp : UnaExp
IntRange getIntRange();
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
void checkEscape();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
@@ -1342,6 +1325,19 @@ struct CastExp : UnaExp
#endif
};
struct VectorExp : UnaExp
{
Type *to;
unsigned dim; // number of elements in the vector
VectorExp(Loc loc, Expression *e, Type *t);
Expression *syntaxCopy();
Expression *semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
};
struct SliceExp : UnaExp
{
@@ -1351,6 +1347,7 @@ struct SliceExp : UnaExp
SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
void checkEscape();
void checkEscapeRef();
@@ -1365,12 +1362,9 @@ struct SliceExp : UnaExp
#if IN_DMD
elem *toElem(IRState *irs);
#endif
void scanForNestedRef(Scope *sc);
void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
Expression *buildArrayLoop(Parameters *fparams);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -1408,17 +1402,16 @@ struct ArrayExp : UnaExp
ArrayExp(Loc loc, Expression *e1, Expressions *arguments);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
int isLvalue();
Expression *toLvalue(Scope *sc, Expression *e);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
void scanForNestedRef(Scope *sc);
// For operator overloading
Identifier *opId();
Expression *op_overload(Scope *sc);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
};
@@ -1443,7 +1436,6 @@ struct CommaExp : BinExp
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
int isBool(int result);
int checkSideEffect(int flag);
MATCH implicitConvTo(Type *t);
Expression *addDtorHook(Scope *sc);
Expression *castTo(Scope *sc, Type *t);
@@ -1473,7 +1465,6 @@ struct IndexExp : BinExp
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
Expression *doInline(InlineDoState *ids);
void scanForNestedRef(Scope *sc);
#if IN_DMD
elem *toElem(IRState *irs);
@@ -1891,7 +1882,6 @@ struct OrOrExp : BinExp
int isBit();
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -1909,7 +1899,6 @@ struct AndAndExp : BinExp
int isBit();
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
int checkSideEffect(int flag);
#if IN_DMD
elem *toElem(IRState *irs);
#endif
@@ -2025,6 +2014,7 @@ struct CondExp : BinExp
CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2);
Expression *syntaxCopy();
int apply(apply_fp_t fp, void *param);
Expression *semantic(Scope *sc);
Expression *optimize(int result);
Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue);
@@ -2034,14 +2024,10 @@ struct CondExp : BinExp
Expression *toLvalue(Scope *sc, Expression *e);
Expression *modifiableLvalue(Scope *sc, Expression *e);
Expression *checkToBoolean(Scope *sc);
int checkSideEffect(int flag);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
MATCH implicitConvTo(Type *t);
Expression *castTo(Scope *sc, Type *t);
void scanForNestedRef(Scope *sc);
int canThrow(bool mustNotThrow);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Expression *inlineScan(InlineScanState *iss);
@@ -2142,4 +2128,11 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2);
Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr);
// Const-folding functions used by CTFE
void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex);
void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex);
void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex);
#endif /* DMD_EXPRESSION_H */
+151 -19
View File
@@ -66,11 +66,12 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, StorageCla
vtblIndex = -1;
hasReturnExp = 0;
naked = 0;
inlineStatus = ILSuninitialized;
inlineStatusExp = ILSuninitialized;
inlineStatusStmt = ILSuninitialized;
inlineNest = 0;
cantInterpret = 0;
isArrayOp = 0;
semanticRun = PASSinit;
semantic3Errors = 0;
#if DMDV1
nestedFrameRef = 0;
#endif
@@ -152,6 +153,7 @@ void FuncDeclaration::semantic(Scope *sc)
ClassDeclaration *cd;
InterfaceDeclaration *id;
Dsymbol *pd;
bool doesoverride;
#if 0
printf("FuncDeclaration::semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc->linkage);
@@ -473,6 +475,7 @@ void FuncDeclaration::semantic(Scope *sc)
vi = cd->baseClass ? findVtblIndex((Dsymbols*)&cd->baseClass->vtbl, cd->baseClass->vtbl.dim)
: -1;
doesoverride = FALSE;
switch (vi)
{
case -1:
@@ -495,8 +498,9 @@ void FuncDeclaration::semantic(Scope *sc)
if (isFinal())
{
if (isOverride())
error("is marked as override, but does not override any function");
// Don't check here, as it may override an interface function
//if (isOverride())
//error("is marked as override, but does not override any function");
cd->vtblFinal.push(this);
}
else
@@ -516,11 +520,12 @@ void FuncDeclaration::semantic(Scope *sc)
return;
default:
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl.tdata()[vi];
{ FuncDeclaration *fdv = (FuncDeclaration *)cd->baseClass->vtbl[vi];
// This function is covariant with fdv
if (fdv->isFinal())
error("cannot override final function %s", fdv->toPrettyChars());
doesoverride = TRUE;
#if DMDV2
if (!isOverride())
warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
@@ -530,11 +535,16 @@ void FuncDeclaration::semantic(Scope *sc)
if (fdc->toParent() == parent)
{
// If both are mixins, then error.
// If either is not, the one that is not overrides
// the other.
if (fdc->parent->isClassDeclaration())
// If either is not, the one that is not overrides the other.
if (this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
error("multiple overrides of same function");
// if (this is mixin) && (fdc is not mixin) then fdc overrides
else if (!this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration())
break;
if (!this->parent->isClassDeclaration()
else if (!this->parent->isClassDeclaration() // if both are mixins then error
#if !BREAKABI
&& !isDtorDeclaration()
#endif
@@ -544,7 +554,7 @@ void FuncDeclaration::semantic(Scope *sc)
)
error("multiple overrides of same function");
}
cd->vtbl.tdata()[vi] = this;
cd->vtbl[vi] = this;
vtblIndex = vi;
/* Remember which functions this overrides
@@ -602,6 +612,14 @@ void FuncDeclaration::semantic(Scope *sc)
*/
foverrides.push(fdv);
#if DMDV2
/* Should we really require 'override' when implementing
* an interface function?
*/
//if (!isOverride())
//warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv->toPrettyChars());
#endif
if (fdv->tintro)
ti = fdv->tintro;
else if (!type->equals(fdv->type))
@@ -640,7 +658,7 @@ void FuncDeclaration::semantic(Scope *sc)
}
}
if (introducing && isOverride())
if (!doesoverride && isOverride())
{
error("does not override any function");
}
@@ -871,6 +889,7 @@ void FuncDeclaration::semantic3(Scope *sc)
if (semanticRun >= PASSsemantic3)
return;
semanticRun = PASSsemantic3;
semantic3Errors = 0;
// LDC
if (!global.params.useAvailableExternally)
@@ -976,7 +995,10 @@ void FuncDeclaration::semantic3(Scope *sc)
Type *t = new TypeIdentifier(loc, Id::va_argsave_t);
t = t->semantic(loc, sc);
if (t == Type::terror)
{
error("must import core.vararg to use variadic functions");
return;
}
else
{
v_argsave = new VarDeclaration(loc, t, Id::va_argsave, NULL);
@@ -1798,7 +1820,10 @@ void FuncDeclaration::semantic3(Scope *sc)
if (global.gag && global.errors != nerrors)
semanticRun = PASSsemanticdone; // Ensure errors get reported again
else
{
semanticRun = PASSsemantic3done;
semantic3Errors = global.errors - nerrors;
}
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars());
//fflush(stdout);
}
@@ -1903,7 +1928,7 @@ int FuncDeclaration::equals(Object *o)
void FuncDeclaration::bodyToCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
if (fbody &&
(!hgs->hdrgen || hgs->tpltMember || canInline(1,1))
(!hgs->hdrgen || hgs->tpltMember || canInline(1,1,1))
)
{ buf->writenl();
@@ -1953,6 +1978,22 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf, Expressions *params)
if (!params)
params = fdrequireParams;
/* If a base function and its override both have an IN contract, then
* only one of them needs to succeed. This is done by generating:
*
* void derived.in() {
* try {
* base.in();
* }
* catch () {
* ... body of derived.in() ...
* }
* }
*
* So if base.in() doesn't throw, derived.in() need not be executed, and the contract is valid.
* If base.in() throws, then derived.in()'s body is executed.
*/
/* Implementing this is done by having the overriding function call
* nested functions (the fdrequire functions) nested inside the overridden
* function. This requires that the stack layout of the calling function's
@@ -1997,6 +2038,7 @@ Statement *FuncDeclaration::mergeFrequire(Statement *sf, Expressions *params)
Statement *s2 = new ExpStatement(loc, e);
Catch *c = new Catch(loc, NULL, NULL, sf);
c->internalCatch = true;
Catches *catches = new Catches();
catches->push(c);
sf = new TryCatchStatement(loc, s2, catches);
@@ -2548,7 +2590,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g)
{
if (tf->mod != tg->mod)
{
if (tg->mod == MODconst)
if (MODimplicitConv(tf->mod, tg->mod))
match = MATCHconst;
else
return MATCHnomatch;
@@ -2695,7 +2737,7 @@ AggregateDeclaration *FuncDeclaration::isMember2()
* >0 decrease nesting by number
*/
int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
int FuncDeclaration::getLevel(Loc loc, Scope *sc, FuncDeclaration *fd)
{ int level;
Dsymbol *s;
Dsymbol *fdparent;
@@ -2732,7 +2774,9 @@ int FuncDeclaration::getLevel(Loc loc, FuncDeclaration *fd)
return level;
Lerr:
error(loc, "cannot access frame of function %s", fd->toPrettyChars());
// Don't give error if in template constraint
if (!((sc->flags & SCOPEstaticif) && parent->isTemplateDeclaration()))
error(loc, "cannot access frame of function %s", fd->toPrettyChars());
return 1;
}
@@ -2812,21 +2856,37 @@ int FuncDeclaration::isImportedSymbol()
int FuncDeclaration::isVirtual()
{
Dsymbol *p = toParent();
#if 0
printf("FuncDeclaration::isVirtual(%s)\n", toChars());
printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROTprivate, isCtorDeclaration(), linkage != LINKd);
printf("result is %d\n",
isMember() &&
!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
toParent()->isClassDeclaration());
p->isClassDeclaration() &&
!(p->isInterfaceDeclaration() && isFinal()));
#endif
Dsymbol *p = toParent();
return isMember() &&
!(isStatic() || protection == PROTprivate || protection == PROTpackage) &&
p->isClassDeclaration() &&
!(p->isInterfaceDeclaration() && isFinal());
}
// Determine if a function is pedantically virtual
int FuncDeclaration::isVirtualMethod()
{
//printf("FuncDeclaration::isVirtualMethod() %s\n", toChars());
if (!isVirtual())
return 0;
// If it's a final method, and does not override anything, then it is not virtual
if (isFinal() && foverrides.dim == 0)
{
return 0;
}
return 1;
}
int FuncDeclaration::isFinal()
{
ClassDeclaration *cd;
@@ -3042,6 +3102,38 @@ const char *FuncDeclaration::kind()
return "function";
}
void FuncDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
//printf("FuncDeclaration::checkNestedReference() %s\n", toChars());
if (parent && parent != sc->parent && this->isNested() &&
this->ident != Id::require && this->ident != Id::ensure)
{
// The function that this function is in
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
// The current function
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
//printf("this = %s in [%s]\n", this->toChars(), this->loc.toChars());
//printf("fdv = %s in [%s]\n", fdv->toChars(), fdv->loc.toChars());
//printf("fdthis = %s in [%s]\n", fdthis->toChars(), fdthis->loc.toChars());
if (fdv && fdthis && fdv != fdthis)
{
int lv = fdthis->getLevel(loc, sc, fdv);
if (lv == -1)
return; // OK
if (lv == 0)
return; // OK
// BUG: may need to walk up outer scopes like Declaration::checkNestedReference() does
// function literal has reference to enclosing scope is delegate
if (FuncLiteralDeclaration *fld = fdthis->isFuncLiteralDeclaration())
fld->tok = TOKdelegate;
}
}
}
/*******************************
* Look at all the variables in this function that are referenced
* by nested functions, and determine if a closure needs to be
@@ -3117,6 +3209,43 @@ Lyes:
}
#endif
/***********************************************
* Determine if function's variables are referenced by a function
* nested within it.
*/
int FuncDeclaration::hasNestedFrameRefs()
{
#if DMDV2
if (closureVars.dim)
#else
if (nestedFrameRef)
#endif
return 1;
/* If a virtual method has contracts, assume its variables are referenced
* by those contracts, even if they aren't. Because they might be referenced
* by the overridden or overriding function's contracts.
* This can happen because frequire and fensure are implemented as nested functions,
* and they can be called directly by an overriding function and the overriding function's
* context had better match, or Bugzilla 7337 will bite.
*/
if ((fdrequire || fdensure) && isVirtualMethod())
return 1;
if (foverrides.dim && isVirtualMethod())
{
for (size_t i = 0; i < foverrides.dim; i++)
{
FuncDeclaration *fdv = foverrides.tdata()[i];
if (fdv->hasNestedFrameRefs())
return 1;
}
}
return 0;
}
/*********************************************
* Return the function's parameter list, and whether
* it is variadic or not.
@@ -3170,6 +3299,8 @@ FuncLiteralDeclaration::FuncLiteralDeclaration(Loc loc, Loc endloc, Type *type,
if (fes)
id = "__foreachbody";
else if (tok == TOKreserved)
id = "__lambda";
else if (tok == TOKdelegate)
id = "__dgliteral";
else
@@ -3198,7 +3329,7 @@ Dsymbol *FuncLiteralDeclaration::syntaxCopy(Dsymbol *s)
int FuncLiteralDeclaration::isNested()
{
//printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
return (tok == TOKdelegate);
return (tok != TOKfunction);
}
int FuncLiteralDeclaration::isVirtual()
@@ -3209,7 +3340,7 @@ int FuncLiteralDeclaration::isVirtual()
const char *FuncLiteralDeclaration::kind()
{
// GCC requires the (char*) casts
return (tok == TOKdelegate) ? (char*)"delegate" : (char*)"function";
return (tok != TOKfunction) ? (char*)"delegate" : (char*)"function";
}
void FuncLiteralDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -3806,6 +3937,7 @@ void InvariantDeclaration::semantic(Scope *sc)
sc = sc->push();
sc->stc &= ~STCstatic; // not a static invariant
sc->stc |= STCconst; // invariant() is always const
sc->incontract++;
sc->linkage = LINKd;
+66 -14
View File
@@ -4,7 +4,7 @@
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// in artistic.txt, or the GNU General Public License in gpl.txt.
// See the included readme.txt for details.
@@ -18,11 +18,49 @@
#include <errno.h>
#include <wchar.h>
#include "mars.h"
#define MARS 1
#include "html.h"
#if MARS
#include <assert.h>
#include "root.h"
//#include "../mars/mars.h"
#else
#include "outbuf.h"
#include "msgs2.h"
extern void html_err(const char *, unsigned, unsigned, ...);
static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"
#endif
#if __GNUC__
int memicmp(const char *s1, const char *s2, int n);
#if 0
{
int result = 0;
for (int i = 0; i < n; i++)
{ char c1 = s1[i];
char c2 = s2[i];
result = c1 - c2;
if (result)
{
if ('A' <= c1 && c1 <= 'Z')
c1 += 'a' - 'A';
if ('A' <= c2 && c2 <= 'Z')
c2 += 'a' - 'A';
result = c1 - c2;
if (result)
break;
}
}
return result;
}
#endif
#endif
extern int HtmlNamedEntity(unsigned char *p, int length);
@@ -64,20 +102,21 @@ Html::Html(const char *sourcename, unsigned char *base, unsigned length)
void Html::error(const char *format, ...)
{
if (!global.gag)
{
printf("%s(%d) : HTML Error: ", sourcename, linnum);
printf("%s(%d) : HTML Error: ", sourcename, linnum);
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
printf("\n");
fflush(stdout);
}
printf("\n");
fflush(stdout);
global.errors++;
//#if MARS
// global.errors++;
//#else
exit(EXIT_FAILURE);
//#endif
}
/**********************************************
@@ -85,7 +124,11 @@ void Html::error(const char *format, ...)
* concatenate it all together, and store in buf.
*/
#if MARS
void Html::extractCode(OutBuffer *buf)
#else
void Html::extractCode(Outbuffer *buf)
#endif
{
//printf("Html::extractCode()\n");
dbuf = buf; // save for other routines
@@ -129,7 +172,11 @@ void Html::extractCode(OutBuffer *buf)
int c;
c = charEntity();
#if MARS
buf->writeUTF8(c);
#else
buf->writeByte(c);
#endif
}
else
p++;
@@ -156,7 +203,12 @@ void Html::extractCode(OutBuffer *buf)
break;
}
buf->writeByte(0); // ending sentinel
#if SCPP
//printf("Code is: '%s'\n", buf->toString() + 3);
#endif
#if MARS
//printf("D code is: '%s'\n", (char *)buf->data);
#endif
}
/***********************************************
@@ -530,7 +582,7 @@ void Html::scanCDATA()
* right.
*/
linnum++;
dbuf->writeUTF8('\n');
dbuf->writeByte('\n');
p += lineSepLength;
continue;
}
+16 -8
View File
@@ -1,16 +1,18 @@
// Copyright (c) 1999-2006 by Digital Mars
// Copyright (c) 1999-2009 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// www.digitalmars.com
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// in artistic.txt, or the GNU General Public License in gpl.txt.
// See the included readme.txt for details.
#ifndef DMD_HTML_H
#define DMD_HTML_H 1
#if MARS
struct OutBuffer;
#else
struct Outbuffer;
#endif
struct Html
{
@@ -20,14 +22,22 @@ struct Html
unsigned char *end; // past end of buffer
unsigned char *p; // current character
unsigned linnum; // current line number
#if MARS
OutBuffer *dbuf; // code source buffer
#else
Outbuffer *dbuf; // code source buffer
#endif
int inCode; // !=0 if in code
Html(const char *sourcename, unsigned char *base, unsigned length);
void error(const char *format, ...) IS_PRINTF(2);
void error(const char *format, ...);
#if MARS
void extractCode(OutBuffer *buf);
#else
void extractCode(Outbuffer *buf);
#endif
void skipTag();
void skipString();
unsigned char *skipWhite(unsigned char *q);
@@ -38,5 +48,3 @@ struct Html
int charEntity();
static int namedEntity(unsigned char *p, int length);
};
#endif
+9 -12
View File
@@ -53,6 +53,7 @@ Msgtable msgtable[] =
{ "length" },
{ "remove" },
{ "ptr" },
{ "array" },
{ "funcptr" },
{ "dollar", "__dollar" },
{ "ctfe", "__ctfe" },
@@ -86,6 +87,7 @@ Msgtable msgtable[] =
{ "TypeInfo_Enum" },
{ "TypeInfo_Typedef" },
{ "TypeInfo_Pointer" },
{ "TypeInfo_Vector" },
{ "TypeInfo_Array" },
{ "TypeInfo_StaticArray" },
{ "TypeInfo_AssociativeArray" },
@@ -236,19 +238,12 @@ Msgtable msgtable[] =
{ "apply", "opApply" },
{ "applyReverse", "opApplyReverse" },
#if 1
// Ranges
{ "Fempty", "empty" },
{ "Fhead", "front" },
{ "Ftoe", "back" },
{ "Fnext", "popFront" },
{ "Fretreat", "popBack" },
#else
{ "Fempty", "empty" },
{ "Fhead", "head" },
{ "Ftoe", "toe" },
{ "Fnext", "next" },
{ "Fretreat", "retreat" },
#endif
{ "Ffront", "front" },
{ "Fback", "back" },
{ "FpopFront", "popFront" },
{ "FpopBack", "popBack" },
{ "adDup", "_adDupT" },
{ "adReverse", "_adReverse" },
@@ -341,6 +336,7 @@ Msgtable msgtable[] =
{ "isStaticArray" },
{ "isUnsigned" },
{ "isVirtualFunction" },
{ "isVirtualMethod" },
{ "isAbstractFunction" },
{ "isFinalFunction" },
{ "isStaticFunction" },
@@ -353,6 +349,7 @@ Msgtable msgtable[] =
{ "getMember" },
{ "getOverloads" },
{ "getVirtualFunctions" },
{ "getVirtualMethods" },
{ "classInstanceSize" },
{ "allMembers" },
{ "derivedMembers" },
+75 -99
View File
@@ -27,7 +27,7 @@
Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *aliasId,
int isstatic)
: Dsymbol(id)
: Dsymbol()
{
assert(id);
this->loc = loc;
@@ -37,12 +37,6 @@ Import::Import(Loc loc, Identifiers *packages, Identifier *id, Identifier *alias
this->isstatic = isstatic;
pkg = NULL;
mod = NULL;
if (aliasId)
this->ident = aliasId;
// Kludge to change Import identifier to first package
else if (packages && packages->dim)
this->ident = packages->tdata()[0];
}
void Import::addAlias(Identifier *name, Identifier *alias)
@@ -50,9 +44,6 @@ void Import::addAlias(Identifier *name, Identifier *alias)
if (isstatic)
error("cannot have an import bind list");
if (!aliasId)
this->ident = NULL; // make it an anonymous import
names.push(name);
aliases.push(alias);
}
@@ -67,13 +58,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s)
{
assert(!s);
Import *si;
si = new Import(loc, packages, id, aliasId, isstatic);
Import *si = new Import(loc, packages, id, aliasId, isstatic);
for (size_t i = 0; i < names.dim; i++)
{
si->addAlias(names.tdata()[i], aliases.tdata()[i]);
si->addAlias(names[i], aliases[i]);
}
return si;
@@ -141,15 +130,12 @@ void Import::importAll(Scope *sc)
load(sc);
mod->importAll(0);
if (!isstatic && !aliasId && !names.dim)
{
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
sc->scopesym->importScope(mod, prot);
}
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
sc->scopesym->importScope(this, prot);
}
}
@@ -179,20 +165,17 @@ void Import::semantic(Scope *sc)
//printf("%s imports %s\n", sc->module->toChars(), mod->toChars());
sc->module->aimports.push(mod);
if (!isstatic && !aliasId && !names.dim)
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
for (Scope *scd = sc; scd; scd = scd->enclosing)
{
/* Default to private importing
*/
enum PROT prot = sc->protection;
if (!sc->explicitProtection)
prot = PROTprivate;
for (Scope *scd = sc; scd; scd = scd->enclosing)
if (scd->scopesym)
{
if (scd->scopesym)
{
scd->scopesym->importScope(mod, prot);
break;
}
scd->scopesym->importScope(this, prot);
break;
}
}
@@ -203,17 +186,12 @@ void Import::semantic(Scope *sc)
sc->module->needmoduleinfo = 1;
}
sc = sc->push(mod);
for (size_t i = 0; i < aliasdecls.dim; i++)
{ Dsymbol *s = aliasdecls.tdata()[i];
//printf("\tImport alias semantic('%s')\n", s->toChars());
if (!mod->search(loc, names.tdata()[i], 0))
error("%s not found", (names.tdata()[i])->toChars());
s->semantic(sc);
if (aliasId)
{
AliasDeclaration *ad = new AliasDeclaration(loc, aliasId, mod);
sc->insert(ad);
ad->semantic(sc);
}
sc = sc->pop();
}
if (global.params.moduleDeps != NULL)
@@ -247,7 +225,7 @@ void Import::semantic(Scope *sc)
{
for (size_t i = 0; i < packages->dim; i++)
{
Identifier *pid = packages->tdata()[i];
Identifier *pid = (*packages)[i];
ob->printf("%s.", pid->toChars());
}
}
@@ -267,8 +245,8 @@ void Import::semantic(Scope *sc)
else
ob->writebyte(',');
Identifier *name = names.tdata()[i];
Identifier *alias = aliases.tdata()[i];
Identifier *name = names[i];
Identifier *alias = aliases[i];
if (!alias)
{
@@ -280,7 +258,7 @@ void Import::semantic(Scope *sc)
}
if (aliasId)
ob->printf(" -> %s", aliasId->toChars());
ob->printf(" -> %s", aliasId->toChars());
ob->writenl();
}
@@ -298,48 +276,6 @@ void Import::semantic2(Scope *sc)
}
}
Dsymbol *Import::toAlias()
{
if (aliasId)
return mod;
return this;
}
/*****************************
* Add import to sd's symbol table.
*/
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
{
int result = 0;
if (names.dim == 0)
return Dsymbol::addMember(sc, sd, memnum);
if (aliasId)
result = Dsymbol::addMember(sc, sd, memnum);
/* Instead of adding the import to sd's symbol table,
* add each of the alias=name pairs
*/
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = names.tdata()[i];
Identifier *alias = aliases.tdata()[i];
if (!alias)
alias = name;
TypeIdentifier *tname = new TypeIdentifier(loc, name);
AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname);
result |= ad->addMember(sc, sd, memnum);
aliasdecls.push(ad);
}
return result;
}
Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
{
//printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
@@ -349,14 +285,50 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags)
mod->semantic();
}
// Forward it to the package/module
return pkg->search(loc, ident, flags);
}
if (names.dim) // selective import
{
for (size_t i = 0; i < names.dim; i++)
{
Identifier *name = (Identifier *)names[i];
Identifier *alias = (Identifier *)aliases[i];
int Import::overloadInsert(Dsymbol *s)
{
// Allow multiple imports of the same name
return s->isImport() != NULL;
if (!alias)
alias = name;
if (alias->equals(ident))
return mod->search(loc, name, flags);
}
// What should happen when renamed and selective imports are mixed?
// This makes the whole module available with the renamed id.
if (aliasId && aliasId->equals(ident))
return mod;
}
else // non-selective import
{
// For renamed imports, only the alias name is visible.
if (aliasId)
{
if (aliasId->equals(ident))
return mod;
return 0;
}
// For non-static imports, prefer symbols in the module over the module name.
if (!isstatic)
{
Dsymbol *s = mod->search(loc, ident, flags);
if (s)
return s;
}
// Make the start of the package name available.
if (pkg->ident->equals(ident))
{
return pkg;
}
}
return 0;
}
void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
@@ -374,7 +346,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
if (packages && packages->dim)
{
for (size_t i = 0; i < packages->dim; i++)
{ Identifier *pid = packages->tdata()[i];
{ Identifier *pid = (*packages)[i];
buf->printf("%s.", pid->toChars());
}
@@ -383,3 +355,7 @@ void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
buf->writenl();
}
char *Import::toChars()
{
return id->toChars();
}
+3 -6
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2007 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -28,6 +28,7 @@ struct HdrGenState;
struct Import : Dsymbol
{
// isstatic import aliasId = packages.id;
Identifiers *packages; // array of Identifier's representing packages
Identifier *id; // module Identifier
Identifier *aliasId;
@@ -37,8 +38,6 @@ struct Import : Dsymbol
Identifiers names;
Identifiers aliases;
AliasDeclarations aliasdecls; // AliasDeclarations for names/aliases
Module *mod;
Package *pkg; // leftmost package/module
@@ -52,11 +51,9 @@ struct Import : Dsymbol
void importAll(Scope *sc);
void semantic(Scope *sc);
void semantic2(Scope *sc);
Dsymbol *toAlias();
int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
Dsymbol *search(Loc loc, Identifier *ident, int flags);
int overloadInsert(Dsymbol *s);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *toChars();
Import *isImport() { return this; }
};
+8
View File
@@ -193,6 +193,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret)
errors = 1;
continue;
}
s = s->toAlias();
// Find out which field index it is
for (fieldi = 0; 1; fieldi++)
@@ -287,6 +288,7 @@ Expression *StructInitializer::toExpression()
error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars());
goto Lno;
}
s = s->toAlias();
// Find out which field index it is
for (fieldi = 0; 1; fieldi++)
@@ -863,6 +865,12 @@ L1:
Type *ExpInitializer::inferType(Scope *sc)
{
//printf("ExpInitializer::inferType() %s\n", toChars());
if (exp->op == TOKfunction && ((FuncExp *)exp)->td)
{
exp->error("cannot infer type from ambiguous function literal %s", exp->toChars());
return Type::terror;
}
exp = exp->semantic(sc);
exp = resolveProperties(sc, exp);
+353 -148
View File
@@ -39,15 +39,29 @@ struct InlineCostState
};
const int COST_MAX = 250;
const int STATEMENT_COST = 0x1000;
const int STATEMENT_COST_MAX = 250 * 0x1000;
// STATEMENT_COST be power of 2 and greater than COST_MAX
//static assert((STATEMENT_COST & (STATEMENT_COST - 1)) == 0);
//static assert(STATEMENT_COST > COST_MAX);
bool tooCostly(int cost) { return ((cost & (STATEMENT_COST - 1)) >= COST_MAX); }
int expressionInlineCost(Expression *e, InlineCostState *ics);
int Statement::inlineCost(InlineCostState *ics)
{
//printf("Statement::inlineCost = %d\n", COST_MAX);
//printf("%p\n", isScopeStatement());
//printf("%s\n", toChars());
return COST_MAX; // default is we can't inline it
}
int ExpStatement::inlineCost(InlineCostState *ics)
{
return exp ? exp->inlineCost(ics) : 0;
return expressionInlineCost(exp, ics);
//return exp ? exp->inlineCost(ics) : 0;
}
int CompoundStatement::inlineCost(InlineCostState *ics)
@@ -58,10 +72,11 @@ int CompoundStatement::inlineCost(InlineCostState *ics)
if (s)
{
cost += s->inlineCost(ics);
if (cost >= COST_MAX)
if (tooCostly(cost))
break;
}
}
//printf("CompoundStatement::inlineCost = %d\n", cost);
return cost;
}
@@ -73,13 +88,18 @@ int UnrolledLoopStatement::inlineCost(InlineCostState *ics)
if (s)
{
cost += s->inlineCost(ics);
if (cost >= COST_MAX)
if (tooCostly(cost))
break;
}
}
return cost;
}
int ScopeStatement::inlineCost(InlineCostState *ics)
{
return statement ? 1 + statement->inlineCost(ics) : 1;
}
int IfStatement::inlineCost(InlineCostState *ics)
{
int cost;
@@ -92,7 +112,7 @@ int IfStatement::inlineCost(InlineCostState *ics)
return COST_MAX;
#endif
cost = condition->inlineCost(ics);
cost = expressionInlineCost(condition, ics);
#if !IN_LLVM
/* Specifically allow:
@@ -121,6 +141,7 @@ int IfStatement::inlineCost(InlineCostState *ics)
cost += elsebody->inlineCost(ics);
ics->nested -= 1;
}
//printf("IfStatement::inlineCost = %d\n", cost);
return cost;
}
@@ -131,46 +152,93 @@ int ReturnStatement::inlineCost(InlineCostState *ics)
if (ics->nested)
return COST_MAX;
#endif
return exp ? exp->inlineCost(ics) : 0;
return expressionInlineCost(exp, ics);
}
#if DMDV2
int ImportStatement::inlineCost(InlineCostState *ics)
{
return 0;
}
#endif
/* -------------------------- */
int arrayInlineCost(InlineCostState *ics, Expressions *arguments)
{ int cost = 0;
if (arguments)
{
for (size_t i = 0; i < arguments->dim; i++)
{ Expression *e = (*arguments)[i];
if (e)
cost += e->inlineCost(ics);
}
}
int ForStatement::inlineCost(InlineCostState *ics)
{
//return COST_MAX;
int cost = STATEMENT_COST;
if (init)
cost += init->inlineCost(ics);
if (condition)
cost += expressionInlineCost(condition, ics);
if (increment)
cost += expressionInlineCost(increment, ics);
if (body)
cost += body->inlineCost(ics);
//printf("ForStatement: inlineCost = %d\n", cost);
return cost;
}
int Expression::inlineCost(InlineCostState *ics)
/* -------------------------- */
struct ICS2
{
int cost;
InlineCostState *ics;
};
int lambdaInlineCost(Expression *e, void *param)
{
ICS2 *ics2 = (ICS2 *)param;
ics2->cost += e->inlineCost3(ics2->ics);
return (ics2->cost >= COST_MAX);
}
int expressionInlineCost(Expression *e, InlineCostState *ics)
{
//printf("expressionInlineCost()\n");
//e->dump(0);
ICS2 ics2;
ics2.cost = 0;
ics2.ics = ics;
if (e)
e->apply(&lambdaInlineCost, &ics2);
return ics2.cost;
}
int Expression::inlineCost3(InlineCostState *ics)
{
return 1;
}
int VarExp::inlineCost(InlineCostState *ics)
int VarExp::inlineCost3(InlineCostState *ics)
{
//printf("VarExp::inlineCost() %s\n", toChars());
//printf("VarExp::inlineCost3() %s\n", toChars());
Type *tb = type->toBasetype();
if (tb->ty == Tstruct)
{
StructDeclaration *sd = ((TypeStruct *)tb)->sym;
if (sd->isnested)
/* An inner struct will be nested inside another function hierarchy than where
* we're inlining into, so don't inline it.
* At least not until we figure out how to 'move' the struct to be nested
* locally. Example:
* struct S(alias pred) { void unused_func(); }
* void abc() { int w; S!(w) m; }
* void bar() { abc(); }
*/
return COST_MAX;
}
FuncDeclaration *fd = var->isFuncDeclaration();
if (fd && fd->isNested()) // see Bugzilla 7199 for test case
return COST_MAX;
return 1;
}
int ThisExp::inlineCost(InlineCostState *ics)
int ThisExp::inlineCost3(InlineCostState *ics)
{
#if !IN_LLVM
//printf("ThisExp::inlineCost() %s\n", toChars());
//printf("ThisExp::inlineCost3() %s\n", toChars());
FuncDeclaration *fd = ics->fd;
if (!fd)
return COST_MAX;
@@ -181,44 +249,19 @@ int ThisExp::inlineCost(InlineCostState *ics)
return 1;
}
int SuperExp::inlineCost(InlineCostState *ics)
{
#if !IN_LLVM
FuncDeclaration *fd = ics->fd;
if (!fd)
return COST_MAX;
if (!ics->hdrscan)
if (fd->isNested() || !ics->hasthis)
return COST_MAX;
#endif
return 1;
}
int TupleExp::inlineCost(InlineCostState *ics)
{
return 1 + arrayInlineCost(ics, exps);
}
int ArrayLiteralExp::inlineCost(InlineCostState *ics)
{
return 1 + arrayInlineCost(ics, elements);
}
int AssocArrayLiteralExp::inlineCost(InlineCostState *ics)
{
return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values);
}
int StructLiteralExp::inlineCost(InlineCostState *ics)
int StructLiteralExp::inlineCost3(InlineCostState *ics)
{
//printf("StructLiteralExp::inlineCost3() %s\n", toChars());
#if DMDV2
if (sd->isnested)
return COST_MAX;
return 1 + arrayInlineCost(ics, elements);
#endif
return 1;
}
int FuncExp::inlineCost(InlineCostState *ics)
int FuncExp::inlineCost3(InlineCostState *ics)
{
//printf("FuncExp::inlineCost()\n");
//printf("FuncExp::inlineCost3()\n");
// This breaks on LDC too, since nested functions have internal linkage
// and thus can't be referenced from other objects.
@@ -226,18 +269,19 @@ int FuncExp::inlineCost(InlineCostState *ics)
return COST_MAX;
}
int DelegateExp::inlineCost(InlineCostState *ics)
int DelegateExp::inlineCost3(InlineCostState *ics)
{
// This breaks on LDC too, since nested functions have internal linkage
// and thus can't be referenced from other objects.
//printf("DelegateExp::inlineCost3()\n");
return COST_MAX;
}
int DeclarationExp::inlineCost(InlineCostState *ics)
int DeclarationExp::inlineCost3(InlineCostState *ics)
{ int cost = 0;
VarDeclaration *vd;
//printf("DeclarationExp::inlineCost()\n");
//printf("DeclarationExp::inlineCost3()\n");
vd = declaration->isVarDeclaration();
if (vd)
{
@@ -264,9 +308,10 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
return COST_MAX;
cost += 1;
#if DMDV2
if (vd->edtor) // if destructor required
return COST_MAX; // needs work to make this work
#endif
// Scan initializer (vd->init)
if (vd->init)
{
@@ -274,7 +319,7 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
if (ie)
{
cost += ie->exp->inlineCost(ics);
cost += expressionInlineCost(ie->exp, ics);
}
}
}
@@ -286,62 +331,25 @@ int DeclarationExp::inlineCost(InlineCostState *ics)
declaration->isClassDeclaration() ||
declaration->isFuncDeclaration() ||
declaration->isTypedefDeclaration() ||
#if DMDV2
declaration->isAttribDeclaration() ||
#endif
declaration->isTemplateMixin())
return COST_MAX;
//printf("DeclarationExp::inlineCost('%s')\n", toChars());
//printf("DeclarationExp::inlineCost3('%s')\n", toChars());
return cost;
}
int UnaExp::inlineCost(InlineCostState *ics)
{
return 1 + e1->inlineCost(ics);
}
int AssertExp::inlineCost(InlineCostState *ics)
{
return 1 + e1->inlineCost(ics) + (msg ? msg->inlineCost(ics) : 0);
}
int BinExp::inlineCost(InlineCostState *ics)
{
return 1 + e1->inlineCost(ics) + e2->inlineCost(ics);
}
int CallExp::inlineCost(InlineCostState *ics)
int CallExp::inlineCost3(InlineCostState *ics)
{
//printf("CallExp::inlineCost3() %s\n", toChars());
// Bugzilla 3500: super.func() calls must be devirtualized, and the inliner
// can't handle that at present.
if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKsuper)
return COST_MAX;
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
}
int SliceExp::inlineCost(InlineCostState *ics)
{ int cost;
cost = 1 + e1->inlineCost(ics);
if (lwr)
cost += lwr->inlineCost(ics);
if (upr)
cost += upr->inlineCost(ics);
return cost;
}
int ArrayExp::inlineCost(InlineCostState *ics)
{
return 1 + e1->inlineCost(ics) + arrayInlineCost(ics, arguments);
}
int CondExp::inlineCost(InlineCostState *ics)
{
return 1 +
e1->inlineCost(ics) +
e2->inlineCost(ics) +
econd->inlineCost(ics);
return 1;
}
@@ -359,10 +367,122 @@ struct InlineDoState
Dsymbols from; // old Dsymbols
Dsymbols to; // parallel array of new Dsymbols
Dsymbol *parent; // new parent
FuncDeclaration *fd; // function being inlined (old parent)
};
/* -------------------------------------------------------------------- */
Statement *Statement::doInlineStatement(InlineDoState *ids)
{
assert(0);
return NULL; // default is we can't inline it
}
Statement *ExpStatement::doInlineStatement(InlineDoState *ids)
{
#if LOG
if (exp) printf("ExpStatement::doInlineStatement() '%s'\n", exp->toChars());
#endif
return new ExpStatement(loc, exp ? exp->doInline(ids) : NULL);
}
Statement *CompoundStatement::doInlineStatement(InlineDoState *ids)
{
//printf("CompoundStatement::doInlineStatement() %d\n", statements->dim);
Statements *as = new Statements();
as->reserve(statements->dim);
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (*statements)[i];
if (s)
{
as->push(s->doInlineStatement(ids));
if (s->isReturnStatement())
break;
/* Check for:
* if (condition)
* return exp1;
* else
* return exp2;
*/
IfStatement *ifs = s->isIfStatement();
if (ifs && ifs->elsebody && ifs->ifbody &&
ifs->ifbody->isReturnStatement() &&
ifs->elsebody->isReturnStatement()
)
break;
}
else
as->push(NULL);
}
return new CompoundStatement(loc, as);
}
Statement *UnrolledLoopStatement::doInlineStatement(InlineDoState *ids)
{
//printf("UnrolledLoopStatement::doInlineStatement() %d\n", statements->dim);
Statements *as = new Statements();
as->reserve(statements->dim);
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (*statements)[i];
if (s)
{
as->push(s->doInlineStatement(ids));
if (s->isReturnStatement())
break;
}
else
as->push(NULL);
}
return new UnrolledLoopStatement(loc, as);
}
Statement *ScopeStatement::doInlineStatement(InlineDoState *ids)
{
//printf("ScopeStatement::doInlineStatement() %d\n", statements->dim);
return statement ? new ScopeStatement(loc, statement->doInlineStatement(ids)) : this;
}
Statement *IfStatement::doInlineStatement(InlineDoState *ids)
{
assert(!arg);
Expression *condition = this->condition ? this->condition->doInline(ids) : NULL;
Statement *ifbody = this->ifbody ? this->ifbody->doInlineStatement(ids) : NULL;
Statement *elsebody = this->elsebody ? this->elsebody->doInlineStatement(ids) : NULL;
return new IfStatement(loc, arg, condition, ifbody, elsebody);
}
Statement *ReturnStatement::doInlineStatement(InlineDoState *ids)
{
//printf("ReturnStatement::doInlineStatement() '%s'\n", exp ? exp->toChars() : "");
return new ReturnStatement(loc, exp ? exp->doInline(ids) : NULL);
}
#if DMDV2
Statement *ImportStatement::doInlineStatement(InlineDoState *ids)
{
return NULL;
}
#endif
Statement *ForStatement::doInlineStatement(InlineDoState *ids)
{
//printf("ForStatement::doInlineStatement()\n");
Statement *init = this->init ? this->init->doInlineStatement(ids) : NULL;
Expression *condition = this->condition ? this->condition->doInline(ids) : NULL;
Expression *increment = this->increment ? this->increment->doInline(ids) : NULL;
Statement *body = this->body ? this->body->doInlineStatement(ids) : NULL;
return new ForStatement(loc, init, condition, increment, body);
}
/* -------------------------------------------------------------------- */
Expression *Statement::doInline(InlineDoState *ids)
{
printf("Statement::doInline()\n%s\n", toChars());
fflush(stdout);
assert(0);
return NULL; // default is we can't inline it
}
@@ -425,6 +545,11 @@ Expression *UnrolledLoopStatement::doInline(InlineDoState *ids)
return e;
}
Expression *ScopeStatement::doInline(InlineDoState *ids)
{
return statement ? statement->doInline(ids) : NULL;
}
Expression *IfStatement::doInline(InlineDoState *ids)
{
Expression *econd;
@@ -471,10 +596,12 @@ Expression *ReturnStatement::doInline(InlineDoState *ids)
return exp ? exp->doInline(ids) : 0;
}
#if DMDV2
Expression *ImportStatement::doInline(InlineDoState *ids)
{
return NULL;
}
#endif
/* --------------------------------------------------------------- */
@@ -536,6 +663,12 @@ Expression *VarExp::doInline(InlineDoState *ids)
return ve;
}
}
if (ids->fd && var == ids->fd->vthis)
{ VarExp *ve = new VarExp(loc, ids->vthis);
ve->type = type;
return ve;
}
return this;
}
@@ -838,7 +971,29 @@ Statement *ExpStatement::inlineScan(InlineScanState *iss)
printf("ExpStatement::inlineScan(%s)\n", toChars());
#endif
if (exp)
{
exp = exp->inlineScan(iss);
/* See if we can inline as a statement rather than as
* an Expression.
*/
if (exp && exp->op == TOKcall)
{
CallExp *ce = (CallExp *)exp;
if (ce->e1->op == TOKvar)
{
VarExp *ve = (VarExp *)ce->e1;
FuncDeclaration *fd = ve->var->isFuncDeclaration();
if (fd && fd != iss->fd && fd->canInline(0, 0, 1))
{
Statement *s;
fd->expandInline(iss, NULL, ce->arguments, &s);
return s;
}
}
}
}
return this;
}
@@ -1169,9 +1324,9 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
VarExp *ve = (VarExp *)e1;
FuncDeclaration *fd = ve->var->isFuncDeclaration();
if (fd && fd != iss->fd && fd->canInline(0))
if (fd && fd != iss->fd && fd->canInline(0, 0, 0))
{
e = fd->doInline(iss, NULL, arguments);
e = fd->expandInline(iss, NULL, arguments, NULL);
}
}
else if (e1->op == TOKdotvar)
@@ -1179,7 +1334,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
DotVarExp *dve = (DotVarExp *)e1;
FuncDeclaration *fd = dve->var->isFuncDeclaration();
if (fd && fd != iss->fd && fd->canInline(1))
if (fd && fd != iss->fd && fd->canInline(1, 0, 0))
{
if (dve->e1->op == TOKcall &&
dve->e1->type->toBasetype()->ty == Tstruct)
@@ -1191,7 +1346,7 @@ Expression *CallExp::inlineScan(InlineScanState *iss)
;
}
else
e = fd->doInline(iss, dve->e1, arguments);
e = fd->expandInline(iss, dve->e1, arguments, NULL);
}
}
@@ -1282,7 +1437,7 @@ void FuncDeclaration::inlineScan()
#endif
memset(&iss, 0, sizeof(iss));
iss.fd = this;
if (fbody)
if (fbody && !naked)
{
inlineNest++;
fbody = fbody->inlineScan(&iss);
@@ -1290,7 +1445,7 @@ void FuncDeclaration::inlineScan()
}
}
int FuncDeclaration::canInline(int hasthis, int hdrscan)
int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
{
InlineCostState ics;
int cost;
@@ -1298,7 +1453,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
#define CANINLINE_LOG 0
#if CANINLINE_LOG
printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toChars());
#endif
if (needThis() && !hasthis)
@@ -1312,7 +1467,8 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
return 0;
}
switch (inlineStatus)
#if 1
switch (statementsToo ? inlineStatusStmt : inlineStatusExp)
{
case ILSyes:
#if CANINLINE_LOG
@@ -1332,6 +1488,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
default:
assert(0);
}
#endif
if (type)
{ assert(type->ty == Tfunction);
@@ -1345,9 +1502,10 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
/* Don't inline a function that returns non-void, but has
* no return expression.
* No statement inlining for non-voids.
*/
if (tf->next && tf->next->ty != Tvoid &&
!(hasReturnExp & 1) &&
(!(hasReturnExp & 1) || statementsToo) &&
!hdrscan)
goto Lno;
}
@@ -1357,6 +1515,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
if (
!fbody ||
ident == Id::ensure || // ensure() has magic properties the inliner loses
!hdrscan &&
(
#if 0
@@ -1368,11 +1527,7 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
isSynchronized() ||
isImportedSymbol() ||
//#if !IN_LLVM
#if DMDV2
closureVars.dim || // no nested references to this frame
#else
nestedFrameRef || // no nested references to this frame
#endif
hasNestedFrameRefs() || // no nested references to this frame
//#endif // !IN_LLVM
(isVirtual() && !isFinal())
))
@@ -1380,26 +1535,20 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
goto Lno;
}
#if !IN_LLVM
#if 0
/* If any parameters are Tsarray's (which are passed by reference)
* or out parameters (also passed by reference), don't do inlining.
*/
#if 0
if (parameters)
{
for (size_t i = 0; i < parameters->dim; i++)
{
VarDeclaration *v = parameters->tdata()[i];
if (
#if DMDV1
v->isOut() || v->isRef() ||
#endif
v->type->toBasetype()->ty == Tsarray)
if (v->type->toBasetype()->ty == Tsarray)
goto Lno;
}
}
#endif
#endif // !IN_LLVM
memset(&ics, 0, sizeof(ics));
ics.hasthis = hasthis;
@@ -1407,18 +1556,47 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
ics.hdrscan = hdrscan;
cost = fbody->inlineCost(&ics);
#if CANINLINE_LOG
printf("cost = %d\n", cost);
printf("cost = %d for %s\n", cost, toChars());
#endif
if (cost >= COST_MAX)
if (tooCostly(cost))
goto Lno;
if (!statementsToo && cost > COST_MAX)
goto Lno;
#if !IN_LLVM
if (!hdrscan) // Don't scan recursively for header content scan
inlineScan();
if (!hdrscan)
{
// Don't modify inlineStatus for header content scan
if (statementsToo)
inlineStatusStmt = ILSyes;
else
inlineStatusExp = ILSyes;
#if !IN_LLVM // TODO: why was it added in the first place?
inlineScan(); // Don't scan recursively for header content scan
#endif
if (!hdrscan) // Don't modify inlineStatus for header content scan
inlineStatus = ILSyes;
if (inlineStatusExp == ILSuninitialized)
{
// Need to redo cost computation, as some statements or expressions have been inlined
memset(&ics, 0, sizeof(ics));
ics.hasthis = hasthis;
ics.fd = this;
ics.hdrscan = hdrscan;
cost = fbody->inlineCost(&ics);
#if CANINLINE_LOG
printf("recomputed cost = %d for %s\n", cost, toChars());
#endif
if (tooCostly(cost))
goto Lno;
if (!statementsToo && cost > COST_MAX)
goto Lno;
if (statementsToo)
inlineStatusStmt = ILSyes;
else
inlineStatusExp = ILSyes;
}
}
#if CANINLINE_LOG
printf("\t2: yes %s\n", toChars());
#endif
@@ -1426,25 +1604,34 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan)
Lno:
if (!hdrscan) // Don't modify inlineStatus for header content scan
inlineStatus = ILSno;
{ if (statementsToo)
inlineStatusStmt = ILSno;
else
inlineStatusExp = ILSno;
}
#if CANINLINE_LOG
printf("\t2: no %s\n", toChars());
#endif
return 0;
}
Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, Expressions *arguments)
Expression *FuncDeclaration::expandInline(InlineScanState *iss, Expression *ethis, Expressions *arguments, Statement **ps)
{
InlineDoState ids;
DeclarationExp *de;
Expression *e = NULL;
Statements *as = NULL;
#if LOG
printf("FuncDeclaration::doInline('%s')\n", toChars());
#if LOG || CANINLINE_LOG
printf("FuncDeclaration::expandInline('%s')\n", toChars());
#endif
memset(&ids, 0, sizeof(ids));
ids.parent = iss->fd;
ids.fd = this;
if (ps)
as = new Statements();
// Set up vthis
if (ethis)
@@ -1501,6 +1688,8 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, E
{
e = new DeclarationExp(0, ids.vthis);
e->type = Type::tvoid;
if (as)
as->push(new ExpStatement(e->loc, e));
}
if (arguments && arguments->dim)
@@ -1540,18 +1729,31 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, E
de = new DeclarationExp(0, vto);
de->type = Type::tvoid;
e = Expression::combine(e, de);
if (as)
as->push(new ExpStatement(0, de));
else
e = Expression::combine(e, de);
}
}
inlineNest++;
Expression *eb = fbody->doInline(&ids);
inlineNest--;
//eb->type->print();
//eb->print();
//eb->dump(0);
e = Expression::combine(e, eb);
if (ps)
{
inlineNest++;
Statement *s = fbody->doInlineStatement(&ids);
as->push(s);
*ps = new ScopeStatement(0, new CompoundStatement(0, as));
inlineNest--;
}
else
{
inlineNest++;
Expression *eb = fbody->doInline(&ids);
e = Expression::combine(e, eb);
inlineNest--;
//eb->type->print();
//eb->print();
//eb->dump(0);
}
/* There's a problem if what the function returns is used subsequently as an
* lvalue, as in a struct return that is then used as a 'this'.
@@ -1563,7 +1765,7 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, E
* See Bugzilla 2127 for an example.
*/
TypeFunction *tf = (TypeFunction*)type;
if (tf->next->ty == Tstruct)
if (!ps && tf->next->ty == Tstruct)
{
/* Generate a new variable to hold the result and initialize it with the
* inlined body of the function:
@@ -1593,6 +1795,9 @@ Expression *FuncDeclaration::doInline(InlineScanState *iss, Expression *ethis, E
//fprintf(stderr, "CallExp::inlineScan: e = "); e->print();
}
// Need to reevaluate whether parent can now be inlined
// in expressions, as we might have inlined statements
iss->fd->inlineStatusExp = ILSuninitialized;
return e;
}
@@ -1612,7 +1817,7 @@ Expression *Expression::inlineCopy(Scope *sc)
memset(&ics, 0, sizeof(ics));
ics.hdrscan = 1; // so DeclarationExp:: will work on 'statics' which are not
int cost = inlineCost(&ics);
int cost = expressionInlineCost(this, &ics);
if (cost >= COST_MAX)
{ error("cannot inline default argument %s", toChars());
return new ErrorExp();
+622 -392
View File
File diff suppressed because it is too large Load Diff
+23 -12
View File
@@ -119,11 +119,11 @@ const char *Token::toChars()
break;
case TOKint64v:
sprintf(buffer,"%jdL",int64value);
sprintf(buffer,"%jdL",(intmax_t)int64value);
break;
case TOKuns64v:
sprintf(buffer,"%juUL",uns64value);
sprintf(buffer,"%juUL",(uintmax_t)uns64value);
break;
#if IN_GCC
@@ -1144,6 +1144,12 @@ void Lexer::scan(Token *t)
else
t->value = TOKequal; // ==
}
#if DMDV2
else if (*p == '>')
{ p++;
t->value = TOKgoesto; // =>
}
#endif
else
t->value = TOKassign; // =
return;
@@ -2069,7 +2075,13 @@ TOK Lexer::number(Token *t)
continue;
}
if (c == '.' && p[1] != '.')
{
#if DMDV2
if (isalpha(p[1]) || p[1] == '_')
goto done;
#endif
goto real;
}
else if (c == 'i' || c == 'f' || c == 'F' ||
c == 'e' || c == 'E')
{
@@ -3013,6 +3025,7 @@ static Keyword keywords[] =
{ "__thread", TOKtls },
{ "__gshared", TOKgshared },
{ "__traits", TOKtraits },
{ "__vector", TOKvector },
{ "__overloadset", TOKoverloadset },
{ "__FILE__", TOKfile },
{ "__LINE__", TOKline },
@@ -3032,25 +3045,22 @@ int Token::isKeyword()
}
void Lexer::initKeywords()
{ StringValue *sv;
unsigned u;
enum TOK v;
{
unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]);
stringtable.init();
stringtable.init(6151);
if (global.params.Dversion == 1)
nkeywords -= 2;
cmtable_init();
for (u = 0; u < nkeywords; u++)
{ const char *s;
for (unsigned u = 0; u < nkeywords; u++)
{
//printf("keyword[%d] = '%s'\n",u, keywords[u].name);
s = keywords[u].name;
v = keywords[u].value;
sv = stringtable.insert(s, strlen(s));
const char *s = keywords[u].name;
enum TOK v = keywords[u].value;
StringValue *sv = stringtable.insert(s, strlen(s));
sv->ptrvalue = (void *) new Identifier(sv->lstring.string,v);
//printf("tochars[%d] = '%s'\n",v, s);
@@ -3147,6 +3157,7 @@ void Lexer::initKeywords()
Token::tochars[TOKat] = "@";
Token::tochars[TOKpow] = "^^";
Token::tochars[TOKpowass] = "^^=";
Token::tochars[TOKgoesto] = "=>";
#endif
// For debugging
+3 -1
View File
@@ -34,7 +34,7 @@ struct Module;
= ! ~ @
^^ ^^=
++ --
. -> : ,
. -> : , =>
? && ||
*/
@@ -168,6 +168,8 @@ enum TOK
TOKat,
TOKpow,
TOKpowass,
TOKgoesto,
TOKvector,
#endif
// LDC specific
+70 -23
View File
@@ -1,10 +1,10 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// http://www.dsource.org/projects/dmd/browser/trunk/src/mars.c
// https://github.com/D-Programming-Language/dmd/blob/master/src/mars.c
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
@@ -96,13 +96,13 @@ Global::Global()
#endif
#endif
copyright = "Copyright (c) 1999-2011 by Digital Mars";
copyright = "Copyright (c) 1999-2012 by Digital Mars";
written = "written by Walter Bright"
#if TARGET_NET
"\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
#endif
;
version = "v2.057";
version = "v2.058";
#if IN_LLVM
ldc_version = "LDC trunk";
llvm_version = "LLVM 3.0";
@@ -162,7 +162,7 @@ bool Loc::equals(const Loc& loc)
}
/**************************************
* Print error message and exit.
* Print error message
*/
void error(Loc loc, const char *format, ...)
@@ -181,6 +181,18 @@ void warning(Loc loc, const char *format, ...)
va_end( ap );
}
/**************************************
* Print supplementary message about the last error
* Used for backtraces, etc
*/
void errorSupplemental(Loc loc, const char *format, ...)
{
va_list ap;
va_start(ap, format);
verrorSupplemental(loc, format, ap);
va_end( ap );
}
void verror(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
@@ -211,6 +223,25 @@ void verror(Loc loc, const char *format, va_list ap)
global.errors++;
}
// Doesn't increase error count, doesn't print "Error:".
void verrorSupplemental(Loc loc, const char *format, va_list ap)
{
if (!global.gag)
{
fprintf(stdmsg, "%s: ", loc.toChars());
#if _MSC_VER
// MS doesn't recognize %zu format
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stdmsg, "%s", tmp.toChars());
#else
vfprintf(stdmsg, format, ap);
#endif
fprintf(stdmsg, "\n");
fflush(stdmsg);
}
}
void vwarning(Loc loc, const char *format, va_list ap)
{
if (global.params.warnings && !global.gag)
@@ -258,7 +289,7 @@ void fatal()
void halt()
{
#ifdef DEBUG
*(char*)0=0;
*(volatile char*)0=0;
#endif
}
@@ -280,7 +311,7 @@ void usage()
sizeof(size_t) == 4 ? "32" : "64",
global.version, global.copyright, global.written);
printf("\
Documentation: http://www.digitalmars.com/d/2.0/index.html\n\
Documentation: http://www.dlang.org/index.html\n\
Usage:\n\
dmd files.d ... { -switch }\n\
\n\
@@ -298,9 +329,6 @@ Usage:\n\
-debuglib=name set symbolic debug library to name\n\
-defaultlib=name set default library to name\n\
-deps=filename write module dependencies to filename\n%s"
#if TARGET_OSX
" -dylib generate dylib\n"
#endif
" -g add symbolic debug info\n\
-gc add symbolic debug info, pretend to be C\n\
-gs always emit stack frame\n\
@@ -313,8 +341,12 @@ Usage:\n\
-inline do function inlining\n\
-Jpath where to look for string imports\n\
-Llinkerflag pass linkerflag to link\n\
-lib generate library rather than object files\n\
-man open web browser on manual page\n\
-lib generate library rather than object files\n"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
" -m32 generate 32 bit code\n\
-m64 generate 64 bit code\n"
#endif
" -man open web browser on manual page\n\
-map generate linker .map file\n\
-noboundscheck turns off array bounds checking for all functions\n\
-nofloat do not emit reference to floating point\n\
@@ -327,8 +359,11 @@ Usage:\n\
-property enforce property syntax\n\
-quiet suppress unnecessary messages\n\
-release compile release version\n\
-run srcfile args... run resulting program, passing args\n\
-unittest compile in unit tests\n\
-run srcfile args... run resulting program, passing args\n"
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
" -shared generate shared library\n"
#endif
" -unittest compile in unit tests\n\
-v verbose\n\
-version=level compile in version code >= level\n\
-version=ident compile in version code identified by ident\n\
@@ -495,12 +530,15 @@ int main(int argc, char *argv[])
else if (strcmp(p + 1, "cov") == 0)
global.params.cov = 1;
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
else if (strcmp(p + 1, "shared") == 0
#if TARGET_OSX
// backwards compatibility with old switch
|| strcmp(p + 1, "dylib") == 0
#endif
)
global.params.dll = 1;
else if (strcmp(p + 1, "fPIC") == 0)
global.params.pic = 1;
#endif
#if TARGET_OSX
else if (strcmp(p + 1, "dylib") == 0)
global.params.dll = 1;
#endif
else if (strcmp(p + 1, "map") == 0)
global.params.map = 1;
@@ -764,35 +802,35 @@ int main(int argc, char *argv[])
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
#else
browse("http://www.digitalmars.com/d/2.0/dmd-windows.html");
browse("http://www.dlang.org/dmd-windows.html");
#endif
#endif
#if linux
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
#else
browse("http://www.digitalmars.com/d/2.0/dmd-linux.html");
browse("http://www.dlang.org/dmd-linux.html");
#endif
#endif
#if __APPLE__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
#else
browse("http://www.digitalmars.com/d/2.0/dmd-osx.html");
browse("http://www.dlang.org/dmd-osx.html");
#endif
#endif
#if __FreeBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
#else
browse("http://www.digitalmars.com/d/2.0/dmd-freebsd.html");
browse("http://www.dlang.org/dmd-freebsd.html");
#endif
#endif
#if __OpenBSD__
#if DMDV1
browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html");
#else
browse("http://www.digitalmars.com/d/2.0/dmd-openbsd.html");
browse("http://www.dlang.org/dmd-openbsd.html");
#endif
#endif
exit(EXIT_SUCCESS);
@@ -852,6 +890,11 @@ int main(int argc, char *argv[])
global.params.pic = 1;
#endif
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
if (global.params.lib && global.params.dll)
error("cannot mix -lib and -shared\n");
#endif
if (global.params.release)
{ global.params.useInvariants = 0;
global.params.useIn = 0;
@@ -928,6 +971,7 @@ int main(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86_64");
VersionCondition::addPredefinedGlobalIdent("X86_64");
VersionCondition::addPredefinedGlobalIdent("D_LP64");
VersionCondition::addPredefinedGlobalIdent("D_SIMD");
#if TARGET_WINDOS
VersionCondition::addPredefinedGlobalIdent("Win64");
#endif
@@ -937,6 +981,9 @@ int main(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
VersionCondition::addPredefinedGlobalIdent("X86");
#if TARGET_OSX
VersionCondition::addPredefinedGlobalIdent("D_SIMD");
#endif
#if TARGET_WINDOS
VersionCondition::addPredefinedGlobalIdent("Win32");
#endif
+2
View File
@@ -466,8 +466,10 @@ typedef uint64_t StorageClass;
void warning(Loc loc, const char *format, ...) IS_PRINTF(2);
void error(Loc loc, const char *format, ...) IS_PRINTF(2);
void errorSupplemental(Loc loc, const char *format, ...);
void verror(Loc loc, const char *format, va_list);
void vwarning(Loc loc, const char *format, va_list);
void verrorSupplemental(Loc loc, const char *format, va_list);
void fatal();
void err_nomem();
#if IN_LLVM
-273
View File
@@ -1,273 +0,0 @@
/* Copyright (c) 2000 Digital Mars */
/* All Rights Reserved */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "rmem.h"
#if USE_BOEHM_GC
// I needed to perfix the dir after upgrading to gc 7.0
#include "gc/gc.h"
#endif
/* This implementation of the storage allocator uses the standard C allocation package.
*/
Mem mem;
#if USE_BOEHM_GC
static bool gc_was_init = false;
void Mem::init()
{
GC_init();
gc_was_init = true;
}
char *Mem::strdup(const char *s)
{
char *p;
if (s)
{
p = GC_strdup(s);
if (p)
return p;
error();
}
return NULL;
}
void *Mem::malloc(size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = GC_malloc(size);
if (!p)
error();
}
return p;
}
void *Mem::calloc(size_t size, size_t n)
{ void *p;
if (!size || !n)
p = NULL;
else
{
p = GC_malloc(size * n);
if (!p)
error();
memset(p, 0, size * n);
}
return p;
}
void *Mem::realloc(void *p, size_t size)
{
if (!size)
{ if (p)
{ GC_free(p);
p = NULL;
}
}
else if (!p)
{
p = GC_malloc(size);
if (!p)
error();
}
else
{
p = GC_realloc(p, size);
if (!p)
error();
}
return p;
}
void Mem::free(void *p)
{
if (p)
GC_free(p);
}
void *Mem::mallocdup(void *o, size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = GC_malloc(size);
if (!p)
error();
else
memcpy(p,o,size);
}
return p;
}
void Mem::error()
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
GC_gcollect();
}
void Mem::mark(void *pointer)
{
(void) pointer; // necessary for VC /W4
}
void Mem::setStackBottom(void */*bottom*/)
{
}
/* =================================================== */
void * operator new(size_t m_size)
{
// without this we segfault with gc 7.0
if (!gc_was_init) {
mem.init();
}
void *p = GC_malloc(m_size);
if (p)
return p;
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
return p;
}
void operator delete(void *p)
{
GC_free(p);
}
#elif !USE_BOEHM_GC
void Mem::init()
{
}
char *Mem::strdup(const char *s)
{
char *p;
if (s)
{
p = ::strdup(s);
if (p)
return p;
error();
}
return NULL;
}
void *Mem::malloc(size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
}
return p;
}
void *Mem::calloc(size_t size, size_t n)
{ void *p;
if (!size || !n)
p = NULL;
else
{
p = ::malloc(size * n);
if (!p)
error();
memset(p, 0, size * n);
}
return p;
}
void *Mem::realloc(void *p, size_t size)
{
if (!size)
{ if (p)
{ ::free(p);
p = NULL;
}
}
else if (!p)
{
p = ::malloc(size);
if (!p)
error();
}
else
{
p = ::realloc(p, size);
if (!p)
error();
}
return p;
}
void Mem::free(void *p)
{
if (p)
::free(p);
}
void *Mem::mallocdup(void *o, size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
else
memcpy(p,o,size);
}
return p;
}
void Mem::error()
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
}
void Mem::mark(void *pointer)
{
}
void Mem::setStackBottom(void */*stackbottom*/)
{
}
#endif // USE_BOEHM_GC
-51
View File
@@ -1,51 +0,0 @@
// Copyright (C) 2000-2001 by Chromium Communications
// All Rights Reserved
#ifndef ROOT_MEM_H
#define ROOT_MEM_H
#include <stddef.h> // for size_t
typedef void (*FINALIZERPROC)(void* pObj, void* pClientData);
struct GC; // thread specific allocator
struct Mem
{
GC *gc; // pointer to our thread specific allocator
Mem() { gc = NULL; }
void init();
// Derive from Mem to get these storage allocators instead of global new/delete
void * operator new(size_t m_size);
void * operator new(size_t m_size, Mem *mem);
void * operator new(size_t m_size, GC *gc);
void operator delete(void *p);
void * operator new[](size_t m_size);
void operator delete[](void *p);
char *strdup(const char *s);
void *malloc(size_t size);
void *malloc_uncollectable(size_t size);
void *calloc(size_t size, size_t n);
void *realloc(void *p, size_t size);
void free(void *p);
void free_uncollectable(void *p);
void *mallocdup(void *o, size_t size);
void error();
void check(void *p); // validate pointer
void fullcollect(); // do full garbage collection
void fullcollectNoStack(); // do full garbage collection, no scan stack
void mark(void *pointer);
void addroots(char* pStart, char* pEnd);
void removeroots(char* pStart);
void setFinalizer(void* pObj, FINALIZERPROC pFn, void* pClientData);
void setStackBottom(void *bottom);
GC *getThreadGC(); // get apartment allocator for this thread
};
extern Mem mem;
#endif /* ROOT_MEM_H */
+13 -7
View File
@@ -851,6 +851,12 @@ void Module::importAll(Scope *prevsc)
if (scope)
return; // already done
if (isDocFile)
{
error("is a Ddoc file, cannot import it");
return;
}
/* Note that modules get their own scope, from scratch.
* This is so regardless of where in the syntax a module
* gets imported, it is unaffected by context.
@@ -858,14 +864,14 @@ void Module::importAll(Scope *prevsc)
*/
Scope *sc = Scope::createGlobal(this); // create root scope
// Add import of "object" if this module isn't "object"
if (ident != Id::object)
// Add import of "object", even for the "object" module.
// If it isn't there, some compiler rewrites, like
// classinst == classinst -> .object.opEquals(classinst, classinst)
// would fail inside object.d.
if (members->dim == 0 || ((*members)[0])->ident != Id::object)
{
if (members->dim == 0 || ((*members)[0])->ident != Id::object)
{
Import *im = new Import(0, NULL, Id::object, NULL, 0);
members->shift(im);
}
Import *im = new Import(0, NULL, Id::object, NULL, 0);
members->shift(im);
}
if (!symtab)
+488 -126
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -107,6 +107,7 @@ enum ENUMTY
Treturn,
Tnull,
Tvector,
TMAX
};
typedef unsigned char TY; // ENUMTY
@@ -203,6 +204,7 @@ struct Type : Object
static ClassDeclaration *typeinfoarray;
static ClassDeclaration *typeinfostaticarray;
static ClassDeclaration *typeinfoassociativearray;
static ClassDeclaration *typeinfovector;
static ClassDeclaration *typeinfoenum;
static ClassDeclaration *typeinfofunction;
static ClassDeclaration *typeinfodelegate;
@@ -432,6 +434,36 @@ struct TypeBasic : Type
TypeBasic *isTypeBasic();
};
struct TypeVector : Type
{
Type *basetype;
TypeVector(Loc loc, Type *basetype);
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize();
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars();
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf, int flag);
#if CPP_MANGLE
void toCppMangle(OutBuffer *buf, CppMangleState *cms);
#endif
int isintegral();
int isfloating();
int isscalar();
int isunsigned();
int checkBoolean();
MATCH implicitConvTo(Type *to);
Expression *defaultInit(Loc loc);
TypeBasic *elementType();
int isZeroInit(Loc loc);
TypeInfoDeclaration *getTypeInfoDeclaration();
TypeTuple *toArgTypes();
};
struct TypeArray : TypeNext
{
TypeArray(TY ty, Type *next);
@@ -1029,6 +1061,7 @@ 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 MODmethodConv(unsigned char modfrom, unsigned char modto);
int MODmerge(unsigned char mod1, unsigned char mod2);
#endif /* DMD_MTYPE_H */
-61
View File
@@ -1,61 +0,0 @@
#ifndef OBJFILE_H
#define OBJFILE_H
#include "root.h"
typedef void *SymHandle;
typedef unsigned SegOffset;
enum ObjFormat
{
NTCOFF,
ELF
};
struct ObjFile : File
{
ObjFile(FileName *);
~ObjFile();
ObjFile *init(ObjFormat);
void comment(const char *); // insert comment into object file
void modulename(const char *); // set module name
void library(const char *); // add default library
void startaddress(SegHandle seg, SegOffset offset); // set start address
// Segments
enum SegHandle
{ code = 1,
data, bss
};
SymHandle defineSym(const char *name, SegHandle seg, SegOffset offset);
SymHandle externSym(const char *name);
SegOffset write(SegHandle seg, const void *data, unsigned nbytes);
SegOffset writestring(SegHandle seg, char *string);
SegOffset write8(SegHandle seg, unsigned b);
SegOffset write16(SegHandle seg, unsigned w);
SegOffset write32(SegHandle seg, unsigned long v);
SegOffset write64(SegHandle seg, unsigned long long v);
SegOffset fill0(SegHandle seg, unsigned nbytes);
SegOffset align(SegHandle seg, unsigned size);
SegOffset writefixup(SegHandle seg, SymHandle sym, unsigned value, int selfrelative);
// Non-binding hint as to how big seg will grow
void reserve(SegHandle seg, SegOffset size);
// Set actual size
void setSize(SegHandle seg, SegOffset size);
// Get/set offset for subsequent writes
void setOffset(SegHandle seg, SegOffset offset);
SegOffset getOffset(SegHandle seg);
SegHandle createSeg(const char *name);
};
#endif
+225 -97
View File
@@ -28,6 +28,7 @@
#include "mtype.h"
#include "init.h"
#include "expression.h"
#include "statement.h"
#include "scope.h"
#include "id.h"
#include "declaration.h"
@@ -35,9 +36,9 @@
#include "template.h"
#include "scope.h"
static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Parameters *arguments);
static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments);
static void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments);
static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments);
static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flags = 0);
static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *arguments);
/******************************** Expression **************************/
@@ -385,6 +386,7 @@ Expression *ArrayExp::op_overload(Scope *sc)
currentDimension = i; // Dimension for $, if required
x = x->semantic(sc);
x = resolveProperties(sc, x);
if (!x->type)
error("%s has no value", x->toChars());
if (lengthVar)
@@ -922,21 +924,26 @@ Expression *EqualExp::op_overload(Scope *sc)
Type *t1 = e1->type->toBasetype();
Type *t2 = e2->type->toBasetype();
if (t1->ty == Tclass && t2->ty == Tclass)
{
/* Rewrite as:
* .object.opEquals(cast(Object)e1, cast(Object)e2)
* The explicit cast is necessary for interfaces,
* see http://d.puremagic.com/issues/show_bug.cgi?id=4088
*/
Expression *e1x = e1; //new CastExp(loc, e1, ClassDeclaration::object->getType());
Expression *e2x = e2; //new CastExp(loc, e2, ClassDeclaration::object->getType());
{ ClassDeclaration *cd1 = t1->isClassHandle();
ClassDeclaration *cd2 = t2->isClassHandle();
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Id::eq);
e = new CallExp(loc, e, e1x, e2x);
e = e->semantic(sc);
return e;
if (!(cd1->isCPPinterface() || cd2->isCPPinterface()))
{
/* Rewrite as:
* .object.opEquals(cast(Object)e1, cast(Object)e2)
* The explicit cast is necessary for interfaces,
* see http://d.puremagic.com/issues/show_bug.cgi?id=4088
*/
Expression *e1x = new CastExp(loc, e1, ClassDeclaration::object->getType());
Expression *e2x = new CastExp(loc, e2, ClassDeclaration::object->getType());
Expression *e = new IdentifierExp(loc, Id::empty);
e = new DotIdExp(loc, e, Id::object);
e = new DotIdExp(loc, e, Id::eq);
e = new CallExp(loc, e, e1x, e2x);
e = e->semantic(sc);
return e;
}
}
return compare_overload(sc, Id::eq);
@@ -1212,34 +1219,161 @@ Dsymbol *search_function(ScopeDsymbol *ad, Identifier *funcid)
}
int ForeachStatement::inferAggregate(Scope *sc, Dsymbol *&sapply)
{
Identifier *idapply = (op == TOKforeach) ? Id::apply : Id::applyReverse;
#if DMDV2
Identifier *idhead = (op == TOKforeach) ? Id::Ffront : Id::Fback;
int sliced = 0;
#endif
Type *tab;
AggregateDeclaration *ad;
while (1)
{
aggr = aggr->semantic(sc);
aggr = resolveProperties(sc, aggr);
aggr = aggr->optimize(WANTvalue);
if (!aggr->type)
goto Lerr;
tab = aggr->type->toBasetype();
switch (tab->ty)
{
case Tarray:
case Tsarray:
case Ttuple:
case Taarray:
break;
case Tclass:
ad = ((TypeClass *)tab)->sym;
goto Laggr;
case Tstruct:
ad = ((TypeStruct *)tab)->sym;
goto Laggr;
Laggr:
#if DMDV2
if (!sliced)
{
sapply = search_function(ad, idapply);
if (sapply)
{ // opApply aggregate
break;
}
Dsymbol *s = search_function(ad, Id::slice);
if (s)
{ Expression *rinit = new SliceExp(aggr->loc, aggr, NULL, NULL);
rinit = rinit->trySemantic(sc);
if (rinit) // if application of [] succeeded
{ aggr = rinit;
sliced = 1;
continue;
}
}
}
if (Dsymbol *shead = search_function(ad, idhead))
{ // range aggregate
break;
}
if (ad->aliasthis)
{
aggr = new DotIdExp(aggr->loc, aggr, ad->aliasthis->ident);
continue;
}
#else
sapply = search_function(ad, idapply);
if (sapply)
{ // opApply aggregate
break;
}
#endif
goto Lerr;
case Tdelegate:
if (aggr->op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)aggr;
sapply = de->func->isFuncDeclaration();
}
break;
case Terror:
break;
default:
goto Lerr;
}
break;
}
return 1;
Lerr:
return 0;
}
/*****************************************
* Given array of arguments and an aggregate type,
* if any of the argument types are missing, attempt to infer
* them from the aggregate type.
*/
void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Module* from)
int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply)
{
if (!arguments || !arguments->dim)
return;
return 0;
if (sapply) // prefer opApply
{
for (size_t u = 0; u < arguments->dim; u++)
{ Parameter *arg = arguments->tdata()[u];
if (arg->type)
arg->type = arg->type->semantic(loc, sc);
}
Expression *ethis;
Type *tab = aggr->type->toBasetype();
if (tab->ty == Tclass || tab->ty == Tstruct)
ethis = aggr;
else
{ assert(tab->ty == Tdelegate && aggr->op == TOKdelegate);
ethis = ((DelegateExp *)aggr)->e1;
}
/* Look for like an
* int opApply(int delegate(ref Type [, ...]) dg);
* overload
*/
FuncDeclaration *fd = sapply->isFuncDeclaration();
if (fd)
{ sapply = inferApplyArgTypesX(ethis, fd, arguments);
}
#if 0
TemplateDeclaration *td = sapply->isTemplateDeclaration();
if (td)
{ inferApplyArgTypesZ(td, arguments);
}
#endif
return sapply ? 1 : 0;
}
/* Return if no arguments need types.
*/
for (size_t u = 0; 1; u++)
{ if (u == arguments->dim)
return;
Parameter *arg = arguments->tdata()[u];
for (size_t u = 0; u < arguments->dim; u++)
{ Parameter *arg = arguments->tdata()[u];
if (!arg->type)
break;
}
Dsymbol *s;
AggregateDeclaration *ad;
Parameter *arg = arguments->tdata()[0];
Type *taggr = aggr->type;
if (!taggr)
return;
assert(taggr);
Type *tab = taggr->toBasetype();
switch (tab->ty)
{
@@ -1279,25 +1413,19 @@ void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Mo
goto Laggr;
Laggr:
s = search_function(ad,
(op == TOKforeach_reverse) ? Id::applyReverse
: Id::apply);
if (s)
goto Lapply; // prefer opApply
if (arguments->dim == 1)
{
if (!arg->type)
{
/* Look for a head() or rear() overload
*/
Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe;
Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback;
Dsymbol *s = search_function(ad, id);
FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
if (!fd)
{ if (s && s->isTemplateDeclaration())
break;
goto Lapply;
break;
}
// Resolve inout qualifier of front type
arg->type = fd->type->nextOf();
@@ -1306,80 +1434,86 @@ void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Mo
}
break;
}
Lapply:
{ /* Look for an
* int opApply(int delegate(ref Type [, ...]) dg);
* overload
*/
if (s)
{
FuncDeclaration *fd = s->isFuncDeclaration();
if (fd)
{ inferApplyArgTypesX(from, fd, arguments);
break;
}
#if 0
TemplateDeclaration *td = s->isTemplateDeclaration();
if (td)
{ inferApplyArgTypesZ(td, arguments);
break;
}
#endif
}
break;
}
case Tdelegate:
{
if (0 && aggr->op == TOKdelegate)
{ DelegateExp *de = (DelegateExp *)aggr;
FuncDeclaration *fd = de->func->isFuncDeclaration();
if (fd)
inferApplyArgTypesX(from, fd, arguments);
}
else
{
inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments);
}
if (!inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments))
return 0;
break;
}
default:
break; // ignore error, caught later
}
return 1;
}
/********************************
* Recursive helper function,
* analogous to func.overloadResolveX().
*/
int fp3(void *param, FuncDeclaration *f)
static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments)
{
Parameters *arguments = (Parameters *)param;
TypeFunction *tf = (TypeFunction *)f->type;
if (inferApplyArgTypesY(tf, arguments) == 1)
return 0;
if (arguments->dim == 0)
return 1;
return 0;
}
struct Param3
{
Parameters *arguments;
int mod;
MATCH match;
FuncDeclaration *fd_best;
FuncDeclaration *fd_ambig;
static void inferApplyArgTypesX(Module* from, FuncDeclaration *fstart, Parameters *arguments)
{
overloadApply(fstart, &fp3, arguments);
static int fp(void *param, FuncDeclaration *f)
{
Param3 *p = (Param3 *)param;
TypeFunction *tf = (TypeFunction *)f->type;
MATCH m = MATCHexact;
if (f->isThis())
{ if (!MODimplicitConv(p->mod, tf->mod))
m = MATCHnomatch;
else if (p->mod != tf->mod)
m = MATCHconst;
}
if (!inferApplyArgTypesY(tf, p->arguments, 1))
m = MATCHnomatch;
if (m > p->match)
{ p->fd_best = f;
p->fd_ambig = NULL;
p->match = m;
}
else if (m == p->match)
p->fd_ambig = f;
return 0;
}
};
Param3 p;
p.arguments = arguments;
p.mod = ethis->type->mod;
p.match = MATCHnomatch;
p.fd_best = NULL;
p.fd_ambig = NULL;
overloadApply(fstart, &Param3::fp, &p);
if (p.fd_best)
{
inferApplyArgTypesY((TypeFunction *)p.fd_best->type, arguments);
if (p.fd_ambig)
{ ::error(ethis->loc, "%s.%s matches more than one declaration:\n\t%s(%d):%s\nand:\n\t%s(%d):%s",
ethis->toChars(), fstart->ident->toChars(),
p.fd_best ->loc.filename, p.fd_best ->loc.linnum, p.fd_best ->type->toChars(),
p.fd_ambig->loc.filename, p.fd_ambig->loc.linnum, p.fd_ambig->type->toChars());
p.fd_best = NULL;
}
}
return p.fd_best;
}
/******************************
* Infer arguments from type of function.
* Returns:
* 0 match for this function
* 1 no match for this function
* 1 match for this function
* 0 no match for this function
*/
static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments)
static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments, int flags)
{ size_t nparams;
Parameter *p;
@@ -1406,22 +1540,16 @@ static int inferApplyArgTypesY(TypeFunction *tf, Parameters *arguments)
Parameter *param = Parameter::getNth(tf->parameters, u);
if (arg->type)
{ if (!arg->type->equals(param->type))
{
/* Cannot resolve argument types. Indicate an
* error by setting the number of arguments to 0.
*/
arguments->dim = 0;
goto Lmatch;
}
continue;
goto Lnomatch;
}
arg->type = param->type;
else if (!flags)
arg->type = param->type;
}
Lmatch:
return 0;
return 1;
Lnomatch:
return 1;
return 0;
}
/*******************************************
+24 -14
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -262,6 +262,7 @@ Expression *TypeExp::optimize(int result)
Expression *UnaExp::optimize(int result)
{
//printf("UnaExp::optimize() %s\n", toChars());
e1 = e1->optimize(result);
return this;
}
@@ -670,7 +671,6 @@ Expression *CastExp::optimize(int result)
// We can convert 'head const' to mutable
if (to->constOf()->equals(e1->type->constOf()))
// if (to->constConv(e1->type) >= MATCHconst)
{
e1->type = type;
if (X) printf(" returning5 %s\n", e1->toChars());
@@ -715,8 +715,8 @@ Expression *BinExp::optimize(int result)
{
dinteger_t i2 = e2->toInteger();
d_uns64 sz = e1->type->size() * 8;
if (i2 < 0 || i2 > sz)
{ error("shift assign by %jd is outside the range 0..%zu", i2, sz);
if (i2 < 0 || i2 >= sz)
{ error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1);
e2 = new IntegerExp(0);
}
}
@@ -810,8 +810,8 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
{
dinteger_t i2 = e->e2->toInteger();
d_uns64 sz = e->e1->type->size() * 8;
if (i2 < 0 || i2 > sz)
{ e->error("shift by %jd is outside the range 0..%zu", i2, sz);
if (i2 < 0 || i2 >= sz)
{ e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1);
e->e2 = new IntegerExp(0);
}
if (e->e1->isConst() == 1)
@@ -955,13 +955,10 @@ Expression *CommaExp::optimize(int result)
e = interpret(NULL);
return (e == EXP_CANT_INTERPRET) ? this : e;
}
// Don't constant fold if it is a compiler-generated temporary.
if (e1->op == TOKdeclaration)
return this;
e1 = e1->optimize(result & WANTinterpret);
e2 = e2->optimize(result);
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->hasSideEffect())
{
e = e2;
if (e)
@@ -1106,8 +1103,12 @@ Expression *AndAndExp::optimize(int result)
e = this;
if (e1->isBool(FALSE))
{
e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
e->type = type;
if (type->toBasetype()->ty == Tvoid)
e = e2;
else
{ e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
e->type = type;
}
e = e->optimize(result);
}
else
@@ -1124,7 +1125,11 @@ Expression *AndAndExp::optimize(int result)
e = new IntegerExp(loc, n1 && n2, type);
}
else if (e1->isBool(TRUE))
e = new BoolExp(loc, e2, type);
{
if (type->toBasetype()->ty == Tvoid)
e = e2;
else e = new BoolExp(loc, e2, type);
}
}
}
return e;
@@ -1155,7 +1160,12 @@ Expression *OrOrExp::optimize(int result)
e = new IntegerExp(loc, n1 || n2, type);
}
else if (e1->isBool(FALSE))
e = new BoolExp(loc, e2, type);
{
if (type->toBasetype()->ty == Tvoid)
e = e2;
else
e = new BoolExp(loc, e2, type);
}
}
}
return e;
+198 -99
View File
@@ -231,6 +231,7 @@ Dsymbols *Parser::parseDeclDefs(int once)
case TOKsuper:
case TOKtypeof:
case TOKdot:
case TOKvector:
Ldeclaration:
a = parseDeclarations(STCundefined, NULL);
decldefs->append(a);
@@ -820,6 +821,23 @@ TypeQualified *Parser::parseTypeof()
}
#endif
/***********************************
* Parse __vector(type).
* Current token is on the '__vector'.
*/
#if DMDV2
Type *Parser::parseVector()
{
Loc loc = this->loc;
nextToken();
check(TOKlparen);
Type *tb = parseType();
check(TOKrparen);
return new TypeVector(loc, tb);
}
#endif
/***********************************
* Parse extern (linkage)
* The parser is on the 'extern' token.
@@ -1247,7 +1265,7 @@ DeleteDeclaration *Parser::parseDelete()
* Parse parameter list.
*/
Parameters *Parser::parseParameters(int *pvarargs)
Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl)
{
Parameters *arguments = new Parameters();
int varargs = 0;
@@ -1351,17 +1369,32 @@ Parameters *Parser::parseParameters(int *pvarargs)
default:
Ldefault:
stc = storageClass & (STCin | STCout | STCref | STClazy);
{ stc = storageClass & (STCin | STCout | STCref | STClazy);
if (stc & (stc - 1)) // if stc is not a power of 2
error("incompatible parameter storage classes");
if ((storageClass & (STCconst | STCout)) == (STCconst | STCout))
error("out cannot be const");
if ((storageClass & (STCimmutable | STCout)) == (STCimmutable | STCout))
error("out cannot be immutable");
if ((storageClass & STCscope) &&
(storageClass & (STCref | STCout)))
if ((storageClass & STCscope) && (storageClass & (STCref | STCout)))
error("scope cannot be ref or out");
at = parseType(&ai);
Token *t;
if (tpl && !stc && token.value == TOKidentifier &&
(t = peek(&token), (t->value == TOKcomma || t->value == TOKrparen)))
{ Identifier *id = Lexer::uniqueId("__T");
at = new TypeIdentifier(loc, id);
if (!*tpl)
*tpl = new TemplateParameters();
TemplateParameter *tp = new TemplateTypeParameter(loc, id, NULL, NULL);
(*tpl)->push(tp);
ai = token.ident;
nextToken();
}
else
at = parseType(&ai);
ae = NULL;
if (token.value == TOKassign) // = defaultArg
{ nextToken();
@@ -1394,6 +1427,7 @@ Parameters *Parser::parseParameters(int *pvarargs)
goto L1;
}
break;
}
}
break;
}
@@ -1494,6 +1528,11 @@ EnumDeclaration *Parser::parseEnum()
}
addComment(em, comment);
comment = token.blockComment;
if (token.value == TOKeof)
{ error("premature end of file");
break;
}
}
nextToken();
}
@@ -1627,26 +1666,33 @@ BaseClasses *Parser::parseBaseClasses()
for (; 1; nextToken())
{
bool prot = false;
enum PROT protection = PROTpublic;
switch (token.value)
{
case TOKprivate:
prot = true;
protection = PROTprivate;
nextToken();
break;
case TOKpackage:
prot = true;
protection = PROTpackage;
nextToken();
break;
case TOKprotected:
prot = true;
protection = PROTprotected;
nextToken();
break;
case TOKpublic:
prot = true;
protection = PROTpublic;
nextToken();
break;
}
if (prot && !global.params.useDeprecated)
error("use of base class protection is deprecated");
if (token.value == TOKidentifier)
{
BaseClass *b = new BaseClass(parseBasicType(), protection);
@@ -1920,6 +1966,11 @@ Dsymbol *Parser::parseMixin()
tqual = parseTypeof();
check(TOKdot);
}
else if (token.value == TOKvector)
{
tqual = parseVector();
check(TOKdot);
}
if (token.value != TOKidentifier)
{
error("identifier expected, not %s", token.toChars());
@@ -2018,56 +2069,11 @@ Objects *Parser::parseTemplateArgumentList2()
{ // Template argument is an expression
Expression *ea = parseAssignExp();
if (ea->op == TOKfunction)
{ FuncLiteralDeclaration *fd = ((FuncExp *)ea)->fd;
if (fd->type->ty == Tfunction)
{
TypeFunction *tf = (TypeFunction *)fd->type;
/* If there are parameters that consist of only an identifier,
* rather than assuming the identifier is a type, as we would
* for regular function declarations, assume the identifier
* is the parameter name, and we're building a template with
* a deduced type.
*/
TemplateParameters *tpl = NULL;
for (size_t i = 0; i < tf->parameters->dim; i++)
{ Parameter *param = tf->parameters->tdata()[i];
if (param->ident == NULL &&
param->type &&
param->type->ty == Tident &&
((TypeIdentifier *)param->type)->idents.dim == 0
)
{
/* Switch parameter type to parameter identifier,
* parameterize with template type parameter _T
*/
TypeIdentifier *pt = (TypeIdentifier *)param->type;
param->ident = pt->ident;
Identifier *id = Lexer::uniqueId("__T");
param->type = new TypeIdentifier(pt->loc, id);
TemplateParameter *tp = new TemplateTypeParameter(fd->loc, id, NULL, NULL);
if (!tpl)
tpl = new TemplateParameters();
tpl->push(tp);
}
}
if (tpl)
{ // Wrap a template around function fd
Dsymbols *decldefs = new Dsymbols();
decldefs->push(fd);
TemplateDeclaration *tempdecl =
new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, 0);
tempdecl->literal = 1; // it's a template 'literal'
tiargs->push(tempdecl);
goto L1;
}
}
}
tiargs->push(ea);
if (ea->op == TOKfunction && ((FuncExp *)ea)->td)
tiargs->push(((FuncExp *)ea)->td);
else
tiargs->push(ea);
}
L1:
if (token.value != TOKcomma)
break;
nextToken();
@@ -2094,6 +2100,10 @@ Objects *Parser::parseTemplateArgument()
ta = new TypeIdentifier(loc, token.ident);
goto LabelX;
case TOKvector:
ta = parseVector();
goto LabelX;
case BASIC_TYPES_X(ta):
tiargs->push(ta);
nextToken();
@@ -2369,6 +2379,10 @@ Type *Parser::parseBasicType()
tid = parseTypeof();
goto Lident2;
case TOKvector:
t = parseVector();
break;
case TOKconst:
// const(type)
nextToken();
@@ -2875,6 +2889,13 @@ L2:
{ Declaration *v;
Initializer *init = NULL;
/* Aliases can no longer have multiple declarators, storage classes,
* linkages, or auto declarations.
* These never made any sense, anyway.
* The code below needs to be fixed to reject them.
* The grammar has already been fixed to preclude them.
*/
if (token.value == TOKassign)
{
nextToken();
@@ -3434,13 +3455,14 @@ Statement *Parser::parseStatement(int flags)
Identifier *ident = token.ident;
nextToken();
nextToken();
s = parseStatement(PSsemi);
s = parseStatement(PSsemi_ok);
s = new LabelStatement(loc, ident, s);
break;
}
// fallthrough to TOKdot
case TOKdot:
case TOKtypeof:
case TOKvector:
if (isDeclaration(&token, 2, TOKreserved, NULL))
goto Ldeclaration;
else
@@ -3559,7 +3581,6 @@ Statement *Parser::parseStatement(int flags)
case TOKgshared:
case TOKat:
#endif
// case TOKtypeof:
Ldeclaration:
{ Dsymbols *a;
@@ -3680,8 +3701,15 @@ Statement *Parser::parseStatement(int flags)
}
case TOKsemicolon:
if (!(flags & PSsemi))
error("use '{ }' for an empty statement, not a ';'");
if (!(flags & PSsemi_ok))
{
if (flags & PSsemi)
{ if (global.params.warnings)
warning(loc, "use '{ }' for an empty statement, not a ';'");
}
else
error("use '{ }' for an empty statement, not a ';'");
}
nextToken();
s = new ExpStatement(loc, (Expression *)NULL);
break;
@@ -3865,13 +3893,13 @@ Statement *Parser::parseStatement(int flags)
else if (token.value == TOKidentifier)
{
Token *t = peek(&token);
if (t->value == TOKcomma || t->value == TOKsemicolon)
if (t->value == TOKsemicolon)
{
arg = new Parameter(0, NULL, token.ident, NULL);
nextToken();
nextToken();
if (1 || !global.params.useDeprecated)
error("if (v; e) is deprecated, use if (auto v = e)");
if (!global.params.useDeprecated)
error("if (v%s e) is deprecated, use if (auto v = e)", t->toChars());
}
}
@@ -4255,7 +4283,7 @@ Statement *Parser::parseStatement(int flags)
s = parseStatement(PSsemi | PScurlyscope);
#if DMDV2
if (!global.params.useDeprecated)
error("volatile statements deprecated; used synchronized statements instead");
error("volatile statements deprecated; use synchronized statements instead");
#endif
s = new VolatileStatement(loc, s);
break;
@@ -4531,6 +4559,7 @@ int Parser::isBasicType(Token **pt)
goto Ldot;
case TOKtypeof:
case TOKvector:
/* typeof(exp).identifier...
*/
t = peek(t);
@@ -4721,9 +4750,12 @@ int Parser::isDeclarator(Token **pt, int *haveId, enum TOK endtok)
case TOKrbracket:
case TOKassign:
case TOKcomma:
case TOKdotdotdot:
case TOKsemicolon:
case TOKlcurly:
case TOKin:
case TOKout:
case TOKbody:
// The !parens is to disallow unnecessary parentheses
if (!parens && (endtok == TOKreserved || endtok == t->value))
{ *pt = t;
@@ -5092,6 +5124,9 @@ Expression *Parser::parsePrimaryExp()
switch (token.value)
{
case TOKidentifier:
if (peekNext() == TOKgoesto)
goto case_delegate;
id = token.ident;
nextToken();
if (token.value == TOKnot && (save = peekNext()) != TOKis && save != TOKin)
@@ -5284,6 +5319,13 @@ Expression *Parser::parsePrimaryExp()
break;
}
case TOKvector:
{
t = parseVector();
e = new TypeExp(loc, t);
break;
}
case TOKtypeid:
{
nextToken();
@@ -5433,9 +5475,14 @@ Expression *Parser::parsePrimaryExp()
}
case TOKlparen:
if (peekPastParen(&token)->value == TOKlcurly)
{ enum TOK past = peekPastParen(&token)->value;
if (past == TOKgoesto)
{ // (arguments) => expression
goto case_delegate;
}
else if (past == TOKlcurly)
{ // (arguments) { statements... }
save = TOKdelegate;
goto case_delegate;
}
// ( expression )
@@ -5444,6 +5491,7 @@ Expression *Parser::parsePrimaryExp()
e->parens = 1;
check(loc, TOKrparen);
break;
}
case TOKlbracket:
{ /* Parse array literals and associative array literals:
@@ -5484,53 +5532,102 @@ Expression *Parser::parsePrimaryExp()
}
case TOKlcurly:
// { statements... }
save = TOKdelegate;
goto case_delegate;
case TOKfunction:
case TOKdelegate:
save = token.value;
nextToken();
case_delegate:
{
/* function type(parameters) { body } pure nothrow
* delegate type(parameters) { body } pure nothrow
* (parameters) { body }
* { body }
*/
Parameters *arguments;
int varargs;
FuncLiteralDeclaration *fd;
Type *t;
TemplateParameters *tpl = NULL;
Parameters *parameters = NULL;
int varargs = 0;
Type *tret = NULL;
StorageClass stc = 0;
enum TOK save = TOKreserved;
Loc loc = this->loc;
if (token.value == TOKlcurly)
switch (token.value)
{
t = NULL;
varargs = 0;
arguments = new Parameters();
case TOKfunction:
case TOKdelegate:
save = token.value;
nextToken();
if (token.value != TOKlparen && token.value != TOKlcurly)
{ // function type (parameters) { statements... }
// delegate type (parameters) { statements... }
tret = parseBasicType();
tret = parseBasicType2(tret); // function return type
}
if (token.value == TOKlparen)
{ // function (parameters) { statements... }
// delegate (parameters) { statements... }
}
else
{ // function { statements... }
// delegate { statements... }
break;
}
/* fall through to TOKlparen */
case TOKlparen:
Lparen:
{ // (parameters) => expression
// (parameters) { statements... }
parameters = parseParameters(&varargs, &tpl);
stc = parsePostfix();
if (stc & (STCconst | STCimmutable | STCshared | STCwild))
error("const/immutable/shared/inout attributes are only valid for non-static member functions");
break;
}
case TOKlcurly:
// { statements... }
break;
case TOKidentifier:
{ // identifier => expression
parameters = new Parameters();
Identifier *id = Lexer::uniqueId("__T");
Type *t = new TypeIdentifier(loc, id);
parameters->push(new Parameter(0, t, token.ident, NULL));
tpl = new TemplateParameters();
TemplateParameter *tp = new TemplateTypeParameter(loc, id, NULL, NULL);
tpl->push(tp);
nextToken();
break;
}
default:
assert(0);
}
if (!parameters)
parameters = new Parameters();
TypeFunction *tf = new TypeFunction(parameters, tret, varargs, linkage, stc);
FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL);
if (token.value == TOKgoesto)
{
check(TOKgoesto);
Loc loc = this->loc;
Expression *ae = parseAssignExp();
fd->fbody = new ReturnStatement(loc, ae);
fd->endloc = this->loc;
}
else
{
if (token.value == TOKlparen)
t = NULL;
else
{
t = parseBasicType();
t = parseBasicType2(t); // function return type
}
arguments = parseParameters(&varargs);
stc = parsePostfix();
if (stc & (STCconst | STCimmutable | STCshared | STCwild))
error("const/immutable/shared/inout attributes are only valid for non-static member functions");
parseContracts(fd);
}
TypeFunction *tf = new TypeFunction(arguments, t, varargs, linkage, stc);
TemplateDeclaration *td = NULL;
if (tpl)
{ // Wrap a template around function fd
Dsymbols *decldefs = new Dsymbols();
decldefs->push(fd);
td = new TemplateDeclaration(fd->loc, fd->ident, tpl, NULL, decldefs, 0);
td->literal = 1; // it's a template 'literal'
}
fd = new FuncLiteralDeclaration(loc, 0, tf, save, NULL);
parseContracts(fd);
e = new FuncExp(loc, fd);
e = new FuncExp(loc, fd, td);
break;
}
@@ -5853,6 +5950,7 @@ Expression *Parser::parseUnaryExp()
case TOKfunction:
case TOKdelegate:
case TOKtypeof:
case TOKvector:
#if DMDV2
case TOKfile:
case TOKline:
@@ -6336,7 +6434,7 @@ Expressions *Parser::parseArguments()
{
nextToken();
while (token.value != endtok)
while (token.value != endtok && token.value != TOKeof)
{
arg = parseAssignExp();
arguments->push(arg);
@@ -6528,6 +6626,7 @@ void initPrecedence()
precedence[TOKcast] = PREC_unary;
#if DMDV2
precedence[TOKvector] = PREC_unary;
precedence[TOKpow] = PREC_pow;
#endif
+4 -2
View File
@@ -52,10 +52,11 @@ struct StaticAssert;
enum ParseStatementFlags
{
PSsemi = 1, // empty ';' statements are allowed
PSsemi = 1, // empty ';' statements are allowed, but deprecated
PSscope = 2, // start a new scope
PScurly = 4, // { } statement is required
PScurlyscope = 8, // { } starts a new scope
PSsemi_ok = 0x10, // empty ';' are really ok
};
@@ -85,6 +86,7 @@ struct Parser : Lexer
Objects *parseTemplateArgument();
StaticAssert *parseStaticAssert();
TypeQualified *parseTypeof();
Type *parseVector();
enum LINK parseLinkage();
Condition *parseDebugCondition();
Condition *parseVersionCondition();
@@ -100,7 +102,7 @@ struct Parser : Lexer
UnitTestDeclaration *parseUnitTest();
NewDeclaration *parseNew();
DeleteDeclaration *parseDelete();
Parameters *parseParameters(int *pvarargs);
Parameters *parseParameters(int *pvarargs, TemplateParameters **tpl = NULL);
EnumDeclaration *parseEnum();
Dsymbol *parseAggregate();
BaseClasses *parseBaseClasses();
+2 -9
View File
@@ -347,7 +347,7 @@ char *Port::strupr(char *s)
#include <assert.h>
static double zero = 0;
double Port::nan = NAN;
double Port::nan = copysign(NAN, 1.0);
double Port::infinity = 1 / zero;
double Port::dbl_max = 1.7976931348623157e308;
double Port::dbl_min = 5e-324;
@@ -362,14 +362,7 @@ static PortInitializer portinitializer;
PortInitializer::PortInitializer()
{
// gcc nan's have the sign bit set by default, so turn it off
// Need the volatile to prevent gcc from doing incorrect
// constant folding.
volatile long double foo;
foo = NAN;
if (signbit(foo)) // signbit sometimes, not always, set
foo = -foo; // turn off sign bit
Port::nan = foo;
assert(!signbit(Port::nan));
#if __FreeBSD__ && __i386__
// LDBL_MAX comes out as infinity. Fix.
+155
View File
@@ -0,0 +1,155 @@
/* Copyright (c) 2000 Digital Mars */
/* All Rights Reserved */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
#include "../root/rmem.h"
#else
#include "rmem.h"
#endif
/* This implementation of the storage allocator uses the standard C allocation package.
*/
Mem mem;
void Mem::init()
{
}
char *Mem::strdup(const char *s)
{
char *p;
if (s)
{
p = ::strdup(s);
if (p)
return p;
error();
}
return NULL;
}
void *Mem::malloc(size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
}
return p;
}
void *Mem::calloc(size_t size, size_t n)
{ void *p;
if (!size || !n)
p = NULL;
else
{
p = ::calloc(size, n);
if (!p)
error();
}
return p;
}
void *Mem::realloc(void *p, size_t size)
{
if (!size)
{ if (p)
{ ::free(p);
p = NULL;
}
}
else if (!p)
{
p = ::malloc(size);
if (!p)
error();
}
else
{
void *psave = p;
p = ::realloc(psave, size);
if (!p)
{ free(psave);
error();
}
}
return p;
}
void Mem::free(void *p)
{
if (p)
::free(p);
}
void *Mem::mallocdup(void *o, size_t size)
{ void *p;
if (!size)
p = NULL;
else
{
p = ::malloc(size);
if (!p)
error();
else
memcpy(p,o,size);
}
return p;
}
void Mem::error()
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
void Mem::fullcollect()
{
}
void Mem::mark(void *pointer)
{
(void) pointer; // necessary for VC /W4
}
void Mem::setStackBottom(void *bottom)
{
}
void Mem::addroots(char* pStart, char* pEnd)
{
}
/* =================================================== */
void * operator new(size_t m_size)
{
void *p = malloc(m_size);
if (p)
return p;
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
return p;
}
void operator delete(void *p)
{
free(p);
}
+250
View File
@@ -0,0 +1,250 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// License for redistribution is by either the Artistic License
// in artistic.txt, or the GNU General Public License in gnu.txt.
// See the included readme.txt for details.
#include <stdio.h>
#include <assert.h>
#include "mars.h"
#include "init.h"
#include "expression.h"
#include "template.h"
#include "statement.h"
#include "mtype.h"
#include "utf.h"
#include "declaration.h"
#include "aggregate.h"
#include "scope.h"
#include "attrib.h"
int lambdaHasSideEffect(Expression *e, void *param);
/********************************************
* Determine if Expression has any side effects.
*/
bool Expression::hasSideEffect()
{
bool has = FALSE;
apply(&lambdaHasSideEffect, &has);
return has;
}
int lambdaHasSideEffect(Expression *e, void *param)
{
bool *phas = (bool *)param;
switch (e->op)
{
// Sort the cases by most frequently used first
case TOKassign:
case TOKplusplus:
case TOKminusminus:
case TOKdeclaration:
case TOKconstruct:
case TOKblit:
case TOKaddass:
case TOKminass:
case TOKcatass:
case TOKmulass:
case TOKdivass:
case TOKmodass:
case TOKshlass:
case TOKshrass:
case TOKushrass:
case TOKandass:
case TOKorass:
case TOKxorass:
case TOKpowass:
case TOKin:
case TOKremove:
case TOKassert:
case TOKhalt:
case TOKdelete:
case TOKnew:
case TOKnewanonclass:
*phas = TRUE;
break;
case TOKcall:
{ CallExp *ce = (CallExp *)e;
/* Calling a function or delegate that is pure nothrow
* has no side effects.
*/
if (ce->e1->type)
{
Type *t = ce->e1->type->toBasetype();
if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
((TypeFunction *)t)->isnothrow)
||
(t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak &&
((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
)
{
}
else
*phas = TRUE;
}
break;
}
case TOKcast:
{ CastExp *ce = (CastExp *)e;
/* if:
* cast(classtype)func() // because it may throw
*/
if (ce->to->ty == Tclass && ce->e1->op == TOKcall && ce->e1->type->ty == Tclass)
*phas = TRUE;
break;
}
default:
break;
}
return *phas; // stop walking if we determine this expression has side effects
}
/***********************************
* The result of this expression will be discarded.
* Complain if the operation has no side effects (and hence is meaningless).
*/
void Expression::discardValue()
{
bool has = FALSE;
lambdaHasSideEffect(this, &has);
if (!has)
{
switch (op)
{
case TOKcast:
{ CastExp *ce = (CastExp *)this;
if (ce->to->equals(Type::tvoid))
{ /*
* Don't complain about an expression with no effect if it was cast to void
*/
ce->e1->useValue();
break;
}
goto Ldefault; // complain
}
case TOKerror:
break;
case TOKcall:
/* Don't complain about calling functions with no effect,
* because purity and nothrow are inferred, and because some of the
* runtime library depends on it. Needs more investigation.
*/
break;
case TOKimport:
error("%s has no effect", toChars());
break;
case TOKandand:
{ AndAndExp *aae = (AndAndExp *)this;
aae->e1->useValue();
aae->e2->discardValue();
break;
}
case TOKoror:
{ OrOrExp *ooe = (OrOrExp *)this;
ooe->e1->useValue();
ooe->e2->discardValue();
break;
}
case TOKquestion:
{ CondExp *ce = (CondExp *)this;
ce->econd->useValue();
ce->e1->discardValue();
ce->e2->discardValue();
break;
}
case TOKcomma:
{ CommaExp *ce = (CommaExp *)this;
/* Check for compiler-generated code of the form auto __tmp, e, __tmp;
* In such cases, only check e for side effect (it's OK for __tmp to have
* no side effect).
* See Bugzilla 4231 for discussion
*/
CommaExp* firstComma = ce;
while (firstComma->e1->op == TOKcomma)
firstComma = (CommaExp *)firstComma->e1;
if (firstComma->e1->op == TOKdeclaration &&
ce->e2->op == TOKvar &&
((DeclarationExp *)firstComma->e1)->declaration == ((VarExp*)ce->e2)->var)
{
ce->e1->useValue();
break;
}
// Don't check e1 until we cast(void) the a,b code generation
//ce->e1->discardValue();
ce->e2->discardValue();
break;
}
case TOKtuple:
/* Pass without complaint if any of the tuple elements have side effects.
* Ideally any tuple elements with no side effects should raise an error,
* this needs more investigation as to what is the right thing to do.
*/
if (!hasSideEffect())
goto Ldefault;
break;
default:
Ldefault:
error("%s has no effect in expression (%s)",
Token::toChars(op), toChars());
break;
}
}
else
{
useValue();
}
}
/* This isn't used yet because the only way an expression has an unused sub-expression
* is with the CommaExp, and that currently generates messages from rewrites into comma
* expressions. Needs more investigation.
*/
void Expression::useValue()
{
#if 0
// Disabled because need to cast(void) the a,b code generation
void *p;
apply(&lambdaUseValue, &p);
#endif
}
#if 0
int lambdaUseValue(Expression *e, void *param)
{
switch (e->op)
{
case TOKcomma:
{ CommaExp *ce = (CommaExp *)e;
discardValue(ce->E1);
break;
}
default:
break;
}
return 0;
}
#endif
+209 -207
View File
File diff suppressed because it is too large Load Diff
+22 -3
View File
@@ -136,6 +136,7 @@ struct Statement : Object
virtual int inlineCost(InlineCostState *ics);
virtual Expression *doInline(InlineDoState *ids);
virtual Statement *doInlineStatement(InlineDoState *ids);
virtual Statement *inlineScan(InlineScanState *iss);
// Back end
@@ -180,6 +181,7 @@ struct ExpStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
@@ -235,6 +237,7 @@ struct CompoundStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
virtual void toIR(IRState *irs);
@@ -274,6 +277,7 @@ struct UnrolledLoopStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
@@ -296,6 +300,9 @@ struct ScopeStatement : Statement
int isEmpty();
Expression *interpret(InterState *istate);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
@@ -362,7 +369,9 @@ struct ForStatement : Statement
Expression *interpret(InterState *istate);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
int inlineCost(InlineCostState *ics);
Statement *inlineScan(InlineScanState *iss);
Statement *doInlineStatement(InlineDoState *ids);
void toIR(IRState *irs);
};
@@ -386,6 +395,8 @@ struct ForeachStatement : Statement
Statement *syntaxCopy();
Statement *semantic(Scope *sc);
bool checkForArgTypes();
int inferAggregate(Scope *sc, Dsymbol *&sapply);
int inferApplyArgTypes(Scope *sc, Dsymbol *&sapply);
int hasBreak();
int hasContinue();
int usesEH();
@@ -448,6 +459,7 @@ struct IfStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
@@ -660,6 +672,7 @@ struct ReturnStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
@@ -775,6 +788,7 @@ struct Catch : Object
Identifier *ident;
VarDeclaration *var;
Statement *handler;
bool internalCatch;
Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
Catch *syntaxCopy();
@@ -927,9 +941,9 @@ struct AsmStatement : Statement
Token *tokens;
code *asmcode;
unsigned asmalign; // alignment of this statement
unsigned refparam; // !=0 if function parameter is referenced
unsigned naked; // !=0 if function is to be naked
unsigned regs; // mask of registers modified
unsigned regs; // mask of registers modified (must match regm_t in back end)
unsigned char refparam; // !=0 if function parameter is referenced
unsigned char naked; // !=0 if function is to be naked
AsmStatement(Loc loc, Token *tokens);
Statement *syntaxCopy();
@@ -940,6 +954,10 @@ struct AsmStatement : Statement
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
//int inlineCost(InlineCostState *ics);
//Expression *doInline(InlineDoState *ids);
//Statement *inlineScan(InlineScanState *iss);
void toIR(IRState *irs);
#if IN_LLVM
@@ -965,6 +983,7 @@ struct ImportStatement : Statement
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Statement *doInlineStatement(InlineDoState *ids);
void toIR(IRState *irs);
};
+8 -3
View File
@@ -58,10 +58,15 @@ void StaticAssert::semantic2(Scope *sc)
sc->flags |= SCOPEstaticassert;
Expression *e = exp->semantic(sc);
sc = sc->pop();
if (e->op == TOKerror)
if (e->type == Type::terror)
return;
unsigned olderrs = global.errors;
e = e->optimize(WANTvalue | WANTinterpret);
if (e->isBool(FALSE))
if (global.errors != olderrs)
{
errorSupplemental(loc, "while evaluating: static assert(%s)", exp->toChars());
}
else if (e->isBool(FALSE))
{
if (msg)
{ HdrGenState hgs;
@@ -86,7 +91,7 @@ void StaticAssert::semantic2(Scope *sc)
}
}
int StaticAssert::oneMember(Dsymbol **ps)
int StaticAssert::oneMember(Dsymbol **ps, Identifier *ident)
{
//printf("StaticAssert::oneMember())\n");
*ps = NULL;
+1 -1
View File
@@ -32,7 +32,7 @@ struct StaticAssert : Dsymbol
void semantic(Scope *sc);
void semantic2(Scope *sc);
void inlineScan();
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
void toObjFile(int multiobj);
const char *kind();
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+46 -37
View File
@@ -41,7 +41,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
hasUnions = 0;
sizeok = 0; // size not determined yet
deferred = NULL;
isdeprecated = 0;
isdeprecated = false;
inv = NULL;
aggNew = NULL;
aggDelete = NULL;
@@ -126,7 +126,7 @@ void AggregateDeclaration::inlineScan()
unsigned AggregateDeclaration::size(Loc loc)
{
//printf("AggregateDeclaration::size() = %d\n", structsize);
//printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope);
if (!members)
error(loc, "unknown size");
if (sizeok != 1 && scope)
@@ -148,6 +148,11 @@ int AggregateDeclaration::isDeprecated()
return isdeprecated;
}
int AggregateDeclaration::isExport()
{
return protection == PROTexport;
}
/****************************
* Do byte or word alignment as necessary.
* Align sizes of 0, as we may not know array sizes yet.
@@ -377,6 +382,8 @@ void StructDeclaration::semantic(Scope *sc)
scope = NULL;
}
int errors = global.gaggedErrors;
unsigned dprogress_save = Module::dprogress;
parent = sc->parent;
@@ -390,7 +397,7 @@ void StructDeclaration::semantic(Scope *sc)
protection = sc->protection;
storage_class |= sc->stc;
if (sc->stc & STCdeprecated)
isdeprecated = 1;
isdeprecated = true;
assert(!isAnonymous());
if (sc->stc & STCabstract)
error("structs, unions cannot be abstract");
@@ -464,7 +471,7 @@ void StructDeclaration::semantic(Scope *sc)
* resolve individual members like enums.
*/
for (size_t i = 0; i < members_dim; i++)
{ Dsymbol *s = members->tdata()[i];
{ Dsymbol *s = (*members)[i];
/* There are problems doing this in the general case because
* Scope keeps track of things like 'offset'
*/
@@ -477,28 +484,19 @@ void StructDeclaration::semantic(Scope *sc)
for (size_t i = 0; i < members_dim; i++)
{
Dsymbol *s = members->tdata()[i];
s->semantic(sc2);
#if 0
if (sizeok == 2)
{ //printf("forward reference\n");
break;
}
#endif
Dsymbol *s = (*members)[i];
#if 0 /* Decided to allow this because if the field is initialized by copying it from
* a correctly initialized struct, it will work.
/* If this is the last member, see if we can finish setting the size.
* This could be much better - finish setting the size after the last
* field was processed. The problem is the chicken-and-egg determination
* of when that is. See Bugzilla 7426 for more info.
*/
Type *t;
if (s->isDeclaration() &&
(t = s->isDeclaration()->type) != NULL &&
t->toBasetype()->ty == Tstruct)
{ StructDeclaration *sd = (StructDeclaration *)t->toDsymbol(sc);
if (sd->isnested)
error("inner struct %s cannot be the type for field %s as it must embed a reference to its enclosing %s",
sd->toChars(), s->toChars(), sd->toParent2()->toPrettyChars());
if (i + 1 == members_dim)
{
if (sizeok == 0 && s->isAliasDeclaration())
finalizeSize();
}
#endif
s->semantic(sc2);
}
if (sizeok == 2)
@@ -518,19 +516,7 @@ void StructDeclaration::semantic(Scope *sc)
return;
}
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
finalizeSize();
Module::dprogress++;
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
@@ -649,7 +635,13 @@ void StructDeclaration::semantic(Scope *sc)
semantic2(sc);
semantic3(sc);
}
if (deferred)
if (global.gag && global.gaggedErrors != errors)
{ // The type is no good, yet the error messages were gagged.
type = Type::terror;
}
if (deferred && !global.gag)
{
deferred->semantic2(sc);
deferred->semantic3(sc);
@@ -672,6 +664,23 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags)
return ScopeDsymbol::search(loc, ident, flags);
}
void StructDeclaration::finalizeSize()
{
// 0 sized struct's are set to 1 byte
if (structsize == 0)
{
structsize = 1;
alignsize = 1;
}
// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
sizeok = 1;
}
void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
{
buf->printf("%s ", kind());
+333 -103
View File
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
// Copyright (c) 1999-2011 by Digital Mars
// Copyright (c) 1999-2012 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -14,6 +14,7 @@
#include <assert.h>
#include "root.h"
#include "aav.h"
#include "rmem.h"
#include "stringtable.h"
#include "mars.h"
@@ -278,6 +279,8 @@ int arrayObjectMatch(Objects *oa1, Objects *oa2, TemplateDeclaration *tempdecl,
}
/****************************************
* This makes a 'pretty' version of the template arguments.
* It's analogous to genIdent() which makes a mangled version.
*/
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
@@ -287,12 +290,21 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
Expression *e = isExpression(oarg);
Dsymbol *s = isDsymbol(oarg);
Tuple *v = isTuple(oarg);
/* The logic of this should match what genIdent() does. The _dynamic_cast()
* function relies on all the pretty strings to be unique for different classes
* (see Bugzilla 7375).
* Perhaps it would be better to demangle what genIdent() does.
*/
if (t)
{ //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
t->toCBuffer(buf, NULL, hgs);
}
else if (e)
{
if (e->op == TOKvar)
e = e->optimize(WANTvalue); // added to fix Bugzilla 7375
e->toCBuffer(buf, hgs);
}
else if (s)
{
char *p = s->ident ? s->ident->toChars() : s->toChars();
@@ -305,7 +317,7 @@ void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
{
if (i)
buf->writeByte(',');
Object *o = args->tdata()[i];
Object *o = (*args)[i];
ObjectToCBuffer(buf, hgs, o);
}
}
@@ -377,13 +389,10 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id,
if (members)
{
Dsymbol *s;
if (Dsymbol::oneMembers(members, &s))
if (Dsymbol::oneMembers(members, &s, ident) && s)
{
if (s && s->ident && s->ident->equals(ident))
{
onemember = s;
s->parent = this;
}
onemember = s;
s->parent = this;
}
}
}
@@ -515,13 +524,10 @@ void TemplateDeclaration::semantic(Scope *sc)
if (members)
{
Dsymbol *s;
if (Dsymbol::oneMembers(members, &s))
if (Dsymbol::oneMembers(members, &s, ident) && s)
{
if (s && s->ident && s->ident->equals(ident))
{
onemember = s;
s->parent = this;
}
onemember = s;
s->parent = this;
}
}
@@ -719,12 +725,7 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
#endif
#if DMDV1
m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
#else
m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
#endif
//printf("\tm2 = %d\n", m2);
if (m2 == MATCHnomatch)
@@ -759,12 +760,19 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti,
}
#if DMDV2
if (m && !(m == MATCHexact && flag == 2) && constraint && !(flag & 1))
if (m && constraint && !flag)
{ /* Check to see if constraint is satisfied.
*/
makeParamNamesVisibleInConstraint(paramscope, fargs);
Expression *e = constraint->syntaxCopy();
Scope *sc = paramscope->push();
/* There's a chicken-and-egg problem here. We don't know yet if this template
* instantiation will be a local one (isnested is set), and we won't know until
* after selecting the correct template. Thus, function we're nesting inside
* is not on the sc scope chain, and this can cause errors in FuncDeclaration::getLevel().
* Workaround the problem by setting a flag to relax the checking on frame errors.
*/
sc->flags |= SCOPEstaticif;
FuncDeclaration *fd = onemember && onemember->toAlias() ?
@@ -1165,7 +1173,7 @@ L2:
mod &= ~STCwild;
if (tthis->mod != mod)
{
if (!MODimplicitConv(tthis->mod, mod))
if (!MODmethodConv(tthis->mod, mod))
goto Lnomatch;
if (MATCHconst < match)
match = MATCHconst;
@@ -1215,6 +1223,9 @@ Lretry:
#endif
Type *argtype = farg->type;
// Apply function parameter storage classes to parameter types
fparam->type = fparam->type->addStorageClass(fparam->storageClass);
#if DMDV2
/* Allow string literals which are type [] to match with [dim]
*/
@@ -1229,15 +1240,41 @@ Lretry:
}
}
/* Allow implicit function literals to delegate conversion
*/
if (farg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)farg;
Type *tp = fparam->type;
if (tp->ty == Tdelegate &&
fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved)
{ Type *tdg = new TypeDelegate(fe->type->nextOf());
tdg = tdg->semantic(loc, sc);
farg = fe->inferType(sc, tdg);
}
else if (fe->type == Type::tvoid)
{
farg = fe->inferType(sc, tp);
if (!farg)
goto Lvarargs;
}
argtype = farg->type;
}
/* Remove top const for dynamic array types and pointer types
*/
if ((argtype->ty == Tarray || argtype->ty == Tpointer) &&
!argtype->isMutable())
!argtype->isMutable() &&
(!(fparam->storageClass & STCref) ||
(fparam->storageClass & STCauto) && !farg->isLvalue()))
{
argtype = argtype->mutableOf();
}
#endif
if (fvarargs == 2 && i + 1 == nfparams && i + 1 < nfargs)
goto Lvarargs;
MATCH m;
m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes,
tf->hasWild() ? &wildmatch : NULL);
@@ -1274,16 +1311,33 @@ Lretry:
ad = ((TypeStruct *)tba)->sym;
Lad:
if (ad->aliasthis)
{
{ /* If a semantic error occurs while doing alias this,
* eg purity(bug 7295), just regard it as not a match.
*/
unsigned olderrors = global.startGagging();
Expression *e = new DotIdExp(farg->loc, farg, ad->aliasthis->ident);
e = e->semantic(sc);
e = resolveProperties(sc, e);
farg = e;
goto Lretry;
if (!global.endGagging(olderrors))
{ farg = e;
goto Lretry;
}
}
}
}
if (m && (fparam->storageClass & (STCref | STCauto)) == STCref)
{ if (!farg->isLvalue())
goto Lnomatch;
}
if (m && (fparam->storageClass & STCout))
{ if (!farg->isLvalue())
goto Lnomatch;
}
if (!m && (fparam->storageClass & STClazy) && fparam->type->ty == Tvoid &&
farg->type->ty != Tvoid)
m = MATCHconvert;
if (m)
{ if (m < match)
match = m; // pick worst match
@@ -1291,6 +1345,7 @@ Lretry:
}
}
Lvarargs:
/* The following code for variadic arguments closely
* matches TypeFunction::callMatch()
*/
@@ -1315,6 +1370,25 @@ Lretry:
{
Expression *arg = fargs->tdata()[i];
assert(arg);
if (arg->op == TOKfunction)
{ FuncExp *fe = (FuncExp *)arg;
Type *tp = tb->nextOf();
if (tp->ty == Tdelegate &&
fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction &&
fe->tok == TOKreserved)
{ tp = new TypeDelegate(fe->type->nextOf());
tp = tp->semantic(loc, sc);
arg = fe->inferType(sc, tp);
}
else if (arg->type == Type::tvoid)
{
arg = fe->inferType(sc, tp);
if (!arg)
goto Lnomatch;
}
}
MATCH m;
/* If lazy array of delegates,
* convert arg(s) to delegate(s)
@@ -1380,7 +1454,7 @@ Lmatch:
*/
Declaration *sparam;
dedargs->tdata()[i] = oded;
MATCH m2 = tparam->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam, 0);
MATCH m2 = tparam->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
//printf("m2 = %d\n", m2);
if (!m2)
goto Lnomatch;
@@ -1412,6 +1486,7 @@ Lmatch:
#if DMDV2
if (constraint)
{ /* Check to see if constraint is satisfied.
* Most of this code appears twice; this is a good candidate for refactoring.
*/
makeParamNamesVisibleInConstraint(paramscope, fargs);
Expression *e = constraint->syntaxCopy();
@@ -1620,7 +1695,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
TemplateDeclaration *td_best = NULL;
Objects *tdargs = new Objects();
TemplateInstance *ti;
FuncDeclaration *fd;
FuncDeclaration *fd_best;
#if 0
printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
@@ -1655,6 +1730,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
MATCH m;
Objects dedargs;
FuncDeclaration *fd = NULL;
m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs);
//printf("deduceFunctionTemplateMatch = %d\n", m);
@@ -1670,14 +1746,53 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
// Disambiguate by picking the most specialized TemplateDeclaration
MATCH c1 = td->leastAsSpecialized(td_best, fargs);
MATCH c2 = td_best->leastAsSpecialized(td, fargs);
//printf("c1 = %d, c2 = %d\n", c1, c2);
//printf("1: c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2)
goto Ltd;
else if (c1 < c2)
goto Ltd_best;
else
goto Lambig;
}
if (!fd_best)
{
fd_best = td_best->doHeaderInstantiation(sc, tdargs, fargs);
if (!fd_best)
goto Lerror;
}
{
tdargs->setDim(dedargs.dim);
memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *));
fd = td->doHeaderInstantiation(sc, tdargs, fargs);
if (!fd)
goto Lerror;
}
assert(fd && fd_best);
{
// Disambiguate by tf->callMatch
TypeFunction *tf1 = (TypeFunction *)fd->type;
TypeFunction *tf2 = (TypeFunction *)fd_best->type;
MATCH c1 = (MATCH) tf1->callMatch(fd->needThis() && !fd->isCtorDeclaration() ? ethis : NULL, fargs);
MATCH c2 = (MATCH) tf2->callMatch(fd_best->needThis() && !fd->isCtorDeclaration() ? ethis : NULL, fargs);
//printf("2: c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2)
goto Ltd;
if (c1 < c2)
goto Ltd_best;
}
{
// Disambiguate by picking the most specialized FunctionDeclaration
MATCH c1 = fd->leastAsSpecialized(fd_best);
MATCH c2 = fd_best->leastAsSpecialized(fd);
//printf("3: c1 = %d, c2 = %d\n", c1, c2);
if (c1 > c2)
goto Ltd;
if (c1 < c2)
goto Ltd_best;
}
Lambig: // td_best and td are ambiguous
@@ -1692,6 +1807,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
td_ambig = NULL;
assert((size_t)td->scope > 0x10000);
td_best = td;
fd_best = fd;
m_best = m;
tdargs->setDim(dedargs.dim);
memcpy(tdargs->tdata(), dedargs.tdata(), tdargs->dim * sizeof(void *));
@@ -1717,10 +1833,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
assert((size_t)td_best->scope > 0x10000);
ti = new TemplateInstance(loc, td_best, tdargs);
ti->semantic(sc, fargs);
fd = ti->toAlias()->isFuncDeclaration();
if (!fd)
fd_best = ti->toAlias()->isFuncDeclaration();
if (!fd_best || !((TypeFunction*)fd_best->type)->callMatch(ethis, fargs, flags))
goto Lerror;
return fd;
return fd_best;
Lerror:
#if DMDV2
@@ -1749,6 +1865,78 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
return NULL;
}
/*************************************************
* Limited function template instantiation for using fd->leastAsSpecialized()
*/
FuncDeclaration *TemplateDeclaration::doHeaderInstantiation(Scope *sc,
Objects *tdargs, Expressions *fargs)
{
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
if (!fd)
return NULL;
#if 0
printf("doHeaderInstantiation this = %s\n", toChars());
for (size_t i = 0; i < tdargs->dim; ++i)
printf("\ttdargs[%d] = %s\n", i, ((Object *)tdargs->data[i])->toChars());
#endif
assert((size_t)scope > 0x10000);
TemplateInstance *ti = new TemplateInstance(loc, this, tdargs);
ti->tinst = sc->tinst;
{
ti->tdtypes.setDim(ti->tempdecl->parameters->dim);
if (!ti->tempdecl->matchWithInstance(ti, &ti->tdtypes, fargs, 2))
return NULL;
}
ti->parent = parent;
// function body and contracts are not need
//fd = fd->syntaxCopy(NULL)->isFuncDeclaration();
fd = new FuncDeclaration(fd->loc, fd->endloc, fd->ident, fd->storage_class, fd->type->syntaxCopy());
fd->parent = ti;
Scope *scope = this->scope;
ti->argsym = new ScopeDsymbol();
ti->argsym->parent = scope->parent;
scope = scope->push(ti->argsym);
Scope *paramscope = scope->push();
paramscope->stc = 0;
ti->declareParameters(paramscope);
paramscope->pop();
{
TypeFunction *tf = (TypeFunction *)fd->type;
if (tf && tf->ty == Tfunction)
tf->fargs = fargs;
}
Scope *sc2;
sc2 = scope->push(ti);
sc2->parent = /*isnested ? sc->parent :*/ ti;
sc2->tinst = ti;
{
Scope *sc = sc2;
sc = sc->push();
if (fd->isCtorDeclaration())
sc->flags |= SCOPEctor;
fd->type = fd->type->semantic(fd->loc, sc);
sc = sc->pop();
}
//printf("\t[%s] fd->type = %s, mod = %x, ", loc.toChars(), fd->type->toChars(), fd->type->mod);
//printf("fd->needThis() = %d\n", fd->needThis());
sc2->pop();
scope->pop();
return fd;
}
bool TemplateDeclaration::hasStaticCtorOrDtor()
{
return FALSE; // don't scan uninstantiated templates
@@ -2128,6 +2316,19 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
else
goto Lnomatch;
}
else if (tparam->ty == Ttypeof)
{
/* Need a loc to go with the semantic routine.
*/
Loc loc;
if (parameters->dim)
{
TemplateParameter *tp = parameters->tdata()[0];
loc = tp->loc;
}
tparam = tparam->semantic(loc, sc);
}
if (ty != tparam->ty)
{
@@ -2135,8 +2336,18 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
// Can't instantiate AssociativeArray!() without a scope
if (tparam->ty == Taarray && !((TypeAArray*)tparam)->sc)
((TypeAArray*)tparam)->sc = sc;
MATCH m = implicitConvTo(tparam);
if (m == MATCHnomatch)
{
Type *at = aliasthisOf();
if (at)
m = at->deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
return m;
#else
return implicitConvTo(tparam);
#endif
return implicitConvTo(tparam);
}
if (nextOf())
@@ -2655,8 +2866,8 @@ MATCH TypeStruct::deduceType(Scope *sc, Type *tparam, TemplateParameters *parame
{
TypeStruct *tp = (TypeStruct *)tparam;
if (sym != tp->sym)
return MATCHnomatch;
//printf("\t%d\n", (MATCH) implicitConvTo(tp));
return implicitConvTo(tp);
}
return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch);
}
@@ -2880,6 +3091,8 @@ TemplateThisParameter *TemplateParameter::isTemplateThisParameter()
// type-parameter
Type *TemplateTypeParameter::tdummy = NULL;
TemplateTypeParameter::TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType,
Type *defaultType)
: TemplateParameter(loc, ident)
@@ -2963,15 +3176,13 @@ Lnomatch:
* parameters[] template parameters
* dedtypes[] deduced arguments to template instance
* *psparam set to symbol declared and initialized to dedtypes[i]
* flags 1: don't do 'toHeadMutable()'
*/
MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam, int flags)
Declaration **psparam)
{
//printf("TemplateTypeParameter::matchArg()\n");
Type *t;
Object *oarg;
MATCH m = MATCHexact;
Type *ta;
@@ -2989,7 +3200,6 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
{
goto Lnomatch;
}
flags |= 1; // already deduced, so don't to toHeadMutable()
}
}
@@ -3001,10 +3211,11 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
}
//printf("ta is %s\n", ta->toChars());
t = (Type *)dedtypes->tdata()[i];
if (specType)
{
if (!ta || ta == tdummy)
goto Lnomatch;
//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta->toChars(), specType->toChars());
MATCH m2 = ta->deduceType(sc, specType, parameters, dedtypes);
if (m2 == MATCHnomatch)
@@ -3014,37 +3225,29 @@ MATCH TemplateTypeParameter::matchArg(Scope *sc, Objects *tiargs,
if (m2 < m)
m = m2;
t = (Type *)dedtypes->tdata()[i];
if (dedtypes->tdata()[i])
ta = (Type *)dedtypes->tdata()[i];
}
else
{
// So that matches with specializations are better
if (!(flags & 1))
m = MATCHconvert;
/* This is so that:
* template Foo(T), Foo!(const int), => ta == int
*/
// if (!(flags & 1))
// ta = ta->toHeadMutable();
if (t)
if (dedtypes->tdata()[i])
{ // Must match already deduced type
Type *t = (Type *)dedtypes->tdata()[i];
m = MATCHexact;
if (!t->equals(ta))
{ //printf("t = %s ta = %s\n", t->toChars(), ta->toChars());
goto Lnomatch;
}
}
else
{
// So that matches with specializations are better
m = MATCHconvert;
}
}
dedtypes->tdata()[i] = ta;
if (!t)
{
dedtypes->tdata()[i] = ta;
t = ta;
}
*psparam = new AliasDeclaration(loc, ident, t);
*psparam = new AliasDeclaration(loc, ident, ta);
//printf("\tm = %d\n", m);
return m;
@@ -3096,7 +3299,9 @@ void *TemplateTypeParameter::dummyArg()
t = specType;
else
{ // Use this for alias-parameter's too (?)
t = new TypeIdentifier(loc, ident);
if (!tdummy)
tdummy = new TypeIdentifier(loc, ident);
t = tdummy;
}
return (void *)t;
}
@@ -3245,10 +3450,9 @@ Lnomatch:
return 0;
}
MATCH TemplateAliasParameter::matchArg(Scope *sc,
Objects *tiargs, size_t i, TemplateParameters *parameters,
Objects *dedtypes,
Declaration **psparam, int flags)
MATCH TemplateAliasParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
{
Object *sa;
Object *oarg;
@@ -3412,7 +3616,7 @@ Object *TemplateAliasParameter::defaultArg(Loc loc, Scope *sc)
// value-parameter
Expression *TemplateValueParameter::edummy = NULL;
AA *TemplateValueParameter::edummies = NULL;
TemplateValueParameter::TemplateValueParameter(Loc loc, Identifier *ident, Type *valType,
Expression *specValue, Expression *defaultValue)
@@ -3510,9 +3714,9 @@ Lnomatch:
}
MATCH TemplateValueParameter::matchArg(Scope *sc,
Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam, int flags)
MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
{
//printf("TemplateValueParameter::matchArg()\n");
@@ -3562,7 +3766,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
if (specValue)
{
if (!ei || ei == edummy)
if (!ei || _aaGetRvalue(edummies, ei->type) == ei)
goto Lnomatch;
Expression *e = specValue;
@@ -3570,13 +3774,11 @@ MATCH TemplateValueParameter::matchArg(Scope *sc,
e = e->semantic(sc);
e = e->implicitCastTo(sc, valType);
e = e->optimize(WANTvalue | WANTinterpret);
//e->type = e->type->toHeadMutable();
ei = ei->syntaxCopy();
ei = ei->semantic(sc);
ei = ei->implicitCastTo(sc, vt);
ei = ei->optimize(WANTvalue | WANTinterpret);
//ei->type = ei->type->toHeadMutable();
//printf("\tei: %s, %s\n", ei->toChars(), ei->type->toChars());
//printf("\te : %s, %s\n", e->toChars(), e->type->toChars());
if (!ei->equals(e))
@@ -3647,9 +3849,10 @@ void *TemplateValueParameter::dummyArg()
if (!e)
{
// Create a dummy value
if (!edummy)
edummy = valType->defaultInit();
e = edummy;
Expression **pe = (Expression **)_aaGet(&edummies, valType);
if (!*pe)
*pe = valType->defaultInit();
e = *pe;
}
return (void *)e;
}
@@ -3720,10 +3923,9 @@ int TemplateTupleParameter::overloadMatch(TemplateParameter *tp)
return 0;
}
MATCH TemplateTupleParameter::matchArg(Scope *sc,
Objects *tiargs, size_t i, TemplateParameters *parameters,
Objects *dedtypes,
Declaration **psparam, int flags)
MATCH TemplateTupleParameter::matchArg(Scope *sc, Objects *tiargs,
size_t i, TemplateParameters *parameters, Objects *dedtypes,
Declaration **psparam)
{
//printf("TemplateTupleParameter::matchArg()\n");
@@ -4232,15 +4434,13 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
if (members->dim)
{
Dsymbol *s;
if (Dsymbol::oneMembers(members, &s) && s)
if (Dsymbol::oneMembers(members, &s, tempdecl->ident) && s)
{
//printf("s->kind = '%s'\n", s->kind());
//s->print();
//printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
if (s->ident && s->ident->equals(tempdecl->ident))
{
//printf("setting aliasdecl\n");
aliasdecl = new AliasDeclaration(loc, s->ident, s);
//printf("setting aliasdecl\n");
aliasdecl = new AliasDeclaration(loc, s->ident, s);
#if IN_LLVM
// LDC propagate internal information
@@ -4251,7 +4451,6 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
}
}
#endif
}
}
}
@@ -4293,6 +4492,12 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
error("recursive expansion");
fatal();
}
for (size_t i = 0; i < members->dim; i++)
{ Dsymbol *s = (*members)[i];
s->setScope(sc2);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
@@ -4333,6 +4538,27 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs)
}
}
/* ConditionalDeclaration may introduce eponymous declaration,
* so we should find it once again after semantic.
*/
if (members->dim)
{
Dsymbol *s;
if (Dsymbol::oneMembers(members, &s, tempdecl->ident) && s)
{
if (!aliasdecl || aliasdecl->toAlias() != s)
{
//printf("s->kind = '%s'\n", s->kind());
//s->print();
//printf("'%s', '%s'\n", s->ident->toChars(), tempdecl->ident->toChars());
//printf("setting aliasdecl 2\n");
aliasdecl = new AliasDeclaration(loc, s->ident, s);
}
}
else if (aliasdecl)
aliasdecl = NULL;
}
/* The problem is when to parse the initializer for a variable.
* Perhaps VarDeclaration::semantic() should do it like it does
* for initializers inside a function.
@@ -4962,6 +5188,8 @@ Identifier *TemplateInstance::genIdent(Objects *args)
}
// Now that we know it is not an alias, we MUST obtain a value
ea = ea->optimize(WANTvalue | WANTinterpret);
if (ea->op == TOKerror)
continue;
#if 1
/* Use deco that matches what it would be for a function parameter
*/
@@ -5180,7 +5408,7 @@ void TemplateInstance::printInstantiationTrace()
return;
const unsigned max_shown = 6;
const char format[] = "%s: instantiated from here: %s\n";
const char format[] = "instantiated from here: %s";
// determine instantiation depth and number of recursive instantiations
int n_instantiations = 1;
@@ -5203,7 +5431,7 @@ void TemplateInstance::printInstantiationTrace()
{
for (TemplateInstance *cur = this; cur; cur = cur->tinst)
{
fprintf(stdmsg, format, cur->loc.toChars(), cur->toChars());
errorSupplemental(cur->loc, format, cur->toChars());
}
}
else if (n_instantiations - n_totalrecursions <= max_shown)
@@ -5221,9 +5449,9 @@ void TemplateInstance::printInstantiationTrace()
else
{
if (recursionDepth)
fprintf(stdmsg, "%s: %d recursive instantiations from here: %s\n", cur->loc.toChars(), recursionDepth+2, cur->toChars());
errorSupplemental(cur->loc, "%d recursive instantiations from here: %s", recursionDepth+2, cur->toChars());
else
fprintf(stdmsg,format, cur->loc.toChars(), cur->toChars());
errorSupplemental(cur->loc, format, cur->toChars());
recursionDepth = 0;
}
}
@@ -5236,11 +5464,11 @@ void TemplateInstance::printInstantiationTrace()
for (TemplateInstance *cur = this; cur; cur = cur->tinst)
{
if (i == max_shown / 2)
fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown);
errorSupplemental(cur->loc, "... (%d instantiations, -v to show) ...", n_instantiations - max_shown);
if (i < max_shown / 2 ||
i >= n_instantiations - max_shown + max_shown / 2)
fprintf(stdmsg, format, cur->loc.toChars(), cur->toChars());
errorSupplemental(cur->loc, format, cur->toChars());
++i;
}
}
@@ -5342,7 +5570,7 @@ const char *TemplateInstance::kind()
return "template instance";
}
int TemplateInstance::oneMember(Dsymbol **ps)
int TemplateInstance::oneMember(Dsymbol **ps, Identifier *ident)
{
*ps = NULL;
return TRUE;
@@ -5561,7 +5789,7 @@ void TemplateMixin::semantic(Scope *sc)
// Run semantic on each argument, place results in tiargs[]
semanticTiargs(sc);
if (errors)
if (errors || arrayObjectIsError(tiargs))
return;
tempdecl = findBestMatch(sc, NULL);
@@ -5789,23 +6017,25 @@ const char *TemplateMixin::kind()
return "mixin";
}
int TemplateMixin::oneMember(Dsymbol **ps)
int TemplateMixin::oneMember(Dsymbol **ps, Identifier *ident)
{
return Dsymbol::oneMember(ps);
return Dsymbol::oneMember(ps, ident);
}
int TemplateMixin::hasPointers()
{
//printf("TemplateMixin::hasPointers() %s\n", toChars());
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = members->tdata()[i];
//printf(" s = %s %s\n", s->kind(), s->toChars());
if (s->hasPointers())
if (members)
for (size_t i = 0; i < members->dim; i++)
{
return 1;
Dsymbol *s = (*members)[i];
//printf(" s = %s %s\n", s->kind(), s->toChars());
if (s->hasPointers())
{
return 1;
}
}
}
return 0;
}
+11 -8
View File
@@ -95,6 +95,7 @@ struct TemplateDeclaration : ScopeDsymbol
MATCH deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, Objects *dedargs);
FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expression *ethis, Expressions *fargs, int flags = 0);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Expressions *fargs);
TemplateDeclaration *isTemplateDeclaration() { return this; }
@@ -151,7 +152,7 @@ struct TemplateParameter
/* Match actual argument against parameter.
*/
virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags = 0) = 0;
virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0;
/* Create dummy argument based on parameter.
*/
@@ -166,6 +167,8 @@ struct TemplateTypeParameter : TemplateParameter
Type *specType; // type parameter: if !=NULL, this is the type specialization
Type *defaultType;
static Type *tdummy;
TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType);
TemplateTypeParameter *isTemplateTypeParameter();
@@ -177,7 +180,7 @@ struct TemplateTypeParameter : TemplateParameter
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
@@ -208,7 +211,7 @@ struct TemplateValueParameter : TemplateParameter
Expression *specValue;
Expression *defaultValue;
static Expression *edummy;
static AA *edummies;
TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue);
@@ -221,7 +224,7 @@ struct TemplateValueParameter : TemplateParameter
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
@@ -248,7 +251,7 @@ struct TemplateAliasParameter : TemplateParameter
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
@@ -269,7 +272,7 @@ struct TemplateTupleParameter : TemplateParameter
Object *specialization();
Object *defaultArg(Loc loc, Scope *sc);
int overloadMatch(TemplateParameter *);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam, int flags);
MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam);
void *dummyArg();
};
@@ -322,7 +325,7 @@ struct TemplateInstance : ScopeDsymbol
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Dsymbol *toAlias(); // resolve real symbol
const char *kind();
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
int needsTypeInference(Scope *sc);
char *toChars();
char *mangle();
@@ -365,7 +368,7 @@ struct TemplateMixin : TemplateInstance
void semantic3(Scope *sc);
void inlineScan();
const char *kind();
int oneMember(Dsymbol **ps);
int oneMember(Dsymbol **ps, Identifier *ident);
int hasPointers();
char *toChars();
char *mangle();
+31 -12
View File
@@ -57,6 +57,9 @@ static int fptraits(void *param, FuncDeclaration *f)
if (p->ident == Id::getVirtualFunctions && !f->isVirtual())
return 0;
if (p->ident == Id::getVirtualMethods && !f->isVirtualMethod())
return 0;
Expression *e;
if (p->e1->op == TOKdotvar)
@@ -156,6 +159,11 @@ Expression *TraitsExp::semantic(Scope *sc)
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
}
else if (ident == Id::isVirtualMethod)
{
FuncDeclaration *f;
ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtualMethod())
}
else if (ident == Id::isFinalFunction)
{
FuncDeclaration *f;
@@ -218,6 +226,7 @@ Expression *TraitsExp::semantic(Scope *sc)
else if (ident == Id::hasMember ||
ident == Id::getMember ||
ident == Id::getOverloads ||
ident == Id::getVirtualMethods ||
ident == Id::getVirtualFunctions)
{
if (dim != 2)
@@ -262,9 +271,12 @@ Expression *TraitsExp::semantic(Scope *sc)
if (t)
{
Dsymbol *sym = t->toDsymbol(sc);
Dsymbol *sm = sym->search(loc, id, 0);
if (sm)
goto Ltrue;
if (sym)
{
Dsymbol *sm = sym->search(loc, id, 0);
if (sm)
goto Ltrue;
}
}
/* Take any errors as meaning it wasn't found
@@ -274,13 +286,7 @@ Expression *TraitsExp::semantic(Scope *sc)
e = e->trySemantic(sc2);
sc2->pop();
if (!e)
{ if (global.gag)
{
global.errors++;
global.gaggedErrors++;
}
goto Lfalse;
}
else
goto Ltrue;
}
@@ -290,6 +296,7 @@ Expression *TraitsExp::semantic(Scope *sc)
return e;
}
else if (ident == Id::getVirtualFunctions ||
ident == Id::getVirtualMethods ||
ident == Id::getOverloads)
{
unsigned errors = global.errors;
@@ -392,9 +399,21 @@ Expression *TraitsExp::semantic(Scope *sc)
ScopeDsymbol::foreach(sd->members, &PushIdentsDg::dg, idents);
ClassDeclaration *cd = sd->isClassDeclaration();
if (cd && cd->baseClass && ident == Id::allMembers)
{ sd = cd->baseClass; // do again with base class
ScopeDsymbol::foreach(sd->members, &PushIdentsDg::dg, idents);
if (cd && ident == Id::allMembers)
{
struct PushBaseMembers
{
static void dg(ClassDeclaration *cd, Identifiers *idents)
{
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{ ClassDeclaration *cb = (*cd->baseclasses)[i]->base;
ScopeDsymbol::foreach(cb->members, &PushIdentsDg::dg, idents);
if (cb->baseclasses->dim)
dg(cb, idents);
}
}
};
PushBaseMembers::dg(cd, idents);
}
// Turn Identifiers into StringExps reusing the allocated array
-1
View File
@@ -166,7 +166,6 @@ Statement *AsmStatement::semantic(Scope *sc)
sc->func->inlineAsm = true;
#endif
sc->func->hasReturnExp |= 8;
sc->func->inlineStatus = ILSno; // %% not sure
// empty statement -- still do the above things because they might be expected?
if (! tokens)
-1
View File
@@ -9,7 +9,6 @@ handling is necessary, they hold enough information to do-the-right-thing (TM)
#include <cassert>
#include "root.h"
#include "mem.h"
struct Type;
struct Dsymbol;
+1 -1
View File
@@ -458,7 +458,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// handle the rest of the arguments based on param passing style
// variadic instrinsics need some custom casts
// variadic intrinsics need some custom casts
if (va_intrinsic)
{
for (int i=0; i<n_arguments; i++)
+5 -4
View File
@@ -2636,7 +2636,10 @@ DValue* FuncExp::toElem(IRState* p)
fd->codegen(Type::sir);
assert(fd->ir.irFunc->func);
if(fd->tok == TOKdelegate) {
if (fd->tok == TOKreserved && type->ty == Tpointer && fd->vthis)
fd->tok = TOKfunction;
if(fd->isNested()) {
LLType* dgty = DtoType(type);
LLValue* cval;
@@ -2673,11 +2676,9 @@ DValue* FuncExp::toElem(IRState* p)
return new DImValue(type, DtoAggrPair(cval, castfptr, ".func"));
} else if(fd->tok == TOKfunction) {
} else {
return new DImValue(type, fd->ir.irFunc->func);
}
assert(0 && "fd->tok must be TOKfunction or TOKdelegate");
}
//////////////////////////////////////////////////////////////////////////////////////////
+9 -3
View File
@@ -208,11 +208,18 @@ TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration()
TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration()
{
if (sym->isInterfaceDeclaration())
return new TypeInfoInterfaceDeclaration(this);
return new TypeInfoInterfaceDeclaration(this);
else
return new TypeInfoClassDeclaration(this);
return new TypeInfoClassDeclaration(this);
}
#if DMDV2
TypeInfoDeclaration *TypeVector::getTypeInfoDeclaration()
{
return new TypeInfoVectorDeclaration(this);
}
#endif
TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration()
{
return new TypeInfoEnumDeclaration(this);
@@ -233,7 +240,6 @@ TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
return new TypeInfoTupleDeclaration(this);
}
/* ========================================================================= */
/* These decide if there's an instance for them already in std.typeinfo,
+3
View File
@@ -64,6 +64,9 @@ list(REMOVE_ITEM DCRT_D
${RUNTIME_DC_DIR}/qsort2.d
${RUNTIME_DC_DIR}/trace.d
)
list(REMOVE_ITEM CORE_D
${RUNTIME_DIR}/src/core/simd.d
)
file(GLOB DCRT_C ${RUNTIME_DC_DIR}/*.c)
list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/deh.c ${RUNTIME_DC_DIR}/dylib_fixes.c)
if(UNIX)