mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-30 09:10:19 +02:00
Merge 2.058beta
This commit is contained in:
+15
-22
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -124,6 +124,11 @@ TypeTuple *TypeBasic::toArgTypes()
|
||||
return t;
|
||||
}
|
||||
|
||||
TypeTuple *TypeVector::toArgTypes()
|
||||
{
|
||||
return new TypeTuple(Type::tfloat64);
|
||||
}
|
||||
|
||||
TypeTuple *TypeSArray::toArgTypes()
|
||||
{
|
||||
#if DMDV2
|
||||
|
||||
+1
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+69
-76
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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; }
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+23
-12
@@ -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
@@ -34,7 +34,7 @@ struct Module;
|
||||
= ! ~ @
|
||||
^^ ^^=
|
||||
++ --
|
||||
. -> : ,
|
||||
. -> : , =>
|
||||
? && ||
|
||||
*/
|
||||
|
||||
@@ -168,6 +168,8 @@ enum TOK
|
||||
TOKat,
|
||||
TOKpow,
|
||||
TOKpowass,
|
||||
TOKgoesto,
|
||||
TOKvector,
|
||||
#endif
|
||||
|
||||
// LDC specific
|
||||
|
||||
+70
-23
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+22
-3
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
Submodule runtime/druntime updated: 3392500611...f2ce54913b
+1
-1
Submodule runtime/phobos updated: 1f6264e942...2cc90b12a6
Reference in New Issue
Block a user